118 checkRemainingItems(); |
118 checkRemainingItems(); |
119 BasicHeader typeHeader = readHeader(); |
119 BasicHeader typeHeader = readHeader(); |
120 // commit(); // TODO: commit here and recover later instead of rollback? |
120 // commit(); // TODO: commit here and recover later instead of rollback? |
121 |
121 |
122 if (!started) { |
122 if (!started) { |
123 handlers.writeStreamStart(); |
123 handlers->writeStreamStart(); |
124 started = true; |
124 started = true; |
125 } |
125 } |
126 |
126 |
127 // TODO: check tagClass and pc |
127 // TODO: check tagClass and pc |
128 |
128 |
129 // TODO: constants, more types |
129 // TODO: constants, more types |
130 if (typeHeader.tag == UniversalType::EndOfContent && typeHeader.tagClass == TagClass::Universal && typeHeader.pc == PC::Primitive) { |
130 if (typeHeader.tag == UniversalType::EndOfContent && typeHeader.tagClass == TagClass::Universal && typeHeader.pc == PC::Primitive) { |
131 handlers.writeCollectionEnd(); |
131 handlers->writeCollectionEnd(); |
132 } else if (typeHeader.tag == UniversalType::Sequence) { |
132 } else if (typeHeader.tag == UniversalType::Sequence) { |
133 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
133 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
134 handlers.writeCollectionStart(typeHeader); |
134 handlers->writeCollectionStart(typeHeader); |
135 } else if (typeHeader.tag == UniversalType::Set) { |
135 } else if (typeHeader.tag == UniversalType::Set) { |
136 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
136 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
137 handlers.writeCollectionStart(typeHeader); |
137 handlers->writeCollectionStart(typeHeader); |
138 } else if (typeHeader.pc == PC::Constructed) { |
138 } else if (typeHeader.pc == PC::Constructed) { |
139 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
139 level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction |
140 handlers.writeCollectionStart(typeHeader); |
140 handlers->writeCollectionStart(typeHeader); |
141 } else if (typeHeader.tag == UniversalType::Null && typeHeader.length == 0) { |
141 } else if (typeHeader.tag == UniversalType::Null && typeHeader.length == 0) { |
142 handlers.writeNull(typeHeader); |
142 handlers->writeNull(typeHeader); |
143 } else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) { |
143 } else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) { |
144 bool value; |
144 bool value; |
145 read((uint8_t*) & value, 1); |
145 read((uint8_t*) & value, 1); |
146 handlers.writeBoolean(typeHeader, value); |
146 handlers->writeBoolean(typeHeader, value); |
147 } else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
147 } else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
148 // TODO: check available bytes before allocating buffer |
148 // TODO: check available bytes before allocating buffer |
149 std::vector<uint8_t> value(typeHeader.length, 0x00); |
149 std::vector<uint8_t> value(typeHeader.length, 0x00); |
150 read(value.data(), typeHeader.length); |
150 read(value.data(), typeHeader.length); |
151 handlers.writeInteger(typeHeader, ASN1ContentHandler::Integer(value)); |
151 handlers->writeInteger(typeHeader, ASN1ContentHandler::Integer(value)); |
152 } else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
152 } else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
153 std::vector<uint8_t> value(typeHeader.length, 0x00); |
153 std::vector<uint8_t> value(typeHeader.length, 0x00); |
154 read(value.data(), typeHeader.length); |
154 read(value.data(), typeHeader.length); |
155 handlers.writeOID(typeHeader,{value}); |
155 handlers->writeOID(typeHeader,{value}); |
156 } else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
156 } else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
157 // TODO: check available bytes before allocating buffer |
157 // TODO: check available bytes before allocating buffer |
158 std::string s; |
158 std::string s; |
159 s.resize(typeHeader.length); |
159 s.resize(typeHeader.length); |
160 read((uint8_t*) s.data(), typeHeader.length); |
160 read((uint8_t*) s.data(), typeHeader.length); |
161 handlers.writeTextString(typeHeader, s); |
161 handlers->writeTextString(typeHeader, s); |
162 } else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
162 } else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
163 // TODO: check encoding |
163 // TODO: check encoding |
164 // TODO: check available bytes before allocating buffer |
164 // TODO: check available bytes before allocating buffer |
165 std::string s; |
165 std::string s; |
166 s.resize(typeHeader.length); |
166 s.resize(typeHeader.length); |
167 read((uint8_t*) s.data(), typeHeader.length); |
167 read((uint8_t*) s.data(), typeHeader.length); |
168 handlers.writeTextString(typeHeader, s); |
168 handlers->writeTextString(typeHeader, s); |
169 } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
169 } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
170 // TODO: check available bytes before allocating buffer |
170 // TODO: check available bytes before allocating buffer |
171 std::string s; |
171 std::string s; |
172 s.resize(typeHeader.length); |
172 s.resize(typeHeader.length); |
173 read((uint8_t*) s.data(), typeHeader.length); |
173 read((uint8_t*) s.data(), typeHeader.length); |
174 if (processEncapsulatedContent(typeHeader, s) == false) handlers.writeOctetString(typeHeader, s); |
174 if (processEncapsulatedContent(typeHeader, s) == false) handlers->writeOctetString(typeHeader, s); |
175 } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
175 } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
176 // TODO: check available bytes before allocating buffer |
176 // TODO: check available bytes before allocating buffer |
177 std::string s; |
177 std::string s; |
178 s.resize(typeHeader.length); |
178 s.resize(typeHeader.length); |
179 read((uint8_t*) s.data(), typeHeader.length); |
179 read((uint8_t*) s.data(), typeHeader.length); |
312 */ |
312 */ |
313 bool processEncapsulatedContent(const BasicHeader& typeHeader, const std::string& input) { |
313 bool processEncapsulatedContent(const BasicHeader& typeHeader, const std::string& input) { |
314 // 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) |
314 // 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) |
315 // 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. |
315 // 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. |
316 if (isValidBER(input)) { |
316 if (isValidBER(input)) { |
317 handlers.writeCollectionStart(typeHeader); |
317 handlers->writeCollectionStart(typeHeader); |
318 |
318 |
319 BasicASN1Reader encapsulatedReader; |
319 BasicASN1Reader encapsulatedReader; |
320 std::shared_ptr<EncapsulatedASN1ContentHandler> encapsulatedHandler = std::make_shared<EncapsulatedASN1ContentHandler>(); |
320 std::shared_ptr<EncapsulatedASN1ContentHandler> encapsulatedHandler = std::make_shared<EncapsulatedASN1ContentHandler>(); |
321 encapsulatedHandler->addHandler(std::shared_ptr<ASN1ContentHandlerProxy>(&handlers, [](auto doNotDeleteHere) { |
321 encapsulatedHandler->addHandler(handlers); |
322 })); // FIXME: correct memory management |
|
323 encapsulatedReader.addHandler(encapsulatedHandler); |
322 encapsulatedReader.addHandler(encapsulatedHandler); |
324 |
323 |
325 encapsulatedReader.write((const uint8_t*) input.c_str(), input.size()); |
324 encapsulatedReader.write((const uint8_t*) input.c_str(), input.size()); |
326 encapsulatedReader.close(); |
325 encapsulatedReader.close(); |
327 |
326 |
328 handlers.writeCollectionEnd(); |
327 handlers->writeCollectionEnd(); |
329 return true; |
328 return true; |
330 } else { |
329 } else { |
331 return false; |
330 return false; |
332 } |
331 } |
333 } |
332 } |