about summary refs log tree commit diff
diff options
context:
space:
mode:
authorC. McEnroe <june@causal.agency>2021-06-11 16:09:27 -0400
committerC. McEnroe <june@causal.agency>2021-06-11 16:09:27 -0400
commit5956e421952721dfea0eff838f74a5d4f13b5e94 (patch)
tree9714a81ac8fdb2dcab2acaf54c1e3f3f29c8c47d
parentIgnore test directory (diff)
downloadbubger-5956e421952721dfea0eff838f74a5d4f13b5e94.tar.gz
bubger-5956e421952721dfea0eff838f74a5d4f13b5e94.zip
Generalize index.{atom,html} to search pages
-rw-r--r--archive.c4
-rw-r--r--archive.h19
-rw-r--r--atom.c32
-rw-r--r--concat.c35
-rw-r--r--html.c43
5 files changed, 93 insertions, 40 deletions
diff --git a/archive.c b/archive.c
index 575bc56..0bee374 100644
--- a/archive.c
+++ b/archive.c
@@ -98,7 +98,7 @@ int main(int argc, char *argv[]) {
 		0 < (opt = getopt(argc, argv, "A:C:H:S:T:a:h:im:p:qs:u:vw:y:"));
 	) {
 		switch (opt) {
-			break; case 'A': concatIndexEntries = strtoul(optarg, NULL, 10);
+			break; case 'A': concatSearchEntries = strtoul(optarg, NULL, 10);
 			break; case 'C': {
 				int error = chdir(optarg);
 				if (error) err(EX_NOINPUT, "%s", optarg);
@@ -260,7 +260,7 @@ concat:;
 	respFree(resp);
 
 	concatThreads(threads, envelopes);
-	concatIndex(threads, envelopes);
+	concatSearch("index", threads, envelopes);
 	fflush(stdout);
 	uidWrite("UIDNEXT", uidNext);
 
diff --git a/archive.h b/archive.h
index 1a94744..3f13109 100644
--- a/archive.h
+++ b/archive.h
@@ -44,6 +44,7 @@
 #define PATH_THREAD "thread/[messageID].[type]"
 #define PATH_ATTACHMENT \
 	"attachment/[messageID]/[section]/[name][disposition][.][subtype]"
+#define PATH_SEARCH "[name].[type]"
 
 #define MBOX_HEADERS \
 	"Date Subject From Sender Reply-To To Cc Bcc " \
@@ -214,13 +215,15 @@ bool exportFetch(FILE *imap, enum Atom tag, struct List threads);
 bool exportData(FILE *imap, enum Atom tag, struct List items);
 
 extern const char *concatHead;
-extern size_t concatIndexEntries;
+extern size_t concatSearchEntries;
 void concatFetch(FILE *imap, enum Atom tag, struct List threads);
 void concatData(
 	struct List threads, struct Envelope *envelopes, struct List items
 );
 void concatThreads(struct List threads, const struct Envelope *envelopes);
-void concatIndex(struct List threads, const struct Envelope *envelopes);
+void concatSearch(
+	const char *name, struct List threads, const struct Envelope *envelopes
+);
 
 int mboxFrom(FILE *file);
 int mboxHeader(FILE *file, const char *header);
@@ -231,8 +234,8 @@ int atomContent(FILE *file, const char *content);
 int atomEntryClose(FILE *file);
 int atomThreadOpen(FILE *file, const struct Envelope *envelope);
 int atomThreadClose(FILE *file);
-int atomIndexOpen(FILE *file);
-int atomIndexClose(FILE *file);
+int atomSearchOpen(FILE *file, const char *name);
+int atomSearchClose(FILE *file);
 
 int htmlMessageOpen(FILE *file, const struct Envelope *envelope, bool nested);
 int htmlInline(FILE *file, const struct BodyPart *part, const char *content);
@@ -247,9 +250,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(
+int htmlSearchHead(FILE *file, const char *name);
+int htmlSearchOpen(FILE *file, const char *name);
+int htmlSearchThread(
 	FILE *file, const struct Envelope *envelope, struct List thread
 );
-int htmlIndexClose(FILE *file);
+int htmlSearchClose(FILE *file);
diff --git a/atom.c b/atom.c
index 14f9d54..a58f71c 100644
--- a/atom.c
+++ b/atom.c
@@ -28,6 +28,7 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sysexits.h>
 #include <time.h>
 
@@ -162,26 +163,43 @@ int atomThreadClose(FILE *file) {
 	return templateRender(file, Q(</feed>), NULL, NULL);
 }
 
-int atomIndexOpen(FILE *file) {
+static char *atomSearchURL(const char *name, const char *type) {
+	struct Variable vars[] = {
+		{ "name", name },
+		{ "type", type },
+		{0},
+	};
+	return templateString("/" PATH_SEARCH, vars, escapeURL);
+}
+
+int atomSearchOpen(FILE *file, const char *name) {
+	char *atom = atomSearchURL(name, "atom");
+	char *html = atomSearchURL(name, "html");
 	const char *template = XML_DECL Q(
 		<feed xmlns="http://www.w3.org/2005/Atom">
 		<generator uri="[generator]">bubger</generator>
-		<id>[base]/</id>
-		<title>[title]</title>
+		<id>[base][atom]</id>
+		<title>[+name][name] - [-][title]</title>
 		<updated>[updated]</updated>
-		<link rel="self" href="[base]/index.atom"/>
-		<link rel="alternate" type="text/html" href="[base]/index.html"/>
+		<link rel="self" href="[base][atom]"/>
+		<link rel="alternate" type="text/html" href="[base][html]"/>
 	);
 	struct Variable vars[] = {
 		{ "generator", GENERATOR_URL },
+		{ "name", (strcmp(name, "index") ? name : NULL) },
 		{ "title", baseTitle },
 		{ "updated", iso8601(time(NULL)).s },
 		{ "base", baseURL },
+		{ "atom", atom },
+		{ "html", html },
 		{0},
 	};
-	return templateRender(file, template, vars, escapeXML);
+	int error = templateRender(file, template, vars, escapeXML);
+	free(atom);
+	free(html);
+	return error;
 }
 
-int atomIndexClose(FILE *file) {
+int atomSearchClose(FILE *file) {
 	return templateRender(file, Q(</feed>), NULL, NULL);
 }
diff --git a/concat.c b/concat.c
index 3e03f3b..82f2c84 100644
--- a/concat.c
+++ b/concat.c
@@ -230,6 +230,15 @@ void concatThreads(struct List threads, const struct Envelope *envelopes) {
 	}
 }
 
+static char *searchPath(const char *name, const char *type) {
+	struct Variable vars[] = {
+		{ "name", name },
+		{ "type", type },
+		{0},
+	};
+	return templateString(PATH_SEARCH, vars, escapePath);
+}
+
 static int numberCompare(const void *_a, const void *_b) {
 	const struct Data *a = _a;
 	const struct Data *b = _b;
@@ -252,20 +261,22 @@ static int sortCompare(const void *_a, const void *_b) {
 	}
 }
 
-size_t concatIndexEntries = 20;
+size_t concatSearchEntries = 20;
 
-void concatIndex(struct List threads, const struct Envelope *envelopes) {
-	const char *path = "index.atom";
+void concatSearch(
+	const char *name, struct List threads, const struct Envelope *envelopes
+) {
+	char *path = searchPath(name, "atom");
 	FILE *file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	int error = atomIndexOpen(file);
+	int error = atomSearchOpen(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	struct List flat = {0};
 	listFlatten(&flat, threads);
 	qsort(flat.ptr, flat.len, sizeof(*flat.ptr), numberCompare);
-	for (size_t i = 0; i < flat.len && i < concatIndexEntries; ++i) {
+	for (size_t i = 0; i < flat.len && i < concatSearchEntries; ++i) {
 		uint32_t uid = dataCheck(flat.ptr[i], Number).number;
 		char *src = uidPath(uid, "atom");
 		error = concatFile(file, src);
@@ -274,9 +285,10 @@ void concatIndex(struct List threads, const struct Envelope *envelopes) {
 	}
 	listFree(flat);
 
-	error = atomIndexClose(file) || fclose(file);
+	error = atomSearchClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
+	free(path);
 
 	struct Sort *order = calloc(threads.len, sizeof(*order));
 	if (!order) err(EX_OSERR, "calloc");
@@ -294,11 +306,11 @@ void concatIndex(struct List threads, const struct Envelope *envelopes) {
 	}
 	qsort(order, threads.len, sizeof(*order), sortCompare);
 
-	path = "index.html";
+	path = searchPath(name, "html");
 	file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	error = htmlIndexHead(file);
+	error = htmlSearchHead(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	if (concatHead) {
@@ -306,18 +318,19 @@ void concatIndex(struct List threads, const struct Envelope *envelopes) {
 		if (error) err(EX_IOERR, "%s", path);
 	}
 
-	error = htmlIndexOpen(file);
+	error = htmlSearchOpen(file, name);
 	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);
+		error = htmlSearchThread(file, envelope, thread);
 		if (error) err(EX_IOERR, "%s", path);
 	}
 	free(order);
 
-	error = htmlIndexClose(file) || fclose(file);
+	error = htmlSearchClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
+	free(path);
 }
diff --git a/html.c b/html.c
index f8f8539..5eb2f29 100644
--- a/html.c
+++ b/html.c
@@ -512,31 +512,46 @@ int htmlThreadClose(FILE *file) {
 		|| htmlFooter(file);
 }
 
-int htmlIndexHead(FILE *file) {
+static char *htmlSearchURL(const char *name, const char *type) {
+	struct Variable vars[] = {
+		{ "name", name },
+		{ "type", type },
+		{0},
+	};
+	return templateString(PATH_SEARCH, vars, escapeURL);
+}
+
+int htmlSearchHead(FILE *file, const char *name) {
+	char *atom = htmlSearchURL(name, "atom");
 	const char *template = Q(
 		<!DOCTYPE html>
 		<meta charset="utf-8">
 		<meta name="generator" content="[generator]">
-		<title>[title]</title>
-		<link rel="alternate" type="application/atom+xml" href="index.atom">
+		<title>[+name][name] - [-][title]</title>
+		<link rel="alternate" type="application/atom+xml" href="[atom]">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0">
 	);
 	struct Variable vars[] = {
 		{ "generator", GENERATOR_URL },
+		{ "name", (strcmp(name, "index") ? name : NULL) },
 		{ "title", baseTitle },
+		{ "atom", atom },
 		{0},
 	};
-	return 0
+	int error = 0
 		|| templateRender(file, template, vars, escapeXML)
 		|| htmlStylesheet(file);
+	free(atom);
+	return error;
 }
 
-int htmlIndexOpen(FILE *file) {
+int htmlSearchOpen(FILE *file, const char *name) {
+	char *atom = htmlSearchURL(name, "atom");
 	const char *template = Q(
 		<header class="index">
-			<h1>[title]</h1>
+			<h1>[+name][name] - [-][title]</h1>
 			<nav>
-				<a href="index.atom">follow</a>
+				<a href="[atom]">follow</a>
 				[+subscribe]
 				<a href="[subscribe]">subscribe</a>
 				[-]
@@ -549,15 +564,19 @@ int htmlIndexOpen(FILE *file) {
 			<ol>
 	);
 	struct Variable vars[] = {
+		{ "name", (strcmp(name, "index") ? name : NULL) },
 		{ "title", baseTitle },
+		{ "atom", atom },
 		{ "subscribe", baseSubscribe },
 		{ "mailto", baseMailto },
 		{0},
 	};
-	return templateRender(file, template, vars, escapeXML);
+	int error = templateRender(file, template, vars, escapeXML);
+	free(atom);
+	return error;
 }
 
-static char *htmlIndexURL(const struct Envelope *envelope) {
+static char *htmlSearchThreadURL(const struct Envelope *envelope) {
 	struct Variable vars[] = {
 		{ "messageID", envelope->messageID },
 		{ "type", "html" },
@@ -566,10 +585,10 @@ static char *htmlIndexURL(const struct Envelope *envelope) {
 	return templateString(PATH_THREAD, vars, escapeURL);
 }
 
-int htmlIndexThread(
+int htmlSearchThread(
 	FILE *file, const struct Envelope *envelope, struct List thread
 ) {
-	char *url = htmlIndexURL(envelope);
+	char *url = htmlSearchThreadURL(envelope);
 	const char *template = Q(
 		<li>
 			<h2 class="Subject"><a href="[url]">[subject]</a></h2>
@@ -594,7 +613,7 @@ int htmlIndexThread(
 	return error;
 }
 
-int htmlIndexClose(FILE *file) {
+int htmlSearchClose(FILE *file) {
 	return 0
 		|| templateRender(file, Q(</ol></main>), NULL, NULL)
 		|| htmlFooter(file);