summary refs log tree commit diff
path: root/html.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-07-12 19:58:20 -0400
committerJune McEnroe <june@causal.agency>2020-07-12 19:58:20 -0400
commit984faba65ba6f8aa7f35e0caf530bc15609935d8 (patch)
tree61346817d512c1039a31f38d1db597d4428952f8 /html.c
parentRender all types of events (diff)
downloadscooper-984faba65ba6f8aa7f35e0caf530bc15609935d8.tar.gz
scooper-984faba65ba6f8aa7f35e0caf530bc15609935d8.zip
Linkify IRC messages
Diffstat (limited to 'html.c')
-rw-r--r--html.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/html.c b/html.c
index 2d987f8..ae4c76f 100644
--- a/html.c
+++ b/html.c
@@ -14,10 +14,13 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
 #include <err.h>
 #include <inttypes.h>
+#include <regex.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sysexits.h>
 #include <time.h>
 
@@ -389,9 +392,39 @@ htmlEvent(struct khtmlreq *html, struct Scope scope, struct Event event) {
 		|| khtml_closeelem(html, 1);
 }
 
+enum kcgi_err linkify(struct khtmlreq *html, const char *str, size_t len) {
+	static const char *Pattern = "https?://([^[:space:]>\"()]|[(][^)]*[)])+";
+	static regex_t regex;
+	if (!regex.re_nsub) {
+		int error = regcomp(&regex, Pattern, REG_EXTENDED);
+		assert(!error);
+	}
+
+	regmatch_t match = {0};
+	while (!regexec(&regex, str, 1, &match, 0)) {
+		if ((size_t)match.rm_eo > len) break;
+
+		char *href = strndup(&str[match.rm_so], match.rm_eo - match.rm_so);
+		if (!href) err(EX_OSERR, "strndup");
+
+		enum kcgi_err error = 0
+			|| khtml_write(str, match.rm_so, html)
+			|| khtml_attr(html, KELEM_A, KATTR_HREF, href, KATTR__MAX)
+			|| khtml_write(&str[match.rm_so], match.rm_eo - match.rm_so, html)
+			|| khtml_closeelem(html, 1);
+		free(href);
+		if (error) return error;
+
+		str += match.rm_eo;
+		len -= match.rm_eo;
+	}
+	if (len) return khtml_write(str, len, html);
+	return KCGI_OK;
+}
+
 enum kcgi_err htmlIRC(struct khtmlreq *html, const char *str) {
 	return 0
 		|| khtml_attr(html, KELEM_SPAN, KATTR_CLASS, "irc", KATTR__MAX)
-		|| khtml_puts(html, str)
+		|| linkify(html, str, strlen(str))
 		|| khtml_closeelem(html, 1);
 }