summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--html.c97
-rw-r--r--xs.h15
2 files changed, 71 insertions, 41 deletions
diff --git a/html.c b/html.c
index 13c8e8b..4541571 100644
--- a/html.c
+++ b/html.c
@@ -105,7 +105,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
105 105
106 { 106 {
107 xs *s1 = xs_fmt("<a href=\"%s\" class=\"p-author h-card snac-author\">%s</a>", 107 xs *s1 = xs_fmt("<a href=\"%s\" class=\"p-author h-card snac-author\">%s</a>",
108 xs_dict_get(actor, "id"), name); 108 xs_dict_get(actor, "id"), xs_encode_html(name));
109 s = xs_str_cat(s, s1); 109 s = xs_str_cat(s, s1);
110 } 110 }
111 111
@@ -139,7 +139,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
139 139
140 xs *s1 = xs_fmt( 140 xs *s1 = xs_fmt(
141 "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n", 141 "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n",
142 date_title, date_label); 142 xs_encode_html(date_title), xs_encode_html(date_label));
143 143
144 s = xs_str_cat(s, s1); 144 s = xs_str_cat(s, s1);
145 } 145 }
@@ -164,7 +164,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
164 164
165 s1 = xs_fmt( 165 s1 = xs_fmt(
166 "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>", 166 "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>",
167 xs_dict_get(actor, "id"), user); 167 xs_dict_get(actor, "id"), xs_encode_html(user));
168 168
169 s = xs_str_cat(s, s1); 169 s = xs_str_cat(s, s1);
170 } 170 }
@@ -245,9 +245,9 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
245 245
246 { 246 {
247 xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n", 247 xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n",
248 xs_dict_get(snac->config, "name"), 248 xs_encode_html(xs_dict_get(snac->config, "name")),
249 snac->uid, 249 xs_encode_html(snac->uid),
250 xs_dict_get(srv_config, "host")); 250 xs_encode_html(xs_dict_get(srv_config, "host")));
251 251
252 s = xs_str_cat(s, s1); 252 s = xs_str_cat(s, s1);
253 } 253 }
@@ -284,18 +284,18 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
284 "<meta property=\"og:image\" content=\"%s\"/>\n" 284 "<meta property=\"og:image\" content=\"%s\"/>\n"
285 "<meta property=\"og:image:width\" content=\"300\"/>\n" 285 "<meta property=\"og:image:width\" content=\"300\"/>\n"
286 "<meta property=\"og:image:height\" content=\"300\"/>\n", 286 "<meta property=\"og:image:height\" content=\"300\"/>\n",
287 xs_dict_get(srv_config, "host"), 287 xs_encode_html(xs_dict_get(srv_config, "host")),
288 xs_dict_get(snac->config, "name"), 288 xs_encode_html(xs_dict_get(snac->config, "name")),
289 snac->uid, 289 xs_encode_html(snac->uid),
290 xs_dict_get(srv_config, "host"), 290 xs_encode_html(xs_dict_get(srv_config, "host")),
291 s_bio, 291 xs_encode_html(s_bio),
292 s_avatar); 292 xs_encode_html(s_avatar));
293 s = xs_str_cat(s, s1); 293 s = xs_str_cat(s, s1);
294 } 294 }
295 295
296 { 296 {
297 xs *s1 = xs_fmt("<link rel=\"alternate\" type=\"application/rss+xml\" " 297 xs *s1 = xs_fmt("<link rel=\"alternate\" type=\"application/rss+xml\" "
298 "title=\"RSS\" href=\"%s.rss\" />\n", snac->actor); 298 "title=\"RSS\" href=\"%s.rss\" />\n", snac->actor); /* snac->actor is likely need to be URLEncoded. */
299 s = xs_str_cat(s, s1); 299 s = xs_str_cat(s, s1);
300 } 300 }
301 301
@@ -355,16 +355,16 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
355 "<p class=\"snac-top-user-id\">@%s@%s</p>\n"; 355 "<p class=\"snac-top-user-id\">@%s@%s</p>\n";
356 356
357 xs *s1 = xs_fmt(_tmpl, 357 xs *s1 = xs_fmt(_tmpl,
358 xs_dict_get(snac->config, "name"), 358 xs_encode_html(xs_dict_get(snac->config, "name")),
359 xs_dict_get(snac->config, "uid"), xs_dict_get(srv_config, "host") 359 xs_encode_html(xs_dict_get(snac->config, "uid")), xs_encode_html(xs_dict_get(srv_config, "host"))
360 ); 360 );
361 361
362 s = xs_str_cat(s, s1); 362 s = xs_str_cat(s, s1);
363 363
364 if (local) { 364 if (local) {
365 xs *bio1 = not_really_markdown(xs_dict_get(snac->config, "bio"), NULL); 365 xs *bio1 = not_really_markdown(xs_encode_html(xs_dict_get(snac->config, "bio")), NULL);
366 xs *tags = xs_list_new(); 366 xs *tags = xs_list_new();
367 xs *bio2 = process_tags(snac, bio1, &tags); 367 xs *bio2 = xs_encode_html(process_tags(snac, bio1, &tags));
368 xs *s1 = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2); 368 xs *s1 = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2);
369 369
370 s = xs_str_cat(s, s1); 370 s = xs_str_cat(s, s1);
@@ -914,7 +914,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
914 xs *s1 = xs_fmt( 914 xs *s1 = xs_fmt(
915 "<div class=\"snac-origin\">" 915 "<div class=\"snac-origin\">"
916 "<a href=\"%s\">%s</a> %s</a></div>", 916 "<a href=\"%s\">%s</a> %s</a></div>",
917 snac->actor, xs_dict_get(snac->config, "name"), L("boosted") 917 snac->actor, xs_encode_html(xs_dict_get(snac->config, "name")), L("boosted")
918 ); 918 );
919 919
920 s = xs_str_cat(s, s1); 920 s = xs_str_cat(s, s1);
@@ -928,7 +928,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
928 "<div class=\"snac-origin\">" 928 "<div class=\"snac-origin\">"
929 "<a href=\"%s\">%s</a> %s</div>\n", 929 "<a href=\"%s\">%s</a> %s</div>\n",
930 xs_dict_get(actor_r, "id"), 930 xs_dict_get(actor_r, "id"),
931 name, 931 xs_encode_html(name),
932 L("boosted") 932 L("boosted")
933 ); 933 );
934 934
@@ -967,7 +967,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
967 char *cw = xs_dict_get(snac->config, "cw"); 967 char *cw = xs_dict_get(snac->config, "cw");
968 if (xs_is_null(cw) || local) 968 if (xs_is_null(cw) || local)
969 cw = ""; 969 cw = "";
970 xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, v, L("SENSITIVE CONTENT")); 970 xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, xs_encode_html(v), L("SENSITIVE CONTENT"));
971 s = xs_str_cat(s, s1); 971 s = xs_str_cat(s, s1);
972 sensitive = 1; 972 sensitive = 1;
973 } 973 }
@@ -1049,7 +1049,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
1049 1049
1050 if (name && replies) { 1050 if (name && replies) {
1051 int nr = xs_number_get(xs_dict_get(replies, "totalItems")); 1051 int nr = xs_number_get(xs_dict_get(replies, "totalItems"));
1052 xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", name, nr); 1052 xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", xs_encode_html(name), nr);
1053 1053
1054 c = xs_str_cat(c, l); 1054 c = xs_str_cat(c, l);
1055 } 1055 }
@@ -1073,7 +1073,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
1073 xs *opt = xs_fmt("<input type=\"%s\"" 1073 xs *opt = xs_fmt("<input type=\"%s\""
1074 " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n", 1074 " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n",
1075 !xs_is_null(oo) ? "radio" : "checkbox", 1075 !xs_is_null(oo) ? "radio" : "checkbox",
1076 name, name, name); 1076 xs_encode_html(name), xs_encode_html(name), xs_encode_html(name));
1077 1077
1078 s1 = xs_str_cat(s1, opt); 1078 s1 = xs_str_cat(s1, opt);
1079 } 1079 }
@@ -1107,7 +1107,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
1107 /* skip leading zeros */ 1107 /* skip leading zeros */
1108 for (; *p == '0' || *p == ':'; p++); 1108 for (; *p == '0' || *p == ':'; p++);
1109 1109
1110 xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), p); 1110 xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), xs_encode_html(p));
1111 c = xs_str_cat(c, s1); 1111 c = xs_str_cat(c, s1);
1112 } 1112 }
1113 } 1113 }
@@ -1136,7 +1136,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
1136 1136
1137 if (xs_startswith(t, "image/")) { 1137 if (xs_startswith(t, "image/")) {
1138 char *url = xs_dict_get(v, "url"); 1138 char *url = xs_dict_get(v, "url");
1139 char *name = xs_dict_get(v, "name"); 1139 char *name = xs_encode_html(xs_dict_get(v, "name"));
1140 1140
1141 if (url != NULL) { 1141 if (url != NULL) {
1142 if (xs_is_null(name)) 1142 if (xs_is_null(name))
@@ -1151,9 +1151,31 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
1151 else 1151 else
1152 if (xs_startswith(t, "video/")) { 1152 if (xs_startswith(t, "video/")) {
1153 char *url = xs_dict_get(v, "url"); 1153 char *url = xs_dict_get(v, "url");
1154 char *name = xs_encode_html(xs_dict_get(v, "name"));
1154 1155
1155 if (url != NULL) { 1156 if (url != NULL) {
1156 xs *s1 = xs_fmt("<object data=\"%s\"></object>\n", url); 1157 xs *s1 = xs_fmt("<video style=\"max-width: 90vw; max-height: 70vh;\" controls src=\"%s\">Video: <a href=\"%s\">%s</a></video>\n", url, url, name ? name : "No description.");
1158
1159 s = xs_str_cat(s, s1);
1160 }
1161 }
1162 else
1163 if (xs_startswith(t, "audio/")) {
1164 char *url = xs_dict_get(v, "url");
1165 char *name = xs_encode_html(xs_dict_get(v, "name"));
1166
1167 if (url != NULL) {
1168 xs *s1 = xs_fmt("<audio style=\"max-width: 90vw\" controls src=\"%s\">Audio: <a href=\"%s\">%s</a></audio>\n", url, url, name ? name : "No description.");
1169
1170 s = xs_str_cat(s, s1);
1171 }
1172 }
1173 else {
1174 char *url = xs_dict_get(v, "url");
1175 char *name = xs_encode_html(xs_dict_get(v, "name"));
1176
1177 if (url != NULL) {
1178 xs *s1 = xs_fmt("<a href=\"%s\">Attachment: %s</a>", url, name ? name : "No description");
1157 1179
1158 s = xs_str_cat(s, s1); 1180 s = xs_str_cat(s, s1);
1159 } 1181 }
@@ -1327,7 +1349,7 @@ xs_str *html_timeline(snac *snac, const xs_list *list, int local, int skip, int
1327d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t) 1349d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t)
1328{ 1350{
1329 xs *s = xs_str_new(NULL); 1351 xs *s = xs_str_new(NULL);
1330 xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", header); 1352 xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", xs_encode_html(header));
1331 char *p, *actor_id; 1353 char *p, *actor_id;
1332 1354
1333 s = xs_str_cat(s, h); 1355 s = xs_str_cat(s, h);
@@ -1357,7 +1379,7 @@ d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *heade
1357 if (xs_startswith(sc, "<p>")) 1379 if (xs_startswith(sc, "<p>"))
1358 s = xs_str_cat(s, sc); 1380 s = xs_str_cat(s, sc);
1359 else { 1381 else {
1360 xs *s1 = xs_fmt("<p>%s</p>", sc); 1382 xs *s1 = xs_fmt("<p>%s</p>", xs_encode_html(sc));
1361 s = xs_str_cat(s, s1); 1383 s = xs_str_cat(s, s1);
1362 } 1384 }
1363 1385
@@ -1529,7 +1551,7 @@ xs_str *html_notifications(snac *snac)
1529 1551
1530 xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n" 1552 xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n"
1531 "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n", 1553 "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n",
1532 label, actor_id, a_name); 1554 xs_encode_html(label), actor_id, xs_encode_html(a_name));
1533 s = xs_str_cat(s, s1); 1555 s = xs_str_cat(s, s1);
1534 1556
1535 if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) { 1557 if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) {
@@ -1754,9 +1776,6 @@ int html_get_handler(const xs_dict *req, const char *q_path,
1754 xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL); 1776 xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL);
1755 char *p, *v; 1777 char *p, *v;
1756 1778
1757 /* escape tags */
1758 bio = xs_replace_i(bio, "<", "&lt;");
1759 bio = xs_replace_i(bio, ">", "&gt;");
1760 1779
1761 rss = xs_fmt( 1780 rss = xs_fmt(
1762 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 1781 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -1766,11 +1785,11 @@ int html_get_handler(const xs_dict *req, const char *q_path,
1766 "<language>en</language>\n" 1785 "<language>en</language>\n"
1767 "<link>%s.rss</link>\n" 1786 "<link>%s.rss</link>\n"
1768 "<description>%s</description>\n", 1787 "<description>%s</description>\n",
1769 xs_dict_get(snac.config, "name"), 1788 xs_encode_html(xs_dict_get(snac.config, "name")),
1770 snac.uid, 1789 xs_encode_html(snac.uid),
1771 xs_dict_get(srv_config, "host"), 1790 xs_encode_html(xs_dict_get(srv_config, "host")),
1772 snac.actor, 1791 snac.actor,
1773 bio 1792 xs_encode_html(bio)
1774 ); 1793 );
1775 1794
1776 p = elems; 1795 p = elems;
@@ -1785,14 +1804,10 @@ int html_get_handler(const xs_dict *req, const char *q_path,
1785 if (!xs_startswith(id, snac.actor)) 1804 if (!xs_startswith(id, snac.actor))
1786 continue; 1805 continue;
1787 1806
1788 xs *content = sanitize(xs_dict_get(msg, "content")); 1807 xs *content = xs_encode_html(sanitize(xs_dict_get(msg, "content")));
1789 xs *title = xs_str_new(NULL); 1808 xs *title = xs_str_new(NULL);
1790 int i; 1809 int i;
1791 1810
1792 /* escape tags */
1793 content = xs_replace_i(content, "<", "&lt;");
1794 content = xs_replace_i(content, ">", "&gt;");
1795
1796 for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++) 1811 for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++)
1797 title = xs_append_m(title, &content[i], 1); 1812 title = xs_append_m(title, &content[i], 1);
1798 1813
@@ -1802,7 +1817,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
1802 "<link>%s</link>\n" 1817 "<link>%s</link>\n"
1803 "<description>%s</description>\n" 1818 "<description>%s</description>\n"
1804 "</item>\n", 1819 "</item>\n",
1805 title, id, content 1820 xs_encode_html(title), id, xs_encode_html(content)
1806 ); 1821 );
1807 1822
1808 rss = xs_str_cat(rss, s); 1823 rss = xs_str_cat(rss, s);
diff --git a/xs.h b/xs.h
index ad8a35d..6bf3eb8 100644
--- a/xs.h
+++ b/xs.h
@@ -72,6 +72,7 @@ xs_str *xs_replace_in(xs_str *str, const char *sfrom, const char *sto, int times
72xs_str *xs_fmt(const char *fmt, ...); 72xs_str *xs_fmt(const char *fmt, ...);
73int xs_str_in(const char *haystack, const char *needle); 73int xs_str_in(const char *haystack, const char *needle);
74int _xs_startsorends(const char *str, const char *xfix, int ends); 74int _xs_startsorends(const char *str, const char *xfix, int ends);
75xs_str *xs_encode_html(const xs_str *str);
75#define xs_startswith(str, prefix) _xs_startsorends(str, prefix, 0) 76#define xs_startswith(str, prefix) _xs_startsorends(str, prefix, 0)
76#define xs_endswith(str, postfix) _xs_startsorends(str, postfix, 1) 77#define xs_endswith(str, postfix) _xs_startsorends(str, postfix, 1)
77xs_str *xs_crop_i(xs_str *str, int start, int end); 78xs_str *xs_crop_i(xs_str *str, int start, int end);
@@ -506,6 +507,20 @@ int _xs_startsorends(const char *str, const char *xfix, int ends)
506 return !!(ssz >= psz && memcmp(xfix, str + (ends ? ssz - psz : 0), psz) == 0); 507 return !!(ssz >= psz && memcmp(xfix, str + (ends ? ssz - psz : 0), psz) == 0);
507} 508}
508 509
510xs_str *xs_encode_html(const char *str)
511/* escapes html characters */
512{
513 xs_str *encoded = xs_replace(str, "&", "&amp;");
514 encoded = xs_replace(encoded, "<", "&lt;");
515 encoded = xs_replace(encoded, ">", "&gt;");
516 encoded = xs_replace(encoded, "\"", "&#34;");
517 encoded = xs_replace(encoded, "'", "&#39;");
518
519 // Restore only <br>. Probably safe. Let's hope nothing goes wrong with this.
520 encoded = xs_replace(encoded, "&lt;br&gt;", "<br>");
521
522 return encoded;
523}
509 524
510xs_str *xs_crop_i(xs_str *str, int start, int end) 525xs_str *xs_crop_i(xs_str *str, int start, int end)
511/* crops the d_char to be only from start to end */ 526/* crops the d_char to be only from start to end */