about summary refs log tree commit diff
path: root/html.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-04-09 20:24:45 -0400
committerJune McEnroe <june@causal.agency>2020-04-09 20:24:45 -0400
commita0a148b1c3ba5ffd4ccd6ee52607629bc58875d0 (patch)
tree9c70d51767187802e71afb54dbad0a61675dd56c /html.c
parentRender basic HTML envelopes with templating (diff)
downloadbubger-a0a148b1c3ba5ffd4ccd6ee52607629bc58875d0.tar.gz
bubger-a0a148b1c3ba5ffd4ccd6ee52607629bc58875d0.zip
Render escaped mailto URL
Diffstat (limited to 'html.c')
-rw-r--r--html.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/html.c b/html.c
index 4903c5b..50a8378 100644
--- a/html.c
+++ b/html.c
@@ -14,6 +14,7 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <err.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -23,47 +24,57 @@
 
 #include "archive.h"
 
-static int htmlEscape(FILE *file, const char *str) {
-	while (*str) {
-		int n = 0;
-		switch (*str) {
-			break; case '"': n = fprintf(file, "&quot;"); str++;
-			break; case '&': n = fprintf(file, "&amp;"); str++;
-			break; case '<': n = fprintf(file, "&lt;"); str++;
-			break; case '>': n = fprintf(file, "&gt;"); str++;
-		}
-		if (n < 0) return n;
-		size_t len = strcspn(str, "\"&<>");
-		if (len) {
-			size_t n = fwrite(str, len, 1, file);
-			if (!n) return -1;
-		}
-		str += len;
-	}
-	return 0;
-}
+static const char *Mailto = {
+	"mailto:[mailbox]@[host]?subject=[re][subject]&In-Reply-To=[messageID]"
+};
 
-static const char *Summary = TEMPLATE(
+static const char *Envelope = TEMPLATE(
 	<details id="[messageID]">
 	<summary>
 		<h1><a href="#[messageID]">[subject]</a></h1>
 		<address>
-			<a href="mailto:[from.mailbox]@[from.host]">[from.name]</a>
+			<a href="[mailto]">[from]</a>
 		</address>
 	</summary>
 );
 
 int htmlEnvelope(FILE *file, const struct Envelope *envelope) {
-	const char *fromName = envelope->from.name;
-	if (!fromName) fromName = envelope->from.mailbox;
+	struct Variable mailtoVars[] = {
+		{ "mailbox", envelope->from.mailbox },
+		{ "host", envelope->from.host },
+		{ "re", (strncmp(envelope->subject, "Re: ", 4) ? "Re: " : "") },
+		{ "subject", envelope->subject },
+		{ "messageID", envelope->messageID },
+		{0},
+	};
+
+	size_t cap = sizeof(Mailto);
+	for (struct Variable *var = mailtoVars; var->value; ++var) {
+		cap += ESCAPE_URL_CAP(strlen(var->value));
+	}
+	char *mailto = malloc(cap);
+	if (!mailto) err(EX_OSERR, "malloc");
+
+	FILE *url = fmemopen(mailto, cap, "w");
+	if (!url) err(EX_OSERR, "fmemopen");
+
+	int error = 0
+		|| templateRender(url, Mailto, mailtoVars, escapeURL)
+		|| fclose(url);
+	assert(!error);
+
+	const char *from = envelope->from.name;
+	if (!from) from = envelope->from.mailbox;
 
 	struct Variable vars[] = {
-		{ "subject", envelope->subject },
-		{ "from.name", fromName },
-		{ "from.mailbox", envelope->from.mailbox },
-		{ "from.host", envelope->from.host },
 		{ "messageID", envelope->messageID },
+		{ "subject", envelope->subject },
+		{ "mailto", mailto },
+		{ "from", from },
 		{0},
 	};
-	return templateRender(file, Summary, vars, htmlEscape);
+	error = templateRender(file, Envelope, vars, escapeXML);
+
+	free(mailto);
+	return error;
 }