commit 4777fc8
default
·
2024-05-21 12:12:15 +0000 UTC
parent b95fbe4
Added const everywhere.
20 files changed,
+549,
-580
+106,
-177
1@@ -67,7 +67,7 @@ int activitypub_request(snac *user, const char *url, xs_dict **data)
2 xs *response = NULL;
3 xs *payload = NULL;
4 int p_size;
5- char *ctype;
6+ const char *ctype;
7
8 *data = NULL;
9
10@@ -154,20 +154,21 @@ int actor_request(snac *user, const char *actor, xs_dict **data)
11 }
12
13
14-char *get_atto(const xs_dict *msg)
15+const char *get_atto(const xs_dict *msg)
16 /* gets the attributedTo field (an actor) */
17 {
18- char *actor = xs_dict_get(msg, "attributedTo");
19+ const xs_val *actor = xs_dict_get(msg, "attributedTo");
20
21 /* if the actor is a list of objects (like on Peertube videos), pick the Person */
22 if (xs_type(actor) == XSTYPE_LIST) {
23- xs_list *p = actor;
24+ const xs_list *p = actor;
25+ int c = 0;
26 xs_dict *v;
27 actor = NULL;
28
29- while (actor == NULL && xs_list_iter(&p, &v)) {
30+ while (actor == NULL && xs_list_next(p, &v, &c)) {
31 if (xs_type(v) == XSTYPE_DICT) {
32- char *type = xs_dict_get(v, "type");
33+ const char *type = xs_dict_get(v, "type");
34 if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) {
35 actor = xs_dict_get(v, "id");
36
37@@ -186,7 +187,7 @@ xs_list *get_attachments(const xs_dict *msg)
38 /* unify the garbage fire that are the attachments */
39 {
40 xs_list *l = xs_list_new();
41- xs_list *p;
42+ const xs_list *p;
43
44 /* try first the attachments list */
45 if (!xs_is_null(p = xs_dict_get(msg, "attachment"))) {
46@@ -203,23 +204,24 @@ xs_list *get_attachments(const xs_dict *msg)
47
48 if (xs_type(attach) == XSTYPE_LIST) {
49 /* does the message have an image? */
50- if (xs_type(v = xs_dict_get(msg, "image")) == XSTYPE_DICT) {
51+ const xs_dict *d = xs_dict_get(msg, "image");
52+ if (xs_type(d) == XSTYPE_DICT) {
53 /* add it to the attachment list */
54- attach = xs_list_append(attach, v);
55+ attach = xs_list_append(attach, d);
56 }
57 }
58
59 /* now iterate the list */
60- p = attach;
61- while (xs_list_iter(&p, &v)) {
62- char *type = xs_dict_get(v, "mediaType");
63+ int c = 0;
64+ while (xs_list_next(attach, &v, &c)) {
65+ const char *type = xs_dict_get(v, "mediaType");
66 if (xs_is_null(type))
67 type = xs_dict_get(v, "type");
68
69 if (xs_is_null(type))
70 continue;
71
72- char *href = xs_dict_get(v, "url");
73+ const char *href = xs_dict_get(v, "url");
74 if (xs_is_null(href))
75 href = xs_dict_get(v, "href");
76 if (xs_is_null(href))
77@@ -233,7 +235,7 @@ xs_list *get_attachments(const xs_dict *msg)
78 type = mt;
79 }
80
81- char *name = xs_dict_get(v, "name");
82+ const char *name = xs_dict_get(v, "name");
83 if (xs_is_null(name))
84 name = xs_dict_get(msg, "name");
85 if (xs_is_null(name))
86@@ -252,29 +254,31 @@ xs_list *get_attachments(const xs_dict *msg)
87 p = xs_dict_get(msg, "url");
88
89 if (xs_type(p) == XSTYPE_LIST) {
90- char *href = NULL;
91- char *type = NULL;
92+ const char *href = NULL;
93+ const char *type = NULL;
94+ int c = 0;
95 xs_val *v;
96
97- while (href == NULL && xs_list_iter(&p, &v)) {
98+ while (href == NULL && xs_list_next(p, &v, &c)) {
99 if (xs_type(v) == XSTYPE_DICT) {
100- char *mtype = xs_dict_get(v, "type");
101+ const char *mtype = xs_dict_get(v, "type");
102
103 if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "Link") == 0) {
104 mtype = xs_dict_get(v, "mediaType");
105- xs_list *tag = xs_dict_get(v, "tag");
106+ const xs_list *tag = xs_dict_get(v, "tag");
107
108 if (xs_type(mtype) == XSTYPE_STRING &&
109 strcmp(mtype, "application/x-mpegURL") == 0 &&
110 xs_type(tag) == XSTYPE_LIST) {
111 /* now iterate the tag list, looking for a video URL */
112 xs_dict *d;
113+ int c = 0;
114
115- while (href == NULL && xs_list_iter(&tag, &d)) {
116+ while (href == NULL && xs_list_next(tag, &d, &c)) {
117 if (xs_type(d) == XSTYPE_DICT) {
118 if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING &&
119 xs_startswith(mtype, "video/")) {
120- char *h = xs_dict_get(d, "href");
121+ const char *h = xs_dict_get(d, "href");
122
123 /* this is probably it */
124 if (xs_type(h) == XSTYPE_STRING) {
125@@ -303,7 +307,7 @@ xs_list *get_attachments(const xs_dict *msg)
126 }
127
128
129-int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
130+int timeline_request(snac *snac, const char **id, xs_str **wrk, int level)
131 /* ensures that an entry and its ancestors are in the timeline */
132 {
133 int status = 0;
134@@ -323,7 +327,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
135 status = activitypub_request(snac, *id, &msg);
136
137 if (valid_status(status)) {
138- xs_dict *object = msg;
139+ const xs_dict *object = msg;
140 const char *type = xs_dict_get(object, "type");
141
142 /* get the id again from the object, as it may be different */
143@@ -369,7 +373,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
144 }
145
146 /* does it have an ancestor? */
147- char *in_reply_to = xs_dict_get(object, "inReplyTo");
148+ const char *in_reply_to = xs_dict_get(object, "inReplyTo");
149
150 /* store */
151 timeline_add(snac, nid, object);
152@@ -381,83 +385,12 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
153 }
154 }
155 }
156-
157- enqueue_request_replies(snac, *id);
158 }
159
160 return status;
161 }
162
163
164-void timeline_request_replies(snac *user, const char *id)
165-/* requests all replies of a message */
166-/* FIXME: experimental -- needs more testing */
167-{
168- /* FIXME: TEMPORARILY DISABLED */
169- /* Reason: I've found that many of the posts in the 'replies' Collection
170- do not have an inReplyTo field (why??? aren't they 'replies'???).
171- For this reason, these requested objects are not stored as children
172- of the original post and they are shown as out-of-context, top level posts.
173- This process is disabled until I find an elegant way of providing a parent
174- for these 'stray' children. */
175- return;
176-
177- xs *msg = NULL;
178-
179- if (!valid_status(object_get(id, &msg)))
180- return;
181-
182- /* does it have a replies collection? */
183- const xs_dict *replies = xs_dict_get(msg, "replies");
184-
185- if (!xs_is_null(replies)) {
186- const char *type = xs_dict_get(replies, "type");
187- const char *first = xs_dict_get(replies, "first");
188-
189- if (!xs_is_null(type) && !xs_is_null(first) && strcmp(type, "Collection") == 0) {
190- const char *next = xs_dict_get(first, "next");
191-
192- if (!xs_is_null(next)) {
193- xs *rpls = NULL;
194- int status = activitypub_request(user, next, &rpls);
195-
196- /* request the Collection of replies */
197- if (valid_status(status)) {
198- xs_list *items = xs_dict_get(rpls, "items");
199-
200- if (xs_type(items) == XSTYPE_LIST) {
201- xs_val *v;
202-
203- /* request them all */
204- while (xs_list_iter(&items, &v)) {
205- if (xs_type(v) == XSTYPE_DICT) {
206- /* not an id, but the object itself (!) */
207- const char *c_id = xs_dict_get(v, "id");
208-
209- if (!xs_is_null(id)) {
210- snac_debug(user, 0, xs_fmt("embedded reply %s", c_id));
211-
212- object_add(c_id, v);
213-
214- /* get its own children */
215- timeline_request_replies(user, v);
216- }
217- }
218- else {
219- snac_debug(user, 0, xs_fmt("request reply %s", v));
220- timeline_request(user, &v, NULL, 0);
221- }
222- }
223- }
224- }
225- else
226- snac_debug(user, 0, xs_fmt("replies request error %s %d", next, status));
227- }
228- }
229- }
230-}
231-
232-
233 int send_to_inbox_raw(const char *keyid, const char *seckey,
234 const xs_str *inbox, const xs_dict *msg,
235 xs_val **payload, int *p_size, int timeout)
236@@ -480,7 +413,7 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg,
237 xs_val **payload, int *p_size, int timeout)
238 /* sends a message to an Inbox */
239 {
240- char *seckey = xs_dict_get(snac->key, "secret");
241+ const char *seckey = xs_dict_get(snac->key, "secret");
242
243 return send_to_inbox_raw(snac->actor, seckey, inbox, msg, payload, p_size, timeout);
244 }
245@@ -490,7 +423,7 @@ xs_str *get_actor_inbox(const char *actor)
246 /* gets an actor's inbox */
247 {
248 xs *data = NULL;
249- char *v = NULL;
250+ const char *v = NULL;
251
252 if (valid_status(actor_request(NULL, actor, &data))) {
253 /* try first endpoints/sharedInbox */
254@@ -539,16 +472,16 @@ void post_message(snac *snac, const char *actor, const xs_dict *msg)
255 xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
256 /* returns the list of recipients for a message */
257 {
258- char *to = xs_dict_get(msg, "to");
259- char *cc = xs_dict_get(msg, "cc");
260+ const xs_val *to = xs_dict_get(msg, "to");
261+ const xs_val *cc = xs_dict_get(msg, "cc");
262 xs_set rcpts;
263 int n;
264
265 xs_set_init(&rcpts);
266
267- char *lists[] = { to, cc, NULL };
268+ const xs_list *lists[] = { to, cc, NULL };
269 for (n = 0; lists[n]; n++) {
270- char *l = lists[n];
271+ xs_list *l = (xs_list *)lists[n];
272 char *v;
273 xs *tl = NULL;
274
275@@ -671,13 +604,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
276
277 /* if it's a Follow, it must be explicitly for us */
278 if (xs_match(type, "Follow")) {
279- char *object = xs_dict_get(c_msg, "object");
280+ const char *object = xs_dict_get(c_msg, "object");
281 return !xs_is_null(object) && strcmp(snac->actor, object) == 0;
282 }
283
284 /* only accept Ping directed to us */
285 if (xs_match(type, "Ping")) {
286- char *dest = xs_dict_get(c_msg, "to");
287+ const char *dest = xs_dict_get(c_msg, "to");
288 return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0;
289 }
290
291@@ -692,7 +625,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
292 if (pub_msg && following_check(snac, actor))
293 return 1;
294
295- xs_dict *msg = xs_dict_get(c_msg, "object");
296+ const xs_dict *msg = xs_dict_get(c_msg, "object");
297 xs *rcpts = recipient_list(snac, msg, 0);
298 xs_list *p = rcpts;
299 xs_str *v;
300@@ -704,8 +637,9 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
301 xs *actor_obj = NULL;
302
303 if (valid_status(object_get(actor, &actor_obj))) {
304- if ((v = xs_dict_get(actor_obj, "followers")))
305- actor_followers = xs_dup(v);
306+ const xs_val *fw = xs_dict_get(actor_obj, "followers");
307+ if (fw)
308+ actor_followers = xs_dup(fw);
309 }
310 }
311
312@@ -728,13 +662,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
313 }
314
315 /* accept if it's by someone we follow */
316- char *atto = get_atto(msg);
317+ const char *atto = get_atto(msg);
318
319 if (pub_msg && !xs_is_null(atto) && following_check(snac, atto))
320 return 3;
321
322 /* is this message a reply to another? */
323- char *irt = xs_dict_get(msg, "inReplyTo");
324+ const char *irt = xs_dict_get(msg, "inReplyTo");
325 if (!xs_is_null(irt)) {
326 xs *r_msg = NULL;
327
328@@ -987,8 +921,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
329
330 /* telegram */
331
332- char *bot = xs_dict_get(snac->config, "telegram_bot");
333- char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
334+ const char *bot = xs_dict_get(snac->config, "telegram_bot");
335+ const char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
336
337 if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id)
338 enqueue_telegram(body, bot, chat_id);
339@@ -1001,8 +935,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
340 objid = actor;
341
342 /* ntfy */
343- char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
344- char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
345+ const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
346+ const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
347
348 if (!xs_is_null(ntfy_server) && *ntfy_server)
349 enqueue_ntfy(body, ntfy_server, ntfy_token);
350@@ -1088,7 +1022,7 @@ xs_dict *msg_base(snac *snac, const char *type, const char *id,
351 }
352
353
354-xs_dict *msg_collection(snac *snac, char *id)
355+xs_dict *msg_collection(snac *snac, const char *id)
356 /* creates an empty OrderedCollection message */
357 {
358 xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL);
359@@ -1102,7 +1036,7 @@ xs_dict *msg_collection(snac *snac, char *id)
360 }
361
362
363-xs_dict *msg_accept(snac *snac, char *object, char *to)
364+xs_dict *msg_accept(snac *snac, const xs_val *object, const char *to)
365 /* creates an Accept message (as a response to a Follow) */
366 {
367 xs_dict *msg = msg_base(snac, "Accept", "@dummy", snac->actor, NULL, object);
368@@ -1113,12 +1047,12 @@ xs_dict *msg_accept(snac *snac, char *object, char *to)
369 }
370
371
372-xs_dict *msg_update(snac *snac, xs_dict *object)
373+xs_dict *msg_update(snac *snac, const xs_dict *object)
374 /* creates an Update message */
375 {
376 xs_dict *msg = msg_base(snac, "Update", "@object", snac->actor, "@now", object);
377
378- char *type = xs_dict_get(object, "type");
379+ const char *type = xs_dict_get(object, "type");
380
381 if (strcmp(type, "Note") == 0) {
382 msg = xs_dict_append(msg, "to", xs_dict_get(object, "to"));
383@@ -1141,7 +1075,7 @@ xs_dict *msg_update(snac *snac, xs_dict *object)
384 }
385
386
387-xs_dict *msg_admiration(snac *snac, char *object, char *type)
388+xs_dict *msg_admiration(snac *snac, const char *object, const char *type)
389 /* creates a Like or Announce message */
390 {
391 xs *a_msg = NULL;
392@@ -1172,7 +1106,7 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type)
393 }
394
395
396-xs_dict *msg_repulsion(snac *user, char *id, char *type)
397+xs_dict *msg_repulsion(snac *user, const char *id, const char *type)
398 /* creates an Undo + admiration message */
399 {
400 xs *a_msg = NULL;
401@@ -1210,7 +1144,7 @@ xs_dict *msg_actor(snac *snac)
402 xs *kid = NULL;
403 xs *f_bio = NULL;
404 xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL);
405- char *p;
406+ const char *p;
407 int n;
408
409 /* change the @context (is this really necessary?) */
410@@ -1268,7 +1202,7 @@ xs_dict *msg_actor(snac *snac)
411 }
412
413 /* add the metadata as attachments of PropertyValue */
414- xs_dict *metadata = xs_dict_get(snac->config, "metadata");
415+ const xs_dict *metadata = xs_dict_get(snac->config, "metadata");
416 if (xs_type(metadata) == XSTYPE_DICT) {
417 xs *attach = xs_list_new();
418 xs_str *k;
419@@ -1314,7 +1248,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
420 /* creates a 'Create' message */
421 {
422 xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object);
423- xs_val *v;
424+ const xs_val *v;
425
426 if ((v = get_atto(object)))
427 msg = xs_dict_append(msg, "attributedTo", v);
428@@ -1331,7 +1265,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
429 }
430
431
432-xs_dict *msg_undo(snac *snac, char *object)
433+xs_dict *msg_undo(snac *snac, const xs_val *object)
434 /* creates an 'Undo' message */
435 {
436 xs_dict *msg = msg_base(snac, "Undo", "@object", snac->actor, "@now", object);
437@@ -1344,7 +1278,7 @@ xs_dict *msg_undo(snac *snac, char *object)
438 }
439
440
441-xs_dict *msg_delete(snac *snac, char *id)
442+xs_dict *msg_delete(snac *snac, const char *id)
443 /* creates a 'Delete' + 'Tombstone' for a local entry */
444 {
445 xs *tomb = xs_dict_new();
446@@ -1386,7 +1320,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
447
448 if (valid_status(status)) {
449 /* check if the actor is an alias */
450- char *r_actor = xs_dict_get(actor_o, "id");
451+ const char *r_actor = xs_dict_get(actor_o, "id");
452
453 if (r_actor && strcmp(actor, r_actor) != 0) {
454 snac_log(snac, xs_fmt("actor to follow is an alias %s -> %s", actor, r_actor));
455@@ -1402,7 +1336,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
456
457
458 xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
459- xs_str *in_reply_to, xs_list *attach, int priv)
460+ const xs_str *in_reply_to, const xs_list *attach, int priv)
461 /* creates a 'Note' message */
462 {
463 xs *ntid = tid(0);
464@@ -1442,7 +1376,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
465
466 if (valid_status(object_get(in_reply_to, &p_msg))) {
467 /* add this author as recipient */
468- char *a, *v;
469+ const char *a, *v;
470
471 if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1)
472 to = xs_list_append(to, a);
473@@ -1453,7 +1387,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
474 xs *actor_o = NULL;
475
476 if (xs_list_len(l) > 3 && valid_status(object_get(a, &actor_o))) {
477- char *uname = xs_dict_get(actor_o, "preferredUsername");
478+ const char *uname = xs_dict_get(actor_o, "preferredUsername");
479
480 if (!xs_is_null(uname) && *uname) {
481 xs *handle = xs_fmt("@%s@%s", uname, xs_list_get(l, 2));
482@@ -1492,7 +1426,8 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
483
484 /* create the attachment list, if there are any */
485 if (!xs_is_null(attach)) {
486- while (xs_list_iter(&attach, &v)) {
487+ int c = 0;
488+ while (xs_list_next(attach, &v, &c)) {
489 xs *d = xs_dict_new();
490 const char *url = xs_list_get(v, 0);
491 const char *alt = xs_list_get(v, 1);
492@@ -1515,7 +1450,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
493 p = tag;
494 while (xs_list_iter(&p, &v)) {
495 if (xs_type(v) == XSTYPE_DICT) {
496- char *t;
497+ const char *t;
498
499 if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) {
500 if (!xs_is_null(t = xs_dict_get(v, "href")))
501@@ -1639,7 +1574,7 @@ int update_question(snac *user, const char *id)
502 xs *msg = NULL;
503 xs *rcnt = xs_dict_new();
504 xs *lopts = xs_list_new();
505- xs_list *opts;
506+ const xs_list *opts;
507 xs_list *p;
508 xs_val *v;
509
510@@ -1657,8 +1592,8 @@ int update_question(snac *user, const char *id)
511 return -3;
512
513 /* fill the initial count */
514- p = opts;
515- while (xs_list_iter(&p, &v)) {
516+ int c = 0;
517+ while (xs_list_next(opts, &v, &c)) {
518 const char *name = xs_dict_get(v, "name");
519 if (name) {
520 lopts = xs_list_append(lopts, name);
521@@ -1764,13 +1699,13 @@ int update_question(snac *user, const char *id)
522
523 /** queues **/
524
525-int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
526+int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
527 /* processes an ActivityPub message from the input queue */
528 /* return values: -1, fatal error; 0, transient error, retry;
529 1, processed and done; 2, propagate to users (only when no user is set) */
530 {
531- char *actor = xs_dict_get(msg, "actor");
532- char *type = xs_dict_get(msg, "type");
533+ const char *actor = xs_dict_get(msg, "actor");
534+ const char *type = xs_dict_get(msg, "type");
535 xs *actor_o = NULL;
536 int a_status;
537 int do_notify = 0;
538@@ -1790,7 +1725,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
539 return -1;
540 }
541
542- char *object, *utype;
543+ const char *object, *utype;
544
545 object = xs_dict_get(msg, "object");
546 if (object != NULL && xs_type(object) == XSTYPE_DICT)
547@@ -1813,7 +1748,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
548 }
549
550 /* also discard if the object to be deleted is not here */
551- char *obj_id = object;
552+ const char *obj_id = object;
553 if (xs_type(obj_id) == XSTYPE_DICT)
554 obj_id = xs_dict_get(obj_id, "id");
555
556@@ -1885,7 +1820,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
557 int min_account_age = xs_number_get(xs_dict_get(srv_config, "min_account_age"));
558
559 if (min_account_age > 0) {
560- char *actor_date = xs_dict_get(actor_o, "published");
561+ const char *actor_date = xs_dict_get(actor_o, "published");
562 if (!xs_is_null(actor_date)) {
563 time_t actor_t = xs_parse_iso_date(actor_date, 0);
564
565@@ -1945,7 +1880,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
566 }
567 else
568 if (strcmp(type, "Undo") == 0) { /** **/
569- char *id = xs_dict_get(object, "object");
570+ const char *id = xs_dict_get(object, "object");
571
572 if (xs_type(object) != XSTYPE_DICT)
573 utype = "Follow";
574@@ -1990,9 +1925,9 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
575 }
576
577 if (xs_match(utype, "Note|Article")) { /** **/
578- char *id = xs_dict_get(object, "id");
579- char *in_reply_to = xs_dict_get(object, "inReplyTo");
580- char *atto = get_atto(object);
581+ const char *id = xs_dict_get(object, "id");
582+ const char *in_reply_to = xs_dict_get(object, "inReplyTo");
583+ const char *atto = get_atto(object);
584 xs *wrk = NULL;
585
586 if (xs_is_null(id))
587@@ -2029,14 +1964,14 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
588 }
589 else
590 if (strcmp(utype, "Question") == 0) { /** **/
591- char *id = xs_dict_get(object, "id");
592+ const char *id = xs_dict_get(object, "id");
593
594 if (timeline_add(snac, id, object))
595 snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id));
596 }
597 else
598 if (strcmp(utype, "Video") == 0) { /** **/
599- char *id = xs_dict_get(object, "id");
600+ const char *id = xs_dict_get(object, "id");
601
602 if (timeline_add(snac, id, object))
603 snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id));
604@@ -2212,7 +2147,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
605 }
606
607
608-int send_email(char *msg)
609+int send_email(const char *msg)
610 /* invoke sendmail with email headers and body in msg */
611 {
612 FILE *f;
613@@ -2244,14 +2179,14 @@ int send_email(char *msg)
614 void process_user_queue_item(snac *snac, xs_dict *q_item)
615 /* processes an item from the user queue */
616 {
617- char *type;
618+ const char *type;
619 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
620
621 if ((type = xs_dict_get(q_item, "type")) == NULL)
622 type = "output";
623
624 if (strcmp(type, "message") == 0) {
625- xs_dict *msg = xs_dict_get(q_item, "message");
626+ const xs_dict *msg = xs_dict_get(q_item, "message");
627 xs *rcpts = recipient_list(snac, msg, 1);
628 xs_set inboxes;
629 xs_list *p;
630@@ -2292,8 +2227,8 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
631 else
632 if (strcmp(type, "input") == 0) {
633 /* process the message */
634- xs_dict *msg = xs_dict_get(q_item, "message");
635- xs_dict *req = xs_dict_get(q_item, "req");
636+ const xs_dict *msg = xs_dict_get(q_item, "message");
637+ const xs_dict *req = xs_dict_get(q_item, "req");
638 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
639
640 if (xs_is_null(msg))
641@@ -2320,13 +2255,6 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
642 update_question(snac, id);
643 }
644 else
645- if (strcmp(type, "request_replies") == 0) {
646- const char *id = xs_dict_get(q_item, "message");
647-
648- if (!xs_is_null(id))
649- timeline_request_replies(snac, id);
650- }
651- else
652 if (strcmp(type, "object_request") == 0) {
653 const char *id = xs_dict_get(q_item, "message");
654
655@@ -2395,15 +2323,15 @@ int process_user_queue(snac *snac)
656 void process_queue_item(xs_dict *q_item)
657 /* processes an item from the global queue */
658 {
659- char *type = xs_dict_get(q_item, "type");
660+ const char *type = xs_dict_get(q_item, "type");
661 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
662
663 if (strcmp(type, "output") == 0) {
664 int status;
665- xs_str *inbox = xs_dict_get(q_item, "inbox");
666- xs_str *keyid = xs_dict_get(q_item, "keyid");
667- xs_str *seckey = xs_dict_get(q_item, "seckey");
668- xs_dict *msg = xs_dict_get(q_item, "message");
669+ const xs_str *inbox = xs_dict_get(q_item, "inbox");
670+ const xs_str *keyid = xs_dict_get(q_item, "keyid");
671+ const xs_str *seckey = xs_dict_get(q_item, "seckey");
672+ const xs_dict *msg = xs_dict_get(q_item, "message");
673 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
674 int p_status = xs_number_get(xs_dict_get(q_item, "p_status"));
675 xs *payload = NULL;
676@@ -2475,7 +2403,7 @@ void process_queue_item(xs_dict *q_item)
677 else
678 if (strcmp(type, "email") == 0) {
679 /* send this email */
680- xs_str *msg = xs_dict_get(q_item, "message");
681+ const xs_str *msg = xs_dict_get(q_item, "message");
682 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
683
684 if (!send_email(msg))
685@@ -2497,8 +2425,8 @@ void process_queue_item(xs_dict *q_item)
686 else
687 if (strcmp(type, "telegram") == 0) {
688 /* send this via telegram */
689- char *bot = xs_dict_get(q_item, "bot");
690- char *msg = xs_dict_get(q_item, "message");
691+ const char *bot = xs_dict_get(q_item, "bot");
692+ const char *msg = xs_dict_get(q_item, "message");
693 xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id"));
694 int status = 0;
695
696@@ -2521,9 +2449,9 @@ void process_queue_item(xs_dict *q_item)
697 else
698 if (strcmp(type, "ntfy") == 0) {
699 /* send this via ntfy */
700- char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
701- char *msg = xs_dict_get(q_item, "message");
702- char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
703+ const char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
704+ const char *msg = xs_dict_get(q_item, "message");
705+ const char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
706 int status = 0;
707
708 xs *url = xs_fmt("%s", ntfy_server);
709@@ -2552,8 +2480,8 @@ void process_queue_item(xs_dict *q_item)
710 }
711 else
712 if (strcmp(type, "input") == 0) {
713- xs_dict *msg = xs_dict_get(q_item, "message");
714- xs_dict *req = xs_dict_get(q_item, "req");
715+ const xs_dict *msg = xs_dict_get(q_item, "message");
716+ const xs_dict *req = xs_dict_get(q_item, "req");
717 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
718
719 /* do some instance-level checks */
720@@ -2572,7 +2500,7 @@ void process_queue_item(xs_dict *q_item)
721 else
722 if (r == 2) {
723 /* redistribute the input message to all users */
724- char *ntid = xs_dict_get(q_item, "ntid");
725+ const char *ntid = xs_dict_get(q_item, "ntid");
726 xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid);
727 FILE *f;
728
729@@ -2647,7 +2575,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
730 char **body, int *b_size, char **ctype)
731 {
732 int status = 200;
733- char *accept = xs_dict_get(req, "accept");
734+ const char *accept = xs_dict_get(req, "accept");
735 snac snac;
736 xs *msg = NULL;
737
738@@ -2659,7 +2587,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
739 return 0;
740
741 xs *l = xs_split_n(q_path, "/", 2);
742- char *uid, *p_path;
743+ const char *uid;
744+ const char *p_path;
745
746 uid = xs_list_get(l, 1);
747 if (!user_open(&snac, uid)) {
748@@ -2677,7 +2606,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
749 msg = msg_actor(&snac);
750 *ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
751
752- char *ua = xs_dict_get(req, "user-agent");
753+ const char *ua = xs_dict_get(req, "user-agent");
754
755 snac_debug(&snac, 0, xs_fmt("serving actor [%s]", ua ? ua : "No UA"));
756 }
757@@ -2694,8 +2623,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
758 xs *i = NULL;
759
760 if (valid_status(object_get_by_md5(v, &i))) {
761- char *type = xs_dict_get(i, "type");
762- char *id = xs_dict_get(i, "id");
763+ const char *type = xs_dict_get(i, "type");
764+ const char *id = xs_dict_get(i, "id");
765
766 if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) {
767 xs *c_msg = msg_create(&snac, i);
768@@ -2748,9 +2677,9 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
769 (void)b_size;
770
771 int status = 202; /* accepted */
772- char *i_ctype = xs_dict_get(req, "content-type");
773+ const char *i_ctype = xs_dict_get(req, "content-type");
774 snac snac;
775- char *v;
776+ const char *v;
777
778 if (i_ctype == NULL) {
779 *body = xs_str_new("no content-type");
M
data.c
+49,
-81
1@@ -29,7 +29,7 @@ pthread_mutex_t data_mutex = {0};
2 int snac_upgrade(xs_str **error);
3
4
5-int srv_open(char *basedir, int auto_upgrade)
6+int srv_open(const char *basedir, int auto_upgrade)
7 /* opens a server */
8 {
9 int ret = 0;
10@@ -58,10 +58,10 @@ int srv_open(char *basedir, int auto_upgrade)
11 if (srv_config == NULL)
12 error = xs_fmt("ERROR: cannot parse '%s'", cfg_file);
13 else {
14- char *host;
15- char *prefix;
16- char *dbglvl;
17- char *proto;
18+ const char *host;
19+ const char *prefix;
20+ const char *dbglvl;
21+ const char *proto;
22
23 host = xs_dict_get(srv_config, "host");
24 prefix = xs_dict_get(srv_config, "prefix");
25@@ -710,7 +710,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow)
26 fclose(f);
27
28 /* does this object has a parent? */
29- char *in_reply_to = xs_dict_get(obj, "inReplyTo");
30+ const char *in_reply_to = xs_dict_get(obj, "inReplyTo");
31
32 if (!xs_is_null(in_reply_to) && *in_reply_to) {
33 /* update the children index of the parent */
34@@ -1124,7 +1124,7 @@ int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg)
35 }
36
37
38-int timeline_del(snac *snac, char *id)
39+int timeline_del(snac *snac, const char *id)
40 /* deletes a message from the timeline */
41 {
42 /* delete from the user's caches */
43@@ -1192,17 +1192,16 @@ int timeline_admire(snac *snac, const char *id, const char *admirer, int like)
44 }
45
46
47-xs_list *timeline_top_level(snac *snac, xs_list *list)
48+xs_list *timeline_top_level(snac *snac, const xs_list *list)
49 /* returns the top level md5 entries from this index */
50 {
51 xs_set seen;
52- xs_list *p;
53 xs_str *v;
54
55 xs_set_init(&seen);
56
57- p = list;
58- while (xs_list_iter(&p, &v)) {
59+ int c = 0;
60+ while (xs_list_next(list, &v, &c)) {
61 char line[256] = "";
62
63 strncpy(line, v, sizeof(line));
64@@ -1290,7 +1289,7 @@ int following_add(snac *snac, const char *actor, const xs_dict *msg)
65 /* object already exists; if it's of type Accept,
66 the actor is already being followed and confirmed,
67 so do nothing */
68- char *type = xs_dict_get(p_object, "type");
69+ const char *type = xs_dict_get(p_object, "type");
70
71 if (!xs_is_null(type) && strcmp(type, "Accept") == 0) {
72 snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor));
73@@ -1546,8 +1545,9 @@ void hide(snac *snac, const char *id)
74
75 /* resolve to get the id */
76 if (valid_status(object_get_by_md5(v, &co))) {
77- if ((v = xs_dict_get(co, "id")) != NULL)
78- hide(snac, v);
79+ const char *id = xs_dict_get(co, "id");
80+ if (id != NULL)
81+ hide(snac, id);
82 }
83 }
84 }
85@@ -1563,7 +1563,7 @@ int is_hidden(snac *snac, const char *id)
86 }
87
88
89-int actor_add(const char *actor, xs_dict *msg)
90+int actor_add(const char *actor, const xs_dict *msg)
91 /* adds an actor */
92 {
93 return object_add_ow(actor, msg);
94@@ -1687,7 +1687,7 @@ int limited(snac *user, const char *id, int cmd)
95 void tag_index(const char *id, const xs_dict *obj)
96 /* update the tag indexes for this object */
97 {
98- xs_list *tags = xs_dict_get(obj, "tag");
99+ const xs_list *tags = xs_dict_get(obj, "tag");
100
101 if (is_msg_public(obj) && xs_type(tags) == XSTYPE_LIST && xs_list_len(tags) > 0) {
102 xs *g_tag_dir = xs_fmt("%s/tag", srv_basedir);
103@@ -1695,9 +1695,10 @@ void tag_index(const char *id, const xs_dict *obj)
104 mkdirx(g_tag_dir);
105
106 xs_dict *v;
107- while (xs_list_iter(&tags, &v)) {
108- char *type = xs_dict_get(v, "type");
109- char *name = xs_dict_get(v, "name");
110+ int ct = 0;
111+ while (xs_list_next(tags, &v, &ct)) {
112+ const char *type = xs_dict_get(v, "type");
113+ const char *name = xs_dict_get(v, "name");
114
115 if (!xs_is_null(type) && !xs_is_null(name) && strcmp(type, "Hashtag") == 0) {
116 while (*name == '#' || *name == '@')
117@@ -1706,7 +1707,7 @@ void tag_index(const char *id, const xs_dict *obj)
118 if (*name == '\0')
119 continue;
120
121- name = xs_tolower_i(name);
122+ name = xs_tolower_i((xs_str *)name);
123
124 xs *md5_tag = xs_md5_hex(name, strlen(name));
125 xs *tag_dir = xs_fmt("%s/%c%c", g_tag_dir, md5_tag[0], md5_tag[1]);
126@@ -1729,7 +1730,7 @@ void tag_index(const char *id, const xs_dict *obj)
127 }
128
129
130-xs_list *tag_search(char *tag, int skip, int show)
131+xs_list *tag_search(const char *tag, int skip, int show)
132 /* returns the list of posts tagged with tag */
133 {
134 if (*tag == '#')
135@@ -1912,7 +1913,7 @@ xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op
136 void list_distribute(snac *user, const char *who, const xs_dict *post)
137 /* distributes the post to all appropriate lists */
138 {
139- char *id = xs_dict_get(post, "id");
140+ const char *id = xs_dict_get(post, "id");
141
142 /* if who is not set, use the attributedTo in the message */
143 if (xs_is_null(who))
144@@ -2164,7 +2165,7 @@ void inbox_add(const char *inbox)
145 void inbox_add_by_actor(const xs_dict *actor)
146 /* collects an actor's shared inbox, if it has one */
147 {
148- char *v;
149+ const char *v;
150
151 if (!xs_is_null(v = xs_dict_get(actor, "endpoints")) &&
152 !xs_is_null(v = xs_dict_get(v, "sharedInbox"))) {
153@@ -2210,7 +2211,7 @@ xs_str *_instance_block_fn(const char *instance)
154 xs *s = xs_replace(instance, "http:/" "/", "");
155 xs *s1 = xs_replace(s, "https:/" "/", "");
156 xs *l = xs_split(s1, "/");
157- char *p = xs_list_get(l, 0);
158+ const char *p = xs_list_get(l, 0);
159 xs *md5 = xs_md5_hex(p, strlen(p));
160
161 return xs_fmt("%s/block/%s", srv_basedir, md5);
162@@ -2279,7 +2280,7 @@ int content_match(const char *file, const xs_dict *msg)
163 xs *fn = xs_fmt("%s/%s", srv_basedir, file);
164 FILE *f;
165 int r = 0;
166- char *v = xs_dict_get(msg, "content");
167+ const char *v = xs_dict_get(msg, "content");
168
169 if (xs_type(v) == XSTYPE_STRING && *v) {
170 if ((f = fopen(fn, "r")) != NULL) {
171@@ -2386,7 +2387,7 @@ xs_list *content_search(snac *user, const char *regex,
172 if (id == NULL || is_hidden(user, id))
173 continue;
174
175- char *content = xs_dict_get(post, "content");
176+ const char *content = xs_dict_get(post, "content");
177
178 if (xs_is_null(content))
179 continue;
180@@ -2639,7 +2640,7 @@ void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retri
181 /* enqueues an input message */
182 {
183 xs *qmsg = _new_qmsg("input", msg, retries);
184- char *ntid = xs_dict_get(qmsg, "ntid");
185+ const char *ntid = xs_dict_get(qmsg, "ntid");
186 xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
187
188 qmsg = xs_dict_append(qmsg, "req", req);
189@@ -2654,7 +2655,7 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries)
190 /* enqueues an input message from the shared input */
191 {
192 xs *qmsg = _new_qmsg("input", msg, retries);
193- char *ntid = xs_dict_get(qmsg, "ntid");
194+ const char *ntid = xs_dict_get(qmsg, "ntid");
195 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
196
197 qmsg = xs_dict_append(qmsg, "req", req);
198@@ -2666,11 +2667,12 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries)
199
200
201 void enqueue_output_raw(const char *keyid, const char *seckey,
202- xs_dict *msg, xs_str *inbox, int retries, int p_status)
203+ const xs_dict *msg, const xs_str *inbox,
204+ int retries, int p_status)
205 /* enqueues an output message to an inbox */
206 {
207 xs *qmsg = _new_qmsg("output", msg, retries);
208- char *ntid = xs_dict_get(qmsg, "ntid");
209+ const char *ntid = xs_dict_get(qmsg, "ntid");
210 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
211
212 xs *ns = xs_number_new(p_status);
213@@ -2690,7 +2692,8 @@ void enqueue_output_raw(const char *keyid, const char *seckey,
214 }
215
216
217-void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status)
218+void enqueue_output(snac *snac, const xs_dict *msg,
219+ const xs_str *inbox, int retries, int p_status)
220 /* enqueues an output message to an inbox */
221 {
222 if (xs_startswith(inbox, snac->actor)) {
223@@ -2698,13 +2701,14 @@ void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_
224 return;
225 }
226
227- char *seckey = xs_dict_get(snac->key, "secret");
228+ const char *seckey = xs_dict_get(snac->key, "secret");
229
230 enqueue_output_raw(snac->actor, seckey, msg, inbox, retries, p_status);
231 }
232
233
234-void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries)
235+void enqueue_output_by_actor(snac *snac, const xs_dict *msg,
236+ const xs_str *actor, int retries)
237 /* enqueues an output message for an actor */
238 {
239 xs *inbox = get_actor_inbox(actor);
240@@ -2716,11 +2720,11 @@ void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int
241 }
242
243
244-void enqueue_email(xs_str *msg, int retries)
245+void enqueue_email(const xs_str *msg, int retries)
246 /* enqueues an email message to be sent */
247 {
248 xs *qmsg = _new_qmsg("email", msg, retries);
249- char *ntid = xs_dict_get(qmsg, "ntid");
250+ const char *ntid = xs_dict_get(qmsg, "ntid");
251 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
252
253 qmsg = _enqueue_put(fn, qmsg);
254@@ -2733,7 +2737,7 @@ void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id)
255 /* enqueues a message to be sent via Telegram */
256 {
257 xs *qmsg = _new_qmsg("telegram", msg, 0);
258- char *ntid = xs_dict_get(qmsg, "ntid");
259+ const char *ntid = xs_dict_get(qmsg, "ntid");
260 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
261
262 qmsg = xs_dict_append(qmsg, "bot", bot);
263@@ -2748,7 +2752,7 @@ void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_t
264 /* enqueues a message to be sent via ntfy */
265 {
266 xs *qmsg = _new_qmsg("ntfy", msg, 0);
267- char *ntid = xs_dict_get(qmsg, "ntid");
268+ const char *ntid = xs_dict_get(qmsg, "ntid");
269 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
270
271 qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server);
272@@ -2764,7 +2768,7 @@ void enqueue_message(snac *snac, const xs_dict *msg)
273 /* enqueues an output message */
274 {
275 xs *qmsg = _new_qmsg("message", msg, 0);
276- char *ntid = xs_dict_get(qmsg, "ntid");
277+ const char *ntid = xs_dict_get(qmsg, "ntid");
278 xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid);
279
280 qmsg = _enqueue_put(fn, qmsg);
281@@ -2807,7 +2811,7 @@ void enqueue_verify_links(snac *user)
282 /* enqueues a link verification */
283 {
284 xs *qmsg = _new_qmsg("verify_links", "", 0);
285- char *ntid = xs_dict_get(qmsg, "ntid");
286+ const char *ntid = xs_dict_get(qmsg, "ntid");
287 xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid);
288
289 qmsg = _enqueue_put(fn, qmsg);
290@@ -2832,42 +2836,6 @@ void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs)
291 }
292
293
294-void enqueue_request_replies(snac *user, const char *id)
295-/* enqueues a request for the replies of a message */
296-{
297- /* test first if this precise request is already in the queue */
298- xs *queue = user_queue(user);
299- xs_list *p = queue;
300- xs_str *v;
301-
302- while (xs_list_iter(&p, &v)) {
303- xs *q_item = queue_get(v);
304-
305- if (q_item != NULL) {
306- const char *type = xs_dict_get(q_item, "type");
307- const char *msg = xs_dict_get(q_item, "message");
308-
309- if (type && msg && strcmp(type, "request_replies") == 0 && strcmp(msg, id) == 0) {
310- /* don't requeue */
311- snac_debug(user, 1, xs_fmt("enqueue_request_replies already here %s", id));
312- return;
313- }
314- }
315- }
316-
317- /* not there; enqueue the request with a small delay */
318- xs *qmsg = _new_qmsg("request_replies", id, 0);
319- xs *ntid = tid(10);
320- xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid);
321-
322- qmsg = xs_dict_set(qmsg, "ntid", ntid);
323-
324- qmsg = _enqueue_put(fn, qmsg);
325-
326- snac_debug(user, 2, xs_fmt("enqueue_request_replies %s", id));
327-}
328-
329-
330 int was_question_voted(snac *user, const char *id)
331 /* returns true if the user voted in this poll */
332 {
333@@ -2881,7 +2849,7 @@ int was_question_voted(snac *user, const char *id)
334 xs *obj = NULL;
335
336 if (valid_status(object_get_by_md5(md5, &obj))) {
337- char *atto = get_atto(obj);
338+ const char *atto = get_atto(obj);
339 if (atto && strcmp(atto, user->actor) == 0 &&
340 !xs_is_null(xs_dict_get(obj, "name"))) {
341 voted = 1;
342@@ -3055,7 +3023,7 @@ void purge_server(void)
343 if (mtime_nl(v2, &n_link) < mt && n_link < 2) {
344 xs *s1 = xs_replace(v2, ".json", "");
345 xs *l = xs_split(s1, "/");
346- char *md5 = xs_list_get(l, -1);
347+ const char *md5 = xs_list_get(l, -1);
348
349 object_del_by_md5(md5);
350 cnt++;
351@@ -3147,7 +3115,7 @@ void purge_user(snac *snac)
352 /* do the purge for this user */
353 {
354 int priv_days, pub_days, user_days = 0;
355- char *v;
356+ const char *v;
357 int n;
358
359 priv_days = xs_number_get(xs_dict_get(srv_config, "timeline_purge_days"));
360@@ -3256,7 +3224,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
361 if (p_size && payload) {
362 xs *payload_fn = NULL;
363 xs *payload_fn_raw = NULL;
364- char *v = xs_dict_get(req, "content-type");
365+ const char *v = xs_dict_get(req, "content-type");
366
367 if (v && xs_str_in(v, "json") != -1) {
368 payload_fn = xs_fmt("%s/payload.json", dir);
369@@ -3287,7 +3255,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
370
371 if (b_size && body) {
372 xs *body_fn = NULL;
373- char *v = xs_dict_get(headers, "content-type");
374+ const char *v = xs_dict_get(headers, "content-type");
375
376 if (v && xs_str_in(v, "json") != -1) {
377 body_fn = xs_fmt("%s/body.json", dir);
378@@ -3356,7 +3324,7 @@ void srv_archive_error(const char *prefix, const xs_str *err,
379 }
380
381
382-void srv_archive_qitem(char *prefix, xs_dict *q_item)
383+void srv_archive_qitem(const char *prefix, xs_dict *q_item)
384 /* archives a q_item in the error folder */
385 {
386 xs *ntid = tid(0);
M
html.c
+143,
-135
1@@ -41,7 +41,7 @@ int login(snac *snac, const xs_dict *headers)
2 }
3
4
5-xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
6+xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems)
7 /* replaces all the :shortnames: with the emojis in tag */
8 {
9 if (!xs_is_null(tag)) {
10@@ -57,18 +57,18 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
11
12 xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems);
13
14- xs_list *p = tag_list;
15 char *v;
16+ int c = 0;
17
18- while (xs_list_iter(&p, &v)) {
19- char *t = xs_dict_get(v, "type");
20+ while (xs_list_next(tag_list, &v, &c)) {
21+ const char *t = xs_dict_get(v, "type");
22
23 if (t && strcmp(t, "Emoji") == 0) {
24- char *n = xs_dict_get(v, "name");
25- char *i = xs_dict_get(v, "icon");
26+ const char *n = xs_dict_get(v, "name");
27+ const char *i = xs_dict_get(v, "icon");
28
29 if (n && i) {
30- char *u = xs_dict_get(i, "url");
31+ const char *u = xs_dict_get(i, "url");
32 xs_html *img = xs_html_sctag("img",
33 xs_html_attr("loading", "lazy"),
34 xs_html_attr("src", u),
35@@ -88,7 +88,7 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems)
36 xs_str *actor_name(xs_dict *actor)
37 /* gets the actor name */
38 {
39- char *v;
40+ const char *v;
41
42 if (xs_is_null((v = xs_dict_get(actor, "name"))) || *v == '\0') {
43 if (xs_is_null(v = xs_dict_get(actor, "preferredUsername")) || *v == '\0') {
44@@ -106,7 +106,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
45 xs_html *actor_icon = xs_html_tag("p", NULL);
46
47 xs *avatar = NULL;
48- char *v;
49+ const char *v;
50 int fwing = 0;
51 int fwer = 0;
52
53@@ -125,7 +125,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
54 if (avatar == NULL)
55 avatar = xs_fmt("data:image/png;base64, %s", default_avatar_base64());
56
57- char *actor_id = xs_dict_get(actor, "id");
58+ const char *actor_id = xs_dict_get(actor, "id");
59 xs *href = NULL;
60
61 if (user) {
62@@ -216,7 +216,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
63 }
64
65 {
66- char *username, *id;
67+ const char *username, *id;
68
69 if (xs_is_null(username = xs_dict_get(actor, "preferredUsername")) || *username == '\0') {
70 /* This should never be reached */
71@@ -244,15 +244,15 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
72 }
73
74
75-xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg)
76+xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg)
77 {
78 xs *actor = NULL;
79 xs_html *actor_icon = NULL;
80
81 if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) {
82- char *date = NULL;
83- char *udate = NULL;
84- char *url = NULL;
85+ const char *date = NULL;
86+ const char *udate = NULL;
87+ const char *url = NULL;
88 int priv = 0;
89 const char *type = xs_dict_get(msg, "type");
90
91@@ -271,14 +271,14 @@ xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg)
92 }
93
94
95-xs_html *html_note(snac *user, char *summary,
96- char *div_id, char *form_id,
97- char *ta_plh, char *ta_content,
98- char *edit_id, char *actor_id,
99- xs_val *cw_yn, char *cw_text,
100- xs_val *mnt_only, char *redir,
101- char *in_reply_to, int poll,
102- char *att_file, char *att_alt_text)
103+xs_html *html_note(snac *user, const char *summary,
104+ const char *div_id, const char *form_id,
105+ const char *ta_plh, const char *ta_content,
106+ const char *edit_id, const char *actor_id,
107+ const xs_val *cw_yn, const char *cw_text,
108+ const xs_val *mnt_only, const char *redir,
109+ const char *in_reply_to, int poll,
110+ const char *att_file, const char *att_alt_text)
111 {
112 xs *action = xs_fmt("%s/admin/note", user->actor);
113
114@@ -460,9 +460,11 @@ static xs_html *html_base_head(void)
115 /* add server CSS and favicon */
116 xs *f;
117 f = xs_fmt("%s/favicon.ico", srv_baseurl);
118- xs_list *p = xs_dict_get(srv_config, "cssurls");
119+ const xs_list *p = xs_dict_get(srv_config, "cssurls");
120 char *v;
121- while (xs_list_iter(&p, &v)) {
122+ int c = 0;
123+
124+ while (xs_list_next(p, &v, &c)) {
125 xs_html_add(head,
126 xs_html_sctag("link",
127 xs_html_attr("rel", "stylesheet"),
128@@ -498,8 +500,8 @@ xs_html *html_instance_head(void)
129 }
130 }
131
132- char *host = xs_dict_get(srv_config, "host");
133- char *title = xs_dict_get(srv_config, "title");
134+ const char *host = xs_dict_get(srv_config, "host");
135+ const char *title = xs_dict_get(srv_config, "title");
136
137 xs_html_add(head,
138 xs_html_tag("title",
139@@ -511,10 +513,10 @@ xs_html *html_instance_head(void)
140
141 static xs_html *html_instance_body(void)
142 {
143- char *host = xs_dict_get(srv_config, "host");
144- char *sdesc = xs_dict_get(srv_config, "short_description");
145- char *email = xs_dict_get(srv_config, "admin_email");
146- char *acct = xs_dict_get(srv_config, "admin_account");
147+ const char *host = xs_dict_get(srv_config, "host");
148+ const char *sdesc = xs_dict_get(srv_config, "short_description");
149+ const char *email = xs_dict_get(srv_config, "admin_email");
150+ const char *acct = xs_dict_get(srv_config, "admin_account");
151
152 xs *blurb = xs_replace(snac_blurb, "%host%", host);
153
154@@ -760,7 +762,7 @@ static xs_html *html_user_body(snac *user, int read_only)
155 xs_html_attr("class", "h-card snac-top-user"));
156
157 if (read_only) {
158- char *header = xs_dict_get(user->config, "header");
159+ const char *header = xs_dict_get(user->config, "header");
160 if (header && *header) {
161 xs_html_add(top_user,
162 xs_html_tag("div",
163@@ -797,7 +799,7 @@ static xs_html *html_user_body(snac *user, int read_only)
164 xs_html_add(top_user,
165 top_user_bio);
166
167- xs_dict *metadata = xs_dict_get(user->config, "metadata");
168+ const xs_dict *metadata = xs_dict_get(user->config, "metadata");
169 if (xs_type(metadata) == XSTYPE_DICT) {
170 xs_str *k;
171 xs_str *v;
172@@ -816,7 +818,7 @@ static xs_html *html_user_body(snac *user, int read_only)
173 if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) {
174 /* is this link validated? */
175 xs *verified_link = NULL;
176- xs_number *val_time = xs_dict_get(val_links, v);
177+ const xs_number *val_time = xs_dict_get(val_links, v);
178
179 if (xs_type(val_time) == XSTYPE_NUMBER) {
180 time_t t = xs_number_get(val_time);
181@@ -928,7 +930,7 @@ xs_html *html_top_controls(snac *snac)
182
183 /** user settings **/
184
185- char *email = "[disabled by admin]";
186+ const char *email = "[disabled by admin]";
187
188 if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) {
189 email = xs_dict_get(snac->config_o, "email");
190@@ -940,38 +942,38 @@ xs_html *html_top_controls(snac *snac)
191 }
192 }
193
194- char *cw = xs_dict_get(snac->config, "cw");
195+ const char *cw = xs_dict_get(snac->config, "cw");
196 if (xs_is_null(cw))
197 cw = "";
198
199- char *telegram_bot = xs_dict_get(snac->config, "telegram_bot");
200+ const char *telegram_bot = xs_dict_get(snac->config, "telegram_bot");
201 if (xs_is_null(telegram_bot))
202 telegram_bot = "";
203
204- char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id");
205+ const char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id");
206 if (xs_is_null(telegram_chat_id))
207 telegram_chat_id = "";
208
209- char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
210+ const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
211 if (xs_is_null(ntfy_server))
212 ntfy_server = "";
213
214- char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
215+ const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
216 if (xs_is_null(ntfy_token))
217 ntfy_token = "";
218
219- char *purge_days = xs_dict_get(snac->config, "purge_days");
220+ const char *purge_days = xs_dict_get(snac->config, "purge_days");
221 if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER)
222 purge_days = (char *)xs_number_str(purge_days);
223 else
224 purge_days = "0";
225
226- xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
227- xs_val *bot = xs_dict_get(snac->config, "bot");
228- xs_val *a_private = xs_dict_get(snac->config, "private");
229+ const xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown");
230+ const xs_val *bot = xs_dict_get(snac->config, "bot");
231+ const xs_val *a_private = xs_dict_get(snac->config, "private");
232
233 xs *metadata = xs_str_new(NULL);
234- xs_dict *md = xs_dict_get(snac->config, "metadata");
235+ const xs_dict *md = xs_dict_get(snac->config, "metadata");
236 xs_str *k;
237 xs_str *v;
238
239@@ -1158,13 +1160,14 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg)
240 /* returns a string with the mentions in msg */
241 {
242 xs_str *s = xs_str_new(NULL);
243- char *list = xs_dict_get(msg, "tag");
244+ const char *list = xs_dict_get(msg, "tag");
245 char *v;
246+ int c = 0;
247
248- while (xs_list_iter(&list, &v)) {
249- char *type = xs_dict_get(v, "type");
250- char *href = xs_dict_get(v, "href");
251- char *name = xs_dict_get(v, "name");
252+ while (xs_list_next(list, &v, &c)) {
253+ const char *type = xs_dict_get(v, "type");
254+ const char *href = xs_dict_get(v, "href");
255+ const char *name = xs_dict_get(v, "name");
256
257 if (type && strcmp(type, "Mention") == 0 &&
258 href && strcmp(href, snac->actor) != 0 && name) {
259@@ -1208,10 +1211,11 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg)
260 }
261
262
263-xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const char *md5)
264+xs_html *html_entry_controls(snac *snac, const char *actor,
265+ const xs_dict *msg, const char *md5)
266 {
267- char *id = xs_dict_get(msg, "id");
268- char *group = xs_dict_get(msg, "audience");
269+ const char *id = xs_dict_get(msg, "id");
270+ const char *group = xs_dict_get(msg, "audience");
271
272 xs *likes = object_likes(id);
273 xs *boosts = object_announces(id);
274@@ -1310,7 +1314,7 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
275 html_button("delete", L("Delete"), L("Delete this post")),
276 html_button("hide", L("Hide"), L("Hide this post and its children")));
277
278- char *prev_src = xs_dict_get(msg, "sourceContent");
279+ const char *prev_src = xs_dict_get(msg, "sourceContent");
280
281 if (!xs_is_null(prev_src) && strcmp(actor, snac->actor) == 0) { /** edit **/
282 /* post can be edited */
283@@ -1318,13 +1322,13 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
284 xs *form_id = xs_fmt("%s_edit_form", md5);
285 xs *redir = xs_fmt("%s_entry", md5);
286
287- char *att_file = "";
288- char *att_alt_text = "";
289- xs_list *att_list = xs_dict_get(msg, "attachment");
290+ const char *att_file = "";
291+ const char *att_alt_text = "";
292+ const xs_list *att_list = xs_dict_get(msg, "attachment");
293
294 /* does it have an attachment? */
295 if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) {
296- xs_dict *d = xs_list_get(att_list, 0);
297+ const xs_dict *d = xs_list_get(att_list, 0);
298
299 if (xs_type(d) == XSTYPE_DICT) {
300 att_file = xs_dict_get_def(d, "url", "");
301@@ -1370,10 +1374,10 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const
302 xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
303 int level, char *md5, int hide_children)
304 {
305- char *id = xs_dict_get(msg, "id");
306- char *type = xs_dict_get(msg, "type");
307- char *actor;
308- char *v;
309+ const char *id = xs_dict_get(msg, "id");
310+ const char *type = xs_dict_get(msg, "type");
311+ const char *actor;
312+ const char *v;
313 int has_title = 0;
314
315 /* do not show non-public messages in the public timeline */
316@@ -1509,7 +1513,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
317
318 if (xs_list_len(boosts)) {
319 /* if somebody boosted this, show as origin */
320- char *p = xs_list_get(boosts, -1);
321+ const char *p = xs_list_get(boosts, -1);
322 xs *actor_r = NULL;
323
324 if (user && xs_list_in(boosts, user->md5) != -1) {
325@@ -1529,7 +1533,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
326
327 if (!xs_is_null(name)) {
328 xs *href = NULL;
329- char *id = xs_dict_get(actor_r, "id");
330+ const char *id = xs_dict_get(actor_r, "id");
331 int fwers = 0;
332 int fwing = 0;
333
334@@ -1558,7 +1562,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
335 if (strcmp(type, "Note") == 0) {
336 if (level == 0) {
337 /* is the parent not here? */
338- char *parent = xs_dict_get(msg, "inReplyTo");
339+ const char *parent = xs_dict_get(msg, "inReplyTo");
340
341 if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) {
342 xs_html_add(post_header,
343@@ -1603,7 +1607,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
344 v = "...";
345
346 /* only show it when not in the public timeline and the config setting is "open" */
347- char *cw = xs_dict_get(user->config, "cw");
348+ const char *cw = xs_dict_get(user->config, "cw");
349 if (xs_is_null(cw) || read_only)
350 cw = "";
351
352@@ -1632,7 +1636,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
353
354 {
355 /** build the content string **/
356- char *content = xs_dict_get(msg, "content");
357+ const char *content = xs_dict_get(msg, "content");
358
359 xs *c = sanitize(xs_is_null(content) ? "" : content);
360
361@@ -1650,7 +1654,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
362 c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2);
363
364 /* Peertube videos content is in markdown */
365- char *mtype = xs_dict_get(msg, "mediaType");
366+ const char *mtype = xs_dict_get(msg, "mediaType");
367 if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "text/markdown") == 0) {
368 /* a full conversion could be better */
369 c = xs_replace_i(c, "\r", "");
370@@ -1663,12 +1667,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
371 }
372
373 if (strcmp(type, "Question") == 0) { /** question content **/
374- xs_list *oo = xs_dict_get(msg, "oneOf");
375- xs_list *ao = xs_dict_get(msg, "anyOf");
376- xs_list *p;
377+ const xs_list *oo = xs_dict_get(msg, "oneOf");
378+ const xs_list *ao = xs_dict_get(msg, "anyOf");
379+ const xs_list *p;
380 xs_dict *v;
381 int closed = 0;
382- char *f_closed = NULL;
383+ const char *f_closed = NULL;
384
385 xs_html *poll = xs_html_tag("div", NULL);
386
387@@ -1697,10 +1701,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
388 /* closed poll */
389 xs_html *poll_result = xs_html_tag("table",
390 xs_html_attr("class", "snac-poll-result"));
391+ int c = 0;
392
393- while (xs_list_iter(&p, &v)) {
394- char *name = xs_dict_get(v, "name");
395- xs_dict *replies = xs_dict_get(v, "replies");
396+ while (xs_list_next(p, &v, &c)) {
397+ const char *name = xs_dict_get(v, "name");
398+ const xs_dict *replies = xs_dict_get(v, "replies");
399
400 if (name && replies) {
401 char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
402@@ -1737,9 +1742,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
403 xs_html_attr("name", "irt"),
404 xs_html_attr("value", id))));
405
406- while (xs_list_iter(&p, &v)) {
407- char *name = xs_dict_get(v, "name");
408- xs_dict *replies = xs_dict_get(v, "replies");
409+ int c = 0;
410+ while (xs_list_next(p, &v, &c)) {
411+ const char *name = xs_dict_get(v, "name");
412+ const xs_dict *replies = xs_dict_get(v, "replies");
413
414 if (name) {
415 char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems"));
416@@ -1777,7 +1783,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
417 }
418 else {
419 /* show when the poll closes */
420- char *end_time = xs_dict_get(msg, "endTime");
421+ const char *end_time = xs_dict_get(msg, "endTime");
422
423 /* Pleroma does not have an endTime field;
424 it has a closed time in the future */
425@@ -1820,12 +1826,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
426 xs_html_add(snac_content,
427 content_attachments);
428
429- xs_list *p = attach;
430-
431- while (xs_list_iter(&p, &v)) {
432- char *type = xs_dict_get(v, "type");
433- char *href = xs_dict_get(v, "href");
434- char *name = xs_dict_get(v, "name");
435+ int c = 0;
436+ xs_dict *a;
437+ while (xs_list_next(attach, &a, &c)) {
438+ const char *type = xs_dict_get(a, "type");
439+ const char *href = xs_dict_get(a, "href");
440+ const char *name = xs_dict_get(a, "name");
441
442 if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) {
443 xs_html_add(content_attachments,
444@@ -1889,7 +1895,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
445 }
446
447 /* has this message an audience (i.e., comes from a channel or community)? */
448- char *audience = xs_dict_get(msg, "audience");
449+ const char *audience = xs_dict_get(msg, "audience");
450 if (strcmp(type, "Page") == 0 && !xs_is_null(audience)) {
451 xs_html *au_tag = xs_html_tag("p",
452 xs_html_text("("),
453@@ -2023,11 +2029,12 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
454
455 if (xs_list_len(list) == 1) {
456 /* only one element? pick the description from the source */
457- char *id = xs_list_get(list, 0);
458+ const char *id = xs_list_get(list, 0);
459 xs *d = NULL;
460 object_get_by_md5(id, &d);
461- if (d && (v = xs_dict_get(d, "sourceContent")) != NULL)
462- desc = xs_dup(v);
463+ const char *sc = xs_dict_get(d, "sourceContent");
464+ if (d && sc != NULL)
465+ desc = xs_dup(sc);
466
467 alternate = xs_dup(xs_dict_get(d, "id"));
468 }
469@@ -2087,13 +2094,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
470
471 /* is this message a non-public reply? */
472 if (user != NULL && !is_msg_public(msg)) {
473- char *irt = xs_dict_get(msg, "inReplyTo");
474+ const char *irt = xs_dict_get(msg, "inReplyTo");
475
476 /* is it a reply to something not in the storage? */
477 if (!xs_is_null(irt) && !object_here(irt)) {
478 /* is it for me? */
479- xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST));
480- xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST));
481+ const xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST));
482+ const xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST));
483
484 if (xs_list_in(to, user->actor) == -1 && xs_list_in(cc, user->actor) == -1) {
485 snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v));
486@@ -2212,7 +2219,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t)
487 html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1)));
488
489 /* content (user bio) */
490- char *c = xs_dict_get(actor, "summary");
491+ const char *c = xs_dict_get(actor, "summary");
492
493 if (!xs_is_null(c)) {
494 xs *sc = sanitize(c);
495@@ -2364,10 +2371,10 @@ xs_str *html_notifications(snac *user, int skip, int show)
496 continue;
497
498 xs *obj = NULL;
499- char *type = xs_dict_get(noti, "type");
500- char *utype = xs_dict_get(noti, "utype");
501- char *id = xs_dict_get(noti, "objid");
502- char *date = xs_dict_get(noti, "date");
503+ const char *type = xs_dict_get(noti, "type");
504+ const char *utype = xs_dict_get(noti, "utype");
505+ const char *id = xs_dict_get(noti, "objid");
506+ const char *date = xs_dict_get(noti, "date");
507
508 if (xs_is_null(id) || !valid_status(object_get(id, &obj)))
509 continue;
510@@ -2375,14 +2382,14 @@ xs_str *html_notifications(snac *user, int skip, int show)
511 if (is_hidden(user, id))
512 continue;
513
514- char *actor_id = xs_dict_get(noti, "actor");
515+ const char *actor_id = xs_dict_get(noti, "actor");
516 xs *actor = NULL;
517
518 if (!valid_status(actor_get(actor_id, &actor)))
519 continue;
520
521 xs *a_name = actor_name(actor);
522- char *label = type;
523+ const char *label = type;
524
525 if (strcmp(type, "Create") == 0)
526 label = L("Mention");
527@@ -2494,14 +2501,14 @@ xs_str *html_notifications(snac *user, int skip, int show)
528 int html_get_handler(const xs_dict *req, const char *q_path,
529 char **body, int *b_size, char **ctype, xs_str **etag)
530 {
531- char *accept = xs_dict_get(req, "accept");
532+ const char *accept = xs_dict_get(req, "accept");
533 int status = 404;
534 snac snac;
535 xs *uid = NULL;
536- char *p_path;
537+ const char *p_path;
538 int cache = 1;
539 int save = 1;
540- char *v;
541+ const char *v;
542
543 xs *l = xs_split_n(q_path, "/", 2);
544 v = xs_list_get(l, 1);
545@@ -2540,7 +2547,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
546
547 int skip = 0;
548 int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
549- xs_dict *q_vars = xs_dict_get(req, "q_vars");
550+ const xs_dict *q_vars = xs_dict_get(req, "q_vars");
551 if ((v = xs_dict_get(q_vars, "skip")) != NULL)
552 skip = atoi(v), cache = 0, save = 0;
553 if ((v = xs_dict_get(q_vars, "show")) != NULL)
554@@ -2585,7 +2592,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
555 status = 401;
556 }
557 else {
558- char *q = xs_dict_get(q_vars, "q");
559+ const char *q = xs_dict_get(q_vars, "q");
560
561 if (q && *q) {
562 if (*q == '#') {
563@@ -2669,7 +2676,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
564 }
565 else {
566 xs *l = xs_split(p_path, "/");
567- char *md5 = xs_list_get(l, -1);
568+ const char *md5 = xs_list_get(l, -1);
569
570 if (md5 && *md5 && timeline_here(&snac, md5)) {
571 xs *list = xs_list_append(xs_list_new(), md5);
572@@ -2728,7 +2735,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
573 }
574 else {
575 xs *l = xs_split(p_path, "/");
576- char *lid = xs_list_get(l, -1);
577+ const char *lid = xs_list_get(l, -1);
578
579 xs *list = list_timeline(&snac, lid, skip, show);
580 xs *next = list_timeline(&snac, lid, skip + show, 1);
581@@ -2767,7 +2774,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
582 else
583 if (xs_startswith(p_path, "s/")) { /** a static file **/
584 xs *l = xs_split(p_path, "/");
585- char *id = xs_list_get(l, 1);
586+ const char *id = xs_list_get(l, 1);
587 int sz;
588
589 if (id && *id) {
590@@ -2788,8 +2795,8 @@ int html_get_handler(const xs_dict *req, const char *q_path,
591 if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE)
592 return 403;
593
594- xs *l = xs_split(p_path, "/");
595- char *id = xs_list_get(l, 1);
596+ xs *l = xs_split(p_path, "/");
597+ const char *id = xs_list_get(l, 1);
598
599 if (id && *id) {
600 if (xs_endswith(id, "timeline.html_")) {
601@@ -2845,8 +2852,9 @@ int html_post_handler(const xs_dict *req, const char *q_path,
602
603 int status = 0;
604 snac snac;
605- char *uid, *p_path;
606- xs_dict *p_vars;
607+ const char *uid;
608+ const char *p_path;
609+ const xs_dict *p_vars;
610
611 xs *l = xs_split_n(q_path, "/", 2);
612
613@@ -2874,15 +2882,15 @@ int html_post_handler(const xs_dict *req, const char *q_path,
614
615 if (p_path && strcmp(p_path, "admin/note") == 0) { /** **/
616 /* post note */
617- xs_str *content = xs_dict_get(p_vars, "content");
618- xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
619- xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
620- xs_list *attach_file = xs_dict_get(p_vars, "attach");
621- xs_str *to = xs_dict_get(p_vars, "to");
622- xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
623- xs_str *summary = xs_dict_get(p_vars, "summary");
624- xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
625- xs_str *alt_text = xs_dict_get(p_vars, "alt_text");
626+ const xs_str *content = xs_dict_get(p_vars, "content");
627+ const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to");
628+ const xs_str *attach_url = xs_dict_get(p_vars, "attach_url");
629+ const xs_list *attach_file = xs_dict_get(p_vars, "attach");
630+ const xs_str *to = xs_dict_get(p_vars, "to");
631+ const xs_str *sensitive = xs_dict_get(p_vars, "sensitive");
632+ const xs_str *summary = xs_dict_get(p_vars, "summary");
633+ const xs_str *edit_id = xs_dict_get(p_vars, "edit_id");
634+ const xs_str *alt_text = xs_dict_get(p_vars, "alt_text");
635 int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only"));
636 xs *attach_list = xs_list_new();
637
638@@ -2902,7 +2910,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
639
640 /* is attach_file set? */
641 if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) {
642- char *fn = xs_list_get(attach_file, 0);
643+ const char *fn = xs_list_get(attach_file, 0);
644
645 if (*fn != '\0') {
646 char *ext = strrchr(fn, '.');
647@@ -2978,7 +2986,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
648 int n;
649
650 for (n = 0; fields[n]; n++) {
651- char *v = xs_dict_get(p_msg, fields[n]);
652+ const char *v = xs_dict_get(p_msg, fields[n]);
653 msg = xs_dict_set(msg, fields[n], v);
654 }
655
656@@ -3007,10 +3015,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
657 else
658 if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/
659 /* action on an entry */
660- char *id = xs_dict_get(p_vars, "id");
661- char *actor = xs_dict_get(p_vars, "actor");
662- char *action = xs_dict_get(p_vars, "action");
663- char *group = xs_dict_get(p_vars, "group");
664+ const char *id = xs_dict_get(p_vars, "id");
665+ const char *actor = xs_dict_get(p_vars, "actor");
666+ const char *action = xs_dict_get(p_vars, "action");
667+ const char *group = xs_dict_get(p_vars, "group");
668
669 if (action == NULL)
670 return 404;
671@@ -3134,7 +3142,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
672 }
673 else
674 if (strcmp(action, L("Delete")) == 0) { /** **/
675- char *actor_form = xs_dict_get(p_vars, "actor-form");
676+ const char *actor_form = xs_dict_get(p_vars, "actor-form");
677 if (actor_form != NULL) {
678 /* delete follower */
679 if (valid_status(follower_del(&snac, actor)))
680@@ -3178,8 +3186,8 @@ int html_post_handler(const xs_dict *req, const char *q_path,
681 else
682 if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/
683 /* change of user data */
684- char *v;
685- char *p1, *p2;
686+ const char *v;
687+ const char *p1, *p2;
688
689 if ((v = xs_dict_get(p_vars, "name")) != NULL)
690 snac.config = xs_dict_set(snac.config, "name", v);
691@@ -3245,7 +3253,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
692 for (n = 0; uploads[n]; n++) {
693 xs *var_name = xs_fmt("%s_file", uploads[n]);
694
695- xs_list *uploaded_file = xs_dict_get(p_vars, var_name);
696+ const xs_list *uploaded_file = xs_dict_get(p_vars, var_name);
697 if (xs_type(uploaded_file) == XSTYPE_LIST) {
698 const char *fn = xs_list_get(uploaded_file, 0);
699
700@@ -3310,7 +3318,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
701 }
702 else
703 if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/
704- char *irt = xs_dict_get(p_vars, "irt");
705+ const char *irt = xs_dict_get(p_vars, "irt");
706 const char *opt = xs_dict_get(p_vars, "question");
707 const char *actor = xs_dict_get(p_vars, "actor");
708
709@@ -3345,7 +3353,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
710 xs *poll = NULL;
711
712 if (valid_status(object_get(irt, &poll))) {
713- char *date = xs_dict_get(poll, "endTime");
714+ const char *date = xs_dict_get(poll, "endTime");
715 if (xs_is_null(date))
716 date = xs_dict_get(poll, "closed");
717
718@@ -3363,7 +3371,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
719 }
720
721 if (status == 303) {
722- char *redir = xs_dict_get(p_vars, "redir");
723+ const char *redir = xs_dict_get(p_vars, "redir");
724
725 if (xs_is_null(redir))
726 redir = "top";
727@@ -3411,8 +3419,8 @@ xs_str *timeline_to_rss(snac *user, const xs_list *timeline, char *title, char *
728 continue;
729 }
730
731- char *id = xs_dict_get(msg, "id");
732- char *content = xs_dict_get(msg, "content");
733+ const char *id = xs_dict_get(msg, "id");
734+ const char *content = xs_dict_get(msg, "content");
735
736 if (user && !xs_startswith(id, user->actor))
737 continue;
M
http.c
+14,
-13
1@@ -12,7 +12,7 @@
2
3 xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
4 const char *method, const char *url,
5- xs_dict *headers,
6+ const xs_dict *headers,
7 const char *body, int b_size,
8 int *status, xs_str **payload, int *p_size,
9 int timeout)
10@@ -24,8 +24,8 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
11 xs *s64 = NULL;
12 xs *signature = NULL;
13 xs *hdrs = NULL;
14- char *host;
15- char *target;
16+ const char *host;
17+ const char *target;
18 char *k, *v;
19 xs_dict *response;
20
21@@ -106,13 +106,13 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
22
23
24 xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
25- xs_dict *headers,
26+ const xs_dict *headers,
27 const char *body, int b_size,
28 int *status, xs_str **payload, int *p_size,
29 int timeout)
30 /* does a signed HTTP request */
31 {
32- char *seckey = xs_dict_get(snac->key, "secret");
33+ const char *seckey = xs_dict_get(snac->key, "secret");
34 xs_dict *response;
35
36 response = http_signed_request_raw(snac->actor, seckey, method, url,
37@@ -122,17 +122,18 @@ xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
38 }
39
40
41-int check_signature(xs_dict *req, xs_str **err)
42+int check_signature(const xs_dict *req, xs_str **err)
43 /* check the signature */
44 {
45- char *sig_hdr = xs_dict_get(req, "signature");
46+ const char *sig_hdr = xs_dict_get(req, "signature");
47 xs *keyId = NULL;
48 xs *headers = NULL;
49 xs *signature = NULL;
50 xs *created = NULL;
51 xs *expires = NULL;
52- char *pubkey;
53 char *p;
54+ const char *pubkey;
55+ const char *k;
56
57 if (xs_is_null(sig_hdr)) {
58 *err = xs_fmt("missing 'signature' header");
59@@ -142,10 +143,10 @@ int check_signature(xs_dict *req, xs_str **err)
60 {
61 /* extract the values */
62 xs *l = xs_split(sig_hdr, ",");
63- xs_list *p = l;
64+ int c = 0;
65 xs_val *v;
66
67- while (xs_list_iter(&p, &v)) {
68+ while (xs_list_next(l, &v, &c)) {
69 xs *kv = xs_split_n(v, "=", 1);
70
71 if (xs_list_len(kv) != 2)
72@@ -192,8 +193,8 @@ int check_signature(xs_dict *req, xs_str **err)
73 return 0;
74 }
75
76- if ((p = xs_dict_get(actor, "publicKey")) == NULL ||
77- ((pubkey = xs_dict_get(p, "publicKeyPem")) == NULL)) {
78+ if ((k = xs_dict_get(actor, "publicKey")) == NULL ||
79+ ((pubkey = xs_dict_get(k, "publicKeyPem")) == NULL)) {
80 *err = xs_fmt("cannot get pubkey from %s", keyId);
81 return 0;
82 }
83@@ -208,7 +209,7 @@ int check_signature(xs_dict *req, xs_str **err)
84
85 p = l;
86 while (xs_list_iter(&p, &v)) {
87- char *hc;
88+ const char *hc;
89 xs *ss = NULL;
90
91 if (*sig_str != '\0')
M
httpd.c
+8,
-8
1@@ -125,7 +125,7 @@ static xs_str *greeting_html(void)
2
3 /* does it have a %userlist% mark? */
4 if (xs_str_in(s, "%userlist%") != -1) {
5- char *host = xs_dict_get(srv_config, "host");
6+ const char *host = xs_dict_get(srv_config, "host");
7 xs *list = user_list();
8 xs_list *p = list;
9 xs_str *uid;
10@@ -171,14 +171,14 @@ int server_get_handler(xs_dict *req, const char *q_path,
11
12 /* is it the server root? */
13 if (*q_path == '\0') {
14- xs_dict *q_vars = xs_dict_get(req, "q_vars");
15- char *t = NULL;
16+ const xs_dict *q_vars = xs_dict_get(req, "q_vars");
17+ const char *t = NULL;
18
19 if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) {
20 /** search by tag **/
21 int skip = 0;
22 int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries"));
23- char *v;
24+ const char *v;
25
26 if ((v = xs_dict_get(q_vars, "skip")) != NULL)
27 skip = atoi(v);
28@@ -193,7 +193,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
29 more = 1;
30 }
31
32- char *accept = xs_dict_get(req, "accept");
33+ const char *accept = xs_dict_get(req, "accept");
34 if (!xs_is_null(accept) && strcmp(accept, "application/rss+xml") == 0) {
35 xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t);
36
37@@ -268,7 +268,7 @@ void httpd_connection(FILE *f)
38 /* the connection processor */
39 {
40 xs *req;
41- char *method;
42+ const char *method;
43 int status = 0;
44 xs_str *body = NULL;
45 int b_size = 0;
46@@ -278,7 +278,7 @@ void httpd_connection(FILE *f)
47 xs *payload = NULL;
48 xs *etag = NULL;
49 int p_size = 0;
50- char *p;
51+ const char *p;
52 int fcgi_id;
53
54 if (p_state->use_fcgi)
55@@ -411,7 +411,7 @@ void httpd_connection(FILE *f)
56 headers = xs_dict_append(headers, "etag", etag);
57
58 /* if there are any additional headers, add them */
59- xs_dict *more_headers = xs_dict_get(srv_config, "http_headers");
60+ const xs_dict *more_headers = xs_dict_get(srv_config, "http_headers");
61 if (xs_type(more_headers) == XSTYPE_DICT) {
62 char *k, *v;
63 int c = 0;
M
main.c
+1,
-1
1@@ -315,7 +315,7 @@ int main(int argc, char *argv[])
2 xs *msg = msg_follow(&snac, url);
3
4 if (msg != NULL) {
5- char *actor = xs_dict_get(msg, "object");
6+ const char *actor = xs_dict_get(msg, "object");
7
8 following_add(&snac, actor, msg);
9
+57,
-52
1@@ -175,7 +175,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
2 return 0;
3
4 int status = 404;
5- xs_dict *msg = xs_dict_get(req, "q_vars");
6+ const xs_dict *msg = xs_dict_get(req, "q_vars");
7 xs *cmd = xs_replace_n(q_path, "/oauth", "", 1);
8
9 srv_debug(1, xs_fmt("oauth_get_handler %s", q_path));
10@@ -239,7 +239,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
11
12 int status = 404;
13
14- char *i_ctype = xs_dict_get(req, "content-type");
15+ const char *i_ctype = xs_dict_get(req, "content-type");
16 xs *args = NULL;
17
18 if (i_ctype && xs_startswith(i_ctype, "application/json")) {
19@@ -568,10 +568,10 @@ xs_dict *mastoapi_account(const xs_dict *actor)
20 acct = xs_dict_append(acct, "uri", id);
21
22 xs *avatar = NULL;
23- xs_dict *av = xs_dict_get(actor, "icon");
24+ const xs_dict *av = xs_dict_get(actor, "icon");
25
26 if (xs_type(av) == XSTYPE_DICT) {
27- char *url = xs_dict_get(av, "url");
28+ const char *url = xs_dict_get(av, "url");
29
30 if (url != NULL)
31 avatar = xs_dup(url);
32@@ -584,7 +584,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
33 acct = xs_dict_append(acct, "avatar_static", avatar);
34
35 xs *header = NULL;
36- xs_dict *hd = xs_dict_get(actor, "image");
37+ const xs_dict *hd = xs_dict_get(actor, "image");
38
39 if (xs_type(hd) == XSTYPE_DICT)
40 header = xs_dup(xs_dict_get(hd, "url"));
41@@ -596,12 +596,13 @@ xs_dict *mastoapi_account(const xs_dict *actor)
42 acct = xs_dict_append(acct, "header_static", header);
43
44 /* emojis */
45- xs_list *p;
46+ const xs_list *p;
47 if (!xs_is_null(p = xs_dict_get(actor, "tag"))) {
48 xs *eml = xs_list_new();
49 xs_dict *v;
50+ int c = 0;
51
52- while (xs_list_iter(&p, &v)) {
53+ while (xs_list_next(p, &v, &c)) {
54 const char *type = xs_dict_get(v, "type");
55
56 if (!xs_is_null(type) && strcmp(type, "Emoji") == 0) {
57@@ -640,7 +641,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
58
59 /* dict of validated links */
60 xs_dict *val_links = NULL;
61- xs_dict *metadata = xs_stock(XSTYPE_DICT);
62+ const xs_dict *metadata = xs_stock(XSTYPE_DICT);
63 snac user = {0};
64
65 if (xs_startswith(id, srv_baseurl)) {
66@@ -654,19 +655,20 @@ xs_dict *mastoapi_account(const xs_dict *actor)
67 if (xs_is_null(val_links))
68 val_links = xs_stock(XSTYPE_DICT);
69
70- while (xs_list_iter(&p, &v)) {
71- char *type = xs_dict_get(v, "type");
72- char *name = xs_dict_get(v, "name");
73- char *value = xs_dict_get(v, "value");
74+ int c = 0;
75+ while (xs_list_next(p, &v, &c)) {
76+ const char *type = xs_dict_get(v, "type");
77+ const char *name = xs_dict_get(v, "name");
78+ const char *value = xs_dict_get(v, "value");
79
80 if (!xs_is_null(type) && !xs_is_null(name) &&
81 !xs_is_null(value) && strcmp(type, "PropertyValue") == 0) {
82 xs *val_date = NULL;
83
84- char *url = xs_dict_get(metadata, name);
85+ const char *url = xs_dict_get(metadata, name);
86
87 if (!xs_is_null(url) && xs_startswith(url, "https:/" "/")) {
88- xs_number *verified_time = xs_dict_get(val_links, url);
89+ const xs_number *verified_time = xs_dict_get(val_links, url);
90 if (xs_type(verified_time) == XSTYPE_NUMBER) {
91 time_t t = xs_number_get(verified_time);
92
93@@ -695,7 +697,7 @@ xs_dict *mastoapi_account(const xs_dict *actor)
94 }
95
96
97-xs_str *mastoapi_date(char *date)
98+xs_str *mastoapi_date(const char *date)
99 /* converts an ISO 8601 date to whatever format Mastodon uses */
100 {
101 xs_str *s = xs_crop_i(xs_dup(date), 0, 19);
102@@ -710,13 +712,13 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg)
103 {
104 xs_dict *poll = xs_dict_new();
105 xs *mid = mastoapi_id(msg);
106- xs_list *opts = NULL;
107+ const xs_list *opts = NULL;
108 xs_val *v;
109 int num_votes = 0;
110 xs *options = xs_list_new();
111
112 poll = xs_dict_append(poll, "id", mid);
113- char *date = xs_dict_get(msg, "endTime");
114+ const char *date = xs_dict_get(msg, "endTime");
115 if (date == NULL)
116 date = xs_dict_get(msg, "closed");
117 if (date == NULL)
118@@ -741,7 +743,8 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg)
119 poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_TRUE));
120 }
121
122- while (xs_list_iter(&opts, &v)) {
123+ int c = 0;
124+ while (xs_list_next(opts, &v, &c)) {
125 const char *title = xs_dict_get(v, "name");
126 const char *replies = xs_dict_get(v, "replies");
127
128@@ -794,7 +797,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
129
130 xs *idx = NULL;
131 xs *ixc = NULL;
132- char *tmp;
133+ const char *tmp;
134 xs *mid = mastoapi_id(msg);
135
136 xs_dict *st = xs_dict_new();
137@@ -851,9 +854,9 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
138 xs *matt = xs_list_new();
139
140 while (xs_list_iter(&p, &v)) {
141- char *type = xs_dict_get(v, "type");
142- char *href = xs_dict_get(v, "href");
143- char *name = xs_dict_get(v, "name");
144+ const char *type = xs_dict_get(v, "type");
145+ const char *href = xs_dict_get(v, "href");
146+ const char *name = xs_dict_get(v, "name");
147
148 if (xs_match(type, "image/*|video/*|Image|Video")) { /* */
149 xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt));
150@@ -879,7 +882,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
151 xs *ml = xs_list_new();
152 xs *htl = xs_list_new();
153 xs *eml = xs_list_new();
154- xs_list *tag = xs_dict_get(msg, "tag");
155+ const xs_list *tag = xs_dict_get(msg, "tag");
156 int n = 0;
157
158 xs *tag_list = NULL;
159@@ -897,7 +900,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
160 tag = tag_list;
161 xs_dict *v;
162
163- while (xs_list_iter(&tag, &v)) {
164+ int c = 0;
165+ while (xs_list_next(tag, &v, &c)) {
166 const char *type = xs_dict_get(v, "type");
167
168 if (xs_is_null(type))
169@@ -1006,7 +1010,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg)
170 xs *irt_mid = mastoapi_id(irto);
171 st = xs_dict_set(st, "in_reply_to_id", irt_mid);
172
173- char *at = NULL;
174+ const char *at = NULL;
175 if (!xs_is_null(at = get_atto(irto))) {
176 xs *at_md5 = xs_md5_hex(at, strlen(at));
177 st = xs_dict_set(st, "in_reply_to_account_id", at_md5);
178@@ -1118,7 +1122,7 @@ int process_auth_token(snac *snac, const xs_dict *req)
179 /* processes an authorization token, if there is one */
180 {
181 int logged_in = 0;
182- char *v;
183+ const char *v;
184
185 /* if there is an authorization field, try to validate it */
186 if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) {
187@@ -1156,7 +1160,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
188 return 0;
189
190 int status = 404;
191- xs_dict *args = xs_dict_get(req, "q_vars");
192+ const xs_dict *args = xs_dict_get(req, "q_vars");
193 xs *cmd = xs_replace_n(q_path, "/api", "", 1);
194
195 snac snac1 = {0};
196@@ -1182,7 +1186,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
197 acct = xs_dict_append(acct, "source", src);
198
199 xs *avatar = NULL;
200- char *av = xs_dict_get(snac1.config, "avatar");
201+ const char *av = xs_dict_get(snac1.config, "avatar");
202
203 if (xs_is_null(av) || *av == '\0')
204 avatar = xs_fmt("%s/susie.png", srv_baseurl);
205@@ -1193,7 +1197,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
206 acct = xs_dict_append(acct, "avatar_static", avatar);
207
208 xs *header = NULL;
209- char *hd = xs_dict_get(snac1.config, "header");
210+ const char *hd = xs_dict_get(snac1.config, "header");
211
212 if (!xs_is_null(hd))
213 header = xs_dup(hd);
214@@ -1203,7 +1207,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
215 acct = xs_dict_append(acct, "header", header);
216 acct = xs_dict_append(acct, "header_static", header);
217
218- xs_dict *metadata = xs_dict_get(snac1.config, "metadata");
219+ const xs_dict *metadata = xs_dict_get(snac1.config, "metadata");
220 if (xs_type(metadata) == XSTYPE_DICT) {
221 xs *fields = xs_list_new();
222 xs_str *k;
223@@ -1217,7 +1221,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
224 while (xs_dict_next(metadata, &k, &v, &c)) {
225 xs *val_date = NULL;
226
227- xs_number *verified_time = xs_dict_get(val_links, v);
228+ const xs_number *verified_time = xs_dict_get(val_links, v);
229 if (xs_type(verified_time) == XSTYPE_NUMBER) {
230 time_t t = xs_number_get(verified_time);
231
232@@ -1283,13 +1287,13 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
233 else
234 if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/
235 /* lookup an account */
236- char *acct = xs_dict_get(args, "acct");
237+ const char *acct = xs_dict_get(args, "acct");
238
239 if (!xs_is_null(acct)) {
240 xs *s = xs_strip_chars_i(xs_dup(acct), "@");
241 xs *l = xs_split_n(s, "@", 1);
242- char *uid = xs_list_get(l, 0);
243- char *host = xs_list_get(l, 1);
244+ const char *uid = xs_list_get(l, 0);
245+ const char *host = xs_list_get(l, 1);
246
247 if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) {
248 snac user;
249@@ -1624,7 +1628,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
250
251 /* get the tag */
252 xs *l = xs_split(cmd, "/");
253- char *tag = xs_list_get(l, -1);
254+ const char *tag = xs_list_get(l, -1);
255
256 xs *timeline = tag_search(tag, 0, limit);
257 xs *out = xs_list_new();
258@@ -1664,7 +1668,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
259 /* get the list id */
260 if (logged_in) {
261 xs *l = xs_split(cmd, "/");
262- char *list = xs_list_get(l, -1);
263+ const char *list = xs_list_get(l, -1);
264
265 xs *timeline = list_timeline(&snac1, list, 0, 2048);
266 xs *out = xs_list_new();
267@@ -1744,7 +1748,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
268 xs *out = xs_list_new();
269 xs_list *p = l;
270 xs_dict *v;
271- xs_list *excl = xs_dict_get(args, "exclude_types[]");
272+ const xs_list *excl = xs_dict_get(args, "exclude_types[]");
273
274 while (xs_list_iter(&p, &v)) {
275 xs *noti = notify_get(&snac1, v);
276@@ -1876,7 +1880,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
277 if (xs_startswith(cmd, "/v1/lists/")) { /** list information **/
278 if (logged_in) {
279 xs *l = xs_split(cmd, "/");
280- char *p = xs_list_get(l, -1);
281+ const char *p = xs_list_get(l, -1);
282
283 if (p) {
284 if (strcmp(p, "accounts") == 0) {
285@@ -1910,7 +1914,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
286 xs_list *v;
287
288 while (xs_list_next(lol, &v, &c)) {
289- char *id = xs_list_get(v, 0);
290+ const char *id = xs_list_get(v, 0);
291
292 if (id && strcmp(id, p) == 0) {
293 xs *d = xs_dict_new();
294@@ -2314,7 +2318,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
295
296 int status = 404;
297 xs *args = NULL;
298- char *i_ctype = xs_dict_get(req, "content-type");
299+ const char *i_ctype = xs_dict_get(req, "content-type");
300
301 if (i_ctype && xs_startswith(i_ctype, "application/json")) {
302 if (!xs_is_null(payload))
303@@ -2487,7 +2491,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
304 mid = MID_TO_MD5(mid);
305
306 if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) {
307- char *id = xs_dict_get(msg, "id");
308+ const char *id = xs_dict_get(msg, "id");
309
310 if (op == NULL) {
311 /* no operation (?) */
312@@ -2593,7 +2597,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
313 if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/
314 /* I don't know what I'm doing */
315 if (logged_in) {
316- char *v;
317+ const char *v;
318
319 xs *wpush = xs_dict_new();
320
321@@ -2765,7 +2769,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
322 const char *id = xs_dict_get(msg, "id");
323 const char *atto = get_atto(msg);
324
325- xs_list *opts = xs_dict_get(msg, "oneOf");
326+ const xs_list *opts = xs_dict_get(msg, "oneOf");
327 if (opts == NULL)
328 opts = xs_dict_get(msg, "anyOf");
329
330@@ -2773,7 +2777,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
331 }
332 else
333 if (strcmp(op, "votes") == 0) {
334- xs_list *choices = xs_dict_get(args, "choices[]");
335+ const xs_list *choices = xs_dict_get(args, "choices[]");
336
337 if (xs_is_null(choices))
338 choices = xs_dict_get(args, "choices");
339@@ -2781,7 +2785,8 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
340 if (xs_type(choices) == XSTYPE_LIST) {
341 xs_str *v;
342
343- while (xs_list_iter(&choices, &v)) {
344+ int c = 0;
345+ while (xs_list_next(choices, &v, &c)) {
346 int io = atoi(v);
347 const xs_dict *o = xs_list_get(opts, io);
348
349@@ -2843,12 +2848,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
350 if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/
351 if (logged_in) {
352 xs *l = xs_split(cmd, "/");
353- char *op = xs_list_get(l, -1);
354- char *id = xs_list_get(l, -2);
355+ const char *op = xs_list_get(l, -1);
356+ const char *id = xs_list_get(l, -2);
357
358 if (op && id && xs_is_hex(id)) {
359 if (strcmp(op, "accounts") == 0) {
360- xs_list *accts = xs_dict_get(args, "account_ids[]");
361+ const xs_list *accts = xs_dict_get(args, "account_ids[]");
362 int c = 0;
363 char *v;
364
365@@ -2888,7 +2893,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
366
367 int status = 404;
368 xs *args = NULL;
369- char *i_ctype = xs_dict_get(req, "content-type");
370+ const char *i_ctype = xs_dict_get(req, "content-type");
371
372 if (i_ctype && xs_startswith(i_ctype, "application/json")) {
373 if (!xs_is_null(payload))
374@@ -2921,13 +2926,13 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
375 if (xs_startswith(cmd, "/v1/lists/")) {
376 if (logged_in) {
377 xs *l = xs_split(cmd, "/");
378- char *p = xs_list_get(l, -1);
379+ const char *p = xs_list_get(l, -1);
380
381 if (p) {
382 if (strcmp(p, "accounts") == 0) {
383 /* delete account from list */
384 p = xs_list_get(l, -2);
385- xs_list *accts = xs_dict_get(args, "account_ids[]");
386+ const xs_list *accts = xs_dict_get(args, "account_ids[]");
387 int c = 0;
388 char *v;
389
390@@ -2971,7 +2976,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
391
392 int status = 404;
393 xs *args = NULL;
394- char *i_ctype = xs_dict_get(req, "content-type");
395+ const char *i_ctype = xs_dict_get(req, "content-type");
396
397 if (i_ctype && xs_startswith(i_ctype, "application/json")) {
398 if (!xs_is_null(payload))
M
snac.h
+23,
-22
1@@ -69,7 +69,7 @@ void snac_log(snac *user, xs_str *str);
2 #define snac_debug(user, level, str) do { if (dbglevel >= (level)) \
3 { snac_log((user), (str)); } } while (0)
4
5-int srv_open(char *basedir, int auto_upgrade);
6+int srv_open(const char *basedir, int auto_upgrade);
7 void srv_free(void);
8
9 int user_open(snac *snac, const char *uid);
10@@ -88,7 +88,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req,
11 const char *body, int b_size);
12 void srv_archive_error(const char *prefix, const xs_str *err,
13 const xs_dict *req, const xs_val *data);
14-void srv_archive_qitem(char *prefix, xs_dict *q_item);
15+void srv_archive_qitem(const char *prefix, xs_dict *q_item);
16
17 double mtime_nl(const char *fn, int *n_link);
18 #define mtime(fn) mtime_nl(fn, NULL)
19@@ -139,13 +139,13 @@ double timeline_mtime(snac *snac);
20 int timeline_touch(snac *snac);
21 int timeline_here(snac *snac, const char *md5);
22 int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg);
23-int timeline_del(snac *snac, char *id);
24+int timeline_del(snac *snac, const char *id);
25 xs_list *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show);
26 xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show);
27 int timeline_add(snac *snac, const char *id, const xs_dict *o_msg);
28 int timeline_admire(snac *snac, const char *id, const char *admirer, int like);
29
30-xs_list *timeline_top_level(snac *snac, xs_list *list);
31+xs_list *timeline_top_level(snac *snac, const xs_list *list);
32 xs_list *local_list(snac *snac, int max);
33 xs_list *timeline_instance_list(int skip, int show);
34
35@@ -174,14 +174,14 @@ void hide(snac *snac, const char *id);
36 int is_hidden(snac *snac, const char *id);
37
38 void tag_index(const char *id, const xs_dict *obj);
39-xs_list *tag_search(char *tag, int skip, int show);
40+xs_list *tag_search(const char *tag, int skip, int show);
41
42 xs_val *list_maint(snac *user, const char *list, int op);
43 xs_list *list_timeline(snac *user, const char *list, int skip, int show);
44 xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op);
45 void list_distribute(snac *user, const char *who, const xs_dict *post);
46
47-int actor_add(const char *actor, xs_dict *msg);
48+int actor_add(const char *actor, const xs_dict *msg);
49 int actor_get(const char *actor, xs_dict **data);
50 int actor_get_refresh(snac *user, const char *actor, xs_dict **data);
51
52@@ -223,10 +223,13 @@ xs_list *content_search(snac *user, const char *regex,
53 void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retries);
54 void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries);
55 void enqueue_output_raw(const char *keyid, const char *seckey,
56- xs_dict *msg, xs_str *inbox, int retries, int p_status);
57-void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status);
58-void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries);
59-void enqueue_email(xs_str *msg, int retries);
60+ const xs_dict *msg, const xs_str *inbox,
61+ int retries, int p_status);
62+void enqueue_output(snac *snac, const xs_dict *msg,
63+ const xs_str *inbox, int retries, int p_status);
64+void enqueue_output_by_actor(snac *snac, const xs_dict *msg,
65+ const xs_str *actor, int retries);
66+void enqueue_email(const xs_str *msg, int retries);
67 void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id);
68 void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token);
69 void enqueue_message(snac *snac, const xs_dict *msg);
70@@ -234,7 +237,6 @@ void enqueue_close_question(snac *user, const char *id, int end_secs);
71 void enqueue_object_request(snac *user, const char *id, int forward_secs);
72 void enqueue_verify_links(snac *user);
73 void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs);
74-void enqueue_request_replies(snac *user, const char *id);
75 int was_question_voted(snac *user, const char *id);
76
77 xs_list *user_queue(snac *snac);
78@@ -247,16 +249,16 @@ void purge_all(void);
79
80 xs_dict *http_signed_request_raw(const char *keyid, const char *seckey,
81 const char *method, const char *url,
82- xs_dict *headers,
83+ const xs_dict *headers,
84 const char *body, int b_size,
85 int *status, xs_str **payload, int *p_size,
86 int timeout);
87 xs_dict *http_signed_request(snac *snac, const char *method, const char *url,
88- xs_dict *headers,
89+ const xs_dict *headers,
90 const char *body, int b_size,
91 int *status, xs_str **payload, int *p_size,
92 int timeout);
93-int check_signature(xs_dict *req, xs_str **err);
94+int check_signature(const xs_dict *req, xs_str **err);
95
96 srv_state *srv_state_op(xs_str **fname, int op);
97 void httpd(void);
98@@ -270,21 +272,21 @@ const char *default_avatar_base64(void);
99
100 xs_str *process_tags(snac *snac, const char *content, xs_list **tag);
101
102-char *get_atto(const xs_dict *msg);
103+const char *get_atto(const xs_dict *msg);
104 xs_list *get_attachments(const xs_dict *msg);
105
106-xs_dict *msg_admiration(snac *snac, char *object, char *type);
107-xs_dict *msg_repulsion(snac *user, char *id, char *type);
108+xs_dict *msg_admiration(snac *snac, const char *object, const char *type);
109+xs_dict *msg_repulsion(snac *user, const char *id, const char *type);
110 xs_dict *msg_create(snac *snac, const xs_dict *object);
111 xs_dict *msg_follow(snac *snac, const char *actor);
112
113 xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
114- xs_str *in_reply_to, xs_list *attach, int priv);
115+ const xs_str *in_reply_to, const xs_list *attach, int priv);
116
117-xs_dict *msg_undo(snac *snac, char *object);
118-xs_dict *msg_delete(snac *snac, char *id);
119+xs_dict *msg_undo(snac *snac, const xs_val *object);
120+xs_dict *msg_delete(snac *snac, const char *id);
121 xs_dict *msg_actor(snac *snac);
122-xs_dict *msg_update(snac *snac, xs_dict *object);
123+xs_dict *msg_update(snac *snac, const xs_dict *object);
124 xs_dict *msg_ping(snac *user, const char *rcpt);
125 xs_dict *msg_pong(snac *user, const char *rcpt, const char *object);
126 xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
127@@ -292,7 +294,6 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach,
128
129 int activitypub_request(snac *snac, const char *url, xs_dict **data);
130 int actor_request(snac *user, const char *actor, xs_dict **data);
131-void timeline_request_replies(snac *user, const char *id);
132 int send_to_inbox_raw(const char *keyid, const char *seckey,
133 const xs_str *inbox, const xs_dict *msg,
134 xs_val **payload, int *p_size, int timeout);
+27,
-13
1@@ -18,7 +18,7 @@ int snac_upgrade(xs_str **error)
2 double f = 0.0;
3
4 for (;;) {
5- char *layout = xs_dict_get(srv_config, "layout");
6+ const char *layout = xs_dict_get(srv_config, "layout");
7 double nf;
8
9 f = nf = xs_number_get(layout);
10@@ -56,8 +56,8 @@ int snac_upgrade(xs_str **error)
11
12 g = list;
13 while (xs_list_iter(&g, &fn)) {
14- xs *l = xs_split(fn, "/");
15- char *b = xs_list_get(l, -1);
16+ xs *l = xs_split(fn, "/");
17+ const char *b = xs_list_get(l, -1);
18 xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]);
19 xs *nfn = xs_fmt("%s/%s", dir, b);
20
21@@ -152,12 +152,12 @@ int snac_upgrade(xs_str **error)
22 xs *o = xs_json_loads(s);
23 fclose(f);
24
25- char *type = xs_dict_get(o, "type");
26+ const char *type = xs_dict_get(o, "type");
27
28 if (!xs_is_null(type) && strcmp(type, "Follow") == 0) {
29 unlink(v);
30
31- char *actor = xs_dict_get(o, "actor");
32+ const char *actor = xs_dict_get(o, "actor");
33
34 if (!xs_is_null(actor))
35 follower_add(&snac, actor);
36@@ -198,22 +198,29 @@ int snac_upgrade(xs_str **error)
37 xs *meta = xs_dup(xs_dict_get(o, "_snac"));
38 o = xs_dict_del(o, "_snac");
39
40- char *id = xs_dict_get(o, "id");
41+ const char *id = xs_dict_get(o, "id");
42
43 /* store object */
44 object_add_ow(id, o);
45
46 /* if it's from us, add to public */
47 if (xs_startswith(id, snac.actor)) {
48- char *p, *v;
49+ const xs_list *p;
50+ char *v;
51+ int c;
52
53 object_user_cache_add(&snac, id, "public");
54
55 p = xs_dict_get(meta, "announced_by");
56- while (xs_list_iter(&p, &v))
57+
58+ c = 0;
59+ while (xs_list_next(p, &v, &c))
60 object_admire(id, v, 0);
61+
62 p = xs_dict_get(meta, "liked_by");
63- while (xs_list_iter(&p, &v))
64+
65+ c = 0;
66+ while (xs_list_next(p, &v, &c))
67 object_admire(id, v, 1);
68 }
69
70@@ -257,21 +264,28 @@ int snac_upgrade(xs_str **error)
71 xs *meta = xs_dup(xs_dict_get(o, "_snac"));
72 o = xs_dict_del(o, "_snac");
73
74- char *id = xs_dict_get(o, "id");
75+ const char *id = xs_dict_get(o, "id");
76
77 /* store object */
78 object_add_ow(id, o);
79
80 {
81- char *p, *v;
82+ const xs_list *p;
83+ char *v;
84+ int c = 0;
85
86 object_user_cache_add(&snac, id, "private");
87
88 p = xs_dict_get(meta, "announced_by");
89- while (xs_list_iter(&p, &v))
90+
91+ c = 0;
92+ while (xs_list_next(p, &v, &c))
93 object_admire(id, v, 0);
94+
95 p = xs_dict_get(meta, "liked_by");
96- while (xs_list_iter(&p, &v))
97+
98+ c = 0;
99+ while (xs_list_next(p, &v, &c))
100 object_admire(id, v, 1);
101 }
102
M
utils.c
+1,
-1
1@@ -418,7 +418,7 @@ int deluser(snac *user)
2 void verify_links(snac *user)
3 /* verifies a user's links */
4 {
5- xs_dict *p = xs_dict_get(user->config, "metadata");
6+ const xs_dict *p = xs_dict_get(user->config, "metadata");
7 char *k, *v;
8 int changed = 0;
9
+12,
-11
1@@ -16,7 +16,7 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
2 int p_size = 0;
3 xs *headers = xs_dict_new();
4 xs *l = NULL;
5- xs_str *host = NULL;
6+ const char *host = NULL;
7 xs *resource = NULL;
8
9 if (xs_startswith(qs, "https:/") || xs_startswith(qs, "http:/")) {
10@@ -87,19 +87,20 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
11
12 if (obj) {
13 if (user != NULL) {
14- char *subject = xs_dict_get(obj, "subject");
15+ const char *subject = xs_dict_get(obj, "subject");
16
17 if (subject)
18 *user = xs_replace_n(subject, "acct:", "", 1);
19 }
20
21 if (actor != NULL) {
22- char *list = xs_dict_get(obj, "links");
23+ const xs_list *list = xs_dict_get(obj, "links");
24+ int c = 0;
25 char *v;
26
27- while (xs_list_iter(&list, &v)) {
28+ while (xs_list_next(list, &v, &c)) {
29 if (xs_type(v) == XSTYPE_DICT) {
30- char *type = xs_dict_get(v, "type");
31+ const char *type = xs_dict_get(v, "type");
32
33 if (type && (strcmp(type, "application/activity+json") == 0 ||
34 strcmp(type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") == 0)) {
35@@ -133,8 +134,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
36 if (strcmp(q_path, "/.well-known/webfinger") != 0)
37 return 0;
38
39- char *q_vars = xs_dict_get(req, "q_vars");
40- char *resource = xs_dict_get(q_vars, "resource");
41+ const char *q_vars = xs_dict_get(req, "q_vars");
42+ const char *resource = xs_dict_get(q_vars, "resource");
43
44 if (resource == NULL)
45 return 400;
46@@ -145,7 +146,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
47 if (xs_startswith(resource, "https:/") || xs_startswith(resource, "http:/")) {
48 /* actor search: find a user with this actor */
49 xs *l = xs_split(resource, "/");
50- char *uid = xs_list_get(l, -1);
51+ const char *uid = xs_list_get(l, -1);
52
53 if (uid)
54 found = user_open(&snac, uid);
55@@ -163,8 +164,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
56 l = xs_split_n(an, "@", 1);
57
58 if (xs_list_len(l) == 2) {
59- char *uid = xs_list_get(l, 0);
60- char *host = xs_list_get(l, 1);
61+ const char *uid = xs_list_get(l, 0);
62+ const char *host = xs_list_get(l, 1);
63
64 if (strcmp(host, xs_dict_get(srv_config, "host")) == 0)
65 found = user_open(&snac, uid);
66@@ -194,7 +195,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
67
68 links = xs_list_append(links, prof);
69
70- char *avatar = xs_dict_get(snac.config, "avatar");
71+ const char *avatar = xs_dict_get(snac.config, "avatar");
72 if (!xs_is_null(avatar) && *avatar) {
73 xs *d = xs_dict_new();
74
M
xs.h
+76,
-34
1@@ -21,8 +21,8 @@ typedef enum {
2 XSTYPE_FALSE = 0x15, /* Boolean */
3 XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */
4 XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */
5- XSTYPE_DICT = 0x1c, /* Sequence of DITEMs up to EOM (with size) */
6- XSTYPE_DITEM = 0x1e, /* Element of a dict (STRING key + any type) */
7+ XSTYPE_DICT = 0x1c, /* Sequence of KEYVALs up to EOM (with size) */
8+ XSTYPE_KEYVAL = 0x1e, /* key + value (STRING key + any type) */
9 XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */
10 XSTYPE_DATA = 0x10 /* A block of anonymous data */
11 } xstype;
12@@ -32,6 +32,7 @@ typedef enum {
13 typedef char xs_val;
14 typedef char xs_str;
15 typedef char xs_list;
16+typedef char xs_keyval;
17 typedef char xs_dict;
18 typedef char xs_number;
19 typedef char xs_data;
20@@ -96,7 +97,7 @@ xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]);
21 int xs_list_iter(xs_list **list, xs_val **value);
22 int xs_list_next(const xs_list *list, xs_val **value, int *ctxt);
23 int xs_list_len(const xs_list *list);
24-xs_val *xs_list_get(const xs_list *list, int num);
25+const xs_val *xs_list_get(const xs_list *list, int num);
26 xs_list *xs_list_del(xs_list *list, int num);
27 xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data);
28 xs_list *xs_list_set(xs_list *list, int num, const xs_val *data);
29@@ -109,14 +110,20 @@ xs_list *xs_split_n(const char *str, const char *sep, int times);
30 #define xs_split(str, sep) xs_split_n(str, sep, XS_ALL)
31 xs_list *xs_list_cat(xs_list *l1, const xs_list *l2);
32
33+int xs_keyval_size(const xs_str *key, const xs_val *value);
34+xs_str *xs_keyval_key(const xs_keyval *keyval);
35+xs_val *xs_keyval_value(const xs_keyval *keyval);
36+xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value);
37+
38 xs_dict *xs_dict_new(void);
39 xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value);
40 xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value);
41 int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt);
42-xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def);
43+const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def);
44 #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL)
45 xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key);
46 xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data);
47+xs_dict *xs_dict_gc(xs_dict *dict);
48
49 xs_val *xs_val_new(xstype t);
50 xs_number *xs_number_new(double f);
51@@ -244,7 +251,7 @@ xstype xs_type(const xs_val *data)
52 case XSTYPE_LIST:
53 case XSTYPE_LITEM:
54 case XSTYPE_DICT:
55- case XSTYPE_DITEM:
56+ case XSTYPE_KEYVAL:
57 case XSTYPE_NUMBER:
58 case XSTYPE_EOM:
59 case XSTYPE_DATA:
60@@ -262,7 +269,7 @@ xstype xs_type(const xs_val *data)
61 void _xs_put_size(xs_val *ptr, int i)
62 /* must match _XS_TYPE_SIZE */
63 {
64- memcpy(ptr, &i, sizeof(i));
65+ memcpy(ptr + 1, &i, sizeof(i));
66 }
67
68
69@@ -296,7 +303,7 @@ int xs_size(const xs_val *data)
70
71 break;
72
73- case XSTYPE_DITEM:
74+ case XSTYPE_KEYVAL:
75 /* calculate the size of the key and the value */
76 p = data + 1;
77 p += xs_size(p);
78@@ -380,7 +387,7 @@ xs_val *xs_expand(xs_val *data, int offset, int size)
79 if (xs_type(data) == XSTYPE_LIST ||
80 xs_type(data) == XSTYPE_DICT ||
81 xs_type(data) == XSTYPE_DATA)
82- _xs_put_size(data + 1, sz);
83+ _xs_put_size(data, sz);
84
85 return data;
86 }
87@@ -405,7 +412,7 @@ xs_val *xs_collapse(xs_val *data, int offset, int size)
88 if (xs_type(data) == XSTYPE_LIST ||
89 xs_type(data) == XSTYPE_DICT ||
90 xs_type(data) == XSTYPE_DATA)
91- _xs_put_size(data + 1, sz);
92+ _xs_put_size(data, sz);
93
94 return xs_realloc(data, _xs_blk_size(sz));
95 }
96@@ -666,10 +673,10 @@ xs_list *xs_list_new(void)
97 {
98 int sz = 1 + _XS_TYPE_SIZE + 1;
99 xs_list *l = xs_realloc(NULL, sz);
100- memset(l, '\0', sz);
101+ memset(l, XSTYPE_EOM, sz);
102
103 l[0] = XSTYPE_LIST;
104- _xs_put_size(&l[1], sz);
105+ _xs_put_size(l, sz);
106
107 return l;
108 }
109@@ -802,7 +809,7 @@ int xs_list_len(const xs_list *list)
110 }
111
112
113-xs_val *xs_list_get(const xs_list *list, int num)
114+const xs_val *xs_list_get(const xs_list *list, int num)
115 /* returns the element #num */
116 {
117 XS_ASSERT_TYPE(list, XSTYPE_LIST);
118@@ -830,7 +837,7 @@ xs_list *xs_list_del(xs_list *list, int num)
119 {
120 XS_ASSERT_TYPE(list, XSTYPE_LIST);
121
122- xs_val *v;
123+ const xs_val *v;
124
125 if ((v = xs_list_get(list, num)) != NULL)
126 list = xs_collapse(list, v - 1 - list, xs_size(v - 1));
127@@ -844,7 +851,7 @@ xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data)
128 {
129 XS_ASSERT_TYPE(list, XSTYPE_LIST);
130
131- xs_val *v;
132+ const xs_val *v;
133 int offset;
134
135 if ((v = xs_list_get(list, num)) != NULL)
136@@ -999,6 +1006,40 @@ xs_list *xs_list_cat(xs_list *l1, const xs_list *l2)
137 }
138
139
140+/** keyvals **/
141+
142+int xs_keyval_size(const xs_str *key, const xs_val *value)
143+/* returns the needed size for a keyval */
144+{
145+ return 1 + xs_size(key) + xs_size(value);
146+}
147+
148+
149+xs_str *xs_keyval_key(const xs_keyval *keyval)
150+/* returns a pointer to the key of the keyval */
151+{
152+ return (xs_str *)&keyval[1];
153+}
154+
155+
156+xs_val *xs_keyval_value(const xs_keyval *keyval)
157+/* returns a pointer to the value of the keyval */
158+{
159+ return (xs_val *)&keyval[1 + xs_size(xs_keyval_key(keyval))];
160+}
161+
162+
163+xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value)
164+/* builds a keyval into mem (should have enough size) */
165+{
166+ keyval[0] = XSTYPE_KEYVAL;
167+ memcpy(xs_keyval_key(keyval), key, xs_size(key));
168+ memcpy(xs_keyval_value(keyval), value, xs_size(value));
169+
170+ return keyval;
171+}
172+
173+
174 /** dicts **/
175
176 xs_dict *xs_dict_new(void)
177@@ -1006,34 +1047,27 @@ xs_dict *xs_dict_new(void)
178 {
179 int sz = 1 + _XS_TYPE_SIZE + 1;
180 xs_dict *d = xs_realloc(NULL, sz);
181- memset(d, '\0', sz);
182+ memset(d, XSTYPE_EOM, sz);
183
184 d[0] = XSTYPE_DICT;
185- _xs_put_size(&d[1], sz);
186+ _xs_put_size(d, sz);
187
188 return d;
189 }
190
191
192-xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key,
193- const xs_val *data, int dsz)
194-/* inserts a memory block into the dict */
195+xs_dict *_xs_dict_write_keyval(xs_dict *dict, int offset, const xs_str *key, const xs_val *value)
196+/* adds a new keyval to the dict */
197 {
198 XS_ASSERT_TYPE(dict, XSTYPE_DICT);
199 XS_ASSERT_TYPE(key, XSTYPE_STRING);
200
201- if (data == NULL) {
202- data = xs_stock(XSTYPE_NULL);
203- dsz = xs_size(data);
204- }
205-
206- int ksz = xs_size(key);
207+ if (value == NULL)
208+ value = xs_stock(XSTYPE_NULL);
209
210- dict = xs_expand(dict, offset, 1 + ksz + dsz);
211+ dict = xs_expand(dict, offset, xs_keyval_size(key, value));
212
213- dict[offset] = XSTYPE_DITEM;
214- memcpy(&dict[offset + 1], key, ksz);
215- memcpy(&dict[offset + 1 + ksz], data, dsz);
216+ xs_keyval_make(&dict[offset], key, value);
217
218 return dict;
219 }
220@@ -1042,14 +1076,14 @@ xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key,
221 xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value)
222 /* appends a memory block to the dict */
223 {
224- return _xs_dict_write_ditem(dict, xs_size(dict) - 1, key, value, xs_size(value));
225+ return _xs_dict_write_keyval(dict, xs_size(dict) - 1, key, value);
226 }
227
228
229 xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value)
230 /* prepends a memory block to the dict */
231 {
232- return _xs_dict_write_ditem(dict, 1 + _XS_TYPE_SIZE, key, value, xs_size(value));
233+ return _xs_dict_write_keyval(dict, 1 + _XS_TYPE_SIZE, key, value);
234 }
235
236
237@@ -1070,7 +1104,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt)
238 p += *ctxt;
239
240 /* an element? */
241- if (xs_type(p) == XSTYPE_DITEM) {
242+ if (xs_type(p) == XSTYPE_KEYVAL) {
243 p++;
244
245 *key = p;
246@@ -1091,7 +1125,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt)
247 }
248
249
250-xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def)
251+const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def)
252 /* returns the value directed by key, or the default value */
253 {
254 XS_ASSERT_TYPE(dict, XSTYPE_DICT);
255@@ -1150,6 +1184,14 @@ xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data)
256 }
257
258
259+xs_dict *xs_dict_gc(xs_dict *dict)
260+/* collects garbage (leaked values) inside a dict */
261+{
262+ /* this kind of dicts does not get garbage */
263+ return dict;
264+}
265+
266+
267 /** other values **/
268
269 xs_val *xs_val_new(xstype t)
270@@ -1235,7 +1277,7 @@ xs_data *xs_data_new(const void *data, int size)
271 v = xs_realloc(NULL, _xs_blk_size(total_size));
272 v[0] = XSTYPE_DATA;
273
274- _xs_put_size(v + 1, total_size);
275+ _xs_put_size(v, total_size);
276
277 memcpy(&v[1 + _XS_TYPE_SIZE], data, size);
278
+1,
-1
1@@ -28,7 +28,7 @@ static size_t _header_callback(char *buffer, size_t size,
2 if (xs_str_in(l, ": ") != -1) {
3 xs *knv = xs_split_n(l, ": ", 1);
4
5- xs_tolower_i(xs_list_get(knv, 0));
6+ xs_tolower_i((xs_str *)xs_list_get(knv, 0));
7
8 headers = xs_dict_set(headers, xs_list_get(knv, 0), xs_list_get(knv, 1));
9 }
+17,
-17
1@@ -6,26 +6,26 @@
2
3 typedef struct xs_html xs_html;
4
5-xs_str *xs_html_encode(char *str);
6+xs_str *xs_html_encode(const char *str);
7
8-xs_html *xs_html_attr(char *key, char *value);
9-xs_html *xs_html_text(char *content);
10-xs_html *xs_html_raw(char *content);
11+xs_html *xs_html_attr(const char *key, const char *value);
12+xs_html *xs_html_text(const char *content);
13+xs_html *xs_html_raw(const char *content);
14
15 xs_html *_xs_html_add(xs_html *tag, xs_html *var[]);
16 #define xs_html_add(tag, ...) _xs_html_add(tag, (xs_html *[]) { __VA_ARGS__, NULL })
17
18-xs_html *_xs_html_tag(char *tag, xs_html *var[]);
19+xs_html *_xs_html_tag(const char *tag, xs_html *var[]);
20 #define xs_html_tag(tag, ...) _xs_html_tag(tag, (xs_html *[]) { __VA_ARGS__, NULL })
21
22-xs_html *_xs_html_sctag(char *tag, xs_html *var[]);
23+xs_html *_xs_html_sctag(const char *tag, xs_html *var[]);
24 #define xs_html_sctag(tag, ...) _xs_html_sctag(tag, (xs_html *[]) { __VA_ARGS__, NULL })
25
26 xs_html *_xs_html_container(xs_html *var[]);
27 #define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL })
28
29 void xs_html_render_f(xs_html *h, FILE *f);
30-xs_str *xs_html_render_s(xs_html *tag, char *prefix);
31+xs_str *xs_html_render_s(xs_html *tag, const char *prefix);
32 #define xs_html_render(tag) xs_html_render_s(tag, NULL)
33
34
35@@ -47,16 +47,16 @@ struct xs_html {
36 xs_html *next;
37 };
38
39-xs_str *xs_html_encode(char *str)
40+xs_str *xs_html_encode(const char *str)
41 /* encodes str using HTML entities */
42 {
43 xs_str *s = xs_str_new(NULL);
44 int o = 0;
45- char *e = str + strlen(str);
46+ const char *e = str + strlen(str);
47
48 for (;;) {
49 char *ec = "<>\"'&"; /* characters to escape */
50- char *q = e;
51+ const char *q = e;
52 int z;
53
54 /* find the nearest happening of a char */
55@@ -90,7 +90,7 @@ xs_str *xs_html_encode(char *str)
56
57 #define XS_HTML_NEW() memset(xs_realloc(NULL, sizeof(xs_html)), '\0', sizeof(xs_html))
58
59-xs_html *xs_html_attr(char *key, char *value)
60+xs_html *xs_html_attr(const char *key, const char *value)
61 /* creates an HTML block with an attribute */
62 {
63 xs_html *a = XS_HTML_NEW();
64@@ -108,7 +108,7 @@ xs_html *xs_html_attr(char *key, char *value)
65 }
66
67
68-xs_html *xs_html_text(char *content)
69+xs_html *xs_html_text(const char *content)
70 /* creates an HTML block of text, escaping it previously */
71 {
72 xs_html *a = XS_HTML_NEW();
73@@ -120,7 +120,7 @@ xs_html *xs_html_text(char *content)
74 }
75
76
77-xs_html *xs_html_raw(char *content)
78+xs_html *xs_html_raw(const char *content)
79 /* creates an HTML block without escaping (for pre-formatted HTML, comments, etc) */
80 {
81 xs_html *a = XS_HTML_NEW();
82@@ -152,7 +152,7 @@ xs_html *_xs_html_add(xs_html *tag, xs_html *var[])
83 }
84
85
86-static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[])
87+static xs_html *_xs_html_tag_t(xs_html_type type, const char *tag, xs_html *var[])
88 /* creates a tag with a variable list of attributes and subtags */
89 {
90 xs_html *a = XS_HTML_NEW();
91@@ -169,13 +169,13 @@ static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[])
92 }
93
94
95-xs_html *_xs_html_tag(char *tag, xs_html *var[])
96+xs_html *_xs_html_tag(const char *tag, xs_html *var[])
97 {
98 return _xs_html_tag_t(XS_HTML_TAG, tag, var);
99 }
100
101
102-xs_html *_xs_html_sctag(char *tag, xs_html *var[])
103+xs_html *_xs_html_sctag(const char *tag, xs_html *var[])
104 {
105 return _xs_html_tag_t(XS_HTML_SCTAG, tag, var);
106 }
107@@ -239,7 +239,7 @@ void xs_html_render_f(xs_html *h, FILE *f)
108 }
109
110
111-xs_str *xs_html_render_s(xs_html *tag, char *prefix)
112+xs_str *xs_html_render_s(xs_html *tag, const char *prefix)
113 /* renders to a string */
114 {
115 xs_str *s = NULL;
+3,
-2
1@@ -16,7 +16,7 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
2 xs *q_vars = NULL;
3 xs *p_vars = NULL;
4 xs *l1, *l2;
5- char *v;
6+ const char *v;
7
8 xs_socket_timeout(fileno(f), 2.0, 0.0);
9
10@@ -60,7 +60,8 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size)
11 p = xs_split_n(l, ": ", 1);
12
13 if (xs_list_len(p) == 2)
14- req = xs_dict_append(req, xs_tolower_i(xs_list_get(p, 0)), xs_list_get(p, 1));
15+ req = xs_dict_append(req, xs_tolower_i(
16+ (xs_str *)xs_list_get(p, 0)), xs_list_get(p, 1));
17 }
18
19 xs_socket_timeout(fileno(f), 5.0, 0.0);
+4,
-5
1@@ -71,12 +71,12 @@ static void _xs_json_indent(int level, int indent, FILE *f)
2 }
3
4
5-static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
6+static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f)
7 /* dumps partial data as JSON */
8 {
9 int c = 0;
10+ int ct = 0;
11 xs_val *v;
12- xs_val *data = (xs_val *)s_data;
13
14 switch (xs_type(data)) {
15 case XSTYPE_NULL:
16@@ -98,7 +98,7 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
17 case XSTYPE_LIST:
18 fputc('[', f);
19
20- while (xs_list_iter(&data, &v)) {
21+ while (xs_list_next(data, &v, &ct)) {
22 if (c != 0)
23 fputc(',', f);
24
25@@ -117,9 +117,8 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f)
26 fputc('{', f);
27
28 xs_str *k;
29- int ct = 0;
30
31- while (xs_dict_next(s_data, &k, &v, &ct)) {
32+ while (xs_dict_next(data, &k, &v, &ct)) {
33 if (c != 0)
34 fputc(',', f);
35
M
xs_set.h
+1,
-1
1@@ -104,7 +104,7 @@ int xs_set_add(xs_set *s, const xs_val *data)
2
3 /* if it's new, add the data */
4 if (ret)
5- s->list = xs_list_append_m(s->list, data, xs_size(data));
6+ s->list = xs_list_append(s->list, data);
7
8 return ret;
9 }
+3,
-3
1@@ -6,7 +6,7 @@
2
3 int _xs_utf8_enc(char buf[4], unsigned int cpoint);
4 int xs_is_utf8_cont_byte(char c);
5- unsigned int xs_utf8_dec(char **str);
6+ unsigned int xs_utf8_dec(const char **str);
7 int xs_unicode_width(unsigned int cpoint);
8 int xs_is_surrogate(unsigned int cpoint);
9 unsigned int xs_surrogate_dec(unsigned int p1, unsigned int p2);
10@@ -66,10 +66,10 @@ int xs_is_utf8_cont_byte(char c)
11 }
12
13
14-unsigned int xs_utf8_dec(char **str)
15+unsigned int xs_utf8_dec(const char **str)
16 /* decodes an utf-8 char inside str and updates the pointer */
17 {
18- char *p = *str;
19+ const char *p = *str;
20 unsigned int cpoint = 0;
21 unsigned char c = *p++;
22 int cb = 0;
M
xs_url.h
+2,
-2
1@@ -119,8 +119,8 @@ xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *hea
2 while ((p = xs_memmem(payload + offset, p_size - offset, boundary, bsz)) != NULL) {
3 xs *s1 = NULL;
4 xs *l1 = NULL;
5- char *vn = NULL;
6- char *fn = NULL;
7+ const char *vn = NULL;
8+ const char *fn = NULL;
9 char *q;
10 int po, ps;
11
+1,
-1
1@@ -1 +1 @@
2-/* 6e75e8736f7f1b6ea6c6774d4bd922b3ad56b771 2024-05-15T11:42:19+02:00 */
3+/* 34850dcdec50b669a2c0bbe9f16f6d9c4b16eafd 2024-05-21T14:06:02+02:00 */