about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-04-14 13:40:54 -0400
committerJune McEnroe <june@causal.agency>2020-04-14 13:40:54 -0400
commita4ed715f7237b99aee25288af07f472882eba24c (patch)
tree5974ceb84d001161f22639edd1bbcf6a0f384089
parentAdd decoding stubs (diff)
downloadbubger-a4ed715f7237b99aee25288af07f472882eba24c.tar.gz
bubger-a4ed715f7237b99aee25288af07f472882eba24c.zip
Build a list of body parts parallel to structure
-rw-r--r--export.c36
-rw-r--r--imap.h7
2 files changed, 32 insertions, 11 deletions
diff --git a/export.c b/export.c
index b34111f..952f72e 100644
--- a/export.c
+++ b/export.c
@@ -131,8 +131,9 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) {
 	uint32_t uid = 0;
 	struct Envelope envelope = {0};
 	struct BodyPart structure = {0};
-	const char *header = NULL;
-	const char *text = NULL;
+	const char *bodyHeader = NULL;
+	const char *bodyText = NULL;
+	struct Data bodyParts = {0};
 
 	for (size_t i = 0; i + 1 < items.len; i += 2) {
 		enum Atom name = dataCheck(items.ptr[i], Atom).atom;
@@ -150,22 +151,34 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) {
 		if (!section.len) {
 			errx(EX_PROTOCOL, "missing body data item section");
 		}
-		if (i + 2 >= items.len) {
+		i++;
+		if (i + 1 >= items.len) {
 			errx(EX_PROTOCOL, "missing body data item value");
 		}
-		data = items.ptr[++i + 1];
+		data = items.ptr[i + 1];
 
 		if (section.ptr[0].type == Atom) {
 			name = section.ptr[0].atom;
 			if (name == AtomHeaderFields) {
-				header = dataCheck(data, String).string;
+				bodyHeader = dataCheck(data, String).string;
 			} else if (name == AtomText) {
-				text = dataCheck(data, String).string;
+				bodyText = dataCheck(data, String).string;
 			}
 			continue;
 		}
 
-		// TODO: Build a structure of body data parallel to structure.
+		data = dataTake(&items.ptr[i + 1]);
+		struct Data *dest = &bodyParts;
+		for (size_t i = 0; i < section.len; ++i) {
+			if (section.ptr[i].type != Number) continue;
+			uint32_t num = section.ptr[i].number;
+			*dest = (struct Data) { .type = List };
+			while (dest->list.len < num) {
+				listPush(&dest->list, (struct Data) {0});
+			}
+			dest = &dest->list.ptr[num - 1];
+			*dest = data;
+		}
 	}
 
 	if (!uid) {
@@ -177,14 +190,14 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) {
 
 	bool fetch = false;
 	if (envelope.subject) {
-		if (!header) {
+		if (!bodyHeader) {
 			errx(EX_PROTOCOL, "missing BODY[HEADER.FIELDS] data item");
 		}
-		if (!text) {
+		if (!bodyText) {
 			errx(EX_PROTOCOL, "missing BODY[TEXT] data item");
 		}
-		exportMbox(uid, &envelope, header, text);
-		exportAtom(uid, &envelope, &structure, text);
+		exportMbox(uid, &envelope, bodyHeader, bodyText);
+		exportAtom(uid, &envelope, &structure, bodyText);
 
 		if (structure.multipart) {
 			fetch = true;
@@ -203,5 +216,6 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) {
 
 	envelopeFree(envelope);
 	bodyPartFree(structure);
+	dataFree(bodyParts);
 	return fetch;
 }
diff --git a/imap.h b/imap.h
index 5919b8f..a2c13bd 100644
--- a/imap.h
+++ b/imap.h
@@ -117,6 +117,13 @@ static inline struct Data dataCheck(struct Data data, enum Type type) {
 	return data;
 }
 
+static inline struct Data dataTake(struct Data *from) {
+	struct Data take = *from;
+	from->type = Atom;
+	from->atom = AtomNil;
+	return take;
+}
+
 static inline void listPush(struct List *list, struct Data data) {
 	if (list->len == list->cap) {
 		list->cap = (list->cap ? list->cap * 2 : 4);