commit 63741cb
Yonle
·
2023-07-11 15:03:51 +0000 UTC
parent eb7bee9
html.c: Escape XML characters & View unknown type attachment link Signed-off-by: Yonle <yonle@lecturify.net>
M
html.c
+56,
-41
1@@ -105,7 +105,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
2
3 {
4 xs *s1 = xs_fmt("<a href=\"%s\" class=\"p-author h-card snac-author\">%s</a>",
5- xs_dict_get(actor, "id"), name);
6+ xs_dict_get(actor, "id"), xs_encode_html(name));
7 s = xs_str_cat(s, s1);
8 }
9
10@@ -139,7 +139,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
11
12 xs *s1 = xs_fmt(
13 "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n",
14- date_title, date_label);
15+ xs_encode_html(date_title), xs_encode_html(date_label));
16
17 s = xs_str_cat(s, s1);
18 }
19@@ -164,7 +164,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
20
21 s1 = xs_fmt(
22 "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>",
23- xs_dict_get(actor, "id"), user);
24+ xs_dict_get(actor, "id"), xs_encode_html(user));
25
26 s = xs_str_cat(s, s1);
27 }
28@@ -245,9 +245,9 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
29
30 {
31 xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n",
32- xs_dict_get(snac->config, "name"),
33- snac->uid,
34- xs_dict_get(srv_config, "host"));
35+ xs_encode_html(xs_dict_get(snac->config, "name")),
36+ xs_encode_html(snac->uid),
37+ xs_encode_html(xs_dict_get(srv_config, "host")));
38
39 s = xs_str_cat(s, s1);
40 }
41@@ -284,18 +284,18 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
42 "<meta property=\"og:image\" content=\"%s\"/>\n"
43 "<meta property=\"og:image:width\" content=\"300\"/>\n"
44 "<meta property=\"og:image:height\" content=\"300\"/>\n",
45- xs_dict_get(srv_config, "host"),
46- xs_dict_get(snac->config, "name"),
47- snac->uid,
48- xs_dict_get(srv_config, "host"),
49- s_bio,
50- s_avatar);
51+ xs_encode_html(xs_dict_get(srv_config, "host")),
52+ xs_encode_html(xs_dict_get(snac->config, "name")),
53+ xs_encode_html(snac->uid),
54+ xs_encode_html(xs_dict_get(srv_config, "host")),
55+ xs_encode_html(s_bio),
56+ xs_encode_html(s_avatar));
57 s = xs_str_cat(s, s1);
58 }
59
60 {
61 xs *s1 = xs_fmt("<link rel=\"alternate\" type=\"application/rss+xml\" "
62- "title=\"RSS\" href=\"%s.rss\" />\n", snac->actor);
63+ "title=\"RSS\" href=\"%s.rss\" />\n", snac->actor); /* snac->actor is likely need to be URLEncoded. */
64 s = xs_str_cat(s, s1);
65 }
66
67@@ -355,16 +355,16 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
68 "<p class=\"snac-top-user-id\">@%s@%s</p>\n";
69
70 xs *s1 = xs_fmt(_tmpl,
71- xs_dict_get(snac->config, "name"),
72- xs_dict_get(snac->config, "uid"), xs_dict_get(srv_config, "host")
73+ xs_encode_html(xs_dict_get(snac->config, "name")),
74+ xs_encode_html(xs_dict_get(snac->config, "uid")), xs_encode_html(xs_dict_get(srv_config, "host"))
75 );
76
77 s = xs_str_cat(s, s1);
78
79 if (local) {
80- xs *bio1 = not_really_markdown(xs_dict_get(snac->config, "bio"), NULL);
81+ xs *bio1 = not_really_markdown(xs_encode_html(xs_dict_get(snac->config, "bio")), NULL);
82 xs *tags = xs_list_new();
83- xs *bio2 = process_tags(snac, bio1, &tags);
84+ xs *bio2 = xs_encode_html(process_tags(snac, bio1, &tags));
85 xs *s1 = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2);
86
87 s = xs_str_cat(s, s1);
88@@ -914,7 +914,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
89 xs *s1 = xs_fmt(
90 "<div class=\"snac-origin\">"
91 "<a href=\"%s\">%s</a> %s</a></div>",
92- snac->actor, xs_dict_get(snac->config, "name"), L("boosted")
93+ snac->actor, xs_encode_html(xs_dict_get(snac->config, "name")), L("boosted")
94 );
95
96 s = xs_str_cat(s, s1);
97@@ -928,7 +928,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
98 "<div class=\"snac-origin\">"
99 "<a href=\"%s\">%s</a> %s</div>\n",
100 xs_dict_get(actor_r, "id"),
101- name,
102+ xs_encode_html(name),
103 L("boosted")
104 );
105
106@@ -967,7 +967,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
107 char *cw = xs_dict_get(snac->config, "cw");
108 if (xs_is_null(cw) || local)
109 cw = "";
110- xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, v, L("SENSITIVE CONTENT"));
111+ xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, xs_encode_html(v), L("SENSITIVE CONTENT"));
112 s = xs_str_cat(s, s1);
113 sensitive = 1;
114 }
115@@ -1049,7 +1049,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
116
117 if (name && replies) {
118 int nr = xs_number_get(xs_dict_get(replies, "totalItems"));
119- xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", name, nr);
120+ xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", xs_encode_html(name), nr);
121
122 c = xs_str_cat(c, l);
123 }
124@@ -1073,7 +1073,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
125 xs *opt = xs_fmt("<input type=\"%s\""
126 " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n",
127 !xs_is_null(oo) ? "radio" : "checkbox",
128- name, name, name);
129+ xs_encode_html(name), xs_encode_html(name), xs_encode_html(name));
130
131 s1 = xs_str_cat(s1, opt);
132 }
133@@ -1107,7 +1107,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
134 /* skip leading zeros */
135 for (; *p == '0' || *p == ':'; p++);
136
137- xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), p);
138+ xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), xs_encode_html(p));
139 c = xs_str_cat(c, s1);
140 }
141 }
142@@ -1136,7 +1136,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
143
144 if (xs_startswith(t, "image/")) {
145 char *url = xs_dict_get(v, "url");
146- char *name = xs_dict_get(v, "name");
147+ char *name = xs_encode_html(xs_dict_get(v, "name"));
148
149 if (url != NULL) {
150 if (xs_is_null(name))
151@@ -1151,9 +1151,31 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
152 else
153 if (xs_startswith(t, "video/")) {
154 char *url = xs_dict_get(v, "url");
155+ char *name = xs_encode_html(xs_dict_get(v, "name"));
156
157 if (url != NULL) {
158- xs *s1 = xs_fmt("<object data=\"%s\"></object>\n", url);
159+ 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.");
160+
161+ s = xs_str_cat(s, s1);
162+ }
163+ }
164+ else
165+ if (xs_startswith(t, "audio/")) {
166+ char *url = xs_dict_get(v, "url");
167+ char *name = xs_encode_html(xs_dict_get(v, "name"));
168+
169+ if (url != NULL) {
170+ 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.");
171+
172+ s = xs_str_cat(s, s1);
173+ }
174+ }
175+ else {
176+ char *url = xs_dict_get(v, "url");
177+ char *name = xs_encode_html(xs_dict_get(v, "name"));
178+
179+ if (url != NULL) {
180+ xs *s1 = xs_fmt("<a href=\"%s\">Attachment: %s</a>", url, name ? name : "No description");
181
182 s = xs_str_cat(s, s1);
183 }
184@@ -1327,7 +1349,7 @@ xs_str *html_timeline(snac *snac, const xs_list *list, int local, int skip, int
185 d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t)
186 {
187 xs *s = xs_str_new(NULL);
188- xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", header);
189+ xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", xs_encode_html(header));
190 char *p, *actor_id;
191
192 s = xs_str_cat(s, h);
193@@ -1357,7 +1379,7 @@ d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *heade
194 if (xs_startswith(sc, "<p>"))
195 s = xs_str_cat(s, sc);
196 else {
197- xs *s1 = xs_fmt("<p>%s</p>", sc);
198+ xs *s1 = xs_fmt("<p>%s</p>", xs_encode_html(sc));
199 s = xs_str_cat(s, s1);
200 }
201
202@@ -1529,7 +1551,7 @@ xs_str *html_notifications(snac *snac)
203
204 xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n"
205 "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n",
206- label, actor_id, a_name);
207+ xs_encode_html(label), actor_id, xs_encode_html(a_name));
208 s = xs_str_cat(s, s1);
209
210 if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) {
211@@ -1754,9 +1776,6 @@ int html_get_handler(const xs_dict *req, const char *q_path,
212 xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL);
213 char *p, *v;
214
215- /* escape tags */
216- bio = xs_replace_i(bio, "<", "<");
217- bio = xs_replace_i(bio, ">", ">");
218
219 rss = xs_fmt(
220 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
221@@ -1766,11 +1785,11 @@ int html_get_handler(const xs_dict *req, const char *q_path,
222 "<language>en</language>\n"
223 "<link>%s.rss</link>\n"
224 "<description>%s</description>\n",
225- xs_dict_get(snac.config, "name"),
226- snac.uid,
227- xs_dict_get(srv_config, "host"),
228+ xs_encode_html(xs_dict_get(snac.config, "name")),
229+ xs_encode_html(snac.uid),
230+ xs_encode_html(xs_dict_get(srv_config, "host")),
231 snac.actor,
232- bio
233+ xs_encode_html(bio)
234 );
235
236 p = elems;
237@@ -1785,14 +1804,10 @@ int html_get_handler(const xs_dict *req, const char *q_path,
238 if (!xs_startswith(id, snac.actor))
239 continue;
240
241- xs *content = sanitize(xs_dict_get(msg, "content"));
242+ xs *content = xs_encode_html(sanitize(xs_dict_get(msg, "content")));
243 xs *title = xs_str_new(NULL);
244 int i;
245
246- /* escape tags */
247- content = xs_replace_i(content, "<", "<");
248- content = xs_replace_i(content, ">", ">");
249-
250 for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++)
251 title = xs_append_m(title, &content[i], 1);
252
253@@ -1802,7 +1817,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
254 "<link>%s</link>\n"
255 "<description>%s</description>\n"
256 "</item>\n",
257- title, id, content
258+ xs_encode_html(title), id, xs_encode_html(content)
259 );
260
261 rss = xs_str_cat(rss, s);
M
xs.h
+15,
-0
1@@ -72,6 +72,7 @@ xs_str *xs_replace_in(xs_str *str, const char *sfrom, const char *sto, int times
2 xs_str *xs_fmt(const char *fmt, ...);
3 int xs_str_in(const char *haystack, const char *needle);
4 int _xs_startsorends(const char *str, const char *xfix, int ends);
5+xs_str *xs_encode_html(const xs_str *str);
6 #define xs_startswith(str, prefix) _xs_startsorends(str, prefix, 0)
7 #define xs_endswith(str, postfix) _xs_startsorends(str, postfix, 1)
8 xs_str *xs_crop_i(xs_str *str, int start, int end);
9@@ -506,6 +507,20 @@ int _xs_startsorends(const char *str, const char *xfix, int ends)
10 return !!(ssz >= psz && memcmp(xfix, str + (ends ? ssz - psz : 0), psz) == 0);
11 }
12
13+xs_str *xs_encode_html(const char *str)
14+/* escapes html characters */
15+{
16+ xs_str *encoded = xs_replace(str, "&", "&");
17+ encoded = xs_replace(encoded, "<", "<");
18+ encoded = xs_replace(encoded, ">", ">");
19+ encoded = xs_replace(encoded, "\"", """);
20+ encoded = xs_replace(encoded, "'", "'");
21+
22+ // Restore only <br>. Probably safe. Let's hope nothing goes wrong with this.
23+ encoded = xs_replace(encoded, "<br>", "<br>");
24+
25+ return encoded;
26+}
27
28 xs_str *xs_crop_i(xs_str *str, int start, int end)
29 /* crops the d_char to be only from start to end */