summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-04-17 14:25:07 -0400
committerJune McEnroe <june@causal.agency>2020-04-17 14:25:07 -0400
commit37afe4cdee822627e42e61910e9e39995822f1c5 (patch)
treede6a971a177aa1a69b6a7b072ffa12c6f6da62b1
parentIgnore config.mk (diff)
downloadbubger-37afe4cdee822627e42e61910e9e39995822f1c5.tar.gz
bubger-37afe4cdee822627e42e61910e9e39995822f1c5.zip
Choose text/plain from multipart/alternative
-rw-r--r--export.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/export.c b/export.c
index ed594de..21f5662 100644
--- a/export.c
+++ b/export.c
@@ -19,6 +19,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <strings.h>
 #include <sysexits.h>
 #include <unistd.h>
 
@@ -73,6 +74,12 @@ static void exportMbox(
 	if (error) err(EX_CANTCREAT, "%s", msg);
 }
 
+static bool isInline(const struct BodyPart *part) {
+	if (!bodyPartType(part, "text", "plain")) return false;
+	if (!part->disposition.type) return true;
+	return !strcasecmp(part->disposition.type, "inline");
+}
+
 static void exportAtom(
 	uint32_t uid, const struct Envelope *envelope,
 	const struct BodyPart *structure, struct Data body
@@ -90,15 +97,14 @@ static void exportAtom(
 		body = dataCheck(body, List).list.ptr[0];
 	}
 	if (bodyPartType(part, "multipart", "alternative")) {
-		for (size_t i = 0; i < part->parts.len; ++i) {
-			if (bodyPartType(&part->parts.ptr[i], "text", "plain")) {
-				part = &part->parts.ptr[i];
-				body = dataCheck(body, List).list.ptr[i];
-				break;
-			}
+		for (size_t i = part->parts.len - 1; i < part->parts.len; --i) {
+			if (!isInline(&part->parts.ptr[i])) continue;
+			part = &part->parts.ptr[i];
+			body = dataCheck(body, List).list.ptr[i];
+			break;
 		}
 	}
-	if (bodyPartType(part, "text", "plain")) {
+	if (isInline(part)) {
 		char *content = decodeToString(part, dataCheck(body, String).string);
 		error = atomContent(file, content);
 		if (error) err(EX_IOERR, "%s", path);
@@ -111,33 +117,43 @@ static void exportAtom(
 
 static int exportHTMLBody(
 	FILE *file, struct List *section,
-	const struct BodyPart *structure, struct Data body
+	const struct BodyPart *part, struct Data body
 ) {
 	int error = 0;
-	if (structure->multipart) {
-		// TODO: Choose a part from multipart/alternative.
-		for (size_t i = 0; i < structure->parts.len; ++i) {
-			struct Data part = { .type = Number, .number = 1 + i };
-			listPush(section, part);
+	if (bodyPartType(part, "multipart", "alternative")) {
+		for (size_t i = part->parts.len - 1; i < part->parts.len; --i) {
+			if (!isInline(&part->parts.ptr[i])) continue;
+			return exportHTMLBody(
+				file, section, &part->parts.ptr[i],
+				dataCheck(body, List).list.ptr[i]
+			);
+		}
+		return exportHTMLBody(
+			file, section, &part->parts.ptr[part->parts.len - 1],
+			dataCheck(body, List).list.ptr[part->parts.len - 1]
+		);
+	} else if (part->multipart) {
+		for (size_t i = 0; i < part->parts.len; ++i) {
+			struct Data num = { .type = Number, .number = 1 + i };
+			listPush(section, num);
 			error = exportHTMLBody(
-				file, section,
-				&structure->parts.ptr[i], dataCheck(body, List).list.ptr[i]
+				file, section, &part->parts.ptr[i],
+				dataCheck(body, List).list.ptr[i]
 			);
 			if (error) return error;
 			section->len--;
 		}
-	} else if (structure->message.envelope) {
+	} else if (part->message.envelope) {
 		error = 0
-			|| htmlMessageOpen(file, structure->message.envelope)
-			|| exportHTMLBody(file, section, structure->message.structure, body)
+			|| htmlMessageOpen(file, part->message.envelope)
+			|| exportHTMLBody(file, section, part->message.structure, body)
 			|| htmlMessageClose(file);
-	} else if (bodyPartType(structure, "text", "plain")) {
-		// TODO: Check if not inline.
-		char *content = decodeToString(
-			structure, dataCheck(body, String).string
-		);
-		error = htmlInline(file, structure, content);
+	} else if (isInline(part)) {
+		char *content = decodeToString(part, dataCheck(body, String).string);
+		error = htmlInline(file, part, content);
 		free(content);
+	} else {
+		// TODO: Write out attachment.
 	}
 	return error;
 }