PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/include/Etag.php

https://github.com/usagi-project/mynets1
PHP | 188 lines | 119 code | 17 blank | 52 comment | 20 complexity | e250e3c1b3f364997f62c93320cebab3 MD5 | raw file
  1. <?php
  2. /**
  3. * Etag class
  4. *
  5. * @author Ryosuke Hosoi <hosoi ryo.com>
  6. * @package Etag
  7. * @access public
  8. * @version 1.0
  9. */
  10. //20091202 PHP5.3対応のため、eregをpreg_matchに変更
  11. //KUNIHARU Tsujioka Usagi Project
  12. class Etag
  13. {
  14. /**
  15. * the http etag string
  16. * @var string
  17. */
  18. var $etag;
  19. /**
  20. * the last modified timestamp
  21. * @var integer
  22. */
  23. var $upd_time;
  24. /**
  25. * the apache httpd request headers
  26. * @var array
  27. */
  28. var $request_headers;
  29. /**
  30. * Constructor
  31. *
  32. * @access publice
  33. * @param string $key the etag md5 key
  34. * @param mixed $time the document last modified timestamp
  35. * @return void
  36. */
  37. function Etag($key = '', $time = '')
  38. {
  39. if (strlen($key))
  40. $this->etag = md5($key);
  41. else
  42. $this->etag = null;
  43. if (is_array($time)) {
  44. $this->upd_time = 0;
  45. foreach ($time as $t) {
  46. if (preg_match("/^[0-9]{10}$/", $t)) {
  47. $tmp = $t;
  48. } else {
  49. $tmp = $this->parse_http_date($t);
  50. $tmp = $tmp['timestamp'];
  51. }
  52. if ($this->upd_time < $tmp)
  53. $this->upd_time = $tmp;
  54. }
  55. if ($this->upd_time === 0)
  56. $this->upd_time = null;
  57. } elseif (strlen($time)) {
  58. if (preg_match("/^[0-9]{10}$/", $time)) {
  59. $this->upd_time = $time;
  60. } else {
  61. $tmp = $this->parse_http_date($time);
  62. if ($tmp['timestamp'])
  63. $this->upd_time = $tmp['timestamp'];
  64. else
  65. $this->upd_time = null;
  66. }
  67. } else {
  68. $this->upd_time = null;
  69. }
  70. if (is_callable('apache_request_headers')) {
  71. $this->request_headers = apache_request_headers();
  72. } else {
  73. $this->request_headers = $_SERVER;
  74. }
  75. }
  76. /**
  77. * http date parser
  78. *
  79. * @access private
  80. * @param string $string_date the date string
  81. * @return array
  82. */
  83. function parse_http_date( $string_date )
  84. {
  85. // 月の名前と数字を定義
  86. $define_month = array(
  87. "01"=> "Jan", "02" => "Feb", "03" => "Mar",
  88. "04" => "Apr", "05" => "May", "06" => "Jun",
  89. "07" => "Jul", "08" => "Aug", "09" => "Sep",
  90. "10" => "Oct", "11" => "Nov", "12" => "Dec"
  91. );
  92. $temp_date = array();
  93. if( preg_match( "/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0-3][0-9]) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$/", $string_date, $temp_date ) ) {
  94. $date["hour"] = $temp_date[5];
  95. $date["minute"] = $temp_date[6];
  96. $date["second"] = $temp_date[7];
  97. // 定義済みの月の名前を数字に変換する
  98. $date["month"] = array_search( $temp_date[3], $define_month );
  99. $date["day"] = $temp_date[2];
  100. $date["year"] = $temp_date[4];
  101. } elseif( preg_match( "/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), ([0-3][0-9])-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-([0-9]{2}) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$/", $string_date, $temp_date ) ) {
  102. $date["hour"] = $temp_date[5];
  103. $date["minute"] = $temp_date[6];
  104. $date["second"] = $temp_date[7];
  105. // 定義済みの月の名前を数字に変換する
  106. $date["month"] = array_search( $temp_date[3], $define_month );
  107. // 年が2桁しかないので1900を足して4桁に
  108. $date["day"] = $temp_date[2];
  109. $date["year"] = 1900 + $temp_date[4];
  110. } elseif( preg_match( "/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-3 ][0-9]) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) ([0-9]{4})$/", $string_date, $temp_date ) ) {
  111. $date["hour"] = $temp_date[4];
  112. $date["minute"] = $temp_date[5];
  113. $date["second"] = $temp_date[6];
  114. $date["month"] = array_search( $temp_date[2], $define_month );
  115. // 日が1桁の場合先、半角スペースを0に置換
  116. $date["day"] = str_replace( " ", 0, $temp_date[3] );
  117. // 定義済みの月の名前を数字に変換する
  118. $date["year"] = $temp_date[7];
  119. } elseif (@strtotime($string_date) > 0) {
  120. $date["timestamp"] = strtotime($string_date);
  121. $date["year"] = gmdate("Y", $date["timestamp"]);
  122. $date["month"] = gmdate("m", $date["timestamp"]);
  123. $date["day"] = gmdate("d", $date["timestamp"]);
  124. $date["hour"] = gmdate("H", $date["timestamp"]);
  125. $date["minute"] = gmdate("i", $date["timestamp"]);
  126. $date["second"] = gmdate("s", $date["timestamp"]);
  127. } else {
  128. return FALSE;
  129. }
  130. // UNIXタイムスタンプを生成(GMT)
  131. $date["timestamp"] = gmmktime( $date["hour"], $date["minute"], $date["second"], $date["month"], $date["day"], $date["year"] );
  132. return $date;
  133. }
  134. /**
  135. * etag checker
  136. *
  137. * @access public
  138. * @return boolean
  139. */
  140. function etagCheck()
  141. {
  142. if (!@isset($this->etag)) {
  143. return false;
  144. }
  145. if (!@isset($this->upd_time)) {
  146. return false;
  147. }
  148. if (@isset($this->request_headers['If-None-Match'])) {
  149. // Etagによる確認
  150. $match = $this->request_headers['If-None-Match'];
  151. $match = trim(str_replace('"', '', $match));
  152. if ($match == $this->etag) {
  153. header('HTTP/1.1 304 Not Modified');
  154. header('Etag: "'.$this->etag.'"');
  155. return true;
  156. }
  157. } elseif (@isset($this->request_headers['If-Modified-Since'])) {
  158. // 最終更新日時による確認
  159. $since = $this->parse_http_date($this->request_headers['If-Modified-Since']);
  160. if($since['timestamp'] >= $this->upd_time ) {
  161. header('HTTP/1.1 304 Not Modified');
  162. header('Etag: "'.$this->etag.'"');
  163. return true;
  164. }
  165. }
  166. @header('Etag: "'.$this->etag.'"');
  167. @header('Last-Modified: '.@gmdate('D, d M Y H:i:s', $this->upd_time).' GMT');
  168. return false;
  169. }
  170. }
  171. ?>