You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. <?php
  2. /**
  3. * SimplePie
  4. *
  5. * A PHP-Based RSS and Atom Feed Framework.
  6. * Takes the hard work out of managing a complete RSS/Atom solution.
  7. *
  8. * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without modification, are
  12. * permitted provided that the following conditions are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright notice, this list of
  15. * conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above copyright notice, this list
  18. * of conditions and the following disclaimer in the documentation and/or other materials
  19. * provided with the distribution.
  20. *
  21. * * Neither the name of the SimplePie Team nor the names of its contributors may be used
  22. * to endorse or promote products derived from this software without specific prior
  23. * written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  26. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  27. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  28. * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * @package SimplePie
  36. * @version 1.3.1
  37. * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  38. * @author Ryan Parman
  39. * @author Geoffrey Sneddon
  40. * @author Ryan McCue
  41. * @link http://simplepie.org/ SimplePie
  42. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  43. */
  44. /**
  45. * Date Parser
  46. *
  47. * @package SimplePie
  48. * @subpackage Parsing
  49. */
  50. class SimplePie_Parse_Date
  51. {
  52. /**
  53. * Input data
  54. *
  55. * @access protected
  56. * @var string
  57. */
  58. var $date;
  59. /**
  60. * List of days, calendar day name => ordinal day number in the week
  61. *
  62. * @access protected
  63. * @var array
  64. */
  65. var $day = array(
  66. // English
  67. 'mon' => 1,
  68. 'monday' => 1,
  69. 'tue' => 2,
  70. 'tuesday' => 2,
  71. 'wed' => 3,
  72. 'wednesday' => 3,
  73. 'thu' => 4,
  74. 'thursday' => 4,
  75. 'fri' => 5,
  76. 'friday' => 5,
  77. 'sat' => 6,
  78. 'saturday' => 6,
  79. 'sun' => 7,
  80. 'sunday' => 7,
  81. // Dutch
  82. 'maandag' => 1,
  83. 'dinsdag' => 2,
  84. 'woensdag' => 3,
  85. 'donderdag' => 4,
  86. 'vrijdag' => 5,
  87. 'zaterdag' => 6,
  88. 'zondag' => 7,
  89. // French
  90. 'lundi' => 1,
  91. 'mardi' => 2,
  92. 'mercredi' => 3,
  93. 'jeudi' => 4,
  94. 'vendredi' => 5,
  95. 'samedi' => 6,
  96. 'dimanche' => 7,
  97. // German
  98. 'montag' => 1,
  99. 'dienstag' => 2,
  100. 'mittwoch' => 3,
  101. 'donnerstag' => 4,
  102. 'freitag' => 5,
  103. 'samstag' => 6,
  104. 'sonnabend' => 6,
  105. 'sonntag' => 7,
  106. // Italian
  107. 'lunedì' => 1,
  108. 'martedì' => 2,
  109. 'mercoledì' => 3,
  110. 'giovedì' => 4,
  111. 'venerdì' => 5,
  112. 'sabato' => 6,
  113. 'domenica' => 7,
  114. // Spanish
  115. 'lunes' => 1,
  116. 'martes' => 2,
  117. 'miércoles' => 3,
  118. 'jueves' => 4,
  119. 'viernes' => 5,
  120. 'sábado' => 6,
  121. 'domingo' => 7,
  122. // Finnish
  123. 'maanantai' => 1,
  124. 'tiistai' => 2,
  125. 'keskiviikko' => 3,
  126. 'torstai' => 4,
  127. 'perjantai' => 5,
  128. 'lauantai' => 6,
  129. 'sunnuntai' => 7,
  130. // Hungarian
  131. 'hétfő' => 1,
  132. 'kedd' => 2,
  133. 'szerda' => 3,
  134. 'csütörtok' => 4,
  135. 'péntek' => 5,
  136. 'szombat' => 6,
  137. 'vasárnap' => 7,
  138. // Greek
  139. 'Δευ' => 1,
  140. 'Τρι' => 2,
  141. 'Τετ' => 3,
  142. 'Πεμ' => 4,
  143. 'Παρ' => 5,
  144. 'Σαβ' => 6,
  145. 'Κυρ' => 7,
  146. );
  147. /**
  148. * List of months, calendar month name => calendar month number
  149. *
  150. * @access protected
  151. * @var array
  152. */
  153. var $month = array(
  154. // English
  155. 'jan' => 1,
  156. 'january' => 1,
  157. 'feb' => 2,
  158. 'february' => 2,
  159. 'mar' => 3,
  160. 'march' => 3,
  161. 'apr' => 4,
  162. 'april' => 4,
  163. 'may' => 5,
  164. // No long form of May
  165. 'jun' => 6,
  166. 'june' => 6,
  167. 'jul' => 7,
  168. 'july' => 7,
  169. 'aug' => 8,
  170. 'august' => 8,
  171. 'sep' => 9,
  172. 'september' => 8,
  173. 'oct' => 10,
  174. 'october' => 10,
  175. 'nov' => 11,
  176. 'november' => 11,
  177. 'dec' => 12,
  178. 'december' => 12,
  179. // Dutch
  180. 'januari' => 1,
  181. 'februari' => 2,
  182. 'maart' => 3,
  183. 'april' => 4,
  184. 'mei' => 5,
  185. 'juni' => 6,
  186. 'juli' => 7,
  187. 'augustus' => 8,
  188. 'september' => 9,
  189. 'oktober' => 10,
  190. 'november' => 11,
  191. 'december' => 12,
  192. // French
  193. 'janvier' => 1,
  194. 'février' => 2,
  195. 'mars' => 3,
  196. 'avril' => 4,
  197. 'mai' => 5,
  198. 'juin' => 6,
  199. 'juillet' => 7,
  200. 'août' => 8,
  201. 'septembre' => 9,
  202. 'octobre' => 10,
  203. 'novembre' => 11,
  204. 'décembre' => 12,
  205. // German
  206. 'januar' => 1,
  207. 'februar' => 2,
  208. 'märz' => 3,
  209. 'april' => 4,
  210. 'mai' => 5,
  211. 'juni' => 6,
  212. 'juli' => 7,
  213. 'august' => 8,
  214. 'september' => 9,
  215. 'oktober' => 10,
  216. 'november' => 11,
  217. 'dezember' => 12,
  218. // Italian
  219. 'gennaio' => 1,
  220. 'febbraio' => 2,
  221. 'marzo' => 3,
  222. 'aprile' => 4,
  223. 'maggio' => 5,
  224. 'giugno' => 6,
  225. 'luglio' => 7,
  226. 'agosto' => 8,
  227. 'settembre' => 9,
  228. 'ottobre' => 10,
  229. 'novembre' => 11,
  230. 'dicembre' => 12,
  231. // Spanish
  232. 'enero' => 1,
  233. 'febrero' => 2,
  234. 'marzo' => 3,
  235. 'abril' => 4,
  236. 'mayo' => 5,
  237. 'junio' => 6,
  238. 'julio' => 7,
  239. 'agosto' => 8,
  240. 'septiembre' => 9,
  241. 'setiembre' => 9,
  242. 'octubre' => 10,
  243. 'noviembre' => 11,
  244. 'diciembre' => 12,
  245. // Finnish
  246. 'tammikuu' => 1,
  247. 'helmikuu' => 2,
  248. 'maaliskuu' => 3,
  249. 'huhtikuu' => 4,
  250. 'toukokuu' => 5,
  251. 'kesäkuu' => 6,
  252. 'heinäkuu' => 7,
  253. 'elokuu' => 8,
  254. 'suuskuu' => 9,
  255. 'lokakuu' => 10,
  256. 'marras' => 11,
  257. 'joulukuu' => 12,
  258. // Hungarian
  259. 'január' => 1,
  260. 'február' => 2,
  261. 'március' => 3,
  262. 'április' => 4,
  263. 'május' => 5,
  264. 'június' => 6,
  265. 'július' => 7,
  266. 'augusztus' => 8,
  267. 'szeptember' => 9,
  268. 'október' => 10,
  269. 'november' => 11,
  270. 'december' => 12,
  271. // Greek
  272. 'Ιαν' => 1,
  273. 'Φεβ' => 2,
  274. 'Μάώ' => 3,
  275. 'Μαώ' => 3,
  276. 'Απρ' => 4,
  277. 'Μάι' => 5,
  278. 'Μαϊ' => 5,
  279. 'Μαι' => 5,
  280. 'Ιούν' => 6,
  281. 'Ιον' => 6,
  282. 'Ιούλ' => 7,
  283. 'Ιολ' => 7,
  284. 'Αύγ' => 8,
  285. 'Αυγ' => 8,
  286. 'Σεπ' => 9,
  287. 'Οκτ' => 10,
  288. 'Νοέ' => 11,
  289. 'Δεκ' => 12,
  290. );
  291. /**
  292. * List of timezones, abbreviation => offset from UTC
  293. *
  294. * @access protected
  295. * @var array
  296. */
  297. var $timezone = array(
  298. 'ACDT' => 37800,
  299. 'ACIT' => 28800,
  300. 'ACST' => 34200,
  301. 'ACT' => -18000,
  302. 'ACWDT' => 35100,
  303. 'ACWST' => 31500,
  304. 'AEDT' => 39600,
  305. 'AEST' => 36000,
  306. 'AFT' => 16200,
  307. 'AKDT' => -28800,
  308. 'AKST' => -32400,
  309. 'AMDT' => 18000,
  310. 'AMT' => -14400,
  311. 'ANAST' => 46800,
  312. 'ANAT' => 43200,
  313. 'ART' => -10800,
  314. 'AZOST' => -3600,
  315. 'AZST' => 18000,
  316. 'AZT' => 14400,
  317. 'BIOT' => 21600,
  318. 'BIT' => -43200,
  319. 'BOT' => -14400,
  320. 'BRST' => -7200,
  321. 'BRT' => -10800,
  322. 'BST' => 3600,
  323. 'BTT' => 21600,
  324. 'CAST' => 18000,
  325. 'CAT' => 7200,
  326. 'CCT' => 23400,
  327. 'CDT' => -18000,
  328. 'CEDT' => 7200,
  329. 'CEST' => 7200,
  330. 'CET' => 3600,
  331. 'CGST' => -7200,
  332. 'CGT' => -10800,
  333. 'CHADT' => 49500,
  334. 'CHAST' => 45900,
  335. 'CIST' => -28800,
  336. 'CKT' => -36000,
  337. 'CLDT' => -10800,
  338. 'CLST' => -14400,
  339. 'COT' => -18000,
  340. 'CST' => -21600,
  341. 'CVT' => -3600,
  342. 'CXT' => 25200,
  343. 'DAVT' => 25200,
  344. 'DTAT' => 36000,
  345. 'EADT' => -18000,
  346. 'EAST' => -21600,
  347. 'EAT' => 10800,
  348. 'ECT' => -18000,
  349. 'EDT' => -14400,
  350. 'EEST' => 10800,
  351. 'EET' => 7200,
  352. 'EGT' => -3600,
  353. 'EKST' => 21600,
  354. 'EST' => -18000,
  355. 'FJT' => 43200,
  356. 'FKDT' => -10800,
  357. 'FKST' => -14400,
  358. 'FNT' => -7200,
  359. 'GALT' => -21600,
  360. 'GEDT' => 14400,
  361. 'GEST' => 10800,
  362. 'GFT' => -10800,
  363. 'GILT' => 43200,
  364. 'GIT' => -32400,
  365. 'GST' => 14400,
  366. 'GST' => -7200,
  367. 'GYT' => -14400,
  368. 'HAA' => -10800,
  369. 'HAC' => -18000,
  370. 'HADT' => -32400,
  371. 'HAE' => -14400,
  372. 'HAP' => -25200,
  373. 'HAR' => -21600,
  374. 'HAST' => -36000,
  375. 'HAT' => -9000,
  376. 'HAY' => -28800,
  377. 'HKST' => 28800,
  378. 'HMT' => 18000,
  379. 'HNA' => -14400,
  380. 'HNC' => -21600,
  381. 'HNE' => -18000,
  382. 'HNP' => -28800,
  383. 'HNR' => -25200,
  384. 'HNT' => -12600,
  385. 'HNY' => -32400,
  386. 'IRDT' => 16200,
  387. 'IRKST' => 32400,
  388. 'IRKT' => 28800,
  389. 'IRST' => 12600,
  390. 'JFDT' => -10800,
  391. 'JFST' => -14400,
  392. 'JST' => 32400,
  393. 'KGST' => 21600,
  394. 'KGT' => 18000,
  395. 'KOST' => 39600,
  396. 'KOVST' => 28800,
  397. 'KOVT' => 25200,
  398. 'KRAST' => 28800,
  399. 'KRAT' => 25200,
  400. 'KST' => 32400,
  401. 'LHDT' => 39600,
  402. 'LHST' => 37800,
  403. 'LINT' => 50400,
  404. 'LKT' => 21600,
  405. 'MAGST' => 43200,
  406. 'MAGT' => 39600,
  407. 'MAWT' => 21600,
  408. 'MDT' => -21600,
  409. 'MESZ' => 7200,
  410. 'MEZ' => 3600,
  411. 'MHT' => 43200,
  412. 'MIT' => -34200,
  413. 'MNST' => 32400,
  414. 'MSDT' => 14400,
  415. 'MSST' => 10800,
  416. 'MST' => -25200,
  417. 'MUT' => 14400,
  418. 'MVT' => 18000,
  419. 'MYT' => 28800,
  420. 'NCT' => 39600,
  421. 'NDT' => -9000,
  422. 'NFT' => 41400,
  423. 'NMIT' => 36000,
  424. 'NOVST' => 25200,
  425. 'NOVT' => 21600,
  426. 'NPT' => 20700,
  427. 'NRT' => 43200,
  428. 'NST' => -12600,
  429. 'NUT' => -39600,
  430. 'NZDT' => 46800,
  431. 'NZST' => 43200,
  432. 'OMSST' => 25200,
  433. 'OMST' => 21600,
  434. 'PDT' => -25200,
  435. 'PET' => -18000,
  436. 'PETST' => 46800,
  437. 'PETT' => 43200,
  438. 'PGT' => 36000,
  439. 'PHOT' => 46800,
  440. 'PHT' => 28800,
  441. 'PKT' => 18000,
  442. 'PMDT' => -7200,
  443. 'PMST' => -10800,
  444. 'PONT' => 39600,
  445. 'PST' => -28800,
  446. 'PWT' => 32400,
  447. 'PYST' => -10800,
  448. 'PYT' => -14400,
  449. 'RET' => 14400,
  450. 'ROTT' => -10800,
  451. 'SAMST' => 18000,
  452. 'SAMT' => 14400,
  453. 'SAST' => 7200,
  454. 'SBT' => 39600,
  455. 'SCDT' => 46800,
  456. 'SCST' => 43200,
  457. 'SCT' => 14400,
  458. 'SEST' => 3600,
  459. 'SGT' => 28800,
  460. 'SIT' => 28800,
  461. 'SRT' => -10800,
  462. 'SST' => -39600,
  463. 'SYST' => 10800,
  464. 'SYT' => 7200,
  465. 'TFT' => 18000,
  466. 'THAT' => -36000,
  467. 'TJT' => 18000,
  468. 'TKT' => -36000,
  469. 'TMT' => 18000,
  470. 'TOT' => 46800,
  471. 'TPT' => 32400,
  472. 'TRUT' => 36000,
  473. 'TVT' => 43200,
  474. 'TWT' => 28800,
  475. 'UYST' => -7200,
  476. 'UYT' => -10800,
  477. 'UZT' => 18000,
  478. 'VET' => -14400,
  479. 'VLAST' => 39600,
  480. 'VLAT' => 36000,
  481. 'VOST' => 21600,
  482. 'VUT' => 39600,
  483. 'WAST' => 7200,
  484. 'WAT' => 3600,
  485. 'WDT' => 32400,
  486. 'WEST' => 3600,
  487. 'WFT' => 43200,
  488. 'WIB' => 25200,
  489. 'WIT' => 32400,
  490. 'WITA' => 28800,
  491. 'WKST' => 18000,
  492. 'WST' => 28800,
  493. 'YAKST' => 36000,
  494. 'YAKT' => 32400,
  495. 'YAPT' => 36000,
  496. 'YEKST' => 21600,
  497. 'YEKT' => 18000,
  498. );
  499. /**
  500. * Cached PCRE for SimplePie_Parse_Date::$day
  501. *
  502. * @access protected
  503. * @var string
  504. */
  505. var $day_pcre;
  506. /**
  507. * Cached PCRE for SimplePie_Parse_Date::$month
  508. *
  509. * @access protected
  510. * @var string
  511. */
  512. var $month_pcre;
  513. /**
  514. * Array of user-added callback methods
  515. *
  516. * @access private
  517. * @var array
  518. */
  519. var $built_in = array();
  520. /**
  521. * Array of user-added callback methods
  522. *
  523. * @access private
  524. * @var array
  525. */
  526. var $user = array();
  527. /**
  528. * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  529. * self::month_pcre, and self::built_in
  530. *
  531. * @access private
  532. */
  533. public function __construct()
  534. {
  535. $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  536. $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  537. static $cache;
  538. if (!isset($cache[get_class($this)]))
  539. {
  540. $all_methods = get_class_methods($this);
  541. foreach ($all_methods as $method)
  542. {
  543. if (strtolower(substr($method, 0, 5)) === 'date_')
  544. {
  545. $cache[get_class($this)][] = $method;
  546. }
  547. }
  548. }
  549. foreach ($cache[get_class($this)] as $method)
  550. {
  551. $this->built_in[] = $method;
  552. }
  553. }
  554. /**
  555. * Get the object
  556. *
  557. * @access public
  558. */
  559. public static function get()
  560. {
  561. static $object;
  562. if (!$object)
  563. {
  564. $object = new SimplePie_Parse_Date;
  565. }
  566. return $object;
  567. }
  568. /**
  569. * Parse a date
  570. *
  571. * @final
  572. * @access public
  573. * @param string $date Date to parse
  574. * @return int Timestamp corresponding to date string, or false on failure
  575. */
  576. public function parse($date)
  577. {
  578. foreach ($this->user as $method)
  579. {
  580. if (($returned = call_user_func($method, $date)) !== false)
  581. {
  582. return $returned;
  583. }
  584. }
  585. foreach ($this->built_in as $method)
  586. {
  587. if (($returned = call_user_func(array($this, $method), $date)) !== false)
  588. {
  589. return $returned;
  590. }
  591. }
  592. return false;
  593. }
  594. /**
  595. * Add a callback method to parse a date
  596. *
  597. * @final
  598. * @access public
  599. * @param callable $callback
  600. */
  601. public function add_callback($callback)
  602. {
  603. if (is_callable($callback))
  604. {
  605. $this->user[] = $callback;
  606. }
  607. else
  608. {
  609. trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  610. }
  611. }
  612. /**
  613. * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  614. * well as allowing any of upper or lower case "T", horizontal tabs, or
  615. * spaces to be used as the time seperator (including more than one))
  616. *
  617. * @access protected
  618. * @return int Timestamp
  619. */
  620. public function date_w3cdtf($date)
  621. {
  622. static $pcre;
  623. if (!$pcre)
  624. {
  625. $year = '([0-9]{4})';
  626. $month = $day = $hour = $minute = $second = '([0-9]{2})';
  627. $decimal = '([0-9]*)';
  628. $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  629. $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  630. }
  631. if (preg_match($pcre, $date, $match))
  632. {
  633. /*
  634. Capturing subpatterns:
  635. 1: Year
  636. 2: Month
  637. 3: Day
  638. 4: Hour
  639. 5: Minute
  640. 6: Second
  641. 7: Decimal fraction of a second
  642. 8: Zulu
  643. 9: Timezone ±
  644. 10: Timezone hours
  645. 11: Timezone minutes
  646. */
  647. // Fill in empty matches
  648. for ($i = count($match); $i <= 3; $i++)
  649. {
  650. $match[$i] = '1';
  651. }
  652. for ($i = count($match); $i <= 7; $i++)
  653. {
  654. $match[$i] = '0';
  655. }
  656. // Numeric timezone
  657. if (isset($match[9]) && $match[9] !== '')
  658. {
  659. $timezone = $match[10] * 3600;
  660. $timezone += $match[11] * 60;
  661. if ($match[9] === '-')
  662. {
  663. $timezone = 0 - $timezone;
  664. }
  665. }
  666. else
  667. {
  668. $timezone = 0;
  669. }
  670. // Convert the number of seconds to an integer, taking decimals into account
  671. $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  672. return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  673. }
  674. else
  675. {
  676. return false;
  677. }
  678. }
  679. /**
  680. * Remove RFC822 comments
  681. *
  682. * @access protected
  683. * @param string $data Data to strip comments from
  684. * @return string Comment stripped string
  685. */
  686. public function remove_rfc2822_comments($string)
  687. {
  688. $string = (string) $string;
  689. $position = 0;
  690. $length = strlen($string);
  691. $depth = 0;
  692. $output = '';
  693. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  694. {
  695. $output .= substr($string, $position, $pos - $position);
  696. $position = $pos + 1;
  697. if ($string[$pos - 1] !== '\\')
  698. {
  699. $depth++;
  700. while ($depth && $position < $length)
  701. {
  702. $position += strcspn($string, '()', $position);
  703. if ($string[$position - 1] === '\\')
  704. {
  705. $position++;
  706. continue;
  707. }
  708. elseif (isset($string[$position]))
  709. {
  710. switch ($string[$position])
  711. {
  712. case '(':
  713. $depth++;
  714. break;
  715. case ')':
  716. $depth--;
  717. break;
  718. }
  719. $position++;
  720. }
  721. else
  722. {
  723. break;
  724. }
  725. }
  726. }
  727. else
  728. {
  729. $output .= '(';
  730. }
  731. }
  732. $output .= substr($string, $position);
  733. return $output;
  734. }
  735. /**
  736. * Parse RFC2822's date format
  737. *
  738. * @access protected
  739. * @return int Timestamp
  740. */
  741. public function date_rfc2822($date)
  742. {
  743. static $pcre;
  744. if (!$pcre)
  745. {
  746. $wsp = '[\x09\x20]';
  747. $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  748. $optional_fws = $fws . '?';
  749. $day_name = $this->day_pcre;
  750. $month = $this->month_pcre;
  751. $day = '([0-9]{1,2})';
  752. $hour = $minute = $second = '([0-9]{2})';
  753. $year = '([0-9]{2,4})';
  754. $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  755. $character_zone = '([A-Z]{1,5})';
  756. $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  757. $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
  758. }
  759. if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  760. {
  761. /*
  762. Capturing subpatterns:
  763. 1: Day name
  764. 2: Day
  765. 3: Month
  766. 4: Year
  767. 5: Hour
  768. 6: Minute
  769. 7: Second
  770. 8: Timezone ±
  771. 9: Timezone hours
  772. 10: Timezone minutes
  773. 11: Alphabetic timezone
  774. */
  775. // Find the month number
  776. $month = $this->month[strtolower($match[3])];
  777. // Numeric timezone
  778. if ($match[8] !== '')
  779. {
  780. $timezone = $match[9] * 3600;
  781. $timezone += $match[10] * 60;
  782. if ($match[8] === '-')
  783. {
  784. $timezone = 0 - $timezone;
  785. }
  786. }
  787. // Character timezone
  788. elseif (isset($this->timezone[strtoupper($match[11])]))
  789. {
  790. $timezone = $this->timezone[strtoupper($match[11])];
  791. }
  792. // Assume everything else to be -0000
  793. else
  794. {
  795. $timezone = 0;
  796. }
  797. // Deal with 2/3 digit years
  798. if ($match[4] < 50)
  799. {
  800. $match[4] += 2000;
  801. }
  802. elseif ($match[4] < 1000)
  803. {
  804. $match[4] += 1900;
  805. }
  806. // Second is optional, if it is empty set it to zero
  807. if ($match[7] !== '')
  808. {
  809. $second = $match[7];
  810. }
  811. else
  812. {
  813. $second = 0;
  814. }
  815. return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  816. }
  817. else
  818. {
  819. return false;
  820. }
  821. }
  822. /**
  823. * Parse RFC850's date format
  824. *
  825. * @access protected
  826. * @return int Timestamp
  827. */
  828. public function date_rfc850($date)
  829. {
  830. static $pcre;
  831. if (!$pcre)
  832. {
  833. $space = '[\x09\x20]+';
  834. $day_name = $this->day_pcre;
  835. $month = $this->month_pcre;
  836. $day = '([0-9]{1,2})';
  837. $year = $hour = $minute = $second = '([0-9]{2})';
  838. $zone = '([A-Z]{1,5})';
  839. $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  840. }
  841. if (preg_match($pcre, $date, $match))
  842. {
  843. /*
  844. Capturing subpatterns:
  845. 1: Day name
  846. 2: Day
  847. 3: Month
  848. 4: Year
  849. 5: Hour
  850. 6: Minute
  851. 7: Second
  852. 8: Timezone
  853. */
  854. // Month
  855. $month = $this->month[strtolower($match[3])];
  856. // Character timezone
  857. if (isset($this->timezone[strtoupper($match[8])]))
  858. {
  859. $timezone = $this->timezone[strtoupper($match[8])];
  860. }
  861. // Assume everything else to be -0000
  862. else
  863. {
  864. $timezone = 0;
  865. }
  866. // Deal with 2 digit year
  867. if ($match[4] < 50)
  868. {
  869. $match[4] += 2000;
  870. }
  871. else
  872. {
  873. $match[4] += 1900;
  874. }
  875. return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  876. }
  877. else
  878. {
  879. return false;
  880. }
  881. }
  882. /**
  883. * Parse C99's asctime()'s date format
  884. *
  885. * @access protected
  886. * @return int Timestamp
  887. */
  888. public function date_asctime($date)
  889. {
  890. static $pcre;
  891. if (!$pcre)
  892. {
  893. $space = '[\x09\x20]+';
  894. $wday_name = $this->day_pcre;
  895. $mon_name = $this->month_pcre;
  896. $day = '([0-9]{1,2})';
  897. $hour = $sec = $min = '([0-9]{2})';
  898. $year = '([0-9]{4})';
  899. $terminator = '\x0A?\x00?';
  900. $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  901. }
  902. if (preg_match($pcre, $date, $match))
  903. {
  904. /*
  905. Capturing subpatterns:
  906. 1: Day name
  907. 2: Month
  908. 3: Day
  909. 4: Hour
  910. 5: Minute
  911. 6: Second
  912. 7: Year
  913. */
  914. $month = $this->month[strtolower($match[2])];
  915. return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  916. }
  917. else
  918. {
  919. return false;
  920. }
  921. }
  922. /**
  923. * Parse dates using strtotime()
  924. *
  925. * @access protected
  926. * @return int Timestamp
  927. */
  928. public function date_strtotime($date)
  929. {
  930. $strtotime = strtotime($date);
  931. if ($strtotime === -1 || $strtotime === false)
  932. {
  933. return false;
  934. }
  935. else
  936. {
  937. return $strtotime;
  938. }
  939. }
  940. }