diff options
| author | 2023-07-11 22:03:51 +0700 | |
|---|---|---|
| committer | 2023-07-11 23:08:01 +0700 | |
| commit | 63741cb66a6146c16898e0cafde1722a327a0059 (patch) | |
| tree | 1cba1e46167512e9e3a6b8f8e278d84fbdb29bf2 | |
| parent | Merge pull request 'xs_mime.h: Add various mimetypes for audios & videos' (#6... (diff) | |
| download | snac2-63741cb66a6146c16898e0cafde1722a327a0059.tar.gz snac2-63741cb66a6146c16898e0cafde1722a327a0059.tar.xz snac2-63741cb66a6146c16898e0cafde1722a327a0059.zip | |
html.c: Escape XML characters & View unknown type attachment link
Signed-off-by: Yonle <yonle@lecturify.net>
| -rw-r--r-- | html.c | 97 | ||||
| -rw-r--r-- | xs.h | 15 |
2 files changed, 71 insertions, 41 deletions
| @@ -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 | |||
| 1327 | d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t) | 1349 | d_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, "<", "<"); | ||
| 1759 | bio = xs_replace_i(bio, ">", ">"); | ||
| 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, "<", "<"); | ||
| 1794 | content = xs_replace_i(content, ">", ">"); | ||
| 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); |
| @@ -72,6 +72,7 @@ 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); | ||
| 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) |
| 77 | xs_str *xs_crop_i(xs_str *str, int start, int end); | 78 | xs_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 | ||
| 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 | } | ||
| 509 | 524 | ||
| 510 | xs_str *xs_crop_i(xs_str *str, int start, int end) | 525 | xs_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 */ |