diff options
| -rw-r--r-- | format.c | 16 | ||||
| -rw-r--r-- | html.c | 109 | ||||
| -rw-r--r-- | snac.h | 1 | ||||
| -rw-r--r-- | xs.h | 15 |
4 files changed, 82 insertions, 59 deletions
| @@ -238,3 +238,19 @@ xs_str *sanitize(const char *content) | |||
| 238 | 238 | ||
| 239 | return s; | 239 | return s; |
| 240 | } | 240 | } |
| 241 | |||
| 242 | |||
| 243 | xs_str *encode_html(const char *str) | ||
| 244 | /* escapes html characters */ | ||
| 245 | { | ||
| 246 | xs_str *encoded = xs_replace(str, "&", "&"); | ||
| 247 | encoded = xs_replace_i(encoded, "<", "<"); | ||
| 248 | encoded = xs_replace_i(encoded, ">", ">"); | ||
| 249 | encoded = xs_replace_i(encoded, "\"", """); | ||
| 250 | encoded = xs_replace_i(encoded, "'", "'"); | ||
| 251 | |||
| 252 | /* Restore only <br>. Probably safe. Let's hope nothing goes wrong with this. */ | ||
| 253 | encoded = xs_replace_i(encoded, "<br>", "<br>"); | ||
| 254 | |||
| 255 | return encoded; | ||
| 256 | } | ||
| @@ -52,7 +52,7 @@ xs_str *actor_name(xs_dict *actor) | |||
| 52 | } | 52 | } |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | name = xs_dup(v); | 55 | name = encode_html(v); |
| 56 | 56 | ||
| 57 | /* replace the :shortnames: */ | 57 | /* replace the :shortnames: */ |
| 58 | if (!xs_is_null(p = xs_dict_get(actor, "tag"))) { | 58 | if (!xs_is_null(p = xs_dict_get(actor, "tag"))) { |
| @@ -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"), xs_encode_html(name)); | 108 | xs_dict_get(actor, "id"), name); |
| 109 | s = xs_str_cat(s, s1); | 109 | s = xs_str_cat(s, s1); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| @@ -137,9 +137,11 @@ xs_str *html_actor_icon(xs_str *os, char *actor, | |||
| 137 | date_title = xs_str_cat(date_title, udate); | 137 | date_title = xs_str_cat(date_title, udate); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | xs *edt = encode_html(date_title); | ||
| 141 | xs *edl = encode_html(date_label); | ||
| 140 | xs *s1 = xs_fmt( | 142 | xs *s1 = xs_fmt( |
| 141 | "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n", | 143 | "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n", |
| 142 | xs_encode_html(date_title), xs_encode_html(date_label)); | 144 | edt, edl); |
| 143 | 145 | ||
| 144 | s = xs_str_cat(s, s1); | 146 | s = xs_str_cat(s, s1); |
| 145 | } | 147 | } |
| @@ -162,9 +164,10 @@ xs_str *html_actor_icon(xs_str *os, char *actor, | |||
| 162 | xs *domain = xs_split(id, "/"); | 164 | xs *domain = xs_split(id, "/"); |
| 163 | xs *user = xs_fmt("@%s@%s", username, xs_list_get(domain, 2)); | 165 | xs *user = xs_fmt("@%s@%s", username, xs_list_get(domain, 2)); |
| 164 | 166 | ||
| 167 | xs *u1 = encode_html(user); | ||
| 165 | s1 = xs_fmt( | 168 | s1 = xs_fmt( |
| 166 | "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>", | 169 | "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>", |
| 167 | xs_dict_get(actor, "id"), xs_encode_html(user)); | 170 | xs_dict_get(actor, "id"), u1); |
| 168 | 171 | ||
| 169 | s = xs_str_cat(s, s1); | 172 | s = xs_str_cat(s, s1); |
| 170 | } | 173 | } |
| @@ -244,10 +247,10 @@ d_char *html_user_header(snac *snac, d_char *s, int local) | |||
| 244 | } | 247 | } |
| 245 | 248 | ||
| 246 | { | 249 | { |
| 247 | xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n", | 250 | xs *es1 = encode_html(xs_dict_get(snac->config, "name")); |
| 248 | xs_encode_html(xs_dict_get(snac->config, "name")), | 251 | xs *es2 = encode_html(snac->uid); |
| 249 | xs_encode_html(snac->uid), | 252 | xs *es3 = encode_html(xs_dict_get(srv_config, "host")); |
| 250 | xs_encode_html(xs_dict_get(srv_config, "host"))); | 253 | xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n", es1, es2, es3); |
| 251 | 254 | ||
| 252 | s = xs_str_cat(s, s1); | 255 | s = xs_str_cat(s, s1); |
| 253 | } | 256 | } |
| @@ -277,6 +280,13 @@ d_char *html_user_header(snac *snac, d_char *s, int local) | |||
| 277 | } | 280 | } |
| 278 | 281 | ||
| 279 | /* og properties */ | 282 | /* og properties */ |
| 283 | xs *es1 = encode_html(xs_dict_get(srv_config, "host")); | ||
| 284 | xs *es2 = encode_html(xs_dict_get(snac->config, "name")); | ||
| 285 | xs *es3 = encode_html(snac->uid); | ||
| 286 | xs *es4 = encode_html(xs_dict_get(srv_config, "host")); | ||
| 287 | xs *es5 = encode_html(s_bio); | ||
| 288 | xs *es6 = encode_html(s_avatar); | ||
| 289 | |||
| 280 | xs *s1 = xs_fmt( | 290 | xs *s1 = xs_fmt( |
| 281 | "<meta property=\"og:site_name\" content=\"%s\"/>\n" | 291 | "<meta property=\"og:site_name\" content=\"%s\"/>\n" |
| 282 | "<meta property=\"og:title\" content=\"%s (@%s@%s)\"/>\n" | 292 | "<meta property=\"og:title\" content=\"%s (@%s@%s)\"/>\n" |
| @@ -284,12 +294,7 @@ d_char *html_user_header(snac *snac, d_char *s, int local) | |||
| 284 | "<meta property=\"og:image\" content=\"%s\"/>\n" | 294 | "<meta property=\"og:image\" content=\"%s\"/>\n" |
| 285 | "<meta property=\"og:image:width\" content=\"300\"/>\n" | 295 | "<meta property=\"og:image:width\" content=\"300\"/>\n" |
| 286 | "<meta property=\"og:image:height\" content=\"300\"/>\n", | 296 | "<meta property=\"og:image:height\" content=\"300\"/>\n", |
| 287 | xs_encode_html(xs_dict_get(srv_config, "host")), | 297 | es1, es2, es3, es4, es5, es6); |
| 288 | xs_encode_html(xs_dict_get(snac->config, "name")), | ||
| 289 | xs_encode_html(snac->uid), | ||
| 290 | xs_encode_html(xs_dict_get(srv_config, "host")), | ||
| 291 | xs_encode_html(s_bio), | ||
| 292 | xs_encode_html(s_avatar)); | ||
| 293 | s = xs_str_cat(s, s1); | 298 | s = xs_str_cat(s, s1); |
| 294 | } | 299 | } |
| 295 | 300 | ||
| @@ -354,17 +359,19 @@ d_char *html_user_header(snac *snac, d_char *s, int local) | |||
| 354 | "<p class=\"p-name snac-top-user-name\">%s</p>\n" | 359 | "<p class=\"p-name snac-top-user-name\">%s</p>\n" |
| 355 | "<p class=\"snac-top-user-id\">@%s@%s</p>\n"; | 360 | "<p class=\"snac-top-user-id\">@%s@%s</p>\n"; |
| 356 | 361 | ||
| 357 | xs *s1 = xs_fmt(_tmpl, | 362 | xs *es1 = encode_html(xs_dict_get(snac->config, "name")); |
| 358 | xs_encode_html(xs_dict_get(snac->config, "name")), | 363 | xs *es2 = encode_html(xs_dict_get(snac->config, "uid")); |
| 359 | xs_encode_html(xs_dict_get(snac->config, "uid")), xs_encode_html(xs_dict_get(srv_config, "host")) | 364 | xs *es3 = encode_html(xs_dict_get(srv_config, "host")); |
| 360 | ); | 365 | |
| 366 | xs *s1 = xs_fmt(_tmpl, es1, es2, es3); | ||
| 361 | 367 | ||
| 362 | s = xs_str_cat(s, s1); | 368 | s = xs_str_cat(s, s1); |
| 363 | 369 | ||
| 364 | if (local) { | 370 | if (local) { |
| 365 | xs *bio1 = not_really_markdown(xs_encode_html(xs_dict_get(snac->config, "bio")), NULL); | 371 | xs *es1 = encode_html(xs_dict_get(snac->config, "bio")); |
| 372 | xs *bio1 = not_really_markdown(es1, NULL); | ||
| 366 | xs *tags = xs_list_new(); | 373 | xs *tags = xs_list_new(); |
| 367 | xs *bio2 = xs_encode_html(process_tags(snac, bio1, &tags)); | 374 | xs *bio2 = encode_html(process_tags(snac, bio1, &tags)); |
| 368 | xs *s1 = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2); | 375 | xs *s1 = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2); |
| 369 | 376 | ||
| 370 | s = xs_str_cat(s, s1); | 377 | s = xs_str_cat(s, s1); |
| @@ -911,10 +918,11 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 911 | 918 | ||
| 912 | if (xs_list_in(boosts, snac->md5) != -1) { | 919 | if (xs_list_in(boosts, snac->md5) != -1) { |
| 913 | /* we boosted this */ | 920 | /* we boosted this */ |
| 921 | xs *es1 = encode_html(xs_dict_get(snac->config, "name")); | ||
| 914 | xs *s1 = xs_fmt( | 922 | xs *s1 = xs_fmt( |
| 915 | "<div class=\"snac-origin\">" | 923 | "<div class=\"snac-origin\">" |
| 916 | "<a href=\"%s\">%s</a> %s</a></div>", | 924 | "<a href=\"%s\">%s</a> %s</a></div>", |
| 917 | snac->actor, xs_encode_html(xs_dict_get(snac->config, "name")), L("boosted") | 925 | snac->actor, es1, L("boosted") |
| 918 | ); | 926 | ); |
| 919 | 927 | ||
| 920 | s = xs_str_cat(s, s1); | 928 | s = xs_str_cat(s, s1); |
| @@ -928,7 +936,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 928 | "<div class=\"snac-origin\">" | 936 | "<div class=\"snac-origin\">" |
| 929 | "<a href=\"%s\">%s</a> %s</div>\n", | 937 | "<a href=\"%s\">%s</a> %s</div>\n", |
| 930 | xs_dict_get(actor_r, "id"), | 938 | xs_dict_get(actor_r, "id"), |
| 931 | xs_encode_html(name), | 939 | name, |
| 932 | L("boosted") | 940 | L("boosted") |
| 933 | ); | 941 | ); |
| 934 | 942 | ||
| @@ -967,7 +975,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 967 | char *cw = xs_dict_get(snac->config, "cw"); | 975 | char *cw = xs_dict_get(snac->config, "cw"); |
| 968 | if (xs_is_null(cw) || local) | 976 | if (xs_is_null(cw) || local) |
| 969 | cw = ""; | 977 | cw = ""; |
| 970 | xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, xs_encode_html(v), L("SENSITIVE CONTENT")); | 978 | xs *es1 = encode_html(v); |
| 979 | xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, es1, L("SENSITIVE CONTENT")); | ||
| 971 | s = xs_str_cat(s, s1); | 980 | s = xs_str_cat(s, s1); |
| 972 | sensitive = 1; | 981 | sensitive = 1; |
| 973 | } | 982 | } |
| @@ -1049,7 +1058,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1049 | 1058 | ||
| 1050 | if (name && replies) { | 1059 | if (name && replies) { |
| 1051 | int nr = xs_number_get(xs_dict_get(replies, "totalItems")); | 1060 | int nr = xs_number_get(xs_dict_get(replies, "totalItems")); |
| 1052 | xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", xs_encode_html(name), nr); | 1061 | xs *es1 = encode_html(name); |
| 1062 | xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", es1, nr); | ||
| 1053 | 1063 | ||
| 1054 | c = xs_str_cat(c, l); | 1064 | c = xs_str_cat(c, l); |
| 1055 | } | 1065 | } |
| @@ -1070,10 +1080,11 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1070 | const char *name = xs_dict_get(v, "name"); | 1080 | const char *name = xs_dict_get(v, "name"); |
| 1071 | 1081 | ||
| 1072 | if (name) { | 1082 | if (name) { |
| 1083 | xs *es1 = encode_html(name); | ||
| 1073 | xs *opt = xs_fmt("<input type=\"%s\"" | 1084 | xs *opt = xs_fmt("<input type=\"%s\"" |
| 1074 | " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n", | 1085 | " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n", |
| 1075 | !xs_is_null(oo) ? "radio" : "checkbox", | 1086 | !xs_is_null(oo) ? "radio" : "checkbox", |
| 1076 | xs_encode_html(name), xs_encode_html(name), xs_encode_html(name)); | 1087 | es1, es1, es1); |
| 1077 | 1088 | ||
| 1078 | s1 = xs_str_cat(s1, opt); | 1089 | s1 = xs_str_cat(s1, opt); |
| 1079 | } | 1090 | } |
| @@ -1107,7 +1118,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1107 | /* skip leading zeros */ | 1118 | /* skip leading zeros */ |
| 1108 | for (; *p == '0' || *p == ':'; p++); | 1119 | for (; *p == '0' || *p == ':'; p++); |
| 1109 | 1120 | ||
| 1110 | xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), xs_encode_html(p)); | 1121 | xs *es1 = encode_html(p); |
| 1122 | xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), es1); | ||
| 1111 | c = xs_str_cat(c, s1); | 1123 | c = xs_str_cat(c, s1); |
| 1112 | } | 1124 | } |
| 1113 | } | 1125 | } |
| @@ -1135,8 +1147,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1135 | continue; | 1147 | continue; |
| 1136 | 1148 | ||
| 1137 | if (xs_startswith(t, "image/")) { | 1149 | if (xs_startswith(t, "image/")) { |
| 1138 | char *url = xs_dict_get(v, "url"); | 1150 | char *url = xs_dict_get(v, "url"); |
| 1139 | char *name = xs_encode_html(xs_dict_get(v, "name")); | 1151 | xs *name = encode_html(xs_dict_get(v, "name")); |
| 1140 | 1152 | ||
| 1141 | if (url != NULL) { | 1153 | if (url != NULL) { |
| 1142 | if (xs_is_null(name)) | 1154 | if (xs_is_null(name)) |
| @@ -1150,8 +1162,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1150 | } | 1162 | } |
| 1151 | else | 1163 | else |
| 1152 | if (xs_startswith(t, "video/")) { | 1164 | if (xs_startswith(t, "video/")) { |
| 1153 | char *url = xs_dict_get(v, "url"); | 1165 | char *url = xs_dict_get(v, "url"); |
| 1154 | char *name = xs_encode_html(xs_dict_get(v, "name")); | 1166 | xs *name = encode_html(xs_dict_get(v, "name")); |
| 1155 | 1167 | ||
| 1156 | if (url != NULL) { | 1168 | if (url != NULL) { |
| 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."); | 1169 | 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."); |
| @@ -1161,8 +1173,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1161 | } | 1173 | } |
| 1162 | else | 1174 | else |
| 1163 | if (xs_startswith(t, "audio/")) { | 1175 | if (xs_startswith(t, "audio/")) { |
| 1164 | char *url = xs_dict_get(v, "url"); | 1176 | char *url = xs_dict_get(v, "url"); |
| 1165 | char *name = xs_encode_html(xs_dict_get(v, "name")); | 1177 | xs *name = encode_html(xs_dict_get(v, "name")); |
| 1166 | 1178 | ||
| 1167 | if (url != NULL) { | 1179 | 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."); | 1180 | 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."); |
| @@ -1171,8 +1183,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local, | |||
| 1171 | } | 1183 | } |
| 1172 | } | 1184 | } |
| 1173 | else { | 1185 | else { |
| 1174 | char *url = xs_dict_get(v, "url"); | 1186 | char *url = xs_dict_get(v, "url"); |
| 1175 | char *name = xs_encode_html(xs_dict_get(v, "name")); | 1187 | xs *name = encode_html(xs_dict_get(v, "name")); |
| 1176 | 1188 | ||
| 1177 | if (url != NULL) { | 1189 | if (url != NULL) { |
| 1178 | xs *s1 = xs_fmt("<a href=\"%s\">Attachment: %s</a>", url, name ? name : "No description"); | 1190 | xs *s1 = xs_fmt("<a href=\"%s\">Attachment: %s</a>", url, name ? name : "No description"); |
| @@ -1349,7 +1361,8 @@ xs_str *html_timeline(snac *snac, const xs_list *list, int local, int skip, int | |||
| 1349 | d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t) | 1361 | d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t) |
| 1350 | { | 1362 | { |
| 1351 | xs *s = xs_str_new(NULL); | 1363 | xs *s = xs_str_new(NULL); |
| 1352 | xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", xs_encode_html(header)); | 1364 | xs *es1 = encode_html(header); |
| 1365 | xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", es1); | ||
| 1353 | char *p, *actor_id; | 1366 | char *p, *actor_id; |
| 1354 | 1367 | ||
| 1355 | s = xs_str_cat(s, h); | 1368 | s = xs_str_cat(s, h); |
| @@ -1379,7 +1392,8 @@ d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *heade | |||
| 1379 | if (xs_startswith(sc, "<p>")) | 1392 | if (xs_startswith(sc, "<p>")) |
| 1380 | s = xs_str_cat(s, sc); | 1393 | s = xs_str_cat(s, sc); |
| 1381 | else { | 1394 | else { |
| 1382 | xs *s1 = xs_fmt("<p>%s</p>", xs_encode_html(sc)); | 1395 | xs *es1 = encode_html(sc); |
| 1396 | xs *s1 = xs_fmt("<p>%s</p>", es1); | ||
| 1383 | s = xs_str_cat(s, s1); | 1397 | s = xs_str_cat(s, s1); |
| 1384 | } | 1398 | } |
| 1385 | 1399 | ||
| @@ -1549,9 +1563,10 @@ xs_str *html_notifications(snac *snac) | |||
| 1549 | if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") == 0) | 1563 | if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") == 0) |
| 1550 | label = L("Unfollow"); | 1564 | label = L("Unfollow"); |
| 1551 | 1565 | ||
| 1566 | xs *es1 = encode_html(label); | ||
| 1552 | xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n" | 1567 | xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n" |
| 1553 | "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n", | 1568 | "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n", |
| 1554 | xs_encode_html(label), actor_id, xs_encode_html(a_name)); | 1569 | es1, actor_id, a_name); |
| 1555 | s = xs_str_cat(s, s1); | 1570 | s = xs_str_cat(s, s1); |
| 1556 | 1571 | ||
| 1557 | if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) { | 1572 | if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) { |
| @@ -1776,7 +1791,10 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 1776 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL); | 1791 | xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL); |
| 1777 | char *p, *v; | 1792 | char *p, *v; |
| 1778 | 1793 | ||
| 1779 | 1794 | xs *es1 = encode_html(xs_dict_get(snac.config, "name")); | |
| 1795 | xs *es2 = encode_html(snac.uid); | ||
| 1796 | xs *es3 = encode_html(xs_dict_get(srv_config, "host")); | ||
| 1797 | xs *es4 = encode_html(bio); | ||
| 1780 | rss = xs_fmt( | 1798 | rss = xs_fmt( |
| 1781 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | 1799 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
| 1782 | "<rss version=\"0.91\">\n" | 1800 | "<rss version=\"0.91\">\n" |
| @@ -1785,11 +1803,11 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 1785 | "<language>en</language>\n" | 1803 | "<language>en</language>\n" |
| 1786 | "<link>%s.rss</link>\n" | 1804 | "<link>%s.rss</link>\n" |
| 1787 | "<description>%s</description>\n", | 1805 | "<description>%s</description>\n", |
| 1788 | xs_encode_html(xs_dict_get(snac.config, "name")), | 1806 | es1, |
| 1789 | xs_encode_html(snac.uid), | 1807 | es2, |
| 1790 | xs_encode_html(xs_dict_get(srv_config, "host")), | 1808 | es3, |
| 1791 | snac.actor, | 1809 | snac.actor, |
| 1792 | xs_encode_html(bio) | 1810 | es4 |
| 1793 | ); | 1811 | ); |
| 1794 | 1812 | ||
| 1795 | p = elems; | 1813 | p = elems; |
| @@ -1804,20 +1822,23 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 1804 | if (!xs_startswith(id, snac.actor)) | 1822 | if (!xs_startswith(id, snac.actor)) |
| 1805 | continue; | 1823 | continue; |
| 1806 | 1824 | ||
| 1807 | xs *content = xs_encode_html(sanitize(xs_dict_get(msg, "content"))); | 1825 | xs *es1 = sanitize(xs_dict_get(msg, "content")); |
| 1826 | xs *content = encode_html(es1); | ||
| 1808 | xs *title = xs_str_new(NULL); | 1827 | xs *title = xs_str_new(NULL); |
| 1809 | int i; | 1828 | int i; |
| 1810 | 1829 | ||
| 1811 | for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++) | 1830 | for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++) |
| 1812 | title = xs_append_m(title, &content[i], 1); | 1831 | title = xs_append_m(title, &content[i], 1); |
| 1813 | 1832 | ||
| 1833 | xs *es11 = encode_html(title); | ||
| 1834 | xs *es12 = encode_html(content); | ||
| 1814 | xs *s = xs_fmt( | 1835 | xs *s = xs_fmt( |
| 1815 | "<item>\n" | 1836 | "<item>\n" |
| 1816 | "<title>%s...</title>\n" | 1837 | "<title>%s...</title>\n" |
| 1817 | "<link>%s</link>\n" | 1838 | "<link>%s</link>\n" |
| 1818 | "<description>%s</description>\n" | 1839 | "<description>%s</description>\n" |
| 1819 | "</item>\n", | 1840 | "</item>\n", |
| 1820 | xs_encode_html(title), id, xs_encode_html(content) | 1841 | es11, id, es12 |
| 1821 | ); | 1842 | ); |
| 1822 | 1843 | ||
| 1823 | rss = xs_str_cat(rss, s); | 1844 | rss = xs_str_cat(rss, s); |
| @@ -251,6 +251,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path, | |||
| 251 | 251 | ||
| 252 | xs_str *not_really_markdown(const char *content, xs_list **attach); | 252 | xs_str *not_really_markdown(const char *content, xs_list **attach); |
| 253 | xs_str *sanitize(const char *content); | 253 | xs_str *sanitize(const char *content); |
| 254 | xs_str *encode_html(const char *str); | ||
| 254 | 255 | ||
| 255 | int html_get_handler(const xs_dict *req, const char *q_path, | 256 | int html_get_handler(const xs_dict *req, const char *q_path, |
| 256 | char **body, int *b_size, char **ctype, xs_str **etag); | 257 | char **body, int *b_size, char **ctype, xs_str **etag); |
| @@ -72,7 +72,6 @@ xs_str *xs_replace_in(xs_str *str, const char *sfrom, const char *sto, int times | |||
| 72 | xs_str *xs_fmt(const char *fmt, ...); | 72 | xs_str *xs_fmt(const char *fmt, ...); |
| 73 | int xs_str_in(const char *haystack, const char *needle); | 73 | int xs_str_in(const char *haystack, const char *needle); |
| 74 | int _xs_startsorends(const char *str, const char *xfix, int ends); | 74 | int _xs_startsorends(const char *str, const char *xfix, int ends); |
| 75 | xs_str *xs_encode_html(const xs_str *str); | ||
| 76 | #define xs_startswith(str, prefix) _xs_startsorends(str, prefix, 0) | 75 | #define xs_startswith(str, prefix) _xs_startsorends(str, prefix, 0) |
| 77 | #define xs_endswith(str, postfix) _xs_startsorends(str, postfix, 1) | 76 | #define xs_endswith(str, postfix) _xs_startsorends(str, postfix, 1) |
| 78 | xs_str *xs_crop_i(xs_str *str, int start, int end); | 77 | xs_str *xs_crop_i(xs_str *str, int start, int end); |
| @@ -507,20 +506,6 @@ int _xs_startsorends(const char *str, const char *xfix, int ends) | |||
| 507 | return !!(ssz >= psz && memcmp(xfix, str + (ends ? ssz - psz : 0), psz) == 0); | 506 | return !!(ssz >= psz && memcmp(xfix, str + (ends ? ssz - psz : 0), psz) == 0); |
| 508 | } | 507 | } |
| 509 | 508 | ||
| 510 | xs_str *xs_encode_html(const char *str) | ||
| 511 | /* escapes html characters */ | ||
| 512 | { | ||
| 513 | xs_str *encoded = xs_replace(str, "&", "&"); | ||
| 514 | encoded = xs_replace(encoded, "<", "<"); | ||
| 515 | encoded = xs_replace(encoded, ">", ">"); | ||
| 516 | encoded = xs_replace(encoded, "\"", """); | ||
| 517 | encoded = xs_replace(encoded, "'", "'"); | ||
| 518 | |||
| 519 | // Restore only <br>. Probably safe. Let's hope nothing goes wrong with this. | ||
| 520 | encoded = xs_replace(encoded, "<br>", "<br>"); | ||
| 521 | |||
| 522 | return encoded; | ||
| 523 | } | ||
| 524 | 509 | ||
| 525 | xs_str *xs_crop_i(xs_str *str, int start, int end) | 510 | xs_str *xs_crop_i(xs_str *str, int start, int end) |
| 526 | /* crops the d_char to be only from start to end */ | 511 | /* crops the d_char to be only from start to end */ |