From 0dbf097da16a5c27ca87d21aa0cb2bdbf1fb8154 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Wed, 29 Apr 2020 12:55:28 -0400 Subject: Turn URLs into HTML links --- html.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index 5147798..850e070 100644 --- a/html.c +++ b/html.c @@ -14,6 +14,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -213,6 +214,48 @@ static int htmlInlineAttrs(FILE *file, const struct BodyPart *part) { return 0; } +static void swap(char *a, char *b) { + char ch = *a; + *a = *b; + *b = ch; +} + +static int htmlMarkupURLs(FILE *file, char *buf) { + static const char *Pattern = "(^|[[:space:]<])(https?:[^[:space:]>]+)(.|$)"; + static regex_t regex; + if (!regex.re_nsub) { + int error = regcomp(®ex, Pattern, REG_EXTENDED); + if (error) { + char buf[256]; + regerror(error, ®ex, buf, sizeof(buf)); + errx(EX_SOFTWARE, "%s: %s", buf, Pattern); + } + } + + int error; + char *ptr; + regmatch_t match[4]; + for (ptr = buf; !regexec(®ex, ptr, 4, match, 0); ptr += match[2].rm_eo) { + char nul = '\0'; + + swap(&ptr[match[2].rm_so], &nul); + error = escapeXML(file, ptr); + if (error) return error; + swap(&ptr[match[2].rm_so], &nul); + + const char *template = TEMPLATE([url]); + swap(&ptr[match[3].rm_so], &nul); + struct Variable vars[] = { + { "url", &ptr[match[2].rm_so] }, + {0}, + }; + error = templateRender(file, template, vars, escapeXML); + if (error) return error; + swap(&ptr[match[3].rm_so], &nul); + } + return escapeXML(file, ptr); +} + static int htmlMarkup(FILE *file, const char *content) { int error = 0; size_t cap = 0; @@ -240,24 +283,30 @@ static int htmlMarkup(FILE *file, const char *content) { if (patch && !strncmp(buf, "@@", 2)) { error = templateRender( - file, TEMPLATE([line]) "\n", vars, escapeXML + file, TEMPLATE([line]), vars, escapeXML ); } else if (patch && buf[0] == '-' && strncmp(buf, "---", 3)) { error = templateRender( - file, TEMPLATE([line]) "\n", vars, escapeXML + file, TEMPLATE([line]), vars, escapeXML ); } else if (patch && buf[0] == '+' && strncmp(buf, "+++", 3)) { error = templateRender( - file, TEMPLATE([line]) "\n", vars, escapeXML + file, TEMPLATE([line]), vars, escapeXML ); + } else if (patch) { + error = escapeXML(file, buf); } else if (buf[0] == '>') { - error = templateRender( - file, TEMPLATE([line]) "\n", vars, escapeXML - ); + error = 0 + || templateRender(file, TEMPLATE(), NULL, NULL) + || htmlMarkupURLs(file, buf) + || templateRender(file, TEMPLATE(), NULL, NULL); } else { - error = templateRender(file, "[line]\n", vars, escapeXML); + error = htmlMarkupURLs(file, buf); } if (error) break; + + error = templateRender(file, "\n", NULL, NULL); + if (error) break; } free(buf); return error; -- cgit 1.4.1