src/lib/BasicASN1Reader.h
branchv_0
changeset 32 00d76921c547
parent 31 a87c97aecbf6
child 33 13aa7280ac7b
equal deleted inserted replaced
31:a87c97aecbf6 32:00d76921c547
    55 	void checkRemainingItems() {
    55 	void checkRemainingItems() {
    56 		if (level.size()) {
    56 		if (level.size()) {
    57 			LevelMetadata& l = level.back();
    57 			LevelMetadata& l = level.back();
    58 			if (l.definiteLength && l.length == getBytesRead() - l.start) {
    58 			if (l.definiteLength && l.length == getBytesRead() - l.start) {
    59 				level.pop_back();
    59 				level.pop_back();
    60 				handlers.writeCollectionEnd();
    60 				handlers->writeCollectionEnd();
    61 				checkRemainingItems(); // multiple collections may end at the same point
    61 				checkRemainingItems(); // multiple collections may end at the same point
    62 			}
    62 			}
    63 		}
    63 		}
    64 	}
    64 	}
    65 
    65 
   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);
   183 				if (s.size() > 1) {
   183 				if (s.size() > 1) {
   184 					uint8_t padding = s[0];
   184 					uint8_t padding = s[0];
   185 					for (uint8_t j = padding; j < 8; j++) bits.push_back(s.back() & 1 << j);
   185 					for (uint8_t j = padding; j < 8; j++) bits.push_back(s.back() & 1 << j);
   186 					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);
   186 					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);
   187 				}
   187 				}
   188 				handlers.writeBitString(typeHeader, bits);
   188 				handlers->writeBitString(typeHeader, bits);
   189 			}
   189 			}
   190 		} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   190 		} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   191 			// TODO: check available bytes before allocating buffer
   191 			// TODO: check available bytes before allocating buffer
   192 			// TODO: check encoding
   192 			// TODO: check encoding
   193 			std::string s;
   193 			std::string s;
   210 				i++;
   210 				i++;
   211 				if (match[i++] != "Z") {
   211 				if (match[i++] != "Z") {
   212 					dateTime.timezoneHour = std::stoi(match[i++]);
   212 					dateTime.timezoneHour = std::stoi(match[i++]);
   213 					dateTime.timezoneMinute = std::stoi(match[i++]);
   213 					dateTime.timezoneMinute = std::stoi(match[i++]);
   214 				}
   214 				}
   215 				handlers.writeDateTime(typeHeader, dateTime);
   215 				handlers->writeDateTime(typeHeader, dateTime);
   216 			} else {
   216 			} else {
   217 				throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception
   217 				throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception
   218 			}
   218 			}
   219 
   219 
   220 		} else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   220 		} else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   242 				else i++;
   242 				else i++;
   243 				if (match[i++] != "Z") {
   243 				if (match[i++] != "Z") {
   244 					dateTime.timezoneHour = std::stoi(match[i++]);
   244 					dateTime.timezoneHour = std::stoi(match[i++]);
   245 					dateTime.timezoneMinute = std::stoi(match[i++]);
   245 					dateTime.timezoneMinute = std::stoi(match[i++]);
   246 				}
   246 				}
   247 				handlers.writeDateTime(typeHeader, dateTime);
   247 				handlers->writeDateTime(typeHeader, dateTime);
   248 			} else {
   248 			} else {
   249 				throw std::invalid_argument("Unsupported GeneralizedTime format: " + s); // TODO: better exception
   249 				throw std::invalid_argument("Unsupported GeneralizedTime format: " + s); // TODO: better exception
   250 			}
   250 			}
   251 
   251 
   252 		} else {
   252 		} else {
   263 					<< " pc = " << (int) typeHeader.pc
   263 					<< " pc = " << (int) typeHeader.pc
   264 					<< " length = " << typeHeader.length
   264 					<< " length = " << typeHeader.length
   265 					<< " definite = " << (typeHeader.definiteLength ? "true" : "false");
   265 					<< " definite = " << (typeHeader.definiteLength ? "true" : "false");
   266 
   266 
   267 			// TODO: special event for unparsed? (instead of a text string)
   267 			// TODO: special event for unparsed? (instead of a text string)
   268 			handlers.writeTextString(typeHeader, description.str());
   268 			handlers->writeTextString(typeHeader, description.str());
   269 		}
   269 		}
   270 
   270 
   271 		commit();
   271 		commit();
   272 	}
   272 	}
   273 
   273 
   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 	}
   340 
   339 
   341 public:
   340 public:
   342 
   341 
   343 	void close() override {
   342 	void close() override {
   344 		if (hasAvailableForReading()) throw std::logic_error("Unexpected content at the end of the stream"); // TODO: better exception
   343 		if (hasAvailableForReading()) throw std::logic_error("Unexpected content at the end of the stream"); // TODO: better exception
   345 		
   344 
   346 		// TODO: check also open sequences etc.; maybe in the handler
   345 		// TODO: check also open sequences etc.; maybe in the handler
   347 
   346 
   348 		checkRemainingItems();
   347 		checkRemainingItems();
   349 		// TODO: check the bytes remaining in the buffer
   348 		// TODO: check the bytes remaining in the buffer
   350 		if (started) handlers.writeStreamEnd();
   349 		if (started) handlers->writeStreamEnd();
   351 	}
   350 	}
   352 
   351 
   353 };
   352 };
   354 
   353 
   355 }
   354 }