# HG changeset patch # User František Kučera # Date 1624814543 -7200 # Node ID fac034e3e867609c1a03aa4bc89d283939cb3399 # Parent b7431bc6069b5cc2c9c6ddd8cc19c3888062ad8c support object identifiers (OID) diff -r b7431bc6069b -r fac034e3e867 src/lib/ASN1ContentHandler.h --- a/src/lib/ASN1ContentHandler.h Sun Jun 27 18:04:34 2021 +0200 +++ b/src/lib/ASN1ContentHandler.h Sun Jun 27 19:22:23 2021 +0200 @@ -112,8 +112,63 @@ }; + class ObjectIdentifier { + private: + // TODO: use std::string (of octets, not ASCII) instead of std::vector? + // TODO: use this class across Relational pipes as one of basic types? + std::vector data; + + public: + + /** + * @param data integer octets as in BER encoding + */ + ObjectIdentifier(std::vector data) : data(data) { + // TODO: cache size and element values? + } + + virtual ~ObjectIdentifier() { + } + + /** + * @return number of elements, not octets + */ + size_t size() const { + return 0; // FIXME: correct OID size + } + + /** + * @param index 0 = root element + * @return value of the element at given position + */ + const uint8_t& operator[](std::size_t index) const { + return data[index]; // FIXME: correct OID value + } + + const std::string toString() const { + if (data.size() == 0) return ""; + + std::stringstream result; + + result << (data[0] / 40) << "." << (data[0] % 40); // first two elements are encoded in the first octet + + for (size_t i = 1, limit = data.size(), octet = 0, element = 0; i < limit; i++) { + octet = data[i]; + element = element << 7 | (octet & 0xFF >> 1); + // TODO: throw exception if the element value overflows? (should not happen) or format even longer values + if ((octet & 1 << 7) == 0) { + result << "." << element; + element = 0; + } + } + + return result.str(); + } + + }; + virtual ~ASN1ContentHandler() = default; - + // TODO: more metadata, support OID decoding and ASN.1 modules (schema), probably through a plug-in virtual void writeStreamStart() = 0; @@ -125,7 +180,7 @@ virtual void writeNull() = 0; virtual void writeInteger(Integer value) = 0; virtual void writeString(StringType type, std::string value) = 0; - // virtual void writeOID(std::string value) = 0; + virtual void writeOID(ObjectIdentifier value) = 0; // Object descriptor // virtual void writeReal(float value) = 0; // Enumerated @@ -186,6 +241,11 @@ handler->writeString(type, value); } + void writeOID(ObjectIdentifier value) override { + handler->writeOID(value); + } + + #undef handler }; diff -r b7431bc6069b -r fac034e3e867 src/lib/BasicASN1Reader.h --- a/src/lib/BasicASN1Reader.h Sun Jun 27 18:04:34 2021 +0200 +++ b/src/lib/BasicASN1Reader.h Sun Jun 27 19:22:23 2021 +0200 @@ -157,6 +157,10 @@ std::vector value(typeHeader.length, 0x00); read(value.data(), typeHeader.length); handlers.writeInteger(ASN1ContentHandler::Integer(value)); + } else if (typeHeader.tag == 6 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { + std::vector value(typeHeader.length, 0x00); + read(value.data(), typeHeader.length); + handlers.writeOID({value}); } else if (typeHeader.tag == 12 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { // TODO: check available bytes before allocating buffer std::string s; diff -r b7431bc6069b -r fac034e3e867 src/lib/GenericASN1ContentHandler.h --- a/src/lib/GenericASN1ContentHandler.h Sun Jun 27 18:04:34 2021 +0200 +++ b/src/lib/GenericASN1ContentHandler.h Sun Jun 27 19:22:23 2021 +0200 @@ -83,6 +83,13 @@ handlers.writeEndElement(); } + void writeOID(ObjectIdentifier value) override { + handlers.writeStartElement("oid"); + handlers.writeCharacters(value.toString()); + handlers.writeEndElement(); + } + + }; }