commit 1c5a689

default  ·  2023-07-11 17:45:58 +0000 UTC
parent a5272a2
Fixed some memory leaks.
4 files changed,  +82, -59
M html.c
M snac.h
M xs.h
+16, -0
 1@@ -238,3 +238,19 @@ xs_str *sanitize(const char *content)
 2 
 3     return s;
 4 }
 5+
 6+
 7+xs_str *encode_html(const char *str)
 8+/* escapes html characters */
 9+{
10+    xs_str *encoded = xs_replace(str, "&", "&");
11+    encoded = xs_replace_i(encoded, "<", "&lt;");
12+    encoded = xs_replace_i(encoded, ">", "&gt;");
13+    encoded = xs_replace_i(encoded, "\"", "&#34;");
14+    encoded = xs_replace_i(encoded, "'", "&#39;");
15+
16+    /* Restore only <br>. Probably safe. Let's hope nothing goes wrong with this. */
17+    encoded = xs_replace_i(encoded, "&lt;br&gt;", "<br>");
18+
19+    return encoded;
20+}
M html.c
+65, -44
  1@@ -52,7 +52,7 @@ xs_str *actor_name(xs_dict *actor)
  2         }
  3     }
  4 
  5-    name = xs_dup(v);
  6+    name = encode_html(v);
  7 
  8     /* replace the :shortnames: */
  9     if (!xs_is_null(p = xs_dict_get(actor, "tag"))) {
 10@@ -105,7 +105,7 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
 11 
 12     {
 13         xs *s1 = xs_fmt("<a href=\"%s\" class=\"p-author h-card snac-author\">%s</a>",
 14-            xs_dict_get(actor, "id"), xs_encode_html(name));
 15+            xs_dict_get(actor, "id"), name);
 16         s = xs_str_cat(s, s1);
 17     }
 18 
 19@@ -137,9 +137,11 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
 20             date_title = xs_str_cat(date_title, udate);
 21         }
 22 
 23+        xs *edt = encode_html(date_title);
 24+        xs *edl = encode_html(date_label);
 25         xs *s1 = xs_fmt(
 26             "\n<time class=\"dt-published snac-pubdate\" title=\"%s\">%s</time>\n",
 27-                xs_encode_html(date_title), xs_encode_html(date_label));
 28+                edt, edl);
 29 
 30         s = xs_str_cat(s, s1);
 31     }
 32@@ -162,9 +164,10 @@ xs_str *html_actor_icon(xs_str *os, char *actor,
 33         xs *domain = xs_split(id, "/");
 34         xs *user   = xs_fmt("@%s@%s", username, xs_list_get(domain, 2));
 35 
 36+        xs *u1 = encode_html(user);
 37         s1 = xs_fmt(
 38             "<br><a href=\"%s\" class=\"p-author-tag h-card snac-author-tag\">%s</a>",
 39-                xs_dict_get(actor, "id"), xs_encode_html(user));
 40+                xs_dict_get(actor, "id"), u1);
 41 
 42         s = xs_str_cat(s, s1);
 43     }
 44@@ -244,10 +247,10 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
 45     }
 46 
 47     {
 48-        xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n",
 49-            xs_encode_html(xs_dict_get(snac->config, "name")),
 50-            xs_encode_html(snac->uid),
 51-            xs_encode_html(xs_dict_get(srv_config,   "host")));
 52+        xs *es1 = encode_html(xs_dict_get(snac->config, "name"));
 53+        xs *es2 = encode_html(snac->uid);
 54+        xs *es3 = encode_html(xs_dict_get(srv_config,   "host"));
 55+        xs *s1 = xs_fmt("<title>%s (@%s@%s)</title>\n", es1, es2, es3);
 56 
 57         s = xs_str_cat(s, s1);
 58     }
 59@@ -277,6 +280,13 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
 60         }
 61 
 62         /* og properties */
 63+        xs *es1 = encode_html(xs_dict_get(srv_config, "host"));
 64+        xs *es2 = encode_html(xs_dict_get(snac->config, "name"));
 65+        xs *es3 = encode_html(snac->uid);
 66+        xs *es4 = encode_html(xs_dict_get(srv_config, "host"));
 67+        xs *es5 = encode_html(s_bio);
 68+        xs *es6 = encode_html(s_avatar);
 69+
 70         xs *s1 = xs_fmt(
 71             "<meta property=\"og:site_name\" content=\"%s\"/>\n"
 72             "<meta property=\"og:title\" content=\"%s (@%s@%s)\"/>\n"
 73@@ -284,12 +294,7 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
 74             "<meta property=\"og:image\" content=\"%s\"/>\n"
 75             "<meta property=\"og:image:width\" content=\"300\"/>\n"
 76             "<meta property=\"og:image:height\" content=\"300\"/>\n",
 77-            xs_encode_html(xs_dict_get(srv_config, "host")),
 78-            xs_encode_html(xs_dict_get(snac->config, "name")),
 79-            xs_encode_html(snac->uid),
 80-            xs_encode_html(xs_dict_get(srv_config, "host")),
 81-            xs_encode_html(s_bio),
 82-            xs_encode_html(s_avatar));
 83+            es1, es2, es3, es4, es5, es6);
 84         s = xs_str_cat(s, s1);
 85     }
 86 
 87@@ -354,17 +359,19 @@ d_char *html_user_header(snac *snac, d_char *s, int local)
 88             "<p class=\"p-name snac-top-user-name\">%s</p>\n"
 89             "<p class=\"snac-top-user-id\">@%s@%s</p>\n";
 90 
 91-        xs *s1 = xs_fmt(_tmpl,
 92-            xs_encode_html(xs_dict_get(snac->config, "name")),
 93-            xs_encode_html(xs_dict_get(snac->config, "uid")), xs_encode_html(xs_dict_get(srv_config, "host"))
 94-        );
 95+        xs *es1 = encode_html(xs_dict_get(snac->config, "name"));
 96+        xs *es2 = encode_html(xs_dict_get(snac->config, "uid"));
 97+        xs *es3 = encode_html(xs_dict_get(srv_config, "host"));
 98+
 99+        xs *s1 = xs_fmt(_tmpl, es1, es2, es3);
100 
101         s = xs_str_cat(s, s1);
102 
103         if (local) {
104-            xs *bio1 = not_really_markdown(xs_encode_html(xs_dict_get(snac->config, "bio")), NULL);
105+            xs *es1 = encode_html(xs_dict_get(snac->config, "bio"));
106+            xs *bio1 = not_really_markdown(es1, NULL);
107             xs *tags = xs_list_new();
108-            xs *bio2 = xs_encode_html(process_tags(snac, bio1, &tags));
109+            xs *bio2 = encode_html(process_tags(snac, bio1, &tags));
110             xs *s1   = xs_fmt("<div class=\"p-note snac-top-user-bio\">%s</div>\n", bio2);
111 
112             s = xs_str_cat(s, s1);
113@@ -911,10 +918,11 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
114 
115         if (xs_list_in(boosts, snac->md5) != -1) {
116             /* we boosted this */
117+            xs *es1 = encode_html(xs_dict_get(snac->config, "name"));
118             xs *s1 = xs_fmt(
119                 "<div class=\"snac-origin\">"
120                 "<a href=\"%s\">%s</a> %s</a></div>",
121-                snac->actor, xs_encode_html(xs_dict_get(snac->config, "name")), L("boosted")
122+                snac->actor, es1, L("boosted")
123             );
124 
125             s = xs_str_cat(s, s1);
126@@ -928,7 +936,7 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
127                     "<div class=\"snac-origin\">"
128                     "<a href=\"%s\">%s</a> %s</div>\n",
129                     xs_dict_get(actor_r, "id"),
130-                    xs_encode_html(name),
131+                    name,
132                     L("boosted")
133                 );
134 
135@@ -967,7 +975,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
136         char *cw = xs_dict_get(snac->config, "cw");
137         if (xs_is_null(cw) || local)
138             cw = "";
139-        xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, xs_encode_html(v), L("SENSITIVE CONTENT"));
140+        xs *es1 = encode_html(v);
141+        xs *s1 = xs_fmt("<details %s><summary>%s [%s]</summary>\n", cw, es1, L("SENSITIVE CONTENT"));
142         s = xs_str_cat(s, s1);
143         sensitive = 1;
144     }
145@@ -1049,7 +1058,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
146 
147                     if (name && replies) {
148                         int nr = xs_number_get(xs_dict_get(replies, "totalItems"));
149-                        xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", xs_encode_html(name), nr);
150+                        xs *es1 = encode_html(name);
151+                        xs *l = xs_fmt("<tr><td>%s:</td><td>%d</td></tr>\n", es1, nr);
152 
153                         c = xs_str_cat(c, l);
154                     }
155@@ -1070,10 +1080,11 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
156                     const char *name = xs_dict_get(v, "name");
157 
158                     if (name) {
159+                        xs *es1 = encode_html(name);
160                         xs *opt = xs_fmt("<input type=\"%s\""
161                                     " id=\"%s\" value=\"%s\" name=\"question\"> %s<br>\n",
162                                     !xs_is_null(oo) ? "radio" : "checkbox",
163-                                    xs_encode_html(name), xs_encode_html(name), xs_encode_html(name));
164+                                    es1, es1, es1);
165 
166                         s1 = xs_str_cat(s1, opt);
167                     }
168@@ -1107,7 +1118,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
169                         /* skip leading zeros */
170                         for (; *p == '0' || *p == ':'; p++);
171 
172-                        xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), xs_encode_html(p));
173+                        xs *es1 = encode_html(p);
174+                        xs *s1 = xs_fmt("<p>%s %s</p>", L("Closes in"), es1);
175                         c = xs_str_cat(c, s1);
176                     }
177                 }
178@@ -1135,8 +1147,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
179                 continue;
180 
181             if (xs_startswith(t, "image/")) {
182-                char *url  = xs_dict_get(v, "url");
183-                char *name = xs_encode_html(xs_dict_get(v, "name"));
184+                char *url = xs_dict_get(v, "url");
185+                xs *name  = encode_html(xs_dict_get(v, "name"));
186 
187                 if (url != NULL) {
188                     if (xs_is_null(name))
189@@ -1150,8 +1162,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
190             }
191             else
192             if (xs_startswith(t, "video/")) {
193-                char *url  = xs_dict_get(v, "url");
194-                char *name = xs_encode_html(xs_dict_get(v, "name"));
195+                char *url = xs_dict_get(v, "url");
196+                xs *name  = encode_html(xs_dict_get(v, "name"));
197 
198                 if (url != NULL) {
199                     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.");
200@@ -1161,8 +1173,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
201             }
202             else
203             if (xs_startswith(t, "audio/")) {
204-                char *url  = xs_dict_get(v, "url");
205-                char *name = xs_encode_html(xs_dict_get(v, "name"));
206+                char *url = xs_dict_get(v, "url");
207+                xs *name  = encode_html(xs_dict_get(v, "name"));
208 
209                 if (url != NULL) {
210                     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.");
211@@ -1171,8 +1183,8 @@ xs_str *html_entry(snac *snac, xs_str *os, const xs_dict *msg, int local,
212                 }
213             }
214             else {
215-                char *url  = xs_dict_get(v, "url");
216-                char *name = xs_encode_html(xs_dict_get(v, "name"));
217+                char *url = xs_dict_get(v, "url");
218+                xs *name  = encode_html(xs_dict_get(v, "name"));
219 
220                 if (url != NULL) {
221                     xs *s1 = xs_fmt("<a href=\"%s\">Attachment: %s</a>", url, name ? name : "No description");
222@@ -1349,7 +1361,8 @@ xs_str *html_timeline(snac *snac, const xs_list *list, int local, int skip, int
223 d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *header, const char *t)
224 {
225     xs *s = xs_str_new(NULL);
226-    xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", xs_encode_html(header));
227+    xs *es1 = encode_html(header);
228+    xs *h = xs_fmt("<h2 class=\"snac-header\">%s</h2>\n", es1);
229     char *p, *actor_id;
230 
231     s = xs_str_cat(s, h);
232@@ -1379,7 +1392,8 @@ d_char *html_people_list(snac *snac, d_char *os, d_char *list, const char *heade
233                 if (xs_startswith(sc, "<p>"))
234                     s = xs_str_cat(s, sc);
235                 else {
236-                    xs *s1 = xs_fmt("<p>%s</p>", xs_encode_html(sc));
237+                    xs *es1 = encode_html(sc);
238+                    xs *s1 = xs_fmt("<p>%s</p>", es1);
239                     s = xs_str_cat(s, s1);
240                 }
241 
242@@ -1549,9 +1563,10 @@ xs_str *html_notifications(snac *snac)
243         if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") == 0)
244             label = L("Unfollow");
245 
246+        xs *es1 = encode_html(label);
247         xs *s1 = xs_fmt("<div class=\"snac-post-with-desc\">\n"
248                         "<p><b>%s by <a href=\"%s\">%s</a></b>:</p>\n",
249-            xs_encode_html(label), actor_id, xs_encode_html(a_name));
250+            es1, actor_id, a_name);
251         s = xs_str_cat(s, s1);
252 
253         if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0) {
254@@ -1776,7 +1791,10 @@ int html_get_handler(const xs_dict *req, const char *q_path,
255         xs *bio   = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL);
256         char *p, *v;
257 
258-
259+        xs *es1 = encode_html(xs_dict_get(snac.config, "name"));
260+        xs *es2 = encode_html(snac.uid);
261+        xs *es3 = encode_html(xs_dict_get(srv_config, "host"));
262+        xs *es4 = encode_html(bio);
263         rss = xs_fmt(
264             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
265             "<rss version=\"0.91\">\n"
266@@ -1785,11 +1803,11 @@ int html_get_handler(const xs_dict *req, const char *q_path,
267             "<language>en</language>\n"
268             "<link>%s.rss</link>\n"
269             "<description>%s</description>\n",
270-            xs_encode_html(xs_dict_get(snac.config, "name")),
271-            xs_encode_html(snac.uid),
272-            xs_encode_html(xs_dict_get(srv_config, "host")),
273+            es1,
274+            es2,
275+            es3,
276             snac.actor,
277-            xs_encode_html(bio)
278+            es4
279         );
280 
281         p = elems;
282@@ -1804,20 +1822,23 @@ int html_get_handler(const xs_dict *req, const char *q_path,
283             if (!xs_startswith(id, snac.actor))
284                 continue;
285 
286-            xs *content = xs_encode_html(sanitize(xs_dict_get(msg, "content")));
287+            xs *es1     = sanitize(xs_dict_get(msg, "content"));
288+            xs *content = encode_html(es1);
289             xs *title   = xs_str_new(NULL);
290             int i;
291 
292             for (i = 0; content[i] && content[i] != '<' && content[i] != '&' && i < 40; i++)
293                 title = xs_append_m(title, &content[i], 1);
294 
295+            xs *es11 = encode_html(title);
296+            xs *es12 = encode_html(content);
297             xs *s = xs_fmt(
298                 "<item>\n"
299                 "<title>%s...</title>\n"
300                 "<link>%s</link>\n"
301                 "<description>%s</description>\n"
302                 "</item>\n",
303-                xs_encode_html(title), id, xs_encode_html(content)
304+                es11, id, es12
305             );
306 
307             rss = xs_str_cat(rss, s);
M snac.h
+1, -0
1@@ -251,6 +251,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2 
3 xs_str *not_really_markdown(const char *content, xs_list **attach);
4 xs_str *sanitize(const char *content);
5+xs_str *encode_html(const char *str);
6 
7 int html_get_handler(const xs_dict *req, const char *q_path,
8                      char **body, int *b_size, char **ctype, xs_str **etag);
M xs.h
+0, -15
 1@@ -72,7 +72,6 @@ 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@@ -507,20 +506,6 @@ 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, "&", "&amp;");
17-    encoded = xs_replace(encoded, "<", "&lt;");
18-    encoded = xs_replace(encoded, ">", "&gt;");
19-    encoded = xs_replace(encoded, "\"", "&#34;");
20-    encoded = xs_replace(encoded, "'", "&#39;");
21-
22-    // Restore only <br>. Probably safe. Let's hope nothing goes wrong with this.
23-    encoded = xs_replace(encoded, "&lt;br&gt;", "<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 */