diff options
Diffstat (limited to '')
-rw-r--r-- | export.c | 83 |
1 files changed, 73 insertions, 10 deletions
diff --git a/export.c b/export.c index 21f5662..9aa3126 100644 --- a/export.c +++ b/export.c @@ -15,11 +15,14 @@ */ #include <err.h> +#include <errno.h> #include <inttypes.h> +#include <limits.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> +#include <sys/stat.h> #include <sysexits.h> #include <unistd.h> @@ -115,8 +118,58 @@ static void exportAtom( if (error) err(EX_IOERR, "%s", path); } +static struct Attachment exportAttachment( + const struct Envelope *envelope, struct List section, + const struct BodyPart *part, struct Data body +) { + struct Attachment attach = { "", "", "" }; + strlcpy( + attach.path[0], pathSafe(envelope->messageID), sizeof(attach.path[0]) + ); + for (size_t i = 0; i < section.len; ++i) { + uint32_t num = dataCheck(section.ptr[i], Number).number; + char buf[32]; + snprintf(buf, sizeof(buf), "%s%" PRIu32, (i ? "." : ""), num); + strlcat(attach.path[1], buf, sizeof(attach.path[1])); + } + struct List params = part->disposition.params; + for (size_t i = 0; i + 1 < params.len; i += 2) { + const char *key = dataCheck(params.ptr[i], String).string; + if (strcasecmp(key, "filename")) continue; + const char *value = dataCheck(params.ptr[i + 1], String).string; + strlcpy(attach.path[2], pathSafe(value), sizeof(attach.path[2])); + } + if (!attach.path[2][0]) { + const char *disposition = part->disposition.type; + if (!disposition) disposition = "INLINE"; + strlcat(attach.path[2], pathSafe(disposition), sizeof(attach.path[2])); + strlcat(attach.path[2], ".", sizeof(attach.path[2])); + strlcat(attach.path[2], pathSafe(part->subtype), sizeof(attach.path[2])); + } + + char path[PATH_MAX + 1] = "attachment"; + for (int i = 0; i < 2; ++i) { + strlcat(path, "/", sizeof(path)); + strlcat(path, attach.path[i], sizeof(path)); + int error = mkdir(path, 0775); + if (error && errno != EEXIST) err(EX_CANTCREAT, "%s", path); + } + strlcat(path, "/", sizeof(path)); + strlcat(path, attach.path[2], sizeof(path)); + + FILE *file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + + int error = 0 + || decodeToFile(file, part, dataCheck(body, String).string) + || fclose(file); + if (error) err(EX_IOERR, "%s", path); + + return attach; +} + static int exportHTMLBody( - FILE *file, struct List *section, + FILE *file, const struct Envelope *envelope, struct List *section, const struct BodyPart *part, struct Data body ) { int error = 0; @@ -124,36 +177,46 @@ static int exportHTMLBody( 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] + file, envelope, section, + &part->parts.ptr[i], dataCheck(body, List).list.ptr[i] ); } return exportHTMLBody( - file, section, &part->parts.ptr[part->parts.len - 1], + file, envelope, 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, &part->parts.ptr[i], - dataCheck(body, List).list.ptr[i] + file, envelope, section, + &part->parts.ptr[i], dataCheck(body, List).list.ptr[i] ); if (error) return error; section->len--; } - } else if (part->message.envelope) { + + } else if (part->message.structure) { + const struct BodyPart *structure = part->message.structure; error = 0 || htmlMessageOpen(file, part->message.envelope) - || exportHTMLBody(file, section, part->message.structure, body) + || exportHTMLBody(file, envelope, section, structure, body) || htmlMessageClose(file); + } else if (isInline(part)) { char *content = decodeToString(part, dataCheck(body, String).string); error = htmlInline(file, part, content); free(content); + } else { - // TODO: Write out attachment. + // TODO: Open and close attachment lists. + struct Attachment attach = exportAttachment( + envelope, *section, part, body + ); + error = htmlAttachment(file, part, &attach); } return error; } @@ -170,7 +233,7 @@ static void exportHTML( if (error) err(EX_IOERR, "%s", path); struct List section = {0}; - error = exportHTMLBody(file, §ion, structure, body); + error = exportHTMLBody(file, envelope, §ion, structure, body); if (error) err(EX_IOERR, "%s", path); listFree(section); |