/net/src/lmbHttpCache.class.php

https://github.com/kugu/limb · PHP · 206 lines · 158 code · 33 blank · 15 comment · 21 complexity · 05ef37b5ddb85064fef103537f49a161 MD5 · raw file

  1. <?php
  2. /*
  3. * Limb PHP Framework
  4. *
  5. * @link http://limb-project.com
  6. * @copyright Copyright &copy; 2004-2009 BIT(http://bit-creative.com)
  7. * @license LGPL http://www.gnu.org/copyleft/lesser.html
  8. */
  9. //inspired by http://alexandre.alapetite.net/doc-alex/php-http-304/
  10. /**
  11. * class lmbHttpCache.
  12. *
  13. * @package net
  14. * @version $Id: lmbHttpCache.class.php 7486 2009-01-26 19:13:20Z pachanga $
  15. */
  16. class lmbHttpCache
  17. {
  18. protected $etag;
  19. protected $last_modified_time;
  20. protected $cache_time;
  21. protected $cache_type;
  22. const TYPE_PRIVATE = 0;
  23. const TYPE_PUBLIC = 1;
  24. function __construct()
  25. {
  26. $this->reset();
  27. }
  28. function reset()
  29. {
  30. $this->last_modified_time = time();
  31. $this->etag = null;
  32. $this->cache_time = 0;
  33. $this->cache_type = self::TYPE_PRIVATE;
  34. }
  35. function checkAndWrite($response)
  36. {
  37. if($this->is412())
  38. {
  39. $this->_write412Response($response);
  40. return true;
  41. }
  42. elseif($this->is304())
  43. {
  44. $this->_write304Response($response);
  45. return true;
  46. }
  47. else
  48. {
  49. $this->_writeCachingResponse($response);
  50. return isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'HEAD'; //rfc2616-sec9.html#sec9.4
  51. }
  52. }
  53. function is412()
  54. {
  55. if (isset($_SERVER['HTTP_IF_MATCH'])) //rfc2616-sec14.html#sec14.24
  56. {
  57. $etag_client = stripslashes($_SERVER['HTTP_IF_MATCH']);
  58. return (($etag_client != '*') && (strpos($etag_client, $this->getEtag()) === false));
  59. }
  60. if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE'])) //http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.28
  61. {
  62. return (strcasecmp($_SERVER['HTTP_IF_UNMODIFIED_SINCE'], $this->formatLastModifiedTime()) != 0);
  63. }
  64. return false;
  65. }
  66. function is304()
  67. {
  68. if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) //rfc2616-sec14.html#sec14.25 //rfc1945.txt
  69. {
  70. return ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $this->formatLastModifiedTime());
  71. }
  72. if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) //rfc2616-sec14.html#sec14.26
  73. {
  74. $etag_client = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
  75. return (($etag_client == $this->getEtag()) || ($etag_client == '*'));
  76. }
  77. return false;
  78. }
  79. protected function _write412Response($response)
  80. {
  81. $response->addHeader('HTTP/1.1 412 Precondition Failed');
  82. $response->addHeader('Cache-Control: protected, max-age=0, must-revalidate');
  83. $response->addHeader('Content-Type: text/plain');
  84. $response->write("HTTP/1.1 Error 412 Precondition Failed: Precondition request failed positive evaluation\n");
  85. }
  86. protected function _write304Response($response)
  87. {
  88. $response->addHeader('HTTP/1.0 304 Not Modified');
  89. $response->addHeader('Etag: ' . $this->getEtag());
  90. $response->addHeader('Pragma: ');
  91. $response->addHeader('Cache-Control: ');
  92. $response->addHeader('Last-Modified: ');
  93. $response->addHeader('Expires: ');
  94. }
  95. protected function _writeCachingResponse($response)
  96. {
  97. $response->addHeader('Cache-Control: ' . $this->_getCacheControl()); //rfc2616-sec14.html#sec14.9
  98. $response->addHeader('Last-Modified: ' . $this->formatLastModifiedTime());
  99. $response->addHeader('Etag: ' . $this->getEtag());
  100. $response->addHeader('Pragma: ');
  101. $response->addHeader('Expires: ');
  102. }
  103. protected function _getCacheControl()
  104. {
  105. if ($this->cache_time == 0)
  106. $cache = 'protected, must-revalidate, ';
  107. elseif ($this->cache_type == self::TYPE_PRIVATE)
  108. $cache = 'protected, ';
  109. elseif ($this->cache_type == self::TYPE_PUBLIC)
  110. $cache = 'public, ';
  111. else
  112. $cache = '';
  113. $cache .= 'max-age=' . floor($this->cache_time);
  114. return $cache;
  115. }
  116. function formatLastModifiedTime()
  117. {
  118. return $this->_formatGmtTime($this->last_modified_time);
  119. }
  120. protected function _formatGmtTime($time)
  121. {
  122. return gmdate('D, d M Y H:i:s \G\M\T', $time);
  123. }
  124. function setLastModifiedTime($last_modified_time)
  125. {
  126. $this->last_modified_time = $last_modified_time;
  127. }
  128. function getLastModifiedTime()
  129. {
  130. return $this->last_modified_time;
  131. }
  132. function setEtag($etag)
  133. {
  134. $this->etag = $etag;
  135. }
  136. function getEtag()
  137. {
  138. if($this->etag)
  139. return $this->etag;
  140. //rfc2616-sec14.html#sec14.19 //='"0123456789abcdef0123456789abcdef"'
  141. if (isset($_SERVER['QUERY_STRING']))
  142. $query = '?' . $_SERVER['QUERY_STRING'];
  143. else
  144. $query = '';
  145. $this->etag = '"' . md5($this->_getScriptName() . $query . '#' . $this->last_modified_time ) . '"';
  146. return $this->etag;
  147. }
  148. protected function _getScriptName()
  149. {
  150. if (isset($_SERVER['SCRIPT_FILENAME']))
  151. return $_SERVER['SCRIPT_FILENAME'];
  152. elseif (isset($_SERVER['PATH_TRANSLATED']))
  153. return $_SERVER['PATH_TRANSLATED'];
  154. else
  155. return '';
  156. }
  157. function setCacheTime($cache_time)
  158. {
  159. $this->cache_time = $cache_time;
  160. }
  161. function getCacheTime()
  162. {
  163. return $this->cache_time;
  164. }
  165. function setCacheType($cache_type)
  166. {
  167. $this->cache_type = $cache_type;
  168. }
  169. function getCacheType()
  170. {
  171. return $this->cache_type;
  172. }
  173. }