CakeResponse.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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.Network
  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.Network
  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. */
  312. public function __construct(array $options = array()) {
  313. if (isset($options['body'])) {
  314. $this->body($options['body']);
  315. }
  316. if (isset($options['status'])) {
  317. $this->statusCode($options['status']);
  318. }
  319. if (isset($options['type'])) {
  320. $this->type($options['type']);
  321. }
  322. if (isset($options['charset'])) {
  323. $this->charset($options['charset']);
  324. }
  325. }
  326. /**
  327. * Sends the complete response to the client including headers and message body.
  328. * Will echo out the content in the response body.
  329. *
  330. * @return void
  331. */
  332. public function send() {
  333. if (isset($this->_headers['Location']) && $this->_status === 200) {
  334. $this->statusCode(302);
  335. }
  336. $codeMessage = $this->_statusCodes[$this->_status];
  337. $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}");
  338. $this->_sendHeader('Content-Type', "{$this->_contentType}; charset={$this->_charset}");
  339. foreach ($this->_headers as $header => $value) {
  340. $this->_sendHeader($header, $value);
  341. }
  342. $this->_sendContent($this->_body);
  343. }
  344. /**
  345. * Sends a header to the client.
  346. *
  347. * @param string $name the header name
  348. * @param string $value the header value
  349. * @return void
  350. */
  351. protected function _sendHeader($name, $value = null) {
  352. if (!headers_sent()) {
  353. if (is_null($value)) {
  354. header($name);
  355. } else {
  356. header("{$name}: {$value}");
  357. }
  358. }
  359. }
  360. /**
  361. * Sends a content string to the client.
  362. *
  363. * @param string $content string to send as response body
  364. * @return void
  365. */
  366. protected function _sendContent($content) {
  367. echo $content;
  368. }
  369. /**
  370. * Buffers a header string to be sent
  371. * Returns the complete list of buffered headers
  372. *
  373. * ### Single header
  374. * e.g `header('Location', 'http://example.com');`
  375. *
  376. * ### Multiple headers
  377. * e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));`
  378. *
  379. * ### String header
  380. * e.g `header('WWW-Authenticate: Negotiate');`
  381. *
  382. * ### Array of string headers
  383. * e.g `header(array('WWW-Authenticate: Negotiate', 'Content-type: application/pdf'));`
  384. *
  385. * Multiple calls for setting the same header name will have the same effect as setting the header once
  386. * with the last value sent for it
  387. * e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');`
  388. * will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');`
  389. *
  390. * @param mixed $header. An array of header strings or a single header string
  391. * - an assotiative array of "header name" => "header value" is also accepted
  392. * - an array of string headers is also accepted
  393. * @param mixed $value. The header value.
  394. * @return array list of headers to be sent
  395. */
  396. public function header($header = null, $value = null) {
  397. if (is_null($header)) {
  398. return $this->_headers;
  399. }
  400. if (is_array($header)) {
  401. foreach ($header as $h => $v) {
  402. if (is_numeric($h)) {
  403. $this->header($v);
  404. continue;
  405. }
  406. $this->_headers[$h] = trim($v);
  407. }
  408. return $this->_headers;
  409. }
  410. if (!is_null($value)) {
  411. $this->_headers[$header] = $value;
  412. return $this->_headers;
  413. }
  414. list($header, $value) = explode(':', $header, 2);
  415. $this->_headers[$header] = trim($value);
  416. return $this->_headers;
  417. }
  418. /**
  419. * Buffers the response message to be sent
  420. * if $content is null the current buffer is returned
  421. *
  422. * @param string $content the string message to be sent
  423. * @return string current message buffer if $content param is passed as null
  424. */
  425. public function body($content = null) {
  426. if (is_null($content)) {
  427. return $this->_body;
  428. }
  429. return $this->_body = $content;
  430. }
  431. /**
  432. * Sets the HTTP status code to be sent
  433. * if $code is null the current code is returned
  434. *
  435. * @param integer $code
  436. * @return integer current status code
  437. * @throws CakeException When an unknown status code is reached.
  438. */
  439. public function statusCode($code = null) {
  440. if (is_null($code)) {
  441. return $this->_status;
  442. }
  443. if (!isset($this->_statusCodes[$code])) {
  444. throw new CakeException(__d('cake_dev', 'Unknown status code'));
  445. }
  446. return $this->_status = $code;
  447. }
  448. /**
  449. * Queries & sets valid HTTP response codes & messages.
  450. *
  451. * @param mixed $code If $code is an integer, then the corresponding code/message is
  452. * returned if it exists, null if it does not exist. If $code is an array,
  453. * then the 'code' and 'message' keys of each nested array are added to the default
  454. * HTTP codes. Example:
  455. *
  456. * httpCodes(404); // returns array(404 => 'Not Found')
  457. *
  458. * httpCodes(array(
  459. * 701 => 'Unicorn Moved',
  460. * 800 => 'Unexpected Minotaur'
  461. * )); // sets these new values, and returns true
  462. *
  463. * @return mixed associative array of the HTTP codes as keys, and the message
  464. * strings as values, or null of the given $code does not exist.
  465. */
  466. public function httpCodes($code = null) {
  467. if (empty($code)) {
  468. return $this->_statusCodes;
  469. }
  470. if (is_array($code)) {
  471. $this->_statusCodes = $code + $this->_statusCodes;
  472. return true;
  473. }
  474. if (!isset($this->_statusCodes[$code])) {
  475. return null;
  476. }
  477. return array($code => $this->_statusCodes[$code]);
  478. }
  479. /**
  480. * Sets the response content type. It can be either a file extension
  481. * which will be mapped internally to a mime-type or a string representing a mime-type
  482. * if $contentType is null the current content type is returned
  483. * if $contentType is an associative array, it will be stored as a content type definition
  484. *
  485. * ### Setting the content type
  486. *
  487. * e.g `type('jpg');`
  488. *
  489. * ### Returning the current content type
  490. *
  491. * e.g `type();`
  492. *
  493. * ### Storing a content type definition
  494. *
  495. * e.g `type(array('keynote' => 'application/keynote'));`
  496. *
  497. * ### Replacing a content type definition
  498. *
  499. * e.g `type(array('jpg' => 'text/plain'));`
  500. *
  501. * @param string $contentType
  502. * @return mixed current content type or false if supplied an invalid content type
  503. */
  504. public function type($contentType = null) {
  505. if (is_null($contentType)) {
  506. return $this->_contentType;
  507. }
  508. if (is_array($contentType)) {
  509. $type = key($contentType);
  510. $defitition = current($contentType);
  511. $this->_mimeTypes[$type] = $defitition;
  512. return $this->_contentType;
  513. }
  514. if (isset($this->_mimeTypes[$contentType])) {
  515. $contentType = $this->_mimeTypes[$contentType];
  516. $contentType = is_array($contentType) ? current($contentType) : $contentType;
  517. }
  518. if (strpos($contentType, '/') === false) {
  519. return false;
  520. }
  521. return $this->_contentType = $contentType;
  522. }
  523. /**
  524. * Returns the mime type definition for an alias
  525. *
  526. * e.g `getMimeType('pdf'); // returns 'application/pdf'`
  527. *
  528. * @param string $alias the content type alias to map
  529. * @return mixed string mapped mime type or false if $alias is not mapped
  530. */
  531. public function getMimeType($alias) {
  532. if (isset($this->_mimeTypes[$alias])) {
  533. return $this->_mimeTypes[$alias];
  534. }
  535. return false;
  536. }
  537. /**
  538. * Maps a content-type back to an alias
  539. *
  540. * e.g `mapType('application/pdf'); // returns 'pdf'`
  541. *
  542. * @param mixed $ctype Either a string content type to map, or an array of types.
  543. * @return mixed Aliases for the types provided.
  544. */
  545. public function mapType($ctype) {
  546. if (is_array($ctype)) {
  547. return array_map(array($this, 'mapType'), $ctype);
  548. }
  549. foreach ($this->_mimeTypes as $alias => $types) {
  550. if (is_array($types) && in_array($ctype, $types)) {
  551. return $alias;
  552. } elseif (is_string($types) && $types == $ctype) {
  553. return $alias;
  554. }
  555. }
  556. return null;
  557. }
  558. /**
  559. * Sets the response charset
  560. * if $charset is null the current charset is returned
  561. *
  562. * @param string $charset
  563. * @return string current charset
  564. */
  565. public function charset($charset = null) {
  566. if (is_null($charset)) {
  567. return $this->_charset;
  568. }
  569. return $this->_charset = $charset;
  570. }
  571. /**
  572. * Sets the correct headers to instruct the client to not cache the response
  573. *
  574. * @return void
  575. */
  576. public function disableCache() {
  577. $this->header(array(
  578. 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
  579. 'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT",
  580. 'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0',
  581. 'Pragma' => 'no-cache'
  582. ));
  583. }
  584. /**
  585. * Sets the correct headers to instruct the client to cache the response.
  586. *
  587. * @param string $since a valid time since the response text has not been modified
  588. * @param string $time a valid time for cache expiry
  589. * @return void
  590. */
  591. public function cache($since, $time = '+1 day') {
  592. if (!is_integer($time)) {
  593. $time = strtotime($time);
  594. }
  595. $this->header(array(
  596. 'Date' => gmdate("D, j M Y G:i:s ", time()) . 'GMT',
  597. 'Last-Modified' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
  598. 'Expires' => gmdate("D, j M Y H:i:s", $time) . " GMT",
  599. 'Cache-Control' => 'public, max-age=' . ($time - time()),
  600. 'Pragma' => 'cache'
  601. ));
  602. }
  603. /**
  604. * Sets the correct output buffering handler to send a compressed response. Responses will
  605. * be compressed with zlib, if the extension is available.
  606. *
  607. * @return boolean false if client does not accept compressed responses or no handler is available, true otherwise
  608. */
  609. public function compress() {
  610. $compressionEnabled = ini_get("zlib.output_compression") !== '1' &&
  611. extension_loaded("zlib") &&
  612. (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
  613. return $compressionEnabled && ob_start('ob_gzhandler');
  614. }
  615. /**
  616. * Sets the correct headers to instruct the browser to dowload the response as a file.
  617. *
  618. * @param string $filename the name of the file as the browser will download the response
  619. * @return void
  620. */
  621. public function download($filename) {
  622. $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
  623. }
  624. /**
  625. * String conversion. Fetches the response body as a string.
  626. * Does *not* send headers.
  627. *
  628. * @return string
  629. */
  630. public function __toString() {
  631. return (string)$this->_body;
  632. }
  633. }