From 2b8d8d0ffd83b9e0e6e9372b599381498c8d2cf1 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Tue, 14 Apr 2020 17:21:43 -0400 Subject: Find text content for Atom in multipart/mixed and /alternative --- export.c | 78 +++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 45 insertions(+), 33 deletions(-) (limited to 'export.c') diff --git a/export.c b/export.c index 952f72e..5647086 100644 --- a/export.c +++ b/export.c @@ -75,7 +75,7 @@ static void exportMbox( static void exportAtom( uint32_t uid, const struct Envelope *envelope, - const struct BodyPart *structure, const char *body + const struct BodyPart *structure, struct Data body ) { const char *path = pathUID(uid, "atom"); FILE *file = fopen(path, "w"); @@ -84,14 +84,25 @@ static void exportAtom( int error = atomEntryOpen(file, envelope); if (error) err(EX_IOERR, "%s", path); - if ( - !structure->multipart && - !strcmp(structure->type, "TEXT") && - !strcmp(structure->subtype, "PLAIN") - ) { + const struct BodyPart *part = structure; + if (bodyPartType(part, "multipart", "mixed")) { + part = &part->parts.ptr[0]; + 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; + } + } + } + if (bodyPartType(part, "text", "plain")) { + const char *content = dataCheck(body, String).string; error = 0 || atomContentOpen(file) - || decodeContent(file, escapeXML, structure, body) + || decodeContent(file, escapeXML, structure, content) || atomContentClose(file); if (error) err(EX_IOERR, "%s", path); } @@ -131,8 +142,8 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) { uint32_t uid = 0; struct Envelope envelope = {0}; struct BodyPart structure = {0}; - const char *bodyHeader = NULL; - const char *bodyText = NULL; + struct Data bodyHeader = {0}; + struct Data bodyText = {0}; struct Data bodyParts = {0}; for (size_t i = 0; i + 1 < items.len; i += 2) { @@ -160,9 +171,9 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) { if (section.ptr[0].type == Atom) { name = section.ptr[0].atom; if (name == AtomHeaderFields) { - bodyHeader = dataCheck(data, String).string; + bodyHeader = data; } else if (name == AtomText) { - bodyText = dataCheck(data, String).string; + bodyText = data; } continue; } @@ -172,7 +183,9 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) { 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 }; + if (dest->type != List) { + *dest = (struct Data) { .type = List }; + } while (dest->list.len < num) { listPush(&dest->list, (struct Data) {0}); } @@ -184,34 +197,33 @@ bool exportData(FILE *imap, enum Atom tag, struct List items) { if (!uid) { errx(EX_PROTOCOL, "missing UID data item"); } + if (!envelope.subject) { + errx(EX_PROTOCOL, "missing ENVELOPE data item"); + } if (!structure.subtype) { errx(EX_PROTOCOL, "missing BODYSTRUCTURE data item"); } + if (bodyHeader.type == String && bodyText.type == String) { + exportMbox(uid, &envelope, bodyHeader.string, bodyText.string); + } + bool fetch = false; - if (envelope.subject) { - if (!bodyHeader) { - errx(EX_PROTOCOL, "missing BODY[HEADER.FIELDS] data item"); - } - if (!bodyText) { - errx(EX_PROTOCOL, "missing BODY[TEXT] data item"); - } - exportMbox(uid, &envelope, bodyHeader, bodyText); + if (!structure.multipart) { exportAtom(uid, &envelope, &structure, bodyText); - - if (structure.multipart) { - fetch = true; - fprintf( - imap, "%s UID FETCH %" PRIu32 " (UID BODYSTRUCTURE", - Atoms[tag], uid - ); - struct List parts = {0}; - exportFetchParts(imap, &parts, &structure); - listFree(parts); - fprintf(imap, ")\r\n"); - } + } else if (bodyParts.type == List) { + // TODO: Validate that bodyParts is parallel to structure. + exportAtom(uid, &envelope, &structure, bodyParts); } else { - // TODO: Correlate body parts to body data. + fetch = true; + fprintf( + imap, "%s UID FETCH %" PRIu32 " (UID ENVELOPE BODYSTRUCTURE", + Atoms[tag], uid + ); + struct List parts = {0}; + exportFetchParts(imap, &parts, &structure); + listFree(parts); + fprintf(imap, ")\r\n"); } envelopeFree(envelope); -- cgit 1.4.1