MediaWiki  master
HttpDate.php
Go to the documentation of this file.
1 <?php
2 
4 
23 class HttpDate extends HeaderParserBase {
24  private static $dayNames = [
25  'Mon' => true,
26  'Tue' => true,
27  'Wed' => true,
28  'Thu' => true,
29  'Fri' => true,
30  'Sat' => true,
31  'Sun' => true
32  ];
33 
34  private static $monthsByName = [
35  'Jan' => 1,
36  'Feb' => 2,
37  'Mar' => 3,
38  'Apr' => 4,
39  'May' => 5,
40  'Jun' => 6,
41  'Jul' => 7,
42  'Aug' => 8,
43  'Sep' => 9,
44  'Oct' => 10,
45  'Nov' => 11,
46  'Dec' => 12,
47  ];
48 
49  private static $dayNamesLong = [
50  'Monday',
51  'Tuesday',
52  'Wednesday',
53  'Thursday',
54  'Friday',
55  'Saturday',
56  'Sunday',
57  ];
58 
59  private $dayName;
60  private $day;
61  private $month;
62  private $year;
63  private $hour;
64  private $minute;
65  private $second;
66 
73  public static function parse( $dateString ) {
74  $parser = new self( $dateString );
75  if ( $parser->execute() ) {
76  return $parser->getUnixTime();
77  } else {
78  return null;
79  }
80  }
81 
89  public static function format( $unixTime ) {
90  return gmdate( 'D, d M Y H:i:s \G\M\T', $unixTime );
91  }
92 
98  private function __construct( $input ) {
99  $this->setInput( $input );
100  }
101 
107  private function execute() {
108  $this->pos = 0;
109  try {
110  $this->consumeFixdate();
111  $this->assertEnd();
112  return true;
113  } catch ( HeaderParserError $e ) {
114  }
115  $this->pos = 0;
116  try {
117  $this->consumeRfc850Date();
118  $this->assertEnd();
119  return true;
120  } catch ( HeaderParserError $e ) {
121  }
122  $this->pos = 0;
123  try {
124  $this->consumeAsctimeDate();
125  $this->assertEnd();
126  return true;
127  } catch ( HeaderParserError $e ) {
128  }
129  return false;
130  }
131 
137  private function consumeFixdate() {
138  $this->consumeDayName();
139  $this->consumeString( ', ' );
140  $this->consumeDate1();
141  $this->consumeString( ' ' );
142  $this->consumeTimeOfDay();
143  $this->consumeString( ' GMT' );
144  }
145 
151  private function consumeDayName() {
152  $next3 = substr( $this->input, $this->pos, 3 );
153  if ( isset( self::$dayNames[$next3] ) ) {
154  $this->dayName = $next3;
155  $this->pos += 3;
156  } else {
157  $this->error( 'expected day-name' );
158  }
159  }
160 
166  private function consumeDate1() {
167  $this->consumeDay();
168  $this->consumeString( ' ' );
169  $this->consumeMonth();
170  $this->consumeString( ' ' );
171  $this->consumeYear();
172  }
173 
179  private function consumeDay() {
180  $this->day = $this->consumeFixedDigits( 2 );
181  }
182 
188  private function consumeMonth() {
189  $next3 = substr( $this->input, $this->pos, 3 );
190  if ( isset( self::$monthsByName[$next3] ) ) {
191  $this->month = self::$monthsByName[$next3];
192  $this->pos += 3;
193  } else {
194  $this->error( 'expected month' );
195  }
196  }
197 
203  private function consumeYear() {
204  $this->year = $this->consumeFixedDigits( 4 );
205  }
206 
211  private function consumeTimeOfDay() {
212  $this->hour = $this->consumeFixedDigits( 2 );
213  $this->consumeString( ':' );
214  $this->minute = $this->consumeFixedDigits( 2 );
215  $this->consumeString( ':' );
216  $this->second = $this->consumeFixedDigits( 2 );
217  }
218 
224  private function consumeRfc850Date() {
225  $this->consumeDayNameLong();
226  $this->consumeString( ', ' );
227  $this->consumeDate2();
228  $this->consumeString( ' ' );
229  $this->consumeTimeOfDay();
230  $this->consumeString( ' GMT' );
231  }
232 
238  private function consumeDate2() {
239  $this->consumeDay();
240  $this->consumeString( '-' );
241  $this->consumeMonth();
242  $this->consumeString( '-' );
243  $year = $this->consumeFixedDigits( 2 );
244  // RFC 2626 section 11.2
245  $currentYear = gmdate( 'Y' );
246  $startOfCentury = round( $currentYear, -2 );
247  $this->year = $startOfCentury + intval( $year );
248  $pivot = $currentYear + 50;
249  if ( $this->year > $pivot ) {
250  $this->year -= 100;
251  }
252  }
253 
259  private function consumeDayNameLong() {
260  foreach ( self::$dayNamesLong as $dayName ) {
261  if ( substr_compare( $this->input, $dayName, $this->pos, strlen( $dayName ) ) === 0 ) {
262  $this->dayName = substr( $dayName, 0, 3 );
263  $this->pos += strlen( $dayName );
264  return;
265  }
266  }
267  $this->error( 'expected day-name-l' );
268  }
269 
275  private function consumeAsctimeDate() {
276  $this->consumeDayName();
277  $this->consumeString( ' ' );
278  $this->consumeDate3();
279  $this->consumeString( ' ' );
280  $this->consumeTimeOfDay();
281  $this->consumeString( ' ' );
282  $this->consumeYear();
283  }
284 
290  private function consumeDate3() {
291  $this->consumeMonth();
292  $this->consumeString( ' ' );
293  if ( ( $this->input[$this->pos] ?? '' ) === ' ' ) {
294  $this->pos++;
295  $this->day = '0' . $this->consumeFixedDigits( 1 );
296  } else {
297  $this->day = $this->consumeFixedDigits( 2 );
298  }
299  }
300 
307  private function getUnixTime() {
308  return gmmktime( $this->hour, $this->minute, $this->second,
309  $this->month, $this->day, $this->year );
310  }
311 }
MediaWiki\Rest\HeaderParser\HttpDate
This is a parser for "HTTP-date" as defined by RFC 7231.
Definition: HttpDate.php:23
MediaWiki\Rest\HeaderParser\HttpDate\consumeDate2
consumeDate2()
Execute the date2 rule.
Definition: HttpDate.php:238
MediaWiki\Rest\HeaderParser\HeaderParserError
Definition: HeaderParserError.php:5
MediaWiki\Rest\HeaderParser\HeaderParserBase\setInput
setInput( $input)
Set the input, and derived convenience properties.
Definition: HeaderParserBase.php:29
MediaWiki\Rest\HeaderParser\HeaderParserBase\assertEnd
assertEnd()
If the position is not at the end of the input string, raise an error, complaining of trailing charac...
Definition: HeaderParserBase.php:91
MediaWiki\Rest\HeaderParser\HttpDate\__construct
__construct( $input)
Private constructor.
Definition: HttpDate.php:98
true
return true
Definition: router.php:90
MediaWiki\Rest\HeaderParser\HttpDate\format
static format( $unixTime)
A convenience function to convert a UNIX timestamp to the preferred IMF-fixdate format for HTTP heade...
Definition: HttpDate.php:89
MediaWiki\Rest\HeaderParser\HeaderParserBase
Definition: HeaderParserBase.php:8
MediaWiki\Rest\HeaderParser\HttpDate\getUnixTime
getUnixTime()
Convert the captured results to a UNIX timestamp.
Definition: HttpDate.php:307
MediaWiki\Rest\HeaderParser\HttpDate\parse
static parse( $dateString)
Parse an HTTP-date string.
Definition: HttpDate.php:73
MediaWiki\Rest\HeaderParser\HttpDate\consumeDate1
consumeDate1()
Execute the date1 rule.
Definition: HttpDate.php:166
MediaWiki\Rest\HeaderParser\HttpDate\consumeDay
consumeDay()
Execute the day rule, and capture the result.
Definition: HttpDate.php:179
MediaWiki\Rest\HeaderParser\HttpDate\consumeDayNameLong
consumeDayNameLong()
Execute the day-name-l rule.
Definition: HttpDate.php:259
MediaWiki\Rest\HeaderParser\HttpDate\consumeDate3
consumeDate3()
Execute the date3 rule.
Definition: HttpDate.php:290
MediaWiki\Rest\HeaderParser\HeaderParserBase\consumeFixedDigits
consumeFixedDigits( $numDigits)
Consume a specified number of digits, or throw an exception.
Definition: HeaderParserBase.php:76
MediaWiki\Rest\HeaderParser\HttpDate\$day
$day
Definition: HttpDate.php:60
MediaWiki\Rest\HeaderParser\HttpDate\$dayNames
static $dayNames
Definition: HttpDate.php:24
MediaWiki\Rest\HeaderParser\HttpDate\$minute
$minute
Definition: HttpDate.php:64
MediaWiki\Rest\HeaderParser\HttpDate\consumeRfc850Date
consumeRfc850Date()
Execute the rfc850-date rule.
Definition: HttpDate.php:224
MediaWiki\Rest\HeaderParser\HttpDate\consumeYear
consumeYear()
Execute the year rule, and capture the result.
Definition: HttpDate.php:203
MediaWiki\Rest\HeaderParser\HttpDate\execute
execute()
Parse the input string.
Definition: HttpDate.php:107
MediaWiki\Rest\HeaderParser\HttpDate\$dayName
$dayName
Definition: HttpDate.php:59
MediaWiki\Rest\HeaderParser\HttpDate\consumeMonth
consumeMonth()
Execute the month rule, and capture the result.
Definition: HttpDate.php:188
MediaWiki\Rest\HeaderParser\HttpDate\$hour
$hour
Definition: HttpDate.php:63
MediaWiki\Rest\HeaderParser\HeaderParserBase\$input
string $input
The input string being processed.
Definition: HeaderParserBase.php:12
MediaWiki\Rest\HeaderParser\HttpDate\consumeTimeOfDay
consumeTimeOfDay()
Execute the time-of-day rule.
Definition: HttpDate.php:211
MediaWiki\Rest\HeaderParser\HeaderParserBase\error
error( $message)
Throw an exception to indicate a parse error.
Definition: HeaderParserBase.php:65
MediaWiki\Rest\HeaderParser\HttpDate\$monthsByName
static $monthsByName
Definition: HttpDate.php:34
MediaWiki\Rest\HeaderParser\HttpDate\$month
$month
Definition: HttpDate.php:61
MediaWiki\Rest\HeaderParser\HttpDate\consumeAsctimeDate
consumeAsctimeDate()
Execute the asctime-date rule.
Definition: HttpDate.php:275
MediaWiki\Rest\HeaderParser\HttpDate\$year
$year
Definition: HttpDate.php:62
MediaWiki\Rest\HeaderParser\HttpDate\$dayNamesLong
static $dayNamesLong
Definition: HttpDate.php:49
MediaWiki\Rest\HeaderParser\HttpDate\consumeFixdate
consumeFixdate()
Execute the IMF-fixdate rule, or throw an exception.
Definition: HttpDate.php:137
MediaWiki\Rest\HeaderParser\HttpDate\consumeDayName
consumeDayName()
Execute the day-name rule, and capture the result.
Definition: HttpDate.php:151
MediaWiki\Rest\HeaderParser\HeaderParserBase\consumeString
consumeString( $s)
Consume a specified string, or throw an exception.
Definition: HeaderParserBase.php:41
MediaWiki\Rest\HeaderParser
Definition: HeaderParserBase.php:3
MediaWiki\Rest\HeaderParser\HttpDate\$second
$second
Definition: HttpDate.php:65