CakeResponse.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. <?php
  2. /**
  3. * CakeResponse
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package cake.libs
  16. * @since CakePHP(tm) v 2.0
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. /**
  20. * CakeResponse is responsible for managing the response text, status and headers of a HTTP response.
  21. *
  22. * By default controllers will use this class to render their response. If you are going to use
  23. * a custom response class it should subclass this object in order to ensure compatibility.
  24. *
  25. * @package cake.libs
  26. */
  27. class CakeResponse {
  28. /**
  29. * Holds HTTP response statuses
  30. *
  31. * @var array
  32. */
  33. protected $_statusCodes = array(
  34. 100 => 'Continue',
  35. 101 => 'Switching Protocols',
  36. 200 => 'OK',
  37. 201 => 'Created',
  38. 202 => 'Accepted',
  39. 203 => 'Non-Authoritative Information',
  40. 204 => 'No Content',
  41. 205 => 'Reset Content',
  42. 206 => 'Partial Content',
  43. 300 => 'Multiple Choices',
  44. 301 => 'Moved Permanently',
  45. 302 => 'Found',
  46. 303 => 'See Other',
  47. 304 => 'Not Modified',
  48. 305 => 'Use Proxy',
  49. 307 => 'Temporary Redirect',
  50. 400 => 'Bad Request',
  51. 401 => 'Unauthorized',
  52. 402 => 'Payment Required',
  53. 403 => 'Forbidden',
  54. 404 => 'Not Found',
  55. 405 => 'Method Not Allowed',
  56. 406 => 'Not Acceptable',
  57. 407 => 'Proxy Authentication Required',
  58. 408 => 'Request Time-out',
  59. 409 => 'Conflict',
  60. 410 => 'Gone',
  61. 411 => 'Length Required',
  62. 412 => 'Precondition Failed',
  63. 413 => 'Request Entity Too Large',
  64. 414 => 'Request-URI Too Large',
  65. 415 => 'Unsupported Media Type',
  66. 416 => 'Requested range not satisfiable',
  67. 417 => 'Expectation Failed',
  68. 500 => 'Internal Server Error',
  69. 501 => 'Not Implemented',
  70. 502 => 'Bad Gateway',
  71. 503 => 'Service Unavailable',
  72. 504 => 'Gateway Time-out'
  73. );
  74. /**
  75. * Holds known mime type mappings
  76. *
  77. * @var array
  78. */
  79. protected $_mimeTypes = array(
  80. 'ai' => 'application/postscript',
  81. 'bcpio' => 'application/x-bcpio',
  82. 'bin' => 'application/octet-stream',
  83. 'ccad' => 'application/clariscad',
  84. 'cdf' => 'application/x-netcdf',
  85. 'class' => 'application/octet-stream',
  86. 'cpio' => 'application/x-cpio',
  87. 'cpt' => 'application/mac-compactpro',
  88. 'csh' => 'application/x-csh',
  89. 'csv' => array('text/csv', 'application/vnd.ms-excel', 'text/plain'),
  90. 'dcr' => 'application/x-director',
  91. 'dir' => 'application/x-director',
  92. 'dms' => 'application/octet-stream',
  93. 'doc' => 'application/msword',
  94. 'drw' => 'application/drafting',
  95. 'dvi' => 'application/x-dvi',
  96. 'dwg' => 'application/acad',
  97. 'dxf' => 'application/dxf',
  98. 'dxr' => 'application/x-director',
  99. 'eot' => 'application/vnd.ms-fontobject',
  100. 'eps' => 'application/postscript',
  101. 'exe' => 'application/octet-stream',
  102. 'ez' => 'application/andrew-inset',
  103. 'flv' => 'video/x-flv',
  104. 'gtar' => 'application/x-gtar',
  105. 'gz' => 'application/x-gzip',
  106. 'bz2' => 'application/x-bzip',
  107. '7z' => 'application/x-7z-compressed',
  108. 'hdf' => 'application/x-hdf',
  109. 'hqx' => 'application/mac-binhex40',
  110. 'ico' => 'image/vnd.microsoft.icon',
  111. 'ips' => 'application/x-ipscript',
  112. 'ipx' => 'application/x-ipix',
  113. 'js' => 'text/javascript',
  114. 'latex' => 'application/x-latex',
  115. 'lha' => 'application/octet-stream',
  116. 'lsp' => 'application/x-lisp',
  117. 'lzh' => 'application/octet-stream',
  118. 'man' => 'application/x-troff-man',
  119. 'me' => 'application/x-troff-me',
  120. 'mif' => 'application/vnd.mif',
  121. 'ms' => 'application/x-troff-ms',
  122. 'nc' => 'application/x-netcdf',
  123. 'oda' => 'application/oda',
  124. 'otf' => 'font/otf',
  125. 'pdf' => 'application/pdf',
  126. 'pgn' => 'application/x-chess-pgn',
  127. 'pot' => 'application/mspowerpoint',
  128. 'pps' => 'application/mspowerpoint',
  129. 'ppt' => 'application/mspowerpoint',
  130. 'ppz' => 'application/mspowerpoint',
  131. 'pre' => 'application/x-freelance',
  132. 'prt' => 'application/pro_eng',
  133. 'ps' => 'application/postscript',
  134. 'roff' => 'application/x-troff',
  135. 'scm' => 'application/x-lotusscreencam',
  136. 'set' => 'application/set',
  137. 'sh' => 'application/x-sh',
  138. 'shar' => 'application/x-shar',
  139. 'sit' => 'application/x-stuffit',
  140. 'skd' => 'application/x-koan',
  141. 'skm' => 'application/x-koan',
  142. 'skp' => 'application/x-koan',
  143. 'skt' => 'application/x-koan',
  144. 'smi' => 'application/smil',
  145. 'smil' => 'application/smil',
  146. 'sol' => 'application/solids',
  147. 'spl' => 'application/x-futuresplash',
  148. 'src' => 'application/x-wais-source',
  149. 'step' => 'application/STEP',
  150. 'stl' => 'application/SLA',
  151. 'stp' => 'application/STEP',
  152. 'sv4cpio' => 'application/x-sv4cpio',
  153. 'sv4crc' => 'application/x-sv4crc',
  154. 'svg' => 'image/svg+xml',
  155. 'svgz' => 'image/svg+xml',
  156. 'swf' => 'application/x-shockwave-flash',
  157. 't' => 'application/x-troff',
  158. 'tar' => 'application/x-tar',
  159. 'tcl' => 'application/x-tcl',
  160. 'tex' => 'application/x-tex',
  161. 'texi' => 'application/x-texinfo',
  162. 'texinfo' => 'application/x-texinfo',
  163. 'tr' => 'application/x-troff',
  164. 'tsp' => 'application/dsptype',
  165. 'ttf' => 'font/ttf',
  166. 'unv' => 'application/i-deas',
  167. 'ustar' => 'application/x-ustar',
  168. 'vcd' => 'application/x-cdlink',
  169. 'vda' => 'application/vda',
  170. 'xlc' => 'application/vnd.ms-excel',
  171. 'xll' => 'application/vnd.ms-excel',
  172. 'xlm' => 'application/vnd.ms-excel',
  173. 'xls' => 'application/vnd.ms-excel',
  174. 'xlw' => 'application/vnd.ms-excel',
  175. 'zip' => 'application/zip',
  176. 'aif' => 'audio/x-aiff',
  177. 'aifc' => 'audio/x-aiff',
  178. 'aiff' => 'audio/x-aiff',
  179. 'au' => 'audio/basic',
  180. 'kar' => 'audio/midi',
  181. 'mid' => 'audio/midi',
  182. 'midi' => 'audio/midi',
  183. 'mp2' => 'audio/mpeg',
  184. 'mp3' => 'audio/mpeg',
  185. 'mpga' => 'audio/mpeg',
  186. 'ra' => 'audio/x-realaudio',
  187. 'ram' => 'audio/x-pn-realaudio',
  188. 'rm' => 'audio/x-pn-realaudio',
  189. 'rpm' => 'audio/x-pn-realaudio-plugin',
  190. 'snd' => 'audio/basic',
  191. 'tsi' => 'audio/TSP-audio',
  192. 'wav' => 'audio/x-wav',
  193. 'asc' => 'text/plain',
  194. 'c' => 'text/plain',
  195. 'cc' => 'text/plain',
  196. 'css' => 'text/css',
  197. 'etx' => 'text/x-setext',
  198. 'f' => 'text/plain',
  199. 'f90' => 'text/plain',
  200. 'h' => 'text/plain',
  201. 'hh' => 'text/plain',
  202. 'html' => array('text/html', '*/*'),
  203. 'htm' => array('text/html', '*/*'),
  204. 'm' => 'text/plain',
  205. 'rtf' => 'text/rtf',
  206. 'rtx' => 'text/richtext',
  207. 'sgm' => 'text/sgml',
  208. 'sgml' => 'text/sgml',
  209. 'tsv' => 'text/tab-separated-values',
  210. 'tpl' => 'text/template',
  211. 'txt' => 'text/plain',
  212. 'text' => 'text/plain',
  213. 'xml' => array('application/xml', 'text/xml'),
  214. 'avi' => 'video/x-msvideo',
  215. 'fli' => 'video/x-fli',
  216. 'mov' => 'video/quicktime',
  217. 'movie' => 'video/x-sgi-movie',
  218. 'mpe' => 'video/mpeg',
  219. 'mpeg' => 'video/mpeg',
  220. 'mpg' => 'video/mpeg',
  221. 'qt' => 'video/quicktime',
  222. 'viv' => 'video/vnd.vivo',
  223. 'vivo' => 'video/vnd.vivo',
  224. 'gif' => 'image/gif',
  225. 'ief' => 'image/ief',
  226. 'jpe' => 'image/jpeg',
  227. 'jpeg' => 'image/jpeg',
  228. 'jpg' => 'image/jpeg',
  229. 'pbm' => 'image/x-portable-bitmap',
  230. 'pgm' => 'image/x-portable-graymap',
  231. 'png' => 'image/png',
  232. 'pnm' => 'image/x-portable-anymap',
  233. 'ppm' => 'image/x-portable-pixmap',
  234. 'ras' => 'image/cmu-raster',
  235. 'rgb' => 'image/x-rgb',
  236. 'tif' => 'image/tiff',
  237. 'tiff' => 'image/tiff',
  238. 'xbm' => 'image/x-xbitmap',
  239. 'xpm' => 'image/x-xpixmap',
  240. 'xwd' => 'image/x-xwindowdump',
  241. 'ice' => 'x-conference/x-cooltalk',
  242. 'iges' => 'model/iges',
  243. 'igs' => 'model/iges',
  244. 'mesh' => 'model/mesh',
  245. 'msh' => 'model/mesh',
  246. 'silo' => 'model/mesh',
  247. 'vrml' => 'model/vrml',
  248. 'wrl' => 'model/vrml',
  249. 'mime' => 'www/mime',
  250. 'pdb' => 'chemical/x-pdb',
  251. 'xyz' => 'chemical/x-pdb',
  252. 'javascript' => 'text/javascript',
  253. 'json' => 'application/json',
  254. 'form' => 'application/x-www-form-urlencoded',
  255. 'file' => 'multipart/form-data',
  256. 'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
  257. 'xhtml-mobile' => 'application/vnd.wap.xhtml+xml',
  258. 'rss' => 'application/rss+xml',
  259. 'atom' => 'application/atom+xml',
  260. 'amf' => 'application/x-amf',
  261. 'wap' => array('text/vnd.wap.wml', 'text/vnd.wap.wmlscript', 'image/vnd.wap.wbmp'),
  262. 'wml' => 'text/vnd.wap.wml',
  263. 'wmlscript' => 'text/vnd.wap.wmlscript',
  264. 'wbmp' => 'image/vnd.wap.wbmp',
  265. );
  266. /**
  267. * Protocol header to send to the client
  268. *
  269. * @var string
  270. */
  271. protected $_protocol = 'HTTP/1.1';
  272. /**
  273. * Status code to send to the client
  274. *
  275. * @var integer
  276. */
  277. protected $_status = 200;
  278. /**
  279. * Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array
  280. * or a complete mime-type
  281. *
  282. * @var integer
  283. */
  284. protected $_contentType = 'text/html';
  285. /**
  286. * Buffer list of headers
  287. *
  288. * @var array
  289. */
  290. protected $_headers = array();
  291. /**
  292. * Buffer string for response message
  293. *
  294. * @var string
  295. */
  296. protected $_body = null;
  297. /**
  298. * The charset the response body is encoded with
  299. *
  300. * @var string
  301. */
  302. protected $_charset = 'UTF-8';
  303. /**
  304. * Class constructor
  305. *
  306. * @param array $options list of parameters to setup the response. Possible values are:
  307. * - body: the rensonse text that should be sent to the client
  308. * - status: the HTTP status code to respond with
  309. * - type: a complete mime-type string or an extension mapepd in this class
  310. * - charset: the charset for the response body
  311. * @return void
  312. */
  313. public function __construct(array $options = array()) {
  314. if (isset($options['body'])) {
  315. $this->body($options['body']);
  316. }
  317. if (isset($options['status'])) {
  318. $this->statusCode($options['status']);
  319. }
  320. if (isset($options['type'])) {
  321. $this->type($options['type']);
  322. }
  323. if (isset($options['charset'])) {
  324. $this->charset($options['charset']);
  325. }
  326. }
  327. /**
  328. * Sends the complete response to the client including headers and message body.
  329. * Will echo out the content in the response body.
  330. *
  331. * @return void
  332. */
  333. public function send() {
  334. if (isset($this->_headers['Location']) && $this->_status === 200) {
  335. $this->statusCode(302);
  336. }
  337. $codeMessage = $this->_statusCodes[$this->_status];
  338. $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}");
  339. $this->_sendHeader('Content-Type', "{$this->_contentType}; charset={$this->_charset}");
  340. foreach ($this->_headers as $header => $value) {
  341. $this->_sendHeader($header, $value);
  342. }
  343. $this->_sendContent($this->_body);
  344. }
  345. /**
  346. * Sends a header to the client.
  347. *
  348. * @param $name the header name
  349. * @param $value the header value
  350. * @return void
  351. */
  352. protected function _sendHeader($name, $value = null) {
  353. if (!headers_sent()) {
  354. if (is_null($value)) {
  355. header($name);
  356. } else {
  357. header("{$name}: {$value}");
  358. }
  359. }
  360. }
  361. /**
  362. * Sends a content string to the client.
  363. *
  364. * @param $content string to send as response body
  365. * @return void
  366. */
  367. protected function _sendContent($content) {
  368. echo $content;
  369. }
  370. /**
  371. * Buffers a header string to be sent
  372. * Returns the complete list of buffered headers
  373. *
  374. * ### Single header
  375. * e.g `header('Location', 'http://example.com');`
  376. *
  377. * ### Multiple headers
  378. * e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));`
  379. *
  380. * ### String header
  381. * e.g `header('WWW-Authenticate: Negotiate');`
  382. *
  383. * ### Array of string headers
  384. * e.g `header(array('WWW-Authenticate: Negotiate', 'Content-type: application/pdf'));`
  385. *
  386. * Multiple calls for setting the same header name will have the same effect as setting the header once
  387. * with the last value sent for it
  388. * e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');`
  389. * will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');`
  390. *
  391. * @param mixed $header. An array of header strings or a single header string
  392. * - an assotiative array of "header name" => "header value" is also accepted
  393. * - an array of string headers is also accepted
  394. * @param mixed $value. The header value.
  395. * @return array list of headers to be sent
  396. */
  397. public function header($header = null, $value = null) {
  398. if (is_null($header)) {
  399. return $this->_headers;
  400. }
  401. if (is_array($header)) {
  402. foreach ($header as $h => $v) {
  403. if (is_numeric($h)) {
  404. $this->header($v);
  405. continue;
  406. }
  407. $this->_headers[$h] = trim($v);
  408. }
  409. return $this->_headers;
  410. }
  411. if (!is_null($value)) {
  412. $this->_headers[$header] = $value;
  413. return $this->_headers;
  414. }
  415. list($header, $value) = explode(':', $header, 2);
  416. $this->_headers[$header] = trim($value);
  417. return $this->_headers;
  418. }
  419. /**
  420. * Buffers the response message to be sent
  421. * if $content is null the current buffer is returned
  422. *
  423. * @param string $content the string message to be sent
  424. * @return string current message buffer if $content param is passed as null
  425. */
  426. public function body($content = null) {
  427. if (is_null($content)) {
  428. return $this->_body;
  429. }
  430. return $this->_body = $content;
  431. }
  432. /**
  433. * Sets the HTTP status code to be sent
  434. * if $code is null the current code is returned
  435. *
  436. * @param integer $code
  437. * @return integer current status code
  438. * @throws CakeException When an unknown status code is reached.
  439. */
  440. public function statusCode($code = null) {
  441. if (is_null($code)) {
  442. return $this->_status;
  443. }
  444. if (!isset($this->_statusCodes[$code])) {
  445. throw new CakeException(__d('cake_dev', 'Unknown status code'));
  446. }
  447. return $this->_status = $code;
  448. }
  449. /**
  450. * Queries & sets valid HTTP response codes & messages.
  451. *
  452. * @param mixed $code If $code is an integer, then the corresponding code/message is
  453. * returned if it exists, null if it does not exist. If $code is an array,
  454. * then the 'code' and 'message' keys of each nested array are added to the default
  455. * HTTP codes. Example:
  456. *
  457. * httpCodes(404); // returns array(404 => 'Not Found')
  458. *
  459. * httpCodes(array(
  460. * 701 => 'Unicorn Moved',
  461. * 800 => 'Unexpected Minotaur'
  462. * )); // sets these new values, and returns true
  463. *
  464. * @return mixed associative array of the HTTP codes as keys, and the message
  465. * strings as values, or null of the given $code does not exist.
  466. */
  467. public function httpCodes($code = null) {
  468. if (empty($code)) {
  469. return $this->_statusCodes;
  470. }
  471. if (is_array($code)) {
  472. $this->_statusCodes = $code + $this->_statusCodes;
  473. return true;
  474. }
  475. if (!isset($this->_statusCodes[$code])) {
  476. return null;
  477. }
  478. return array($code => $this->_statusCodes[$code]);
  479. }
  480. /**
  481. * Sets the response content type. It can be either a file extension
  482. * which will be mapped internally to a mime-type or a string representing a mime-type
  483. * if $contentType is null the current content type is returned
  484. * if $contentType is an associative array, it will be stored as a content type definition
  485. *
  486. * ### Setting the content type
  487. *
  488. * e.g `type('jpg');`
  489. *
  490. * ### Returning the current content type
  491. *
  492. * e.g `type();`
  493. *
  494. * ### Storing a content type definition
  495. *
  496. * e.g `type(array('keynote' => 'application/keynote'));`
  497. *
  498. * ### Replacing a content type definition
  499. *
  500. * e.g `type(array('jpg' => 'text/plain'));`
  501. *
  502. * @param string $contentType
  503. * @return mixed current content type or false if supplied an invalid content type
  504. */
  505. public function type($contentType = null) {
  506. if (is_null($contentType)) {
  507. return $this->_contentType;
  508. }
  509. if (is_array($contentType)) {
  510. $type = key($contentType);
  511. $defitition = current($contentType);
  512. $this->_mimeTypes[$type] = $defitition;
  513. return $this->_contentType;
  514. }
  515. if (isset($this->_mimeTypes[$contentType])) {
  516. $contentType = $this->_mimeTypes[$contentType];
  517. $contentType = is_array($contentType) ? current($contentType) : $contentType;
  518. }
  519. if (strpos($contentType, '/') === false) {
  520. return false;
  521. }
  522. return $this->_contentType = $contentType;
  523. }
  524. /**
  525. * Returns the mime type definition for an alias
  526. *
  527. * e.g `getMimeType('pdf'); // returns 'application/pdf'`
  528. *
  529. * @param string $alias the content type alias to map
  530. * @return mixed string mapped mime type or false if $alias is not mapped
  531. */
  532. public function getMimeType($alias) {
  533. if (isset($this->_mimeTypes[$alias])) {
  534. return $this->_mimeTypes[$alias];
  535. }
  536. return false;
  537. }
  538. /**
  539. * Maps a content-type back to an alias
  540. *
  541. * e.g `mapType('application/pdf'); // returns 'pdf'`
  542. *
  543. * @param mixed $type Either a string content type to map, or an array of types.
  544. * @return mixed Aliases for the types provided.
  545. */
  546. public function mapType($ctype) {
  547. if (is_array($ctype)) {
  548. return array_map(array($this, 'mapType'), $ctype);
  549. }
  550. $keys = array_keys($this->_mimeTypes);
  551. foreach ($this->_mimeTypes as $alias => $types) {
  552. if (is_array($types) && in_array($ctype, $types)) {
  553. return $alias;
  554. } elseif (is_string($types) && $types == $ctype) {
  555. return $alias;
  556. }
  557. }
  558. return null;
  559. }
  560. /**
  561. * Sets the response charset
  562. * if $charset is null the current charset is returned
  563. *
  564. * @param string $charset
  565. * @return string current charset
  566. */
  567. public function charset($charset = null) {
  568. if (is_null($charset)) {
  569. return $this->_charset;
  570. }
  571. return $this->_charset = $charset;
  572. }
  573. /**
  574. * Sets the correct headers to instruct the client to not cache the response
  575. *
  576. * @return void
  577. */
  578. public function disableCache() {
  579. $this->header(array(
  580. 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
  581. 'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT",
  582. 'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0',
  583. 'Pragma' => 'no-cache'
  584. ));
  585. }
  586. /**
  587. * Sets the correct headers to instruct the client to cache the response.
  588. *
  589. * @param string $since a valid time since the response text has not been modified
  590. * @param string $time a valid time for cache expiry
  591. * @return void
  592. */
  593. public function cache($since, $time = '+1 day') {
  594. if (!is_integer($time)) {
  595. $time = strtotime($time);
  596. }
  597. $this->header(array(
  598. 'Date' => gmdate("D, j M Y G:i:s ", time()) . 'GMT',
  599. 'Last-Modified' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
  600. 'Expires' => gmdate("D, j M Y H:i:s", $time) . " GMT",
  601. 'Cache-Control' => 'public, max-age=' . ($time - time()),
  602. 'Pragma' => 'cache'
  603. ));
  604. }
  605. /**
  606. * Sets the correct output buffering handler to send a compressed response. Responses will
  607. * be compressed with zlib, if the extension is available.
  608. *
  609. * @return boolean false if client does not accept compressed responses or no handler is available, true otherwise
  610. */
  611. public function compress() {
  612. $compressionEnabled = ini_get("zlib.output_compression") !== '1' &&
  613. extension_loaded("zlib") &&
  614. (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
  615. return $compressionEnabled && ob_start('ob_gzhandler');
  616. }
  617. /**
  618. * Sets the correct headers to instruct the browser to dowload the response as a file.
  619. *
  620. * @param string $filename the name of the file as the browser will download the response
  621. * @return void
  622. */
  623. public function download($filename) {
  624. $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
  625. }
  626. }