about summary refs log tree commit diff
path: root/atom.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-04-13 15:21:32 -0400
committerJune McEnroe <june@causal.agency>2020-04-13 15:21:32 -0400
commitcdd739f0a31f08ff9dbb0bfa7796e271bc9fb58d (patch)
treea031262d3e705a1df92ec5912e4e09f8ed363d42 /atom.c
parentUse <content type="text"> in Atom (diff)
downloadbubger-cdd739f0a31f08ff9dbb0bfa7796e271bc9fb58d.tar.gz
bubger-cdd739f0a31f08ff9dbb0bfa7796e271bc9fb58d.zip
Add <link> elements in Atom
Diffstat (limited to 'atom.c')
-rw-r--r--atom.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/atom.c b/atom.c
index d3463ce..0572cab 100644
--- a/atom.c
+++ b/atom.c
@@ -22,6 +22,8 @@
 
 #include "archive.h"
 
+const char *atomBaseURL;
+
 static char *atomID(const struct Envelope *envelope) {
 	struct Variable vars[] = {
 		{ "messageID", envelope->messageID },
@@ -47,27 +49,39 @@ static int atomAuthor(FILE *file, struct Address addr) {
 	return templateRender(file, template, vars, escapeXML);
 }
 
+static char *atomEntryURL(const struct Envelope *envelope) {
+	struct Variable vars[] = {
+		{ "name", pathMangle(envelope->messageID) },
+		{0},
+	};
+	return templateURL("/message/[name].mbox", vars);
+}
+
 int atomEntryOpen(FILE *file, const struct Envelope *envelope) {
-	// TODO: <link> to corresponding mbox, needs base URL.
 	const char *template = TEMPLATE(
 		<entry>
 		<id>[id]</id>
 		<title>[title]</title>
 		<updated>[updated]</updated>
+		<link rel="alternate" type="application/mbox" href="[base][url]"/>
 	);
 	char *id = atomID(envelope);
 	char updated[sizeof("0000-00-00T00:00:00Z")];
 	strftime(updated, sizeof(updated), "%FT%TZ", gmtime(&envelope->time));
+	char *url = atomEntryURL(envelope);
 	struct Variable vars[] = {
 		{ "id", id },
 		{ "title", envelope->subject },
 		{ "updated", updated },
+		{ "base", (atomBaseURL ? atomBaseURL : "") },
+		{ "url", url },
 		{0},
 	};
 	int error = 0
 		|| templateRender(file, template, vars, escapeXML)
 		|| atomAuthor(file, envelope->from);
 	free(id);
+	free(url);
 	return error;
 }
 
@@ -83,30 +97,51 @@ int atomEntryClose(FILE *file) {
 	return templateRender(file, TEMPLATE(</entry>), NULL, NULL);
 }
 
+static char *atomFeedURL(const struct Envelope *envelope, const char *type) {
+	struct Variable vars[] = {
+		{ "name", pathMangle(envelope->messageID) },
+		{ "type", type },
+		{0},
+	};
+	return templateURL("/thread/[name].[type]", vars);
+}
+
 int atomFeedOpen(FILE *file, const struct Envelope *envelope) {
-	// TODO: <link> to the corresponding HTML, mbox.
 	const char *template = TEMPLATE(
 		<[q]xml version="1.0" encoding="utf-8"[q]>
 		<feed xmlns="http://www.w3.org/2005/Atom">
 		<id>[id]</id>
 		<title>[title]</title>
 		<updated>[updated]</updated>
+		<link rel="self" href="[base][atom]"/>
+		<link rel="alternate" type="text/html" href="[base][html]"/>
+		<link rel="alternate" type="application/mbox" href="[base][mbox]"/>
 	);
 	char *id = atomID(envelope);
 	time_t now = time(NULL);
 	char updated[sizeof("0000-00-00T00:00:00Z")];
 	strftime(updated, sizeof(updated), "%FT%TZ", gmtime(&now));
+	char *atom = atomFeedURL(envelope, "atom");
+	char *html = atomFeedURL(envelope, "html");
+	char *mbox = atomFeedURL(envelope, "mbox");
 	struct Variable vars[] = {
 		{ "q", "?" },
 		{ "id", id },
 		{ "title", envelope->subject },
 		{ "updated", updated },
+		{ "base", (atomBaseURL ? atomBaseURL : "") },
+		{ "atom", atom },
+		{ "html", html },
+		{ "mbox", mbox },
 		{0},
 	};
 	int error = 0
 		|| templateRender(file, template, vars, escapeXML)
 		|| atomAuthor(file, envelope->from);
 	free(id);
+	free(atom);
+	free(html);
+	free(mbox);
 	return error;
 }