src/lib/BasicASN1Reader.h
author František Kučera <franta-hg@frantovo.cz>
Sun, 18 Jul 2021 22:43:16 +0200
branchv_0
changeset 37 0845ca3636b6
parent 36 caed9146f72f
child 40 85b6f13f1088
permissions -rw-r--r--
parse encapsulated structures (octet string or bit string containing valid ASN.1): add omitted finalCheck() Among other things, it avoids interpreting zezo-length octet strings as encapsulated structures.
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
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   115
	const std::string readString(size_t length) {
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   116
		std::string result;
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   117
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   118
		for (size_t remaining = length; remaining;) {
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   119
			size_t current = std::min(remaining, (size_t) 3);
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   120
			result.resize(result.size() + current);
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   121
			read((uint8_t*) result.data() + result.size() - current, current);
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   122
			remaining -= current;
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   123
		}
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   124
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   125
		return result;
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   126
	}
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   127
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   128
	const std::vector<uint8_t> readVector(size_t length) {
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   129
		std::vector<uint8_t> result;
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   130
		std::string s = readString(length); // TODO: read directly to the vector
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   131
		result.resize(length);
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   132
		for (size_t i = 0; i < length; i++) result[i] = (uint8_t) s[i];
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   133
		return result;
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   134
	}
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   135
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   136
	void processNext() {
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   137
		using TagClass = ASN1ContentHandler::TagClass;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   138
		using PC = ASN1ContentHandler::PC;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   139
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
   140
		checkRemainingItems();
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   141
		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
   142
		// 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
   143
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   144
		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
   145
			handlers->writeStreamStart();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   146
			started = true;
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   147
		}
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   148
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
   149
		// TODO: check tagClass and pc
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   150
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
   151
		// TODO: constants, more types
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   152
		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
   153
			handlers->writeCollectionEnd();
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   154
		} 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
   155
			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
   156
			handlers->writeCollectionStart(typeHeader);
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::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
   158
			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
   159
			handlers->writeCollectionStart(typeHeader);
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   160
		} else if (typeHeader.pc == PC::Constructed) {
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   161
			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
   162
			handlers->writeCollectionStart(typeHeader);
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::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
   164
			handlers->writeNull(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   165
		} 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
   166
			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
   167
			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
   168
			handlers->writeBoolean(typeHeader, value);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   169
		} else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   170
			std::vector<uint8_t> value = readVector(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
   171
			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
   172
		} 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
   173
			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
   174
			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
   175
			handlers->writeOID(typeHeader,{value});
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   176
		} else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   177
			std::string s = readString(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
   178
			handlers->writeTextString(typeHeader, s);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   179
		} 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
   180
			// TODO: check encoding
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   181
			std::string s = readString(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
   182
			handlers->writeTextString(typeHeader, s);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   183
		} else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   184
			std::string s = readString(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
   185
			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
   186
		} else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   187
			std::string s = readString(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
   188
			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
   189
				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
   190
				// 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
   191
				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
   192
					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
   193
					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
   194
					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
   195
				}
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
   196
				handlers->writeBitString(typeHeader, bits);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   197
			}
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   198
		} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   199
			// TODO: check encoding
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   200
			std::string s = readString(typeHeader.length);
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   201
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   202
			ASN1ContentHandler::DateTime dateTime;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   203
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   204
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   205
			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
   206
				int i = 1;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   207
				uint32_t year = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   208
				dateTime.year = year < 50 ? 2000 + year : 1900 + year;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   209
				dateTime.month = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   210
				dateTime.day = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   211
				dateTime.hour = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   212
				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
   213
				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
   214
				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
   215
				i++;
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   216
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   217
					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
   218
					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
   219
				}
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
   220
				handlers->writeDateTime(typeHeader, dateTime);
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   221
			} else {
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   222
				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
   223
			}
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   224
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   225
		} else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   226
			std::string s = readString(typeHeader.length);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   227
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   228
			ASN1ContentHandler::DateTime dateTime;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   229
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   230
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   231
			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
   232
				// 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
   233
				int i = 1;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   234
				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
   235
				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
   236
				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
   237
				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
   238
				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
   239
				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
   240
				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
   241
				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
   242
				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
   243
				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
   244
				else i++;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   245
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   246
					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
   247
					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
   248
				}
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
   249
				handlers->writeDateTime(typeHeader, dateTime);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   250
			} else {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   251
				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
   252
			}
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   253
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
   254
		} 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
   255
			// TODO: do not skip, parse
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   256
			std::string s = readString(typeHeader.length);
35
bf2c546f49d1 format specific/unknown/unparsed/raw values in ASN1ContentHandler instead of in ASN1Reader
František Kučera <franta-hg@frantovo.cz>
parents: 34
diff changeset
   257
			handlers->writeSpecific(typeHeader, s);
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
   258
		}
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
		commit();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   261
	}
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   262
30
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   263
	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
   264
		// 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
   265
		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
   266
		try {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   267
			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
   268
			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
   269
		} catch (...) {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   270
			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
   271
		}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   272
	}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   273
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
   274
	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
   275
		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
   276
		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
   277
		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
   278
		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
   279
			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
   280
			encapsulatedReader.close();
37
0845ca3636b6 parse encapsulated structures (octet string or bit string containing valid ASN.1): add omitted finalCheck()
František Kučera <franta-hg@frantovo.cz>
parents: 36
diff changeset
   281
			validatingHandler->finalCheck();
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
   282
			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
   283
		} 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
   284
			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
   285
		}
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
   286
	}
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
   287
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
   288
	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
   289
	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
   290
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
		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
   292
			// 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
   293
		}
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
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
		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
   296
			// 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
   297
		}
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
	};
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
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
	 * @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
   302
	 * @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
   303
	 * @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
   304
	 */
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
	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
   306
		// 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
   307
		// 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
   308
		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
   309
			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
   310
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
			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
   312
			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
   313
			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
   314
			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
   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
			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
   317
			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
   318
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
   319
			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
   320
			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
   321
		} 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
   322
			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
   323
		}
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
   324
	}
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
11
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   326
protected:
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   327
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   328
	void update() override {
36
caed9146f72f parse encapsulated structures (octet string or bit string containing valid ASN.1): reusable readString() method + let exception do its job on invalid input instead of attempt to allocate too much memory
František Kučera <franta-hg@frantovo.cz>
parents: 35
diff changeset
   329
		while (true) processNext();
11
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   330
	}
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   331
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   332
public:
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   333
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   334
	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
   335
		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
   336
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
   337
		// 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
   338
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   339
		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
   340
		// 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
   341
		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
   342
	}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   343
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   344
};
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   345
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   346
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   347
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   348
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   349
}