src/lib/BasicASN1Reader.h
branchv_0
changeset 40 85b6f13f1088
parent 37 0845ca3636b6
--- a/src/lib/BasicASN1Reader.h	Thu Jul 22 01:06:14 2021 +0200
+++ b/src/lib/BasicASN1Reader.h	Thu Jul 22 20:01:03 2021 +0200
@@ -24,6 +24,7 @@
 
 #include "ASN1Reader.h"
 #include "ValidatingASN1ContentHandler.h"
+#include "uri.h"
 
 namespace relpipe {
 namespace in {
@@ -38,6 +39,17 @@
 
 	bool started = false;
 
+	bool parseEncapsulated = true;
+
+	/**
+	 * TODO: use a common method
+	 */
+	bool parseBoolean(const std::string& value) {
+		if (value == "true") return true;
+		else if (value == "false") return false;
+		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
+	}
+
 	class BasicHeader : public ASN1ContentHandler::Header {
 	public:
 		bool definiteLength;
@@ -305,7 +317,7 @@
 	bool processEncapsulatedContent(const BasicHeader& typeHeader, const std::string& input) {
 		// 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)
 		// 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.
-		if (isValidBER(input)) {
+		if (parseEncapsulated && isValidBER(input)) {
 			handlers->writeCollectionStart(typeHeader);
 
 			BasicASN1Reader encapsulatedReader;
@@ -331,6 +343,20 @@
 
 public:
 
+	bool setOption(const std::string& uri, const std::string& value) override {
+		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
+		else if (uri == option::Encoding && value == encoding::cer); // in future versions, this might switch the parser into more strict mode
+		else if (uri == option::Encoding && value == encoding::der); // in future versions, this might switch the parser into more strict mode
+		else if (uri == option::Encoding && value == encoding::per) throw std::invalid_argument("PER encoding is not yet supported");
+		else if (uri == option::Encoding && value == encoding::xer) throw std::invalid_argument("XER encoding is not yet supported");
+		else if (uri == option::Encoding && value == encoding::asn1) throw std::invalid_argument("ASN.1 encoding is not yet supported");
+		else if (uri == option::Encoding) throw std::invalid_argument("Unsupported ASN.1 encoding: " + value);
+		else if (uri == option::ParseEncapsulated) parseEncapsulated = parseBoolean(value);
+		else return false;
+
+		return true;
+	}
+
 	void close() override {
 		if (hasAvailableForReading()) throw std::logic_error("Unexpected content at the end of the stream"); // TODO: better exception