From 93aa78f326683d14f243f74809f7bf000d7faebf Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Fri, 10 Apr 2020 17:22:13 -0400 Subject: Concatenate Atom threads --- archive.h | 5 ++++- atom.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- concat.c | 22 ++++++++++++++++++++++ export.c | 3 ++- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/archive.h b/archive.h index b43fe87..bcadb70 100644 --- a/archive.h +++ b/archive.h @@ -101,4 +101,7 @@ int mboxBody(FILE *file, char *body); int htmlEnvelope(FILE *file, const struct Envelope *envelope); -int atomEnvelope(FILE *file, const struct Envelope *envelope); +int atomEntryHead(FILE *file, const struct Envelope *envelope); +int atomEntryTail(FILE *file); +int atomFeedHead(FILE *file, const struct Envelope *envelope); +int atomFeedTail(FILE *file); diff --git a/atom.c b/atom.c index 6692acc..2851e3c 100644 --- a/atom.c +++ b/atom.c @@ -22,13 +22,16 @@ #include "archive.h" -int atomEnvelope(FILE *file, const struct Envelope *envelope) { - struct Variable idVars[] = { - { "messageID", envelope->messageID }, +static char *atomID(const char *messageID) { + struct Variable vars[] = { + { "messageID", messageID }, {0}, }; - char *id = templateURL("mailto:?In-Reply-To=[messageID]", idVars); + return templateURL("mailto:?In-Reply-To=[messageID]", vars); +} +int atomEntryHead(FILE *file, const struct Envelope *envelope) { + char *id = atomID(envelope->messageID); char date[sizeof("0000-00-00T00:00:00Z")]; strftime(date, sizeof(date), "%FT%TZ", gmtime(&envelope->utc)); struct Variable vars[] = { @@ -54,3 +57,43 @@ int atomEnvelope(FILE *file, const struct Envelope *envelope) { free(id); return error; } + +int atomEntryTail(FILE *file) { + int n = fprintf(file, "\n"); + return (n < 0 ? n : 0); +} + +int atomFeedHead(FILE *file, const struct Envelope *envelope) { + char *id = atomID(envelope->messageID); + char date[sizeof("0000-00-00T00:00:00Z")]; + strftime(date, sizeof(date), "%FT%TZ", gmtime(&(time_t) { time(NULL) })); + struct Variable vars[] = { + { "subject", envelope->subject }, + { "from.name", addressName(envelope->from) }, + { "from.mailbox", envelope->from.mailbox }, + { "from.host", envelope->from.host }, + { "date", date }, + { "id", id }, + { "q", "?" }, + {0}, + }; + const char *Feed = TEMPLATE( + <[q]xml version="1.0" encoding="utf-8"[q]> + + [subject] + + [from.name] + [from.mailbox]@[from.host] + + [date] + [id] + ); + int error = templateRender(file, Feed, vars, escapeXML); + free(id); + return error; +} + +int atomFeedTail(FILE *file) { + int n = fprintf(file, "\n"); + return (n < 0 ? n : 0); +} diff --git a/concat.c b/concat.c index 2c58d8a..eeab073 100644 --- a/concat.c +++ b/concat.c @@ -119,14 +119,36 @@ void concatData(struct List threads, struct List items) { if (error || file.st_mtime < uidNewest(flat, "mbox")) { FILE *mbox = fopen(path, "w"); if (!mbox) err(EX_CANTCREAT, "%s", path); + for (size_t i = 0; i < flat.len; ++i) { uint32_t uid = dataCheck(flat.ptr[i], Number).number; error = concatFile(mbox, uidPath(uid, "mbox")); if (error) err(EX_IOERR, "%s", path); } + error = fclose(mbox); if (error) err(EX_IOERR, "%s", path); } + path = threadPath(envelope.messageID, "atom"); + error = stat(path, &file); + if (error || file.st_mtime < uidNewest(flat, "atom")) { + FILE *atom = fopen(path, "w"); + if (!atom) err(EX_CANTCREAT, "%s", path); + + error = atomFeedHead(atom, &envelope); + if (error) err(EX_IOERR, "%s", path); + + for (size_t i = 0; i < flat.len; ++i) { + uint32_t uid = dataCheck(flat.ptr[i], Number).number; + error = concatFile(atom, uidPath(uid, "atom")); + if (error) err(EX_IOERR, "%s", path); + } + + error = atomFeedTail(atom) + || fclose(atom); + if (error) err(EX_IOERR, "%s", path); + } + listFree(flat); } diff --git a/export.c b/export.c index 3e0933d..dcd6b18 100644 --- a/export.c +++ b/export.c @@ -134,7 +134,8 @@ void exportData(struct List items) { path = uidPath(uid, "atom"); file = fopen(path, "w"); if (!file) err(EX_CANTCREAT, "%s", path); - error = atomEnvelope(file, &envelope) + error = atomEntryHead(file, &envelope) + || atomEntryTail(file) || fclose(file); if (error) err(EX_IOERR, "%s", path); -- cgit 1.4.1