src/lib/BasicASN1Reader.h
author František Kučera <franta-hg@frantovo.cz>
Sat, 17 Jul 2021 20:38:03 +0200
branchv_0
changeset 34 c15dc8762bdb
parent 33 13aa7280ac7b
child 35 bf2c546f49d1
permissions -rw-r--r--
format unknown values as HEX and ASCII when possible
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2021 František Kučera (Frantovo.cz, GlobalCode.info)
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
#pragma once
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
#include <memory>
4
7230e1ea0b07 proxy handlers forwarding events to all subordinate handlers
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    20
#include <vector>
12
243ef6c91dbb BasicASN1Reader: parse type and length as array
František Kučera <franta-hg@frantovo.cz>
parents: 11
diff changeset
    21
#include <array>
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    22
#include <sstream>
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
    23
#include <regex>
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include "ASN1Reader.h"
33
13aa7280ac7b parse encapsulated structures (octet string or bit string containing valid ASN.1): add ValidatingASN1ContentHandler → avoid at least some false positives
František Kučera <franta-hg@frantovo.cz>
parents: 32
diff changeset
    26
#include "ValidatingASN1ContentHandler.h"
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
namespace relpipe {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
namespace in {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
namespace asn1 {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
namespace lib {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
/**
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
 * Reads ASN.1 data encoded as BER (DER, CER).
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
 */
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
class BasicASN1Reader : public ASN1Reader {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
private:
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    39
	bool started = false;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    40
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    41
	class BasicHeader : public ASN1ContentHandler::Header {
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    42
	public:
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    43
		bool definiteLength;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    44
		size_t length;
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
	};
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    47
	class LevelMetadata {
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    48
	public:
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    49
		bool definiteLength;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    50
		size_t length;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    51
		size_t start;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    52
	};
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    53
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    54
	std::vector<LevelMetadata> level;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    55
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    56
	void checkRemainingItems() {
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    57
		if (level.size()) {
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    58
			LevelMetadata& l = level.back();
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    59
			if (l.definiteLength && l.length == getBytesRead() - l.start) {
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    60
				level.pop_back();
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
    61
				handlers->writeCollectionEnd();
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    62
				checkRemainingItems(); // multiple collections may end at the same point
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    63
			}
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    64
		}
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    65
	}
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    66
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    67
	BasicHeader readHeader() {
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    68
		using TagClass = ASN1ContentHandler::TagClass;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    69
		using PC = ASN1ContentHandler::PC;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    70
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    71
		BasicHeader h;
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    72
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    73
		memset(&h, 0, sizeof (h)); // TODO: remove, not needed
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    74
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    75
		uint8_t tagByte;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    76
		read(&tagByte, 1);
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    77
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    78
		h.tagClass = (TagClass) (tagByte >> 6);
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    79
		h.pc = (PC) ((tagByte >> 5) & 1);
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    80
		h.tag = tagByte & (0xFF >> 3);
19
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    81
		if (h.tag == 31) { // all five tag bits are set → tag number (greater than 30) is encoded in following octets
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    82
			h.tag = 0;
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    83
			uint8_t moreTag = 0;
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    84
			do {
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    85
				read(&moreTag, 1);
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    86
				h.tag = h.tag << 7 | (moreTag & (0xFF >> 1));
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    87
			} while (moreTag & (1 << 7));
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    88
		}
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    89
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    90
		uint8_t lengthByte;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    91
		read(&lengthByte, 1);
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    92
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    93
		if (lengthByte >> 7 == 0) {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    94
			// definite short
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    95
			h.definiteLength = true;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    96
			h.length = lengthByte;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    97
		} else if (lengthByte == 0b10000000) {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
    98
			// indefinite
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
    99
			h.definiteLength = false;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   100
			h.length = 0;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   101
		} else if (lengthByte == 0xFF) {
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   102
			throw relpipe::writer::RelpipeWriterException(L"ASN.1 lengthByte == 0xFF (reserved value)"); // TODO: better exception
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   103
		} else {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   104
			// definite long
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   105
			h.definiteLength = true;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   106
			h.length = 0;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   107
			std::vector<uint8_t> lengthBytes(lengthByte & 0b01111111, 0);
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   108
			read(lengthBytes.data(), lengthBytes.size());
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   109
			for (uint8_t l : lengthBytes) h.length = (h.length << 8) + l;
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   110
		}
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   111
13
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   112
		return h;
d5e2cb9e31f1 switch TransactionalBuffer from char to uint8_t + partial parser of tags and lengths
František Kučera <franta-hg@frantovo.cz>
parents: 12
diff changeset
   113
	}
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   114
11
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   115
	void readNext() {
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   116
		using TagClass = ASN1ContentHandler::TagClass;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   117
		using PC = ASN1ContentHandler::PC;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   118
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   119
		checkRemainingItems();
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   120
		BasicHeader typeHeader = readHeader();
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   121
		// commit(); // TODO: commit here and recover later instead of rollback?
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   122
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   123
		if (!started) {
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   124
			handlers->writeStreamStart();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   125
			started = true;
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   126
		}
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   127
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   128
		// TODO: check tagClass and pc
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   129
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   130
		// TODO: constants, more types
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   131
		if (typeHeader.tag == UniversalType::EndOfContent && typeHeader.tagClass == TagClass::Universal && typeHeader.pc == PC::Primitive) {
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   132
			handlers->writeCollectionEnd();
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   133
		} else if (typeHeader.tag == UniversalType::Sequence) {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   134
			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   135
			handlers->writeCollectionStart(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   136
		} else if (typeHeader.tag == UniversalType::Set) {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   137
			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   138
			handlers->writeCollectionStart(typeHeader);
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   139
		} else if (typeHeader.pc == PC::Constructed) {
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   140
			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   141
			handlers->writeCollectionStart(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   142
		} else if (typeHeader.tag == UniversalType::Null && typeHeader.length == 0) {
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   143
			handlers->writeNull(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   144
		} else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) {
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   145
			bool value;
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   146
			read((uint8_t*) & value, 1);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   147
			handlers->writeBoolean(typeHeader, value);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   148
		} else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
17
f5281ab3e68f some support for Integers
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   149
			// TODO: check available bytes before allocating buffer
f5281ab3e68f some support for Integers
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   150
			std::vector<uint8_t> value(typeHeader.length, 0x00);
f5281ab3e68f some support for Integers
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   151
			read(value.data(), typeHeader.length);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   152
			handlers->writeInteger(typeHeader, ASN1ContentHandler::Integer(value));
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   153
		} else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
20
fac034e3e867 support object identifiers (OID)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   154
			std::vector<uint8_t> value(typeHeader.length, 0x00);
fac034e3e867 support object identifiers (OID)
František Kučera <franta-hg@frantovo.cz>
parents: 19
diff changeset
   155
			read(value.data(), typeHeader.length);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   156
			handlers->writeOID(typeHeader,{value});
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   157
		} else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
17
f5281ab3e68f some support for Integers
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   158
			// TODO: check available bytes before allocating buffer
16
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   159
			std::string s;
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   160
			s.resize(typeHeader.length);
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   161
			read((uint8_t*) s.data(), typeHeader.length);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   162
			handlers->writeTextString(typeHeader, s);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   163
		} else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
16
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   164
			// TODO: check encoding
17
f5281ab3e68f some support for Integers
František Kučera <franta-hg@frantovo.cz>
parents: 16
diff changeset
   165
			// TODO: check available bytes before allocating buffer
16
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   166
			std::string s;
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   167
			s.resize(typeHeader.length);
bb457bb5b515 some support for UTF8String and PrintableString
František Kučera <franta-hg@frantovo.cz>
parents: 15
diff changeset
   168
			read((uint8_t*) s.data(), typeHeader.length);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   169
			handlers->writeTextString(typeHeader, s);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   170
		} else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   171
			// TODO: check available bytes before allocating buffer
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   172
			std::string s;
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   173
			s.resize(typeHeader.length);
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   174
			read((uint8_t*) s.data(), typeHeader.length);
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   175
			if (processEncapsulatedContent(typeHeader, s) == false) handlers->writeOctetString(typeHeader, s);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   176
		} else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   177
			// TODO: check available bytes before allocating buffer
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   178
			std::string s;
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   179
			s.resize(typeHeader.length);
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   180
			read((uint8_t*) s.data(), typeHeader.length);
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   181
			if (processEncapsulatedContent(typeHeader, s) == false) {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   182
				std::vector<bool> bits;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   183
				// TODO: throw exception on wrong padding or insufficient length?
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   184
				if (s.size() > 1) {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   185
					uint8_t padding = s[0];
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   186
					for (uint8_t j = padding; j < 8; j++) bits.push_back(s.back() & 1 << j);
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   187
					for (size_t i = s.size() - 2; i > 0; i--) for (uint8_t j = 0; j < 8; j++) bits.push_back(s[i] & 1 << j);
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   188
				}
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   189
				handlers->writeBitString(typeHeader, bits);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   190
			}
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   191
		} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   192
			// TODO: check available bytes before allocating buffer
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   193
			// TODO: check encoding
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   194
			std::string s;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   195
			s.resize(typeHeader.length);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   196
			read((uint8_t*) s.data(), typeHeader.length);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   197
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   198
			ASN1ContentHandler::DateTime dateTime;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   199
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   200
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   201
			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|([+-][0-9]{2})([0-9]{2}))"))) {
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   202
				int i = 1;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   203
				uint32_t year = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   204
				dateTime.year = year < 50 ? 2000 + year : 1900 + year;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   205
				dateTime.month = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   206
				dateTime.day = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   207
				dateTime.hour = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   208
				dateTime.minute = std::stoi(match[i++]);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   209
				dateTime.precision = match[i].length() ? ASN1ContentHandler::DateTime::Precision::Second : ASN1ContentHandler::DateTime::Precision::Minute;
28
fade2f562970 UTCTime: fix short variant
František Kučera <franta-hg@frantovo.cz>
parents: 27
diff changeset
   210
				dateTime.second = match[i].length() ? std::stoi(match[i]) : 0;
fade2f562970 UTCTime: fix short variant
František Kučera <franta-hg@frantovo.cz>
parents: 27
diff changeset
   211
				i++;
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   212
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   213
					dateTime.timezoneHour = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   214
					dateTime.timezoneMinute = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   215
				}
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   216
				handlers->writeDateTime(typeHeader, dateTime);
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   217
			} else {
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   218
				throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   219
			}
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   220
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   221
		} else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   222
			// TODO: check available bytes before allocating buffer
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   223
			std::string s;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   224
			s.resize(typeHeader.length);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   225
			read((uint8_t*) s.data(), typeHeader.length);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   226
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   227
			ASN1ContentHandler::DateTime dateTime;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   228
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   229
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   230
			if (std::regex_match(s, match, std::regex("([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\\.([0-9]{1,3}))?(Z|([+-][0-9]{2})([0-9]{2}))"))) {
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   231
				// TODO: support also fractions of minutes and hours in GeneralizedTime
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   232
				int i = 1;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   233
				dateTime.year = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   234
				dateTime.month = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   235
				dateTime.day = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   236
				dateTime.hour = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   237
				dateTime.minute = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   238
				dateTime.second = match[i].length() ? std::stoi(match[i++]) : 0;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   239
				dateTime.precision = match[i++].length() ? ASN1ContentHandler::DateTime::Precision::Nanosecond : ASN1ContentHandler::DateTime::Precision::Second;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   240
				if (match[i].length() == 1) dateTime.nanosecond = std::stoi(match[i++]) * 100 * 1000000;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   241
				else if (match[i].length() == 2) dateTime.nanosecond = std::stoi(match[i++]) * 10 * 1000000;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   242
				else if (match[i].length() == 3) dateTime.nanosecond = std::stoi(match[i++]) * 1000000;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   243
				else i++;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   244
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   245
					dateTime.timezoneHour = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   246
					dateTime.timezoneMinute = std::stoi(match[i++]);
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   247
				}
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   248
				handlers->writeDateTime(typeHeader, dateTime);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   249
			} else {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   250
				throw std::invalid_argument("Unsupported GeneralizedTime format: " + s); // TODO: better exception
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   251
			}
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   252
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   253
		} else {
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   254
			// TODO: do not skip, parse
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   255
			// TODO: check available bytes before allocating buffer
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   256
			std::vector<uint8_t> temp(typeHeader.length, 0);
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   257
			read(temp.data(), typeHeader.length);
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   258
			// TODO: recover transaction?
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   259
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   260
			std::stringstream description;
34
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   261
			description << "UNKNOWN:"
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   262
					<< " tag = " << typeHeader.tag
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   263
					<< " tagClass = " << (int) typeHeader.tagClass
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   264
					<< " pc = " << (int) typeHeader.pc
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   265
					<< " length = " << typeHeader.length
34
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   266
					<< " definite = " << (typeHeader.definiteLength ? "true" : "false")
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   267
					<< " hex = ";
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   268
			description << std::hex << std::setfill('0');
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   269
			for (uint8_t b : temp) description << std::setw(2) << (int) b;
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   270
			description << " ascii = ";
c15dc8762bdb format unknown values as HEX and ASCII when possible
František Kučera <franta-hg@frantovo.cz>
parents: 33
diff changeset
   271
			for (uint8_t b : temp) description << (b >= 32 && b < 127 ? (char) b : '.');
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   272
			// TODO: special event for unparsed? (instead of a text string)
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   273
			handlers->writeTextString(typeHeader, description.str());
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   274
		}
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   275
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   276
		commit();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   277
	}
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   278
30
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   279
	bool hasAvailableForReading() {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   280
		// TODO: API in AbstractParser for checking available bytes?
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   281
		uint8_t tmp;
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   282
		try {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   283
			peek(&tmp, 1);
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   284
			return true;
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   285
		} catch (...) {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   286
			return false;
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   287
		}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   288
	}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   289
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   290
	bool isValidBER(const std::string& input) {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   291
		BasicASN1Reader encapsulatedReader;
33
13aa7280ac7b parse encapsulated structures (octet string or bit string containing valid ASN.1): add ValidatingASN1ContentHandler → avoid at least some false positives
František Kučera <franta-hg@frantovo.cz>
parents: 32
diff changeset
   292
		std::shared_ptr<ValidatingASN1ContentHandler> validatingHandler = std::make_shared<ValidatingASN1ContentHandler>();
13aa7280ac7b parse encapsulated structures (octet string or bit string containing valid ASN.1): add ValidatingASN1ContentHandler → avoid at least some false positives
František Kučera <franta-hg@frantovo.cz>
parents: 32
diff changeset
   293
		encapsulatedReader.addHandler(validatingHandler);
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   294
		try {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   295
			encapsulatedReader.write((const uint8_t*) input.c_str(), input.size());
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   296
			encapsulatedReader.close();
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   297
			return true;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   298
		} catch (...) {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   299
			return false;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   300
		}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   301
	}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   302
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   303
	class EncapsulatedASN1ContentHandler : public ASN1ContentHandlerProxy {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   304
	public:
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   305
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   306
		void writeStreamStart() override {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   307
			// skip this event
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   308
		}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   309
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   310
		void writeStreamEnd() override {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   311
			// skip this event
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   312
		}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   313
	};
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   314
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   315
	/**
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   316
	 * @param typeHeader
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   317
	 * @param input OCTET STRING or BIT STRING raw bytes
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   318
	 * @return whether we found valid content and passed parsed results to handlers
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   319
	 */
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   320
	bool processEncapsulatedContent(const BasicHeader& typeHeader, const std::string& input) {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   321
		// TODO: avoid double parsing + encapsulated content might be also processed at the XML/DOM level where we may even do conditional processing based on XPath (evaluate only certain octet- or bit- strings)
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   322
		// We may also do the same as with SEQUENCE or SET (continue nested reading in this ASN1Rreader instance), but it would require valid encapsulated data and would avoid easy fallback to raw OCTET or BIT STRING. We would also have to check the boundaries of the nested part.
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   323
		if (isValidBER(input)) {
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   324
			handlers->writeCollectionStart(typeHeader);
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   325
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   326
			BasicASN1Reader encapsulatedReader;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   327
			std::shared_ptr<EncapsulatedASN1ContentHandler> encapsulatedHandler = std::make_shared<EncapsulatedASN1ContentHandler>();
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   328
			encapsulatedHandler->addHandler(handlers);
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   329
			encapsulatedReader.addHandler(encapsulatedHandler);
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   330
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   331
			encapsulatedReader.write((const uint8_t*) input.c_str(), input.size());
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   332
			encapsulatedReader.close();
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   333
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   334
			handlers->writeCollectionEnd();
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   335
			return true;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   336
		} else {
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   337
			return false;
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   338
		}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   339
	}
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   340
11
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   341
protected:
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   342
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   343
	void update() override {
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   344
		while (true) readNext();
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   345
	}
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   346
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   347
public:
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   348
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   349
	void close() override {
30
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   350
		if (hasAvailableForReading()) throw std::logic_error("Unexpected content at the end of the stream"); // TODO: better exception
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   351
31
a87c97aecbf6 parse encapsulated structures (octet string or bit string containing valid ASN.1): first dirty version
František Kučera <franta-hg@frantovo.cz>
parents: 30
diff changeset
   352
		// TODO: check also open sequences etc.; maybe in the handler
30
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   353
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   354
		checkRemainingItems();
14
02725d301010 somehow parse nested SEQUENCEs and SETs + support definite long form of lengths (multiple length octets)
František Kučera <franta-hg@frantovo.cz>
parents: 13
diff changeset
   355
		// TODO: check the bytes remaining in the buffer
32
00d76921c547 parse encapsulated structures (octet string or bit string containing valid ASN.1): improved memory management
František Kučera <franta-hg@frantovo.cz>
parents: 31
diff changeset
   356
		if (started) handlers->writeStreamEnd();
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   357
	}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   358
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   359
};
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   360
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   361
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   362
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   363
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   364
}