| * | Author: Aleksander Machniak | * +-----------------------------------------------------------------------+ */ namespace AcyMailing\Libraries\Imap2\Roundcube; use DateTimeZone; /** * Utility class providing common functions * * @package Framework * @subpackage Utils */ class Utils { /** * Explode quoted string * * @param string $delimiter Delimiter expression string for preg_match() * @param string $string Input string * * @return array String items */ public static function explode_quoted_string($delimiter, $string) { $result = []; $strlen = strlen($string); for ($q = $p = $i = 0 ; $i < $strlen ; $i++) { if ($string[$i] == "\"" && $string[$i - 1] != "\\") { $q = $q ? false : true; } elseif (!$q && preg_match("/$delimiter/", $string[$i])) { $result[] = substr($string, $p, $i - $p); $p = $i + 1; } } $result[] = (string)substr($string, $p); return $result; } /** * Improved equivalent to strtotime() * * @param string $date Date string * @param DateTimeZone $timezone Timezone to use for DateTime object * * @return int Unix timestamp */ public static function strtotime($date, $timezone = null) { $date = self::clean_datestr($date); $tzname = $timezone ? ' '.$timezone->getName() : ''; // unix timestamp if (is_numeric($date)) { return (int)$date; } // It can be very slow when provided string is not a date and very long if (strlen($date) > 128) { $date = substr($date, 0, 128); } // if date parsing fails, we have a date in non-rfc format. // remove token from the end and try again while (($ts = @strtotime($date.$tzname)) === false || $ts < 0) { if (($pos = strrpos($date, ' ')) === false) { break; } $date = rtrim(substr($date, 0, $pos)); } return (int)$ts; } /** * Clean up date string for strtotime() input * * @param string $date Date string * * @return string Date string */ public static function clean_datestr($date) { $date = trim($date); // check for MS Outlook vCard date format YYYYMMDD if (preg_match('/^([12][90]\d\d)([01]\d)([0123]\d)$/', $date, $m)) { return sprintf('%04d-%02d-%02d 00:00:00', intval($m[1]), intval($m[2]), intval($m[3])); } // Clean malformed data $date = preg_replace( [ '/\(.*\)/', // remove RFC comments '/GMT\s*([+-][0-9]+)/', // support non-standard "GMTXXXX" literal '/[^a-z0-9\x20\x09:\/\.+-]/i', // remove any invalid characters '/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i', // remove weekday names ], [ '', '\\1', '', '', ], $date ); $date = trim($date); // try to fix dd/mm vs. mm/dd discrepancy, we can't do more here if (preg_match('/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})(\s.*)?$/', $date, $m)) { $mdy = $m[2] > 12 && $m[1] <= 12; $day = $mdy ? $m[2] : $m[1]; $month = $mdy ? $m[1] : $m[2]; $date = sprintf('%04d-%02d-%02d%s', $m[3], $month, $day, $m[4] ? : ' 00:00:00'); } // I've found that YYYY.MM.DD is recognized wrong, so here's a fix elseif (preg_match('/^(\d{4})\.(\d{1,2})\.(\d{1,2})(\s.*)?$/', $date, $m)) { $date = sprintf('%04d-%02d-%02d%s', $m[1], $m[2], $m[3], $m[4] ? : ' 00:00:00'); } return $date; } }