# HG changeset patch # User David Demelier # Date 1616936576 -7200 # Node ID 330a5db51c627e59b928c1b096df70597b5d5f1c # Parent 06b35c32a1796d6df8beb569096de2d81bfb6da6 plugin links: remove basic entities diff -r 06b35c32a179 -r 330a5db51c62 plugins/links/links.c --- a/plugins/links/links.c Tue Mar 02 20:03:00 2021 +0100 +++ b/plugins/links/links.c Sun Mar 28 15:02:56 2021 +0200 @@ -65,6 +65,18 @@ [TPL_INFO] = "link from #{nickname}: #{title}" }; +static const struct { + const char *key; + int repl; +} entities[] = { + { "quot", '"' }, + { "amp", '&' }, + { "apos", '\'' }, + { "lt", '<' }, + { "gt", '>' }, + { NULL, 0 } +}; + static size_t callback(char *ptr, size_t size, size_t nmemb, struct req *req) { @@ -76,7 +88,7 @@ return size * nmemb; } -static const char * +static char * parse(struct req *req) { regex_t regex; @@ -96,10 +108,67 @@ return ret; } +static int +find_entity(const char *key) +{ + for (size_t i = 0; entities[i].key; ++i) + if (strcmp(entities[i].key, key) == 0) + return entities[i].repl; + + return EOF; +} + static const char * -fmt(const struct req *req, const char *title) +untitle(char *title) +{ + static char ret[256] = {0}; + char *save; + int repl; + FILE *fp = NULL; + + if (!(fp = fmemopen(ret, sizeof (ret) - 1, "w"))) + goto fallback; + + for (char *p = title; *p; ) { + /* Standard character. */ + if (*p != '&') { + if (fputc(*p++, fp) == EOF) + goto fallback; + + continue; + } + + /* HTML entity. */ + save = ++p; + + while (*p && *p != ';') + ++p; + + /* Found an entity. */ + if (*p == ';') { + *p++ = '\0'; + + if ((repl = find_entity(save)) != EOF) + fputc(repl, fp); + } + } + + fclose(fp); + + return ret; + +fallback: + if (fp) + fclose(fp); + + return title; +} + +static const char * +fmt(const struct req *req, char *title) { static char line[IRC_MESSAGE_LEN]; + struct irc_subst subst = { .time = time(NULL), .flags = IRC_SUBST_DATE | IRC_SUBST_KEYWORDS | IRC_SUBST_IRC_ATTRS, @@ -108,7 +177,7 @@ { "nickname", req->nickname }, { "origin", req->origin }, { "server", req->server->name }, - { "title", title } + { "title", untitle(title) } }, .keywordsz = 5 }; @@ -124,7 +193,7 @@ static void complete(struct req *req) { - const char *title; + char *title; if (req->status && (title = parse(req))) irc_server_message(req->server, req->chan, fmt(req, title));