From d3bc945e6317b7f1b80464387e11b191c8143c69 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sat, 25 Apr 2020 15:45:17 -0400 Subject: Render index.html --- archive.h | 6 ++++ concat.c | 55 +++++++++++++++++++++++++++++++++++++ html.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 150 insertions(+), 5 deletions(-) diff --git a/archive.h b/archive.h index 65f8a84..136723b 100644 --- a/archive.h +++ b/archive.h @@ -209,3 +209,9 @@ int htmlThreadOpen(FILE *file, const struct Envelope *envelope); int htmlSubthreadOpen(FILE *file, struct List thread); int htmlSubthreadClose(FILE *file); int htmlThreadClose(FILE *file); +int htmlIndexHead(FILE *file); +int htmlIndexOpen(FILE *file); +int htmlIndexThread( + FILE *file, const struct Envelope *envelope, struct List thread +); +int htmlIndexClose(FILE *file); diff --git a/concat.c b/concat.c index e75c857..8e165d2 100644 --- a/concat.c +++ b/concat.c @@ -213,5 +213,60 @@ void concatThreads(struct List threads, const struct Envelope *envelopes) { } } +struct Sort { + size_t index; + time_t updated; + time_t created; +}; + +static int compar(const void *_a, const void *_b) { + const struct Sort *a = _a; + const struct Sort *b = _b; + if (a->updated == b->updated) { + return (a->created > b->created) - (a->created < b->created); + } else { + return (a->updated > b->updated) - (a->updated < b->updated); + } +} + void concatIndex(struct List threads, const struct Envelope *envelopes) { + struct Sort *order = calloc(threads.len, sizeof(*order)); + if (!order) err(EX_OSERR, "calloc"); + + for (size_t i = 0; i < threads.len; ++i) { + struct stat status; + const char *path = threadPath(envelopes[i].messageID, "html"); + int error = stat(path, &status); + if (error) err(EX_DATAERR, "%s", path); + + order[i].index = i; + order[i].created = envelopes[i].time; + order[i].updated = status.st_mtime; + } + qsort(order, threads.len, sizeof(*order), compar); + + const char *path = "index.html"; + FILE *file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + + int error = htmlIndexHead(file); + if (error) err(EX_IOERR, "%s", path); + + if (concatHead) { + error = concatFile(file, concatHead); + if (error) err(EX_IOERR, "%s", path); + } + + error = htmlIndexOpen(file); + if (error) err(EX_IOERR, "%s", path); + + for (size_t i = threads.len - 1; i < threads.len; --i) { + const struct Envelope *envelope = &envelopes[order[i].index]; + struct List thread = dataCheck(threads.ptr[order[i].index], List).list; + error = htmlIndexThread(file, envelope, thread); + if (error) err(EX_IOERR, "%s", path); + } + + error = htmlIndexClose(file) || fclose(file); + if (error) err(EX_IOERR, "%s", path); } diff --git a/html.c b/html.c index 0d1ae11..8f349e5 100644 --- a/html.c +++ b/html.c @@ -393,12 +393,9 @@ int htmlSubthreadClose(FILE *file) { return templateRender(file, TEMPLATE(), NULL, NULL); } -int htmlThreadClose(FILE *file) { +static int htmlFooter(FILE *file) { const char *template = TEMPLATE( - - + ); time_t now = time(NULL); char time[sizeof("0000-00-00T00:00:00Z")]; @@ -409,3 +406,90 @@ int htmlThreadClose(FILE *file) { }; return templateRender(file, template, vars, escapeXML); } + +int htmlThreadClose(FILE *file) { + return 0 + || templateRender(file, TEMPLATE(), NULL, NULL) + || htmlFooter(file); +} + +int htmlIndexHead(FILE *file) { + const char *template = TEMPLATE( + + + [title] + + ); + struct Variable vars[] = { + { "title", htmlTitle }, + {0}, + }; + return templateRender(file, template, vars, escapeXML); +} + +int htmlIndexOpen(FILE *file) { + const char *template = TEMPLATE( +
+

[title]

+ +
+
+
    + ); + struct Variable vars[] = { + { "title", htmlTitle }, + {0}, + }; + return templateRender(file, template, vars, escapeXML); +} + +static char *htmlIndexURL(const struct Envelope *envelope) { + struct Variable vars[] = { + { "messageID", envelope->messageID }, + { "type", "html" }, + {0}, + }; + return templateURL(PATH_THREAD, vars); +} + +int htmlIndexThread( + FILE *file, const struct Envelope *envelope, struct List thread +) { + const char *template = TEMPLATE( +
  1. +

    [subject]

    +
    [from]
    + + [replies] repl[ies] +
  2. + ); + char *url = htmlIndexURL(envelope); + char utc[sizeof("0000-00-00T00:00:00Z")]; + strftime(utc, sizeof(utc), "%FT%TZ", gmtime(&envelope->time)); + size_t count = threadCount(thread) - 1; + char replies[32]; + snprintf(replies, sizeof(replies), "%zu", count); + struct Variable vars[] = { + { "url", url }, + { "subject", envelope->subject }, + { "from", addressName(envelope->from) }, + { "utc", utc }, + { "date", envelope->date }, + { "replies", replies }, + { "ies", (count == 1 ? "y" : "ies") }, + {0}, + }; + int error = templateRender(file, template, vars, escapeXML); + free(url); + return error; +} + +int htmlIndexClose(FILE *file) { + return 0 + || templateRender(file, TEMPLATE(
), NULL, NULL) + || htmlFooter(file); +} -- cgit 1.4.1