# HG changeset patch # User František Kučera # Date 1624913284 -7200 # Node ID 7050364456720d755934cfadb2ba5cfabf60cd25 # Parent fac034e3e867609c1a03aa4bc89d283939cb3399 partial UTCTime support diff -r fac034e3e867 -r 705036445672 src/lib/ASN1ContentHandler.h --- a/src/lib/ASN1ContentHandler.h Sun Jun 27 19:22:23 2021 +0200 +++ b/src/lib/ASN1ContentHandler.h Mon Jun 28 22:48:04 2021 +0200 @@ -52,6 +52,17 @@ BMPString, }; + enum class DateTimeType : uint64_t { + UTCTime, + GeneralizedTime, + Time, + Date, + TimeOfDay, + DateTime, + Duration, + // TODO: review date/time types + }; + class Integer { private: // TODO: use std::string (of octets, not ASCII) instead of std::vector? @@ -167,9 +178,52 @@ }; + class DateTime { + public: + + enum class Precision { + Year, + Month, + Day, + Hour, + Minute, + Second, + Milisecond, + Nanosecond + }; + + // TODO: timezone (in minutes or 1/4 hours) + + Precision precision = Precision::Second; + int32_t year = 1970; + int8_t month = 1; + int8_t day = 1; + int8_t hour = 0; + int8_t minute = 0; + int8_t second = 0; + // TODO: ms/ns + + virtual ~DateTime() { + } + + const std::string toString() const { + std::stringstream result; + result << std::setfill('0'); + result << std::setw(4) << (int) year; + result << "-" << std::setw(2) << (int) month; + result << "-" << std::setw(2) << (int) day; + result << "T" << std::setw(2) << (int) hour; + result << ":" << std::setw(2) << (int) minute; + result << ":" << std::setw(2) << (int) second; + result << "+00:00"; // TODO: timezone + return result.str(); + } + }; + virtual ~ASN1ContentHandler() = default; // TODO: more metadata, support OID decoding and ASN.1 modules (schema), probably through a plug-in + // TODO: support also extension extractor plug-ins? (could decode some opaque structures like octet strings and replace them with nested elements) e.g. subjectAltName in https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 virtual void writeStreamStart() = 0; virtual void writeStreamEnd() = 0; @@ -181,18 +235,12 @@ virtual void writeInteger(Integer value) = 0; virtual void writeString(StringType type, std::string value) = 0; virtual void writeOID(ObjectIdentifier value) = 0; + virtual void writeDateTime(DateTimeType type, DateTime value) = 0; // Object descriptor // virtual void writeReal(float value) = 0; // Enumerated // Embedded PVD // Relative OID - // TIME - // UTC time - // Generalized time - // Date - // Time of day - // Date-time - // Duration // OID-IRI // Relative OID-IRI @@ -245,6 +293,9 @@ handler->writeOID(value); } + void writeDateTime(DateTimeType type, DateTime value) override { + handler->writeDateTime(type, value); + } #undef handler diff -r fac034e3e867 -r 705036445672 src/lib/BasicASN1Reader.h --- a/src/lib/BasicASN1Reader.h Sun Jun 27 19:22:23 2021 +0200 +++ b/src/lib/BasicASN1Reader.h Mon Jun 28 22:48:04 2021 +0200 @@ -20,6 +20,7 @@ #include #include #include +#include #include "ASN1Reader.h" @@ -174,6 +175,36 @@ s.resize(typeHeader.length); read((uint8_t*) s.data(), typeHeader.length); handlers.writeString(ASN1ContentHandler::StringType::PrintableString, s); + } else if (typeHeader.tag == 0x17 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { + // TODO: check available bytes before allocating buffer + std::string s; + s.resize(typeHeader.length); + read((uint8_t*) s.data(), typeHeader.length); + + ASN1ContentHandler::DateTime dateTime; + + std::smatch match; + if (std::regex_match(s, match, std::regex("([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})Z"))) { + int i = 1; + uint32_t year = std::stoi(match[i++]); + dateTime.year = year < 50 ? 2000 + year : 1900 + year; + dateTime.month = std::stoi(match[i++]); + dateTime.day = std::stoi(match[i++]); + dateTime.hour = std::stoi(match[i++]); + dateTime.minute = std::stoi(match[i++]); + dateTime.precision = ASN1ContentHandler::DateTime::Precision::Second; + handlers.writeDateTime(ASN1ContentHandler::DateTimeType::UTCTime, dateTime); + } else { + // FIXME: decode more UTCTime formats: + // YYMMDDhhmmZ + // YYMMDDhhmm+hh'mm' + // YYMMDDhhmm-hh'mm' + // YYMMDDhhmmssZ + // YYMMDDhhmmss+hh'mm' + // YYMMDDhhmmss-hh'mm' + handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "FIXME: UTCTime format not yet supported: " + s); + } + } else { // TODO: do not skip, parse std::vector temp(typeHeader.length, 0); diff -r fac034e3e867 -r 705036445672 src/lib/GenericASN1ContentHandler.h --- a/src/lib/GenericASN1ContentHandler.h Sun Jun 27 19:22:23 2021 +0200 +++ b/src/lib/GenericASN1ContentHandler.h Mon Jun 28 22:48:04 2021 +0200 @@ -89,6 +89,11 @@ handlers.writeEndElement(); } + void writeDateTime(DateTimeType type, DateTime value) override { + handlers.writeStartElement("date-time"); + handlers.writeCharacters(value.toString()); + handlers.writeEndElement(); + } };