src/lib/BasicASN1Reader.h
author František Kučera <franta-hg@frantovo.cz>
Thu, 22 Jul 2021 20:01:03 +0200
branchv_0
changeset 40 85b6f13f1088
parent 37 0845ca3636b6
permissions -rw-r--r--
configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
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"
40
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    27
#include "uri.h"
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
namespace relpipe {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
namespace in {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
namespace asn1 {
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
namespace lib {
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
/**
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
 * 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
    36
 */
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
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
    38
private:
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    39
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
    40
	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
    41
40
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    42
	bool parseEncapsulated = true;
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    43
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    44
	/**
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    45
	 * TODO: use a common method
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    46
	 */
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    47
	bool parseBoolean(const std::string& value) {
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    48
		if (value == "true") return true;
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    49
		else if (value == "false") return false;
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    50
		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    51
	}
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
    52
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    53
	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
    54
	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
    55
		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
    56
		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
    57
	};
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    58
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
    59
	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
    60
	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
    61
		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
    62
		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
    63
		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
    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
	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
    67
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
    68
	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
    69
		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
    70
			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
    71
			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
    72
				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
    73
				handlers->writeCollectionEnd();
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
    74
				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
    75
			}
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
    76
		}
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
    77
	}
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
    78
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    79
	BasicHeader readHeader() {
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    80
		using TagClass = ASN1ContentHandler::TagClass;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    81
		using PC = ASN1ContentHandler::PC;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    82
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
    83
		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
    84
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
    85
		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
    86
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
    87
		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
    88
		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
    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
		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
    91
		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
    92
		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
    93
		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
    94
			h.tag = 0;
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    95
			uint8_t moreTag = 0;
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    96
			do {
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    97
				read(&moreTag, 1);
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
    98
				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
    99
			} while (moreTag & (1 << 7));
b7431bc6069b support tag numbers > 30 (multiple octets)
František Kučera <franta-hg@frantovo.cz>
parents: 17
diff changeset
   100
		}
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
   101
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
		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
   103
		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
   104
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
   105
		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
   106
			// 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
   107
			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
   108
			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
   109
		} 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
   110
			// 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
   111
			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
   112
			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
   113
		} 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
   114
			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
   115
		} 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
   116
			// 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
   117
			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
   118
			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
   119
			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
   120
			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
   121
			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
   122
		}
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
   123
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
   124
		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
   125
	}
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   126
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
   127
	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
   128
		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
   129
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
		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
   131
			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
   132
			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
   133
			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
   134
			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
   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
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
   137
		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
   138
	}
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
   139
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
   140
	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
   141
		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
   142
		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
   143
		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
   144
		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
   145
		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
   146
	}
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
   147
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
   148
	void processNext() {
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   149
		using TagClass = ASN1ContentHandler::TagClass;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   150
		using PC = ASN1ContentHandler::PC;
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   151
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
   152
		checkRemainingItems();
25
ba79cebde109 move TagClass, PC and Header to ASN1ContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 23
diff changeset
   153
		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
   154
		// 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
   155
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   156
		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
   157
			handlers->writeStreamStart();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   158
			started = true;
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   159
		}
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   160
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
   161
		// TODO: check tagClass and pc
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   162
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
   163
		// TODO: constants, more types
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   164
		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
   165
			handlers->writeCollectionEnd();
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   166
		} 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
   167
			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
   168
			handlers->writeCollectionStart(typeHeader);
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::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
   170
			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
   171
			handlers->writeCollectionStart(typeHeader);
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   172
		} else if (typeHeader.pc == PC::Constructed) {
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   173
			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
   174
			handlers->writeCollectionStart(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   175
		} 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
   176
			handlers->writeNull(typeHeader);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   177
		} 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
   178
			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
   179
			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
   180
			handlers->writeBoolean(typeHeader, value);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   181
		} 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
   182
			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
   183
			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
   184
		} 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
   185
			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
   186
			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
   187
			handlers->writeOID(typeHeader,{value});
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   188
		} 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
   189
			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
   190
			handlers->writeTextString(typeHeader, s);
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::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
   192
			// 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
   193
			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
   194
			handlers->writeTextString(typeHeader, s);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   195
		} 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
   196
			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
   197
			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
   198
		} 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
   199
			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
   200
			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
   201
				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
   202
				// 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
   203
				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
   204
					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
   205
					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
   206
					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
   207
				}
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
   208
				handlers->writeBitString(typeHeader, bits);
23
8941a679299f BitString and OctetString support
František Kučera <franta-hg@frantovo.cz>
parents: 22
diff changeset
   209
			}
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   210
		} 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
   211
			// 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
   212
			std::string s = readString(typeHeader.length);
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   213
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   214
			ASN1ContentHandler::DateTime dateTime;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   215
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   216
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   217
			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
   218
				int i = 1;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   219
				uint32_t year = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   220
				dateTime.year = year < 50 ? 2000 + year : 1900 + year;
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   221
				dateTime.month = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   222
				dateTime.day = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   223
				dateTime.hour = std::stoi(match[i++]);
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   224
				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
   225
				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
   226
				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
   227
				i++;
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   228
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   229
					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
   230
					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
   231
				}
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
   232
				handlers->writeDateTime(typeHeader, dateTime);
21
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   233
			} else {
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   234
				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
   235
			}
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   236
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   237
		} 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
   238
			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
   239
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   240
			ASN1ContentHandler::DateTime dateTime;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   241
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   242
			std::smatch match;
29
c232d8b8efbf UTCTime and GeneralizedTime clean-up and comment
František Kučera <franta-hg@frantovo.cz>
parents: 28
diff changeset
   243
			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
   244
				// 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
   245
				int i = 1;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   246
				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
   247
				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
   248
				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
   249
				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
   250
				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
   251
				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
   252
				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
   253
				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
   254
				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
   255
				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
   256
				else i++;
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   257
				if (match[i++] != "Z") {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   258
					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
   259
					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
   260
				}
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
   261
				handlers->writeDateTime(typeHeader, dateTime);
22
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   262
			} else {
9b6f86760384 slightly improved UTCTime and GeneralizedTime support
František Kučera <franta-hg@frantovo.cz>
parents: 21
diff changeset
   263
				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
   264
			}
705036445672 partial UTCTime support
František Kučera <franta-hg@frantovo.cz>
parents: 20
diff changeset
   265
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
   266
		} 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
   267
			// 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
   268
			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
   269
			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
   270
		}
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
   271
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
   272
		commit();
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   273
	}
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   274
30
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   275
	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
   276
		// 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
   277
		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
   278
		try {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   279
			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
   280
			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
   281
		} catch (...) {
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   282
			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
   283
		}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   284
	}
e27e133731ee throw error when we get superfluous octets at the end
František Kučera <franta-hg@frantovo.cz>
parents: 29
diff changeset
   285
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
   286
	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
   287
		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
   288
		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
   289
		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
   290
		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
   291
			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
   292
			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
   293
			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
   294
			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
   295
		} 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
   296
			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
   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
	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
   301
	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
   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
		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
   304
			// 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
   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
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
		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
   308
			// 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
   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
	};
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
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
	 * @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
   314
	 * @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
   315
	 * @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
   316
	 */
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
	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
   318
		// 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
   319
		// 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.
40
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   320
		if (parseEncapsulated && 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
   321
			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
   322
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
			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
   324
			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
   325
			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
   326
			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
   327
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
   328
			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
   329
			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
   330
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
   331
			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
   332
			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
   333
		} 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
   334
			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
   335
		}
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
	}
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
11
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   338
protected:
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   339
8fbe93f78e2b BasicASN1Reader: read from the buffer and commit
František Kučera <franta-hg@frantovo.cz>
parents: 9
diff changeset
   340
	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
   341
		while (true) processNext();
11
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
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   344
public:
1
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   345
40
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   346
	bool setOption(const std::string& uri, const std::string& value) override {
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   347
		if (uri == option::Encoding && value == encoding::ber); // currently, we support only BER (and thus also CER and DER) encoding, but options have no actual effect – we just validate them
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   348
		else if (uri == option::Encoding && value == encoding::cer); // in future versions, this might switch the parser into more strict mode
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   349
		else if (uri == option::Encoding && value == encoding::der); // in future versions, this might switch the parser into more strict mode
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   350
		else if (uri == option::Encoding && value == encoding::per) throw std::invalid_argument("PER encoding is not yet supported");
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   351
		else if (uri == option::Encoding && value == encoding::xer) throw std::invalid_argument("XER encoding is not yet supported");
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   352
		else if (uri == option::Encoding && value == encoding::asn1) throw std::invalid_argument("ASN.1 encoding is not yet supported");
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   353
		else if (uri == option::Encoding) throw std::invalid_argument("Unsupported ASN.1 encoding: " + value);
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   354
		else if (uri == option::ParseEncapsulated) parseEncapsulated = parseBoolean(value);
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   355
		else return false;
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   356
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   357
		return true;
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   358
	}
85b6f13f1088 configuration: --parser-option encoding, parse-encapsulated, root-name, tree-style, tree-with-namespaces
František Kučera <franta-hg@frantovo.cz>
parents: 37
diff changeset
   359
9
7a6abdd00ab5 partial implementation of DOMBuildingXMLContentHandler
František Kučera <franta-hg@frantovo.cz>
parents: 8
diff changeset
   360
	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
   361
		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
   362
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
   363
		// 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
   364
15
95ca127ba816 support constructed (like a collection)
František Kučera <franta-hg@frantovo.cz>
parents: 14
diff changeset
   365
		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
   366
		// 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
   367
		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
   368
	}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   369
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   370
};
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   371
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   372
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   373
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   374
}
2179f13227f4 AbstractParser: AbstractParser, ASN1Reader, ASN1ContentHandler, SAXContentHandler, BasicASN1Reader, DOMBuildingSAXContentHandler, GenericASN1ContentHandler skeletons
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   375
}