summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--archive.c9
-rw-r--r--bubger.12
-rw-r--r--export.c10
-rw-r--r--html.c4
5 files changed, 23 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index e96af27..b29b2c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,3 @@
 *.o
-UID/
-UIDNEXT
-UIDVALIDITY
 bubger
 tags
diff --git a/archive.c b/archive.c
index 97bb99a..350fdfa 100644
--- a/archive.c
+++ b/archive.c
@@ -47,6 +47,11 @@ static void uidWrite(const char *path, uint32_t uid) {
 	if (error) err(EX_IOERR, "%s", path);
 }
 
+static void createDir(const char *path) {
+	int error = mkdir(path, 0775);
+	if (error && errno != EEXIST) err(EX_CANTCREAT, "%s", path);
+}
+
 int main(int argc, char *argv[]) {
 	const char *host = NULL;
 	const char *port = "imaps";
@@ -166,8 +171,8 @@ int main(int argc, char *argv[]) {
 			if (!resp.data.len) {
 				errx(EX_TEMPFAIL, "no messages matching %s", search);
 			}
-			int error = mkdir("UID", 0775);
-			if (error && errno != EEXIST) err(EX_CANTCREAT, "UID");
+			createDir("UID");
+			createDir("message");
 			export = exportThreads(imap, resp.data);
 		}
 
diff --git a/bubger.1 b/bubger.1
index db93077..932e6bc 100644
--- a/bubger.1
+++ b/bubger.1
@@ -108,6 +108,8 @@ Stores the mailbox UID validity.
 Stores the next UID of the mailbox.
 .It Pa UID/*.atom , Pa UID/*.html , Pa UID/*.mbox
 Cached Atom, HTML and mboxrd fragments for each message.
+.It Pa message/*.mbox
+Rendered mboxrd files for each message.
 .It Pa thread/*.atom , Pa thread/*.html , Pa thread/*.mbox
 Rendered Atom, HTML and mboxrd files for each thread.
 .El
diff --git a/export.c b/export.c
index 3e87521..b1f63b8 100644
--- a/export.c
+++ b/export.c
@@ -34,6 +34,12 @@ static const char *uidPath(uint32_t uid, const char *type) {
 	return buf;
 }
 
+static const char *messagePath(const char *messageID, const char *type) {
+	static char buf[PATH_MAX];
+	snprintf(buf, sizeof(buf), "message/%s.%s", messageID, type);
+	return buf;
+}
+
 static void flatten(struct List *flat, struct List nested) {
 	for (size_t i = 0; i < nested.len; ++i) {
 		if (nested.ptr[i].type == List) {
@@ -253,6 +259,10 @@ void exportData(struct List items) {
 		|| fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 
+	const char *dest = messagePath(envelope.messageID, "mbox");
+	error = link(path, dest);
+	if (error) err(EX_CANTCREAT, "%s", dest);
+
 	path = uidPath(uid, "html");
 	file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
diff --git a/html.c b/html.c
index 8aa872d..14a4be9 100644
--- a/html.c
+++ b/html.c
@@ -65,6 +65,7 @@ int htmlEnvelope(FILE *file, const struct Envelope *envelope) {
 		"mailto:[mailbox]@[host]?subject=[re][subject]&In-Reply-To=[messageID]",
 		urlVars
 	);
+	char *mbox = templateURL("../message/[messageID].mbox", urlVars);
 
 	char date[256];
 	char utc[sizeof("0000-00-00T00:00:00Z")];
@@ -78,6 +79,7 @@ int htmlEnvelope(FILE *file, const struct Envelope *envelope) {
 		{ "from", addressName(envelope->from) },
 		{ "date", date },
 		{ "utc", utc },
+		{ "mbox", mbox },
 		{0},
 	};
 	const char *Summary = TEMPLATE(
@@ -86,11 +88,13 @@ int htmlEnvelope(FILE *file, const struct Envelope *envelope) {
 			<h1 class="subject"><a href="[fragment]">[subject]</a></h1>
 			<address class="from"><a href="[mailto]">[from]</a></address>
 			<time datetime="[utc]">[date]</time>
+			<a class="mbox" href="[mbox]">mbox</a>
 		</summary>
 	);
 	int error = templateRender(file, Summary, vars, escapeXML);
 	free(fragment);
 	free(mailto);
+	free(mbox);
 	if (error) return error;
 
 	return 0