summaryrefslogtreecommitdiff
path: root/activitypub.c
diff options
context:
space:
mode:
authorGravatar default2024-05-21 14:12:15 +0200
committerGravatar default2024-05-21 14:12:15 +0200
commit4777fc86cb962917a8f34afb3bfa40f26290815d (patch)
tree268c078531a018f07c1b6d029f14f87134805f7b /activitypub.c
parentVersion 2.53 RELEASED. (diff)
downloadsnac2-4777fc86cb962917a8f34afb3bfa40f26290815d.tar.gz
snac2-4777fc86cb962917a8f34afb3bfa40f26290815d.tar.xz
snac2-4777fc86cb962917a8f34afb3bfa40f26290815d.zip
Added const everywhere.
Diffstat (limited to 'activitypub.c')
-rw-r--r--activitypub.c283
1 files changed, 106 insertions, 177 deletions
diff --git a/activitypub.c b/activitypub.c
index 231715b..f4b4eac 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -67,7 +67,7 @@ int activitypub_request(snac *user, const char *url, xs_dict **data)
67 xs *response = NULL; 67 xs *response = NULL;
68 xs *payload = NULL; 68 xs *payload = NULL;
69 int p_size; 69 int p_size;
70 char *ctype; 70 const char *ctype;
71 71
72 *data = NULL; 72 *data = NULL;
73 73
@@ -154,20 +154,21 @@ int actor_request(snac *user, const char *actor, xs_dict **data)
154} 154}
155 155
156 156
157char *get_atto(const xs_dict *msg) 157const char *get_atto(const xs_dict *msg)
158/* gets the attributedTo field (an actor) */ 158/* gets the attributedTo field (an actor) */
159{ 159{
160 char *actor = xs_dict_get(msg, "attributedTo"); 160 const xs_val *actor = xs_dict_get(msg, "attributedTo");
161 161
162 /* if the actor is a list of objects (like on Peertube videos), pick the Person */ 162 /* if the actor is a list of objects (like on Peertube videos), pick the Person */
163 if (xs_type(actor) == XSTYPE_LIST) { 163 if (xs_type(actor) == XSTYPE_LIST) {
164 xs_list *p = actor; 164 const xs_list *p = actor;
165 int c = 0;
165 xs_dict *v; 166 xs_dict *v;
166 actor = NULL; 167 actor = NULL;
167 168
168 while (actor == NULL && xs_list_iter(&p, &v)) { 169 while (actor == NULL && xs_list_next(p, &v, &c)) {
169 if (xs_type(v) == XSTYPE_DICT) { 170 if (xs_type(v) == XSTYPE_DICT) {
170 char *type = xs_dict_get(v, "type"); 171 const char *type = xs_dict_get(v, "type");
171 if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) { 172 if (xs_type(type) == XSTYPE_STRING && strcmp(type, "Person") == 0) {
172 actor = xs_dict_get(v, "id"); 173 actor = xs_dict_get(v, "id");
173 174
@@ -186,7 +187,7 @@ xs_list *get_attachments(const xs_dict *msg)
186/* unify the garbage fire that are the attachments */ 187/* unify the garbage fire that are the attachments */
187{ 188{
188 xs_list *l = xs_list_new(); 189 xs_list *l = xs_list_new();
189 xs_list *p; 190 const xs_list *p;
190 191
191 /* try first the attachments list */ 192 /* try first the attachments list */
192 if (!xs_is_null(p = xs_dict_get(msg, "attachment"))) { 193 if (!xs_is_null(p = xs_dict_get(msg, "attachment"))) {
@@ -203,23 +204,24 @@ xs_list *get_attachments(const xs_dict *msg)
203 204
204 if (xs_type(attach) == XSTYPE_LIST) { 205 if (xs_type(attach) == XSTYPE_LIST) {
205 /* does the message have an image? */ 206 /* does the message have an image? */
206 if (xs_type(v = xs_dict_get(msg, "image")) == XSTYPE_DICT) { 207 const xs_dict *d = xs_dict_get(msg, "image");
208 if (xs_type(d) == XSTYPE_DICT) {
207 /* add it to the attachment list */ 209 /* add it to the attachment list */
208 attach = xs_list_append(attach, v); 210 attach = xs_list_append(attach, d);
209 } 211 }
210 } 212 }
211 213
212 /* now iterate the list */ 214 /* now iterate the list */
213 p = attach; 215 int c = 0;
214 while (xs_list_iter(&p, &v)) { 216 while (xs_list_next(attach, &v, &c)) {
215 char *type = xs_dict_get(v, "mediaType"); 217 const char *type = xs_dict_get(v, "mediaType");
216 if (xs_is_null(type)) 218 if (xs_is_null(type))
217 type = xs_dict_get(v, "type"); 219 type = xs_dict_get(v, "type");
218 220
219 if (xs_is_null(type)) 221 if (xs_is_null(type))
220 continue; 222 continue;
221 223
222 char *href = xs_dict_get(v, "url"); 224 const char *href = xs_dict_get(v, "url");
223 if (xs_is_null(href)) 225 if (xs_is_null(href))
224 href = xs_dict_get(v, "href"); 226 href = xs_dict_get(v, "href");
225 if (xs_is_null(href)) 227 if (xs_is_null(href))
@@ -233,7 +235,7 @@ xs_list *get_attachments(const xs_dict *msg)
233 type = mt; 235 type = mt;
234 } 236 }
235 237
236 char *name = xs_dict_get(v, "name"); 238 const char *name = xs_dict_get(v, "name");
237 if (xs_is_null(name)) 239 if (xs_is_null(name))
238 name = xs_dict_get(msg, "name"); 240 name = xs_dict_get(msg, "name");
239 if (xs_is_null(name)) 241 if (xs_is_null(name))
@@ -252,29 +254,31 @@ xs_list *get_attachments(const xs_dict *msg)
252 p = xs_dict_get(msg, "url"); 254 p = xs_dict_get(msg, "url");
253 255
254 if (xs_type(p) == XSTYPE_LIST) { 256 if (xs_type(p) == XSTYPE_LIST) {
255 char *href = NULL; 257 const char *href = NULL;
256 char *type = NULL; 258 const char *type = NULL;
259 int c = 0;
257 xs_val *v; 260 xs_val *v;
258 261
259 while (href == NULL && xs_list_iter(&p, &v)) { 262 while (href == NULL && xs_list_next(p, &v, &c)) {
260 if (xs_type(v) == XSTYPE_DICT) { 263 if (xs_type(v) == XSTYPE_DICT) {
261 char *mtype = xs_dict_get(v, "type"); 264 const char *mtype = xs_dict_get(v, "type");
262 265
263 if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "Link") == 0) { 266 if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "Link") == 0) {
264 mtype = xs_dict_get(v, "mediaType"); 267 mtype = xs_dict_get(v, "mediaType");
265 xs_list *tag = xs_dict_get(v, "tag"); 268 const xs_list *tag = xs_dict_get(v, "tag");
266 269
267 if (xs_type(mtype) == XSTYPE_STRING && 270 if (xs_type(mtype) == XSTYPE_STRING &&
268 strcmp(mtype, "application/x-mpegURL") == 0 && 271 strcmp(mtype, "application/x-mpegURL") == 0 &&
269 xs_type(tag) == XSTYPE_LIST) { 272 xs_type(tag) == XSTYPE_LIST) {
270 /* now iterate the tag list, looking for a video URL */ 273 /* now iterate the tag list, looking for a video URL */
271 xs_dict *d; 274 xs_dict *d;
275 int c = 0;
272 276
273 while (href == NULL && xs_list_iter(&tag, &d)) { 277 while (href == NULL && xs_list_next(tag, &d, &c)) {
274 if (xs_type(d) == XSTYPE_DICT) { 278 if (xs_type(d) == XSTYPE_DICT) {
275 if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING && 279 if (xs_type(mtype = xs_dict_get(d, "mediaType")) == XSTYPE_STRING &&
276 xs_startswith(mtype, "video/")) { 280 xs_startswith(mtype, "video/")) {
277 char *h = xs_dict_get(d, "href"); 281 const char *h = xs_dict_get(d, "href");
278 282
279 /* this is probably it */ 283 /* this is probably it */
280 if (xs_type(h) == XSTYPE_STRING) { 284 if (xs_type(h) == XSTYPE_STRING) {
@@ -303,7 +307,7 @@ xs_list *get_attachments(const xs_dict *msg)
303} 307}
304 308
305 309
306int timeline_request(snac *snac, char **id, xs_str **wrk, int level) 310int timeline_request(snac *snac, const char **id, xs_str **wrk, int level)
307/* ensures that an entry and its ancestors are in the timeline */ 311/* ensures that an entry and its ancestors are in the timeline */
308{ 312{
309 int status = 0; 313 int status = 0;
@@ -323,7 +327,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
323 status = activitypub_request(snac, *id, &msg); 327 status = activitypub_request(snac, *id, &msg);
324 328
325 if (valid_status(status)) { 329 if (valid_status(status)) {
326 xs_dict *object = msg; 330 const xs_dict *object = msg;
327 const char *type = xs_dict_get(object, "type"); 331 const char *type = xs_dict_get(object, "type");
328 332
329 /* get the id again from the object, as it may be different */ 333 /* get the id again from the object, as it may be different */
@@ -369,7 +373,7 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
369 } 373 }
370 374
371 /* does it have an ancestor? */ 375 /* does it have an ancestor? */
372 char *in_reply_to = xs_dict_get(object, "inReplyTo"); 376 const char *in_reply_to = xs_dict_get(object, "inReplyTo");
373 377
374 /* store */ 378 /* store */
375 timeline_add(snac, nid, object); 379 timeline_add(snac, nid, object);
@@ -381,83 +385,12 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level)
381 } 385 }
382 } 386 }
383 } 387 }
384
385 enqueue_request_replies(snac, *id);
386 } 388 }
387 389
388 return status; 390 return status;
389} 391}
390 392
391 393
392void timeline_request_replies(snac *user, const char *id)
393/* requests all replies of a message */
394/* FIXME: experimental -- needs more testing */
395{
396 /* FIXME: TEMPORARILY DISABLED */
397 /* Reason: I've found that many of the posts in the 'replies' Collection
398 do not have an inReplyTo field (why??? aren't they 'replies'???).
399 For this reason, these requested objects are not stored as children
400 of the original post and they are shown as out-of-context, top level posts.
401 This process is disabled until I find an elegant way of providing a parent
402 for these 'stray' children. */
403 return;
404
405 xs *msg = NULL;
406
407 if (!valid_status(object_get(id, &msg)))
408 return;
409
410 /* does it have a replies collection? */
411 const xs_dict *replies = xs_dict_get(msg, "replies");
412
413 if (!xs_is_null(replies)) {
414 const char *type = xs_dict_get(replies, "type");
415 const char *first = xs_dict_get(replies, "first");
416
417 if (!xs_is_null(type) && !xs_is_null(first) && strcmp(type, "Collection") == 0) {
418 const char *next = xs_dict_get(first, "next");
419
420 if (!xs_is_null(next)) {
421 xs *rpls = NULL;
422 int status = activitypub_request(user, next, &rpls);
423
424 /* request the Collection of replies */
425 if (valid_status(status)) {
426 xs_list *items = xs_dict_get(rpls, "items");
427
428 if (xs_type(items) == XSTYPE_LIST) {
429 xs_val *v;
430
431 /* request them all */
432 while (xs_list_iter(&items, &v)) {
433 if (xs_type(v) == XSTYPE_DICT) {
434 /* not an id, but the object itself (!) */
435 const char *c_id = xs_dict_get(v, "id");
436
437 if (!xs_is_null(id)) {
438 snac_debug(user, 0, xs_fmt("embedded reply %s", c_id));
439
440 object_add(c_id, v);
441
442 /* get its own children */
443 timeline_request_replies(user, v);
444 }
445 }
446 else {
447 snac_debug(user, 0, xs_fmt("request reply %s", v));
448 timeline_request(user, &v, NULL, 0);
449 }
450 }
451 }
452 }
453 else
454 snac_debug(user, 0, xs_fmt("replies request error %s %d", next, status));
455 }
456 }
457 }
458}
459
460
461int send_to_inbox_raw(const char *keyid, const char *seckey, 394int send_to_inbox_raw(const char *keyid, const char *seckey,
462 const xs_str *inbox, const xs_dict *msg, 395 const xs_str *inbox, const xs_dict *msg,
463 xs_val **payload, int *p_size, int timeout) 396 xs_val **payload, int *p_size, int timeout)
@@ -480,7 +413,7 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg,
480 xs_val **payload, int *p_size, int timeout) 413 xs_val **payload, int *p_size, int timeout)
481/* sends a message to an Inbox */ 414/* sends a message to an Inbox */
482{ 415{
483 char *seckey = xs_dict_get(snac->key, "secret"); 416 const char *seckey = xs_dict_get(snac->key, "secret");
484 417
485 return send_to_inbox_raw(snac->actor, seckey, inbox, msg, payload, p_size, timeout); 418 return send_to_inbox_raw(snac->actor, seckey, inbox, msg, payload, p_size, timeout);
486} 419}
@@ -490,7 +423,7 @@ xs_str *get_actor_inbox(const char *actor)
490/* gets an actor's inbox */ 423/* gets an actor's inbox */
491{ 424{
492 xs *data = NULL; 425 xs *data = NULL;
493 char *v = NULL; 426 const char *v = NULL;
494 427
495 if (valid_status(actor_request(NULL, actor, &data))) { 428 if (valid_status(actor_request(NULL, actor, &data))) {
496 /* try first endpoints/sharedInbox */ 429 /* try first endpoints/sharedInbox */
@@ -539,16 +472,16 @@ void post_message(snac *snac, const char *actor, const xs_dict *msg)
539xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) 472xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public)
540/* returns the list of recipients for a message */ 473/* returns the list of recipients for a message */
541{ 474{
542 char *to = xs_dict_get(msg, "to"); 475 const xs_val *to = xs_dict_get(msg, "to");
543 char *cc = xs_dict_get(msg, "cc"); 476 const xs_val *cc = xs_dict_get(msg, "cc");
544 xs_set rcpts; 477 xs_set rcpts;
545 int n; 478 int n;
546 479
547 xs_set_init(&rcpts); 480 xs_set_init(&rcpts);
548 481
549 char *lists[] = { to, cc, NULL }; 482 const xs_list *lists[] = { to, cc, NULL };
550 for (n = 0; lists[n]; n++) { 483 for (n = 0; lists[n]; n++) {
551 char *l = lists[n]; 484 xs_list *l = (xs_list *)lists[n];
552 char *v; 485 char *v;
553 xs *tl = NULL; 486 xs *tl = NULL;
554 487
@@ -671,13 +604,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
671 604
672 /* if it's a Follow, it must be explicitly for us */ 605 /* if it's a Follow, it must be explicitly for us */
673 if (xs_match(type, "Follow")) { 606 if (xs_match(type, "Follow")) {
674 char *object = xs_dict_get(c_msg, "object"); 607 const char *object = xs_dict_get(c_msg, "object");
675 return !xs_is_null(object) && strcmp(snac->actor, object) == 0; 608 return !xs_is_null(object) && strcmp(snac->actor, object) == 0;
676 } 609 }
677 610
678 /* only accept Ping directed to us */ 611 /* only accept Ping directed to us */
679 if (xs_match(type, "Ping")) { 612 if (xs_match(type, "Ping")) {
680 char *dest = xs_dict_get(c_msg, "to"); 613 const char *dest = xs_dict_get(c_msg, "to");
681 return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0; 614 return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0;
682 } 615 }
683 616
@@ -692,7 +625,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
692 if (pub_msg && following_check(snac, actor)) 625 if (pub_msg && following_check(snac, actor))
693 return 1; 626 return 1;
694 627
695 xs_dict *msg = xs_dict_get(c_msg, "object"); 628 const xs_dict *msg = xs_dict_get(c_msg, "object");
696 xs *rcpts = recipient_list(snac, msg, 0); 629 xs *rcpts = recipient_list(snac, msg, 0);
697 xs_list *p = rcpts; 630 xs_list *p = rcpts;
698 xs_str *v; 631 xs_str *v;
@@ -704,8 +637,9 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
704 xs *actor_obj = NULL; 637 xs *actor_obj = NULL;
705 638
706 if (valid_status(object_get(actor, &actor_obj))) { 639 if (valid_status(object_get(actor, &actor_obj))) {
707 if ((v = xs_dict_get(actor_obj, "followers"))) 640 const xs_val *fw = xs_dict_get(actor_obj, "followers");
708 actor_followers = xs_dup(v); 641 if (fw)
642 actor_followers = xs_dup(fw);
709 } 643 }
710 } 644 }
711 645
@@ -728,13 +662,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg)
728 } 662 }
729 663
730 /* accept if it's by someone we follow */ 664 /* accept if it's by someone we follow */
731 char *atto = get_atto(msg); 665 const char *atto = get_atto(msg);
732 666
733 if (pub_msg && !xs_is_null(atto) && following_check(snac, atto)) 667 if (pub_msg && !xs_is_null(atto) && following_check(snac, atto))
734 return 3; 668 return 3;
735 669
736 /* is this message a reply to another? */ 670 /* is this message a reply to another? */
737 char *irt = xs_dict_get(msg, "inReplyTo"); 671 const char *irt = xs_dict_get(msg, "inReplyTo");
738 if (!xs_is_null(irt)) { 672 if (!xs_is_null(irt)) {
739 xs *r_msg = NULL; 673 xs *r_msg = NULL;
740 674
@@ -987,8 +921,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
987 921
988 /* telegram */ 922 /* telegram */
989 923
990 char *bot = xs_dict_get(snac->config, "telegram_bot"); 924 const char *bot = xs_dict_get(snac->config, "telegram_bot");
991 char *chat_id = xs_dict_get(snac->config, "telegram_chat_id"); 925 const char *chat_id = xs_dict_get(snac->config, "telegram_chat_id");
992 926
993 if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id) 927 if (!xs_is_null(bot) && !xs_is_null(chat_id) && *bot && *chat_id)
994 enqueue_telegram(body, bot, chat_id); 928 enqueue_telegram(body, bot, chat_id);
@@ -1001,8 +935,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor,
1001 objid = actor; 935 objid = actor;
1002 936
1003 /* ntfy */ 937 /* ntfy */
1004 char *ntfy_server = xs_dict_get(snac->config, "ntfy_server"); 938 const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server");
1005 char *ntfy_token = xs_dict_get(snac->config, "ntfy_token"); 939 const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token");
1006 940
1007 if (!xs_is_null(ntfy_server) && *ntfy_server) 941 if (!xs_is_null(ntfy_server) && *ntfy_server)
1008 enqueue_ntfy(body, ntfy_server, ntfy_token); 942 enqueue_ntfy(body, ntfy_server, ntfy_token);
@@ -1088,7 +1022,7 @@ xs_dict *msg_base(snac *snac, const char *type, const char *id,
1088} 1022}
1089 1023
1090 1024
1091xs_dict *msg_collection(snac *snac, char *id) 1025xs_dict *msg_collection(snac *snac, const char *id)
1092/* creates an empty OrderedCollection message */ 1026/* creates an empty OrderedCollection message */
1093{ 1027{
1094 xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL); 1028 xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL);
@@ -1102,7 +1036,7 @@ xs_dict *msg_collection(snac *snac, char *id)
1102} 1036}
1103 1037
1104 1038
1105xs_dict *msg_accept(snac *snac, char *object, char *to) 1039xs_dict *msg_accept(snac *snac, const xs_val *object, const char *to)
1106/* creates an Accept message (as a response to a Follow) */ 1040/* creates an Accept message (as a response to a Follow) */
1107{ 1041{
1108 xs_dict *msg = msg_base(snac, "Accept", "@dummy", snac->actor, NULL, object); 1042 xs_dict *msg = msg_base(snac, "Accept", "@dummy", snac->actor, NULL, object);
@@ -1113,12 +1047,12 @@ xs_dict *msg_accept(snac *snac, char *object, char *to)
1113} 1047}
1114 1048
1115 1049
1116xs_dict *msg_update(snac *snac, xs_dict *object) 1050xs_dict *msg_update(snac *snac, const xs_dict *object)
1117/* creates an Update message */ 1051/* creates an Update message */
1118{ 1052{
1119 xs_dict *msg = msg_base(snac, "Update", "@object", snac->actor, "@now", object); 1053 xs_dict *msg = msg_base(snac, "Update", "@object", snac->actor, "@now", object);
1120 1054
1121 char *type = xs_dict_get(object, "type"); 1055 const char *type = xs_dict_get(object, "type");
1122 1056
1123 if (strcmp(type, "Note") == 0) { 1057 if (strcmp(type, "Note") == 0) {
1124 msg = xs_dict_append(msg, "to", xs_dict_get(object, "to")); 1058 msg = xs_dict_append(msg, "to", xs_dict_get(object, "to"));
@@ -1141,7 +1075,7 @@ xs_dict *msg_update(snac *snac, xs_dict *object)
1141} 1075}
1142 1076
1143 1077
1144xs_dict *msg_admiration(snac *snac, char *object, char *type) 1078xs_dict *msg_admiration(snac *snac, const char *object, const char *type)
1145/* creates a Like or Announce message */ 1079/* creates a Like or Announce message */
1146{ 1080{
1147 xs *a_msg = NULL; 1081 xs *a_msg = NULL;
@@ -1172,7 +1106,7 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type)
1172} 1106}
1173 1107
1174 1108
1175xs_dict *msg_repulsion(snac *user, char *id, char *type) 1109xs_dict *msg_repulsion(snac *user, const char *id, const char *type)
1176/* creates an Undo + admiration message */ 1110/* creates an Undo + admiration message */
1177{ 1111{
1178 xs *a_msg = NULL; 1112 xs *a_msg = NULL;
@@ -1210,7 +1144,7 @@ xs_dict *msg_actor(snac *snac)
1210 xs *kid = NULL; 1144 xs *kid = NULL;
1211 xs *f_bio = NULL; 1145 xs *f_bio = NULL;
1212 xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL); 1146 xs_dict *msg = msg_base(snac, "Person", snac->actor, NULL, NULL, NULL);
1213 char *p; 1147 const char *p;
1214 int n; 1148 int n;
1215 1149
1216 /* change the @context (is this really necessary?) */ 1150 /* change the @context (is this really necessary?) */
@@ -1268,7 +1202,7 @@ xs_dict *msg_actor(snac *snac)
1268 } 1202 }
1269 1203
1270 /* add the metadata as attachments of PropertyValue */ 1204 /* add the metadata as attachments of PropertyValue */
1271 xs_dict *metadata = xs_dict_get(snac->config, "metadata"); 1205 const xs_dict *metadata = xs_dict_get(snac->config, "metadata");
1272 if (xs_type(metadata) == XSTYPE_DICT) { 1206 if (xs_type(metadata) == XSTYPE_DICT) {
1273 xs *attach = xs_list_new(); 1207 xs *attach = xs_list_new();
1274 xs_str *k; 1208 xs_str *k;
@@ -1314,7 +1248,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
1314/* creates a 'Create' message */ 1248/* creates a 'Create' message */
1315{ 1249{
1316 xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object); 1250 xs_dict *msg = msg_base(snac, "Create", "@wrapper", snac->actor, NULL, object);
1317 xs_val *v; 1251 const xs_val *v;
1318 1252
1319 if ((v = get_atto(object))) 1253 if ((v = get_atto(object)))
1320 msg = xs_dict_append(msg, "attributedTo", v); 1254 msg = xs_dict_append(msg, "attributedTo", v);
@@ -1331,7 +1265,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object)
1331} 1265}
1332 1266
1333 1267
1334xs_dict *msg_undo(snac *snac, char *object) 1268xs_dict *msg_undo(snac *snac, const xs_val *object)
1335/* creates an 'Undo' message */ 1269/* creates an 'Undo' message */
1336{ 1270{
1337 xs_dict *msg = msg_base(snac, "Undo", "@object", snac->actor, "@now", object); 1271 xs_dict *msg = msg_base(snac, "Undo", "@object", snac->actor, "@now", object);
@@ -1344,7 +1278,7 @@ xs_dict *msg_undo(snac *snac, char *object)
1344} 1278}
1345 1279
1346 1280
1347xs_dict *msg_delete(snac *snac, char *id) 1281xs_dict *msg_delete(snac *snac, const char *id)
1348/* creates a 'Delete' + 'Tombstone' for a local entry */ 1282/* creates a 'Delete' + 'Tombstone' for a local entry */
1349{ 1283{
1350 xs *tomb = xs_dict_new(); 1284 xs *tomb = xs_dict_new();
@@ -1386,7 +1320,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
1386 1320
1387 if (valid_status(status)) { 1321 if (valid_status(status)) {
1388 /* check if the actor is an alias */ 1322 /* check if the actor is an alias */
1389 char *r_actor = xs_dict_get(actor_o, "id"); 1323 const char *r_actor = xs_dict_get(actor_o, "id");
1390 1324
1391 if (r_actor && strcmp(actor, r_actor) != 0) { 1325 if (r_actor && strcmp(actor, r_actor) != 0) {
1392 snac_log(snac, xs_fmt("actor to follow is an alias %s -> %s", actor, r_actor)); 1326 snac_log(snac, xs_fmt("actor to follow is an alias %s -> %s", actor, r_actor));
@@ -1402,7 +1336,7 @@ xs_dict *msg_follow(snac *snac, const char *q)
1402 1336
1403 1337
1404xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, 1338xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1405 xs_str *in_reply_to, xs_list *attach, int priv) 1339 const xs_str *in_reply_to, const xs_list *attach, int priv)
1406/* creates a 'Note' message */ 1340/* creates a 'Note' message */
1407{ 1341{
1408 xs *ntid = tid(0); 1342 xs *ntid = tid(0);
@@ -1442,7 +1376,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1442 1376
1443 if (valid_status(object_get(in_reply_to, &p_msg))) { 1377 if (valid_status(object_get(in_reply_to, &p_msg))) {
1444 /* add this author as recipient */ 1378 /* add this author as recipient */
1445 char *a, *v; 1379 const char *a, *v;
1446 1380
1447 if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1) 1381 if ((a = get_atto(p_msg)) && xs_list_in(to, a) == -1)
1448 to = xs_list_append(to, a); 1382 to = xs_list_append(to, a);
@@ -1453,7 +1387,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1453 xs *actor_o = NULL; 1387 xs *actor_o = NULL;
1454 1388
1455 if (xs_list_len(l) > 3 && valid_status(object_get(a, &actor_o))) { 1389 if (xs_list_len(l) > 3 && valid_status(object_get(a, &actor_o))) {
1456 char *uname = xs_dict_get(actor_o, "preferredUsername"); 1390 const char *uname = xs_dict_get(actor_o, "preferredUsername");
1457 1391
1458 if (!xs_is_null(uname) && *uname) { 1392 if (!xs_is_null(uname) && *uname) {
1459 xs *handle = xs_fmt("@%s@%s", uname, xs_list_get(l, 2)); 1393 xs *handle = xs_fmt("@%s@%s", uname, xs_list_get(l, 2));
@@ -1492,7 +1426,8 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1492 1426
1493 /* create the attachment list, if there are any */ 1427 /* create the attachment list, if there are any */
1494 if (!xs_is_null(attach)) { 1428 if (!xs_is_null(attach)) {
1495 while (xs_list_iter(&attach, &v)) { 1429 int c = 0;
1430 while (xs_list_next(attach, &v, &c)) {
1496 xs *d = xs_dict_new(); 1431 xs *d = xs_dict_new();
1497 const char *url = xs_list_get(v, 0); 1432 const char *url = xs_list_get(v, 0);
1498 const char *alt = xs_list_get(v, 1); 1433 const char *alt = xs_list_get(v, 1);
@@ -1515,7 +1450,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts,
1515 p = tag; 1450 p = tag;
1516 while (xs_list_iter(&p, &v)) { 1451 while (xs_list_iter(&p, &v)) {
1517 if (xs_type(v) == XSTYPE_DICT) { 1452 if (xs_type(v) == XSTYPE_DICT) {
1518 char *t; 1453 const char *t;
1519 1454
1520 if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) { 1455 if (!xs_is_null(t = xs_dict_get(v, "type")) && strcmp(t, "Mention") == 0) {
1521 if (!xs_is_null(t = xs_dict_get(v, "href"))) 1456 if (!xs_is_null(t = xs_dict_get(v, "href")))
@@ -1639,7 +1574,7 @@ int update_question(snac *user, const char *id)
1639 xs *msg = NULL; 1574 xs *msg = NULL;
1640 xs *rcnt = xs_dict_new(); 1575 xs *rcnt = xs_dict_new();
1641 xs *lopts = xs_list_new(); 1576 xs *lopts = xs_list_new();
1642 xs_list *opts; 1577 const xs_list *opts;
1643 xs_list *p; 1578 xs_list *p;
1644 xs_val *v; 1579 xs_val *v;
1645 1580
@@ -1657,8 +1592,8 @@ int update_question(snac *user, const char *id)
1657 return -3; 1592 return -3;
1658 1593
1659 /* fill the initial count */ 1594 /* fill the initial count */
1660 p = opts; 1595 int c = 0;
1661 while (xs_list_iter(&p, &v)) { 1596 while (xs_list_next(opts, &v, &c)) {
1662 const char *name = xs_dict_get(v, "name"); 1597 const char *name = xs_dict_get(v, "name");
1663 if (name) { 1598 if (name) {
1664 lopts = xs_list_append(lopts, name); 1599 lopts = xs_list_append(lopts, name);
@@ -1764,13 +1699,13 @@ int update_question(snac *user, const char *id)
1764 1699
1765/** queues **/ 1700/** queues **/
1766 1701
1767int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) 1702int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
1768/* processes an ActivityPub message from the input queue */ 1703/* processes an ActivityPub message from the input queue */
1769/* return values: -1, fatal error; 0, transient error, retry; 1704/* return values: -1, fatal error; 0, transient error, retry;
1770 1, processed and done; 2, propagate to users (only when no user is set) */ 1705 1, processed and done; 2, propagate to users (only when no user is set) */
1771{ 1706{
1772 char *actor = xs_dict_get(msg, "actor"); 1707 const char *actor = xs_dict_get(msg, "actor");
1773 char *type = xs_dict_get(msg, "type"); 1708 const char *type = xs_dict_get(msg, "type");
1774 xs *actor_o = NULL; 1709 xs *actor_o = NULL;
1775 int a_status; 1710 int a_status;
1776 int do_notify = 0; 1711 int do_notify = 0;
@@ -1790,7 +1725,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
1790 return -1; 1725 return -1;
1791 } 1726 }
1792 1727
1793 char *object, *utype; 1728 const char *object, *utype;
1794 1729
1795 object = xs_dict_get(msg, "object"); 1730 object = xs_dict_get(msg, "object");
1796 if (object != NULL && xs_type(object) == XSTYPE_DICT) 1731 if (object != NULL && xs_type(object) == XSTYPE_DICT)
@@ -1813,7 +1748,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
1813 } 1748 }
1814 1749
1815 /* also discard if the object to be deleted is not here */ 1750 /* also discard if the object to be deleted is not here */
1816 char *obj_id = object; 1751 const char *obj_id = object;
1817 if (xs_type(obj_id) == XSTYPE_DICT) 1752 if (xs_type(obj_id) == XSTYPE_DICT)
1818 obj_id = xs_dict_get(obj_id, "id"); 1753 obj_id = xs_dict_get(obj_id, "id");
1819 1754
@@ -1885,7 +1820,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
1885 int min_account_age = xs_number_get(xs_dict_get(srv_config, "min_account_age")); 1820 int min_account_age = xs_number_get(xs_dict_get(srv_config, "min_account_age"));
1886 1821
1887 if (min_account_age > 0) { 1822 if (min_account_age > 0) {
1888 char *actor_date = xs_dict_get(actor_o, "published"); 1823 const char *actor_date = xs_dict_get(actor_o, "published");
1889 if (!xs_is_null(actor_date)) { 1824 if (!xs_is_null(actor_date)) {
1890 time_t actor_t = xs_parse_iso_date(actor_date, 0); 1825 time_t actor_t = xs_parse_iso_date(actor_date, 0);
1891 1826
@@ -1945,7 +1880,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
1945 } 1880 }
1946 else 1881 else
1947 if (strcmp(type, "Undo") == 0) { /** **/ 1882 if (strcmp(type, "Undo") == 0) { /** **/
1948 char *id = xs_dict_get(object, "object"); 1883 const char *id = xs_dict_get(object, "object");
1949 1884
1950 if (xs_type(object) != XSTYPE_DICT) 1885 if (xs_type(object) != XSTYPE_DICT)
1951 utype = "Follow"; 1886 utype = "Follow";
@@ -1990,9 +1925,9 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
1990 } 1925 }
1991 1926
1992 if (xs_match(utype, "Note|Article")) { /** **/ 1927 if (xs_match(utype, "Note|Article")) { /** **/
1993 char *id = xs_dict_get(object, "id"); 1928 const char *id = xs_dict_get(object, "id");
1994 char *in_reply_to = xs_dict_get(object, "inReplyTo"); 1929 const char *in_reply_to = xs_dict_get(object, "inReplyTo");
1995 char *atto = get_atto(object); 1930 const char *atto = get_atto(object);
1996 xs *wrk = NULL; 1931 xs *wrk = NULL;
1997 1932
1998 if (xs_is_null(id)) 1933 if (xs_is_null(id))
@@ -2029,14 +1964,14 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
2029 } 1964 }
2030 else 1965 else
2031 if (strcmp(utype, "Question") == 0) { /** **/ 1966 if (strcmp(utype, "Question") == 0) { /** **/
2032 char *id = xs_dict_get(object, "id"); 1967 const char *id = xs_dict_get(object, "id");
2033 1968
2034 if (timeline_add(snac, id, object)) 1969 if (timeline_add(snac, id, object))
2035 snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id)); 1970 snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id));
2036 } 1971 }
2037 else 1972 else
2038 if (strcmp(utype, "Video") == 0) { /** **/ 1973 if (strcmp(utype, "Video") == 0) { /** **/
2039 char *id = xs_dict_get(object, "id"); 1974 const char *id = xs_dict_get(object, "id");
2040 1975
2041 if (timeline_add(snac, id, object)) 1976 if (timeline_add(snac, id, object))
2042 snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id)); 1977 snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id));
@@ -2212,7 +2147,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req)
2212} 2147}
2213 2148
2214 2149
2215int send_email(char *msg) 2150int send_email(const char *msg)
2216/* invoke sendmail with email headers and body in msg */ 2151/* invoke sendmail with email headers and body in msg */
2217{ 2152{
2218 FILE *f; 2153 FILE *f;
@@ -2244,14 +2179,14 @@ int send_email(char *msg)
2244void process_user_queue_item(snac *snac, xs_dict *q_item) 2179void process_user_queue_item(snac *snac, xs_dict *q_item)
2245/* processes an item from the user queue */ 2180/* processes an item from the user queue */
2246{ 2181{
2247 char *type; 2182 const char *type;
2248 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max")); 2183 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
2249 2184
2250 if ((type = xs_dict_get(q_item, "type")) == NULL) 2185 if ((type = xs_dict_get(q_item, "type")) == NULL)
2251 type = "output"; 2186 type = "output";
2252 2187
2253 if (strcmp(type, "message") == 0) { 2188 if (strcmp(type, "message") == 0) {
2254 xs_dict *msg = xs_dict_get(q_item, "message"); 2189 const xs_dict *msg = xs_dict_get(q_item, "message");
2255 xs *rcpts = recipient_list(snac, msg, 1); 2190 xs *rcpts = recipient_list(snac, msg, 1);
2256 xs_set inboxes; 2191 xs_set inboxes;
2257 xs_list *p; 2192 xs_list *p;
@@ -2292,8 +2227,8 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
2292 else 2227 else
2293 if (strcmp(type, "input") == 0) { 2228 if (strcmp(type, "input") == 0) {
2294 /* process the message */ 2229 /* process the message */
2295 xs_dict *msg = xs_dict_get(q_item, "message"); 2230 const xs_dict *msg = xs_dict_get(q_item, "message");
2296 xs_dict *req = xs_dict_get(q_item, "req"); 2231 const xs_dict *req = xs_dict_get(q_item, "req");
2297 int retries = xs_number_get(xs_dict_get(q_item, "retries")); 2232 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
2298 2233
2299 if (xs_is_null(msg)) 2234 if (xs_is_null(msg))
@@ -2320,13 +2255,6 @@ void process_user_queue_item(snac *snac, xs_dict *q_item)
2320 update_question(snac, id); 2255 update_question(snac, id);
2321 } 2256 }
2322 else 2257 else
2323 if (strcmp(type, "request_replies") == 0) {
2324 const char *id = xs_dict_get(q_item, "message");
2325
2326 if (!xs_is_null(id))
2327 timeline_request_replies(snac, id);
2328 }
2329 else
2330 if (strcmp(type, "object_request") == 0) { 2258 if (strcmp(type, "object_request") == 0) {
2331 const char *id = xs_dict_get(q_item, "message"); 2259 const char *id = xs_dict_get(q_item, "message");
2332 2260
@@ -2395,15 +2323,15 @@ int process_user_queue(snac *snac)
2395void process_queue_item(xs_dict *q_item) 2323void process_queue_item(xs_dict *q_item)
2396/* processes an item from the global queue */ 2324/* processes an item from the global queue */
2397{ 2325{
2398 char *type = xs_dict_get(q_item, "type"); 2326 const char *type = xs_dict_get(q_item, "type");
2399 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max")); 2327 int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max"));
2400 2328
2401 if (strcmp(type, "output") == 0) { 2329 if (strcmp(type, "output") == 0) {
2402 int status; 2330 int status;
2403 xs_str *inbox = xs_dict_get(q_item, "inbox"); 2331 const xs_str *inbox = xs_dict_get(q_item, "inbox");
2404 xs_str *keyid = xs_dict_get(q_item, "keyid"); 2332 const xs_str *keyid = xs_dict_get(q_item, "keyid");
2405 xs_str *seckey = xs_dict_get(q_item, "seckey"); 2333 const xs_str *seckey = xs_dict_get(q_item, "seckey");
2406 xs_dict *msg = xs_dict_get(q_item, "message"); 2334 const xs_dict *msg = xs_dict_get(q_item, "message");
2407 int retries = xs_number_get(xs_dict_get(q_item, "retries")); 2335 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
2408 int p_status = xs_number_get(xs_dict_get(q_item, "p_status")); 2336 int p_status = xs_number_get(xs_dict_get(q_item, "p_status"));
2409 xs *payload = NULL; 2337 xs *payload = NULL;
@@ -2475,7 +2403,7 @@ void process_queue_item(xs_dict *q_item)
2475 else 2403 else
2476 if (strcmp(type, "email") == 0) { 2404 if (strcmp(type, "email") == 0) {
2477 /* send this email */ 2405 /* send this email */
2478 xs_str *msg = xs_dict_get(q_item, "message"); 2406 const xs_str *msg = xs_dict_get(q_item, "message");
2479 int retries = xs_number_get(xs_dict_get(q_item, "retries")); 2407 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
2480 2408
2481 if (!send_email(msg)) 2409 if (!send_email(msg))
@@ -2497,8 +2425,8 @@ void process_queue_item(xs_dict *q_item)
2497 else 2425 else
2498 if (strcmp(type, "telegram") == 0) { 2426 if (strcmp(type, "telegram") == 0) {
2499 /* send this via telegram */ 2427 /* send this via telegram */
2500 char *bot = xs_dict_get(q_item, "bot"); 2428 const char *bot = xs_dict_get(q_item, "bot");
2501 char *msg = xs_dict_get(q_item, "message"); 2429 const char *msg = xs_dict_get(q_item, "message");
2502 xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id")); 2430 xs *chat_id = xs_dup(xs_dict_get(q_item, "chat_id"));
2503 int status = 0; 2431 int status = 0;
2504 2432
@@ -2521,9 +2449,9 @@ void process_queue_item(xs_dict *q_item)
2521 else 2449 else
2522 if (strcmp(type, "ntfy") == 0) { 2450 if (strcmp(type, "ntfy") == 0) {
2523 /* send this via ntfy */ 2451 /* send this via ntfy */
2524 char *ntfy_server = xs_dict_get(q_item, "ntfy_server"); 2452 const char *ntfy_server = xs_dict_get(q_item, "ntfy_server");
2525 char *msg = xs_dict_get(q_item, "message"); 2453 const char *msg = xs_dict_get(q_item, "message");
2526 char *ntfy_token = xs_dict_get(q_item, "ntfy_token"); 2454 const char *ntfy_token = xs_dict_get(q_item, "ntfy_token");
2527 int status = 0; 2455 int status = 0;
2528 2456
2529 xs *url = xs_fmt("%s", ntfy_server); 2457 xs *url = xs_fmt("%s", ntfy_server);
@@ -2552,8 +2480,8 @@ void process_queue_item(xs_dict *q_item)
2552 } 2480 }
2553 else 2481 else
2554 if (strcmp(type, "input") == 0) { 2482 if (strcmp(type, "input") == 0) {
2555 xs_dict *msg = xs_dict_get(q_item, "message"); 2483 const xs_dict *msg = xs_dict_get(q_item, "message");
2556 xs_dict *req = xs_dict_get(q_item, "req"); 2484 const xs_dict *req = xs_dict_get(q_item, "req");
2557 int retries = xs_number_get(xs_dict_get(q_item, "retries")); 2485 int retries = xs_number_get(xs_dict_get(q_item, "retries"));
2558 2486
2559 /* do some instance-level checks */ 2487 /* do some instance-level checks */
@@ -2572,7 +2500,7 @@ void process_queue_item(xs_dict *q_item)
2572 else 2500 else
2573 if (r == 2) { 2501 if (r == 2) {
2574 /* redistribute the input message to all users */ 2502 /* redistribute the input message to all users */
2575 char *ntid = xs_dict_get(q_item, "ntid"); 2503 const char *ntid = xs_dict_get(q_item, "ntid");
2576 xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid); 2504 xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid);
2577 FILE *f; 2505 FILE *f;
2578 2506
@@ -2647,7 +2575,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2647 char **body, int *b_size, char **ctype) 2575 char **body, int *b_size, char **ctype)
2648{ 2576{
2649 int status = 200; 2577 int status = 200;
2650 char *accept = xs_dict_get(req, "accept"); 2578 const char *accept = xs_dict_get(req, "accept");
2651 snac snac; 2579 snac snac;
2652 xs *msg = NULL; 2580 xs *msg = NULL;
2653 2581
@@ -2659,7 +2587,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2659 return 0; 2587 return 0;
2660 2588
2661 xs *l = xs_split_n(q_path, "/", 2); 2589 xs *l = xs_split_n(q_path, "/", 2);
2662 char *uid, *p_path; 2590 const char *uid;
2591 const char *p_path;
2663 2592
2664 uid = xs_list_get(l, 1); 2593 uid = xs_list_get(l, 1);
2665 if (!user_open(&snac, uid)) { 2594 if (!user_open(&snac, uid)) {
@@ -2677,7 +2606,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2677 msg = msg_actor(&snac); 2606 msg = msg_actor(&snac);
2678 *ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""; 2607 *ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"";
2679 2608
2680 char *ua = xs_dict_get(req, "user-agent"); 2609 const char *ua = xs_dict_get(req, "user-agent");
2681 2610
2682 snac_debug(&snac, 0, xs_fmt("serving actor [%s]", ua ? ua : "No UA")); 2611 snac_debug(&snac, 0, xs_fmt("serving actor [%s]", ua ? ua : "No UA"));
2683 } 2612 }
@@ -2694,8 +2623,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2694 xs *i = NULL; 2623 xs *i = NULL;
2695 2624
2696 if (valid_status(object_get_by_md5(v, &i))) { 2625 if (valid_status(object_get_by_md5(v, &i))) {
2697 char *type = xs_dict_get(i, "type"); 2626 const char *type = xs_dict_get(i, "type");
2698 char *id = xs_dict_get(i, "id"); 2627 const char *id = xs_dict_get(i, "id");
2699 2628
2700 if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) { 2629 if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) {
2701 xs *c_msg = msg_create(&snac, i); 2630 xs *c_msg = msg_create(&snac, i);
@@ -2748,9 +2677,9 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2748 (void)b_size; 2677 (void)b_size;
2749 2678
2750 int status = 202; /* accepted */ 2679 int status = 202; /* accepted */
2751 char *i_ctype = xs_dict_get(req, "content-type"); 2680 const char *i_ctype = xs_dict_get(req, "content-type");
2752 snac snac; 2681 snac snac;
2753 char *v; 2682 const char *v;
2754 2683
2755 if (i_ctype == NULL) { 2684 if (i_ctype == NULL) {
2756 *body = xs_str_new("no content-type"); 2685 *body = xs_str_new("no content-type");