diff --git a/library/Icinga/Repository/Repository.php b/library/Icinga/Repository/Repository.php index 83a073418..bda93aa2a 100644 --- a/library/Icinga/Repository/Repository.php +++ b/library/Icinga/Repository/Repository.php @@ -11,7 +11,9 @@ use Icinga\Data\Selectable; use Icinga\Exception\ProgrammingError; use Icinga\Exception\QueryException; use Icinga\Exception\StatementException; +use Icinga\Util\ASN1; use Icinga\Util\StringHelper; +use InvalidArgumentException; /** * Abstract base class for concrete repository implementations @@ -211,36 +213,6 @@ abstract class Repository implements Selectable */ protected $columnAliasMap; - /** - * "3.3.13. Generalized Time" syntax as specified by IETF RFC 4517 - * - * @var string - * - * @see https://tools.ietf.org/html/rfc4517#section-3.3.13 - */ - protected $generalizedTimePattern = << - [0-9]{4} # century year - (?:0[1-9]|1[0-2]) # month - (?:0[1-9]|[12][0-9]|3[0-1]) # day - (?:[01][0-9]|2[0-3]) # hour - ) - (?: - (?P[0-5][0-9]) # minute - (?P[0-5][0-9]|60)? # second or leap-second - )? - (?:[.,](?P[0-9]+))? # fraction - (?P # g-time-zone - Z - | - [-+] - (?:[01][0-9]|2[0-3]) # hour - (?:[0-5][0-9])? # minute - ) -\z/x -EOD; - /** * Create a new repository object * @@ -968,57 +940,11 @@ EOD; return $value; } - $matches = array(); - - if (preg_match($this->generalizedTimePattern, $value, $matches)) { - $dateTimeRaw = $matches['YmdH']; - $dateTimeFormat = 'YmdH'; - - if ($matches['i'] !== '') { - $dateTimeRaw .= $matches['i']; - $dateTimeFormat .= 'i'; - - if ($matches['s'] !== '') { - $dateTimeRaw .= $matches['s']; - $dateTimeFormat .= 's'; - $fractionOfSeconds = 1; - } else { - $fractionOfSeconds = 60; - } - } else { - $fractionOfSeconds = 3600; - } - - $dateTimeFormat .= 'O'; - - if ($matches['tz'] === 'Z') { - $dateTimeRaw .= '+0000'; - } else { - $dateTimeRaw .= $matches['tz']; - - if (strlen($matches['tz']) === 3) { - $dateTimeRaw .= '00'; - } - } - - $dateTime = DateTime::createFromFormat($dateTimeFormat, $dateTimeRaw); - - if ($dateTime !== false) { - $timestamp = $dateTime->getTimeStamp(); - - if (isset($matches['frac'])) { - $timestamp += (int) round((float) ('0.' . $matches['frac']) * $fractionOfSeconds); - } - - return $timestamp; - } + try { + return ASN1::parseGeneralizedTime($value)->getTimeStamp(); + } catch (InvalidArgumentException $e) { + Logger::debug(sprintf('Repository "%s": %s', $this->getName(), $e->getMessage())); } - - Logger::debug(sprintf( - 'Failed to parse "%s" based on the ASN.1 standard (GeneralizedTime) in repository "%s".', - $value, - $this->getName() - )); } /** diff --git a/library/Icinga/Util/ASN1.php b/library/Icinga/Util/ASN1.php new file mode 100644 index 000000000..9e00258de --- /dev/null +++ b/library/Icinga/Util/ASN1.php @@ -0,0 +1,102 @@ + + [0-9]{4} # century year + (?:0[1-9]|1[0-2]) # month + (?:0[1-9]|[12][0-9]|3[0-1]) # day + (?:[01][0-9]|2[0-3]) # hour + ) + (?: + (?P[0-5][0-9]) # minute + (?P[0-5][0-9]|60)? # second or leap-second + )? + (?:[.,](?P[0-9]+))? # fraction + (?P # g-time-zone + Z + | + [-+] + (?:[01][0-9]|2[0-3]) # hour + (?:[0-5][0-9])? # minute + ) +\z/x +EOD; + + $matches = array(); + + if (preg_match($generalizedTimePattern, $value, $matches)) { + $dateTimeRaw = $matches['YmdH']; + $dateTimeFormat = 'YmdH'; + + if ($matches['i'] !== '') { + $dateTimeRaw .= $matches['i']; + $dateTimeFormat .= 'i'; + + if ($matches['s'] !== '') { + $dateTimeRaw .= $matches['s']; + $dateTimeFormat .= 's'; + $fractionOfSeconds = 1; + } else { + $fractionOfSeconds = 60; + } + } else { + $fractionOfSeconds = 3600; + } + + $dateTimeFormat .= 'O'; + + if ($matches['tz'] === 'Z') { + $dateTimeRaw .= '+0000'; + } else { + $dateTimeRaw .= $matches['tz']; + + if (strlen($matches['tz']) === 3) { + $dateTimeRaw .= '00'; + } + } + + $dateTime = DateTime::createFromFormat($dateTimeFormat, $dateTimeRaw); + + if ($dateTime !== false) { + if (isset($matches['frac'])) { + $dateTime->add(new DateInterval( + 'PT' . round((float) ('0.' . $matches['frac']) * $fractionOfSeconds) . 'S' + )); + } + + return $dateTime; + } + } + + throw new InvalidArgumentException(sprintf( + 'Failed to parse %s based on the ASN.1 standard (GeneralizedTime)', + var_export($value, true) + )); + } +}