--- a/src/lib/BasicASN1Reader.h Sun Jun 20 20:16:46 2021 +0200
+++ b/src/lib/BasicASN1Reader.h Sun Jun 20 21:06:02 2021 +0200
@@ -19,6 +19,7 @@
#include <memory>
#include <vector>
#include <array>
+#include <sstream>
#include "ASN1Reader.h"
@@ -56,6 +57,25 @@
size_t length;
};
+ class LevelMetadata {
+ public:
+ bool definiteLength;
+ size_t length;
+ size_t start;
+ };
+
+ std::vector<LevelMetadata> level;
+
+ void checkRemainingItems() {
+ if (level.size()) {
+ LevelMetadata& l = level.back();
+ if (l.definiteLength && l.length == getBytesRead() - l.start) {
+ level.pop_back();
+ handlers.writeCollectionEnd();
+ }
+ }
+ }
+
Header readHeader() {
Header h;
@@ -72,33 +92,76 @@
uint8_t lengthByte;
read(&lengthByte, 1);
- std::wcerr << L"lengthByte = " << lengthByte << std::endl;
-
if (lengthByte >> 7 == 0) {
+ // definite short
h.definiteLength = true;
h.length = lengthByte;
} else if (lengthByte == 0b10000000) {
+ // indefinite
h.definiteLength = false;
h.length = 0;
} else if (lengthByte == 0xFF) {
throw relpipe::writer::RelpipeWriterException(L"ASN.1 lengthByte == 0xFF (reserved value)"); // TODO: better exception
} else {
- // FIXME: longer values
- throw relpipe::writer::RelpipeWriterException(L"not yet implemented, ASN.1 lengthBytes: longer value"); // TODO: better exception
+ // definite long
+ h.definiteLength = true;
+ h.length = 0;
+ std::vector<uint8_t> lengthBytes(lengthByte & 0b01111111, 0);
+ read(lengthBytes.data(), lengthBytes.size());
+ for (uint8_t l : lengthBytes) h.length = (h.length << 8) + l;
}
-
+
return h;
}
void readNext() {
+ checkRemainingItems();
Header typeHeader = readHeader();
- commit();
+ // commit(); // TODO: commit here and recover later instead of rollback?
if (!started) {
handlers.writeStreamStart();
started = true;
}
+
+ // TODO: check tagClass and pc
+ // TODO: constants, more types
+ if (typeHeader.tag == 0) handlers.writeCollectionEnd();
+ else if (typeHeader.tag == 16) {
+ level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
+ handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
+ } else if (typeHeader.tag == 17) {
+ level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
+ handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Set);
+ } else if (typeHeader.tag == 5 && typeHeader.length == 0) {
+ handlers.writeNull();
+ } else if (typeHeader.tag == 1) {
+ bool value;
+ read((uint8_t*) & value, 1);
+ handlers.writeBoolean(value);
+ } else {
+ // TODO: do not skip, parse
+ std::vector<uint8_t> temp(typeHeader.length, 0);
+ read(temp.data(), typeHeader.length);
+ // TODO: recover transaction?
+
+ std::stringstream description;
+ description << "value:"
+ << " tag = " << typeHeader.tag
+ << " tagClass = " << (int) typeHeader.tagClass
+ << " pc = " << (int) typeHeader.pc
+ << " length = " << typeHeader.length
+ << " definite = " << (typeHeader.definiteLength ? "true" : "false");
+
+ handlers.writeString(ASN1ContentHandler::StringType::UTF8String, description.str());
+ }
+
+ commit();
+
+
+ // TODO: remove debug/demo output:
+ return;
handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
handlers.writeNull();
handlers.writeBoolean(true);
@@ -127,7 +190,8 @@
public:
void close() override {
- if (started) handlers.writeStreamEnd();
+ // TODO: check the bytes remaining in the buffer
+ //if (started) handlers.writeStreamEnd();
}
};