From 10dc1e2cb4c4940981a3abd776350dc07f92fc3e Mon Sep 17 00:00:00 2001 From: filip Date: Fri, 3 Aug 2018 16:37:28 +0200 Subject: upgrade SimplePie from 1.3.1 to 1.5.2 as a part of a #mga23215 bugfix --- lib/simplepie/library/SimplePie/Parse/Date.php | 972 +++++++++++++++++++++++++ 1 file changed, 972 insertions(+) create mode 100644 lib/simplepie/library/SimplePie/Parse/Date.php (limited to 'lib/simplepie/library/SimplePie/Parse/Date.php') diff --git a/lib/simplepie/library/SimplePie/Parse/Date.php b/lib/simplepie/library/SimplePie/Parse/Date.php new file mode 100644 index 000000000..b29274c64 --- /dev/null +++ b/lib/simplepie/library/SimplePie/Parse/Date.php @@ -0,0 +1,972 @@ + ordinal day number in the week + * + * @access protected + * @var array + */ + var $day = array( + // English + 'mon' => 1, + 'monday' => 1, + 'tue' => 2, + 'tuesday' => 2, + 'wed' => 3, + 'wednesday' => 3, + 'thu' => 4, + 'thursday' => 4, + 'fri' => 5, + 'friday' => 5, + 'sat' => 6, + 'saturday' => 6, + 'sun' => 7, + 'sunday' => 7, + // Dutch + 'maandag' => 1, + 'dinsdag' => 2, + 'woensdag' => 3, + 'donderdag' => 4, + 'vrijdag' => 5, + 'zaterdag' => 6, + 'zondag' => 7, + // French + 'lundi' => 1, + 'mardi' => 2, + 'mercredi' => 3, + 'jeudi' => 4, + 'vendredi' => 5, + 'samedi' => 6, + 'dimanche' => 7, + // German + 'montag' => 1, + 'dienstag' => 2, + 'mittwoch' => 3, + 'donnerstag' => 4, + 'freitag' => 5, + 'samstag' => 6, + 'sonnabend' => 6, + 'sonntag' => 7, + // Italian + 'lunedì' => 1, + 'martedì' => 2, + 'mercoledì' => 3, + 'giovedì' => 4, + 'venerdì' => 5, + 'sabato' => 6, + 'domenica' => 7, + // Spanish + 'lunes' => 1, + 'martes' => 2, + 'miércoles' => 3, + 'jueves' => 4, + 'viernes' => 5, + 'sábado' => 6, + 'domingo' => 7, + // Finnish + 'maanantai' => 1, + 'tiistai' => 2, + 'keskiviikko' => 3, + 'torstai' => 4, + 'perjantai' => 5, + 'lauantai' => 6, + 'sunnuntai' => 7, + // Hungarian + 'hétfő' => 1, + 'kedd' => 2, + 'szerda' => 3, + 'csütörtok' => 4, + 'péntek' => 5, + 'szombat' => 6, + 'vasárnap' => 7, + // Greek + 'Δευ' => 1, + 'Τρι' => 2, + 'Τετ' => 3, + 'Πεμ' => 4, + 'Παρ' => 5, + 'Σαβ' => 6, + 'Κυρ' => 7, + ); + + /** + * List of months, calendar month name => calendar month number + * + * @access protected + * @var array + */ + var $month = array( + // English + 'jan' => 1, + 'january' => 1, + 'feb' => 2, + 'february' => 2, + 'mar' => 3, + 'march' => 3, + 'apr' => 4, + 'april' => 4, + 'may' => 5, + // No long form of May + 'jun' => 6, + 'june' => 6, + 'jul' => 7, + 'july' => 7, + 'aug' => 8, + 'august' => 8, + 'sep' => 9, + 'september' => 9, + 'oct' => 10, + 'october' => 10, + 'nov' => 11, + 'november' => 11, + 'dec' => 12, + 'december' => 12, + // Dutch + 'januari' => 1, + 'februari' => 2, + 'maart' => 3, + 'april' => 4, + 'mei' => 5, + 'juni' => 6, + 'juli' => 7, + 'augustus' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'december' => 12, + // French + 'janvier' => 1, + 'février' => 2, + 'mars' => 3, + 'avril' => 4, + 'mai' => 5, + 'juin' => 6, + 'juillet' => 7, + 'août' => 8, + 'septembre' => 9, + 'octobre' => 10, + 'novembre' => 11, + 'décembre' => 12, + // German + 'januar' => 1, + 'februar' => 2, + 'märz' => 3, + 'april' => 4, + 'mai' => 5, + 'juni' => 6, + 'juli' => 7, + 'august' => 8, + 'september' => 9, + 'oktober' => 10, + 'november' => 11, + 'dezember' => 12, + // Italian + 'gennaio' => 1, + 'febbraio' => 2, + 'marzo' => 3, + 'aprile' => 4, + 'maggio' => 5, + 'giugno' => 6, + 'luglio' => 7, + 'agosto' => 8, + 'settembre' => 9, + 'ottobre' => 10, + 'novembre' => 11, + 'dicembre' => 12, + // Spanish + 'enero' => 1, + 'febrero' => 2, + 'marzo' => 3, + 'abril' => 4, + 'mayo' => 5, + 'junio' => 6, + 'julio' => 7, + 'agosto' => 8, + 'septiembre' => 9, + 'setiembre' => 9, + 'octubre' => 10, + 'noviembre' => 11, + 'diciembre' => 12, + // Finnish + 'tammikuu' => 1, + 'helmikuu' => 2, + 'maaliskuu' => 3, + 'huhtikuu' => 4, + 'toukokuu' => 5, + 'kesäkuu' => 6, + 'heinäkuu' => 7, + 'elokuu' => 8, + 'suuskuu' => 9, + 'lokakuu' => 10, + 'marras' => 11, + 'joulukuu' => 12, + // Hungarian + 'január' => 1, + 'február' => 2, + 'március' => 3, + 'április' => 4, + 'május' => 5, + 'június' => 6, + 'július' => 7, + 'augusztus' => 8, + 'szeptember' => 9, + 'október' => 10, + 'november' => 11, + 'december' => 12, + // Greek + 'Ιαν' => 1, + 'Φεβ' => 2, + 'Μάώ' => 3, + 'Μαώ' => 3, + 'Απρ' => 4, + 'Μάι' => 5, + 'Μαϊ' => 5, + 'Μαι' => 5, + 'Ιούν' => 6, + 'Ιον' => 6, + 'Ιούλ' => 7, + 'Ιολ' => 7, + 'Αύγ' => 8, + 'Αυγ' => 8, + 'Σεπ' => 9, + 'Οκτ' => 10, + 'Νοέ' => 11, + 'Δεκ' => 12, + ); + + /** + * List of timezones, abbreviation => offset from UTC + * + * @access protected + * @var array + */ + var $timezone = array( + 'ACDT' => 37800, + 'ACIT' => 28800, + 'ACST' => 34200, + 'ACT' => -18000, + 'ACWDT' => 35100, + 'ACWST' => 31500, + 'AEDT' => 39600, + 'AEST' => 36000, + 'AFT' => 16200, + 'AKDT' => -28800, + 'AKST' => -32400, + 'AMDT' => 18000, + 'AMT' => -14400, + 'ANAST' => 46800, + 'ANAT' => 43200, + 'ART' => -10800, + 'AZOST' => -3600, + 'AZST' => 18000, + 'AZT' => 14400, + 'BIOT' => 21600, + 'BIT' => -43200, + 'BOT' => -14400, + 'BRST' => -7200, + 'BRT' => -10800, + 'BST' => 3600, + 'BTT' => 21600, + 'CAST' => 18000, + 'CAT' => 7200, + 'CCT' => 23400, + 'CDT' => -18000, + 'CEDT' => 7200, + 'CEST' => 7200, + 'CET' => 3600, + 'CGST' => -7200, + 'CGT' => -10800, + 'CHADT' => 49500, + 'CHAST' => 45900, + 'CIST' => -28800, + 'CKT' => -36000, + 'CLDT' => -10800, + 'CLST' => -14400, + 'COT' => -18000, + 'CST' => -21600, + 'CVT' => -3600, + 'CXT' => 25200, + 'DAVT' => 25200, + 'DTAT' => 36000, + 'EADT' => -18000, + 'EAST' => -21600, + 'EAT' => 10800, + 'ECT' => -18000, + 'EDT' => -14400, + 'EEST' => 10800, + 'EET' => 7200, + 'EGT' => -3600, + 'EKST' => 21600, + 'EST' => -18000, + 'FJT' => 43200, + 'FKDT' => -10800, + 'FKST' => -14400, + 'FNT' => -7200, + 'GALT' => -21600, + 'GEDT' => 14400, + 'GEST' => 10800, + 'GFT' => -10800, + 'GILT' => 43200, + 'GIT' => -32400, + 'GST' => 14400, + 'GST' => -7200, + 'GYT' => -14400, + 'HAA' => -10800, + 'HAC' => -18000, + 'HADT' => -32400, + 'HAE' => -14400, + 'HAP' => -25200, + 'HAR' => -21600, + 'HAST' => -36000, + 'HAT' => -9000, + 'HAY' => -28800, + 'HKST' => 28800, + 'HMT' => 18000, + 'HNA' => -14400, + 'HNC' => -21600, + 'HNE' => -18000, + 'HNP' => -28800, + 'HNR' => -25200, + 'HNT' => -12600, + 'HNY' => -32400, + 'IRDT' => 16200, + 'IRKST' => 32400, + 'IRKT' => 28800, + 'IRST' => 12600, + 'JFDT' => -10800, + 'JFST' => -14400, + 'JST' => 32400, + 'KGST' => 21600, + 'KGT' => 18000, + 'KOST' => 39600, + 'KOVST' => 28800, + 'KOVT' => 25200, + 'KRAST' => 28800, + 'KRAT' => 25200, + 'KST' => 32400, + 'LHDT' => 39600, + 'LHST' => 37800, + 'LINT' => 50400, + 'LKT' => 21600, + 'MAGST' => 43200, + 'MAGT' => 39600, + 'MAWT' => 21600, + 'MDT' => -21600, + 'MESZ' => 7200, + 'MEZ' => 3600, + 'MHT' => 43200, + 'MIT' => -34200, + 'MNST' => 32400, + 'MSDT' => 14400, + 'MSST' => 10800, + 'MST' => -25200, + 'MUT' => 14400, + 'MVT' => 18000, + 'MYT' => 28800, + 'NCT' => 39600, + 'NDT' => -9000, + 'NFT' => 41400, + 'NMIT' => 36000, + 'NOVST' => 25200, + 'NOVT' => 21600, + 'NPT' => 20700, + 'NRT' => 43200, + 'NST' => -12600, + 'NUT' => -39600, + 'NZDT' => 46800, + 'NZST' => 43200, + 'OMSST' => 25200, + 'OMST' => 21600, + 'PDT' => -25200, + 'PET' => -18000, + 'PETST' => 46800, + 'PETT' => 43200, + 'PGT' => 36000, + 'PHOT' => 46800, + 'PHT' => 28800, + 'PKT' => 18000, + 'PMDT' => -7200, + 'PMST' => -10800, + 'PONT' => 39600, + 'PST' => -28800, + 'PWT' => 32400, + 'PYST' => -10800, + 'PYT' => -14400, + 'RET' => 14400, + 'ROTT' => -10800, + 'SAMST' => 18000, + 'SAMT' => 14400, + 'SAST' => 7200, + 'SBT' => 39600, + 'SCDT' => 46800, + 'SCST' => 43200, + 'SCT' => 14400, + 'SEST' => 3600, + 'SGT' => 28800, + 'SIT' => 28800, + 'SRT' => -10800, + 'SST' => -39600, + 'SYST' => 10800, + 'SYT' => 7200, + 'TFT' => 18000, + 'THAT' => -36000, + 'TJT' => 18000, + 'TKT' => -36000, + 'TMT' => 18000, + 'TOT' => 46800, + 'TPT' => 32400, + 'TRUT' => 36000, + 'TVT' => 43200, + 'TWT' => 28800, + 'UYST' => -7200, + 'UYT' => -10800, + 'UZT' => 18000, + 'VET' => -14400, + 'VLAST' => 39600, + 'VLAT' => 36000, + 'VOST' => 21600, + 'VUT' => 39600, + 'WAST' => 7200, + 'WAT' => 3600, + 'WDT' => 32400, + 'WEST' => 3600, + 'WFT' => 43200, + 'WIB' => 25200, + 'WIT' => 32400, + 'WITA' => 28800, + 'WKST' => 18000, + 'WST' => 28800, + 'YAKST' => 36000, + 'YAKT' => 32400, + 'YAPT' => 36000, + 'YEKST' => 21600, + 'YEKT' => 18000, + ); + + /** + * Cached PCRE for SimplePie_Parse_Date::$day + * + * @access protected + * @var string + */ + var $day_pcre; + + /** + * Cached PCRE for SimplePie_Parse_Date::$month + * + * @access protected + * @var string + */ + var $month_pcre; + + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $built_in = array(); + + /** + * Array of user-added callback methods + * + * @access private + * @var array + */ + var $user = array(); + + /** + * Create new SimplePie_Parse_Date object, and set self::day_pcre, + * self::month_pcre, and self::built_in + * + * @access private + */ + public function __construct() + { + $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')'; + $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')'; + + static $cache; + if (!isset($cache[get_class($this)])) + { + $all_methods = get_class_methods($this); + + foreach ($all_methods as $method) + { + if (strtolower(substr($method, 0, 5)) === 'date_') + { + $cache[get_class($this)][] = $method; + } + } + } + + foreach ($cache[get_class($this)] as $method) + { + $this->built_in[] = $method; + } + } + + /** + * Get the object + * + * @access public + */ + public static function get() + { + static $object; + if (!$object) + { + $object = new SimplePie_Parse_Date; + } + return $object; + } + + /** + * Parse a date + * + * @final + * @access public + * @param string $date Date to parse + * @return int Timestamp corresponding to date string, or false on failure + */ + public function parse($date) + { + foreach ($this->user as $method) + { + if (($returned = call_user_func($method, $date)) !== false) + { + return $returned; + } + } + + foreach ($this->built_in as $method) + { + if (($returned = call_user_func(array($this, $method), $date)) !== false) + { + return $returned; + } + } + + return false; + } + + /** + * Add a callback method to parse a date + * + * @final + * @access public + * @param callback $callback + */ + public function add_callback($callback) + { + if (is_callable($callback)) + { + $this->user[] = $callback; + } + else + { + trigger_error('User-supplied function must be a valid callback', E_USER_WARNING); + } + } + + /** + * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as + * well as allowing any of upper or lower case "T", horizontal tabs, or + * spaces to be used as the time separator (including more than one)) + * + * @access protected + * @return int Timestamp + */ + public function date_w3cdtf($date) + { + static $pcre; + if (!$pcre) + { + $year = '([0-9]{4})'; + $month = $day = $hour = $minute = $second = '([0-9]{2})'; + $decimal = '([0-9]*)'; + $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))'; + $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Year + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Decimal fraction of a second + 8: Zulu + 9: Timezone ± + 10: Timezone hours + 11: Timezone minutes + */ + + // Fill in empty matches + for ($i = count($match); $i <= 3; $i++) + { + $match[$i] = '1'; + } + + for ($i = count($match); $i <= 7; $i++) + { + $match[$i] = '0'; + } + + // Numeric timezone + if (isset($match[9]) && $match[9] !== '') + { + $timezone = $match[10] * 3600; + $timezone += $match[11] * 60; + if ($match[9] === '-') + { + $timezone = 0 - $timezone; + } + } + else + { + $timezone = 0; + } + + // Convert the number of seconds to an integer, taking decimals into account + $second = round((int)$match[6] + (int)$match[7] / pow(10, strlen($match[7]))); + + return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone; + } + + return false; + } + + /** + * Remove RFC822 comments + * + * @access protected + * @param string $data Data to strip comments from + * @return string Comment stripped string + */ + public function remove_rfc2822_comments($string) + { + $string = (string) $string; + $position = 0; + $length = strlen($string); + $depth = 0; + + $output = ''; + + while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) + { + $output .= substr($string, $position, $pos - $position); + $position = $pos + 1; + if ($pos === 0 || $string[$pos - 1] !== '\\') + { + $depth++; + while ($depth && $position < $length) + { + $position += strcspn($string, '()', $position); + if ($string[$position - 1] === '\\') + { + $position++; + continue; + } + elseif (isset($string[$position])) + { + switch ($string[$position]) + { + case '(': + $depth++; + break; + + case ')': + $depth--; + break; + } + $position++; + } + else + { + break; + } + } + } + else + { + $output .= '('; + } + } + $output .= substr($string, $position); + + return $output; + } + + /** + * Parse RFC2822's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc2822($date) + { + static $pcre; + if (!$pcre) + { + $wsp = '[\x09\x20]'; + $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)'; + $optional_fws = $fws . '?'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $minute = $second = '([0-9]{2})'; + $year = '([0-9]{2,4})'; + $num_zone = '([+\-])([0-9]{2})([0-9]{2})'; + $character_zone = '([A-Z]{1,5})'; + $zone = '(?:' . $num_zone . '|' . $character_zone . ')'; + $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'; + } + if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone ± + 9: Timezone hours + 10: Timezone minutes + 11: Alphabetic timezone + */ + + // Find the month number + $month = $this->month[strtolower($match[3])]; + + // Numeric timezone + if ($match[8] !== '') + { + $timezone = $match[9] * 3600; + $timezone += $match[10] * 60; + if ($match[8] === '-') + { + $timezone = 0 - $timezone; + } + } + // Character timezone + elseif (isset($this->timezone[strtoupper($match[11])])) + { + $timezone = $this->timezone[strtoupper($match[11])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } + + // Deal with 2/3 digit years + if ($match[4] < 50) + { + $match[4] += 2000; + } + elseif ($match[4] < 1000) + { + $match[4] += 1900; + } + + // Second is optional, if it is empty set it to zero + if ($match[7] !== '') + { + $second = $match[7]; + } + else + { + $second = 0; + } + + return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone; + } + + return false; + } + + /** + * Parse RFC850's date format + * + * @access protected + * @return int Timestamp + */ + public function date_rfc850($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $day_name = $this->day_pcre; + $month = $this->month_pcre; + $day = '([0-9]{1,2})'; + $year = $hour = $minute = $second = '([0-9]{2})'; + $zone = '([A-Z]{1,5})'; + $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Day + 3: Month + 4: Year + 5: Hour + 6: Minute + 7: Second + 8: Timezone + */ + + // Month + $month = $this->month[strtolower($match[3])]; + + // Character timezone + if (isset($this->timezone[strtoupper($match[8])])) + { + $timezone = $this->timezone[strtoupper($match[8])]; + } + // Assume everything else to be -0000 + else + { + $timezone = 0; + } + + // Deal with 2 digit year + if ($match[4] < 50) + { + $match[4] += 2000; + } + else + { + $match[4] += 1900; + } + + return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone; + } + + return false; + } + + /** + * Parse C99's asctime()'s date format + * + * @access protected + * @return int Timestamp + */ + public function date_asctime($date) + { + static $pcre; + if (!$pcre) + { + $space = '[\x09\x20]+'; + $wday_name = $this->day_pcre; + $mon_name = $this->month_pcre; + $day = '([0-9]{1,2})'; + $hour = $sec = $min = '([0-9]{2})'; + $year = '([0-9]{4})'; + $terminator = '\x0A?\x00?'; + $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i'; + } + if (preg_match($pcre, $date, $match)) + { + /* + Capturing subpatterns: + 1: Day name + 2: Month + 3: Day + 4: Hour + 5: Minute + 6: Second + 7: Year + */ + + $month = $this->month[strtolower($match[2])]; + return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]); + } + + return false; + } + + /** + * Parse dates using strtotime() + * + * @access protected + * @return int Timestamp + */ + public function date_strtotime($date) + { + $strtotime = strtotime($date); + if ($strtotime === -1 || $strtotime === false) + { + return false; + } + + return $strtotime; + } +} -- cgit v1.2.1