diff options
| author | 2024-05-25 08:05:36 +0000 | |
|---|---|---|
| committer | 2024-05-25 08:05:36 +0000 | |
| commit | 84a767dd0878013194ed7551b5ae6ef715e841a6 (patch) | |
| tree | 9fb1b2b89e0bfbb4b8bf1e85d840c8653e646bb7 /activitypub.c | |
| parent | Prevent some browsers from caching servers basic auth request (diff) | |
| parent | Backport from xs (fix regex.h compilation with tcc). (diff) | |
| download | snac2-84a767dd0878013194ed7551b5ae6ef715e841a6.tar.gz snac2-84a767dd0878013194ed7551b5ae6ef715e841a6.tar.xz snac2-84a767dd0878013194ed7551b5ae6ef715e841a6.zip | |
Merge pull request 'master' (#1) from grunfink/snac2:master into master
Reviewed-on: https://codeberg.org/louis77/snac2/pulls/1
Diffstat (limited to 'activitypub.c')
| -rw-r--r-- | activitypub.c | 420 |
1 files changed, 206 insertions, 214 deletions
diff --git a/activitypub.c b/activitypub.c index 9a23e14..6e40a88 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 | ||
| 157 | char *get_atto(const xs_dict *msg) | 157 | const 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 | xs_dict *v; | 165 | int c = 0; |
| 166 | const 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,12 +187,12 @@ 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"))) { |
| 193 | xs *attach = NULL; | 194 | xs *attach = NULL; |
| 194 | xs_val *v; | 195 | const xs_val *v; |
| 195 | 196 | ||
| 196 | /* ensure it's a list */ | 197 | /* ensure it's a list */ |
| 197 | if (xs_type(p) == XSTYPE_DICT) { | 198 | if (xs_type(p) == XSTYPE_DICT) { |
| @@ -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; |
| 257 | xs_val *v; | 259 | int c = 0; |
| 260 | const 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 | const 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 | ||
| 306 | int timeline_request(snac *snac, char **id, xs_str **wrk, int level) | 310 | int 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 */ |
| @@ -355,102 +359,35 @@ int timeline_request(snac *snac, char **id, xs_str **wrk, int level) | |||
| 355 | type = "(null)"; | 359 | type = "(null)"; |
| 356 | } | 360 | } |
| 357 | 361 | ||
| 358 | if (xs_match(type, "Note|Page|Article|Video")) { | 362 | if (xs_match(type, POSTLIKE_OBJECT_TYPE)) { |
| 359 | const char *actor = get_atto(object); | 363 | if (content_match("filter_reject.txt", object)) |
| 360 | |||
| 361 | if (content_check("filter_reject.txt", object)) | ||
| 362 | snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); | 364 | snac_log(snac, xs_fmt("timeline_request rejected by content %s", nid)); |
| 363 | else { | 365 | else { |
| 364 | /* request (and drop) the actor for this entry */ | 366 | const char *actor = get_atto(object); |
| 365 | if (!xs_is_null(actor)) | ||
| 366 | actor_request(snac, actor, NULL); | ||
| 367 | |||
| 368 | /* does it have an ancestor? */ | ||
| 369 | char *in_reply_to = xs_dict_get(object, "inReplyTo"); | ||
| 370 | |||
| 371 | /* store */ | ||
| 372 | timeline_add(snac, nid, object); | ||
| 373 | |||
| 374 | /* recurse! */ | ||
| 375 | timeline_request(snac, &in_reply_to, NULL, level + 1); | ||
| 376 | } | ||
| 377 | } | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | enqueue_request_replies(snac, *id); | ||
| 382 | } | ||
| 383 | |||
| 384 | return status; | ||
| 385 | } | ||
| 386 | 367 | ||
| 368 | if (!xs_is_null(actor)) { | ||
| 369 | /* request (and drop) the actor for this entry */ | ||
| 370 | if (!valid_status(actor_request(snac, actor, NULL))) { | ||
| 371 | /* failed? retry later */ | ||
| 372 | enqueue_actor_refresh(snac, actor, 60); | ||
| 373 | } | ||
| 387 | 374 | ||
| 388 | void timeline_request_replies(snac *user, const char *id) | 375 | /* does it have an ancestor? */ |
| 389 | /* requests all replies of a message */ | 376 | const char *in_reply_to = xs_dict_get(object, "inReplyTo"); |
| 390 | /* FIXME: experimental -- needs more testing */ | ||
| 391 | { | ||
| 392 | /* FIXME: TEMPORARILY DISABLED */ | ||
| 393 | /* Reason: I've found that many of the posts in the 'replies' Collection | ||
| 394 | do not have an inReplyTo field (why??? aren't they 'replies'???). | ||
| 395 | For this reason, these requested objects are not stored as children | ||
| 396 | of the original post and they are shown as out-of-context, top level posts. | ||
| 397 | This process is disabled until I find an elegant way of providing a parent | ||
| 398 | for these 'stray' children. */ | ||
| 399 | return; | ||
| 400 | |||
| 401 | xs *msg = NULL; | ||
| 402 | |||
| 403 | if (!valid_status(object_get(id, &msg))) | ||
| 404 | return; | ||
| 405 | |||
| 406 | /* does it have a replies collection? */ | ||
| 407 | const xs_dict *replies = xs_dict_get(msg, "replies"); | ||
| 408 | |||
| 409 | if (!xs_is_null(replies)) { | ||
| 410 | const char *type = xs_dict_get(replies, "type"); | ||
| 411 | const char *first = xs_dict_get(replies, "first"); | ||
| 412 | |||
| 413 | if (!xs_is_null(type) && !xs_is_null(first) && strcmp(type, "Collection") == 0) { | ||
| 414 | const char *next = xs_dict_get(first, "next"); | ||
| 415 | |||
| 416 | if (!xs_is_null(next)) { | ||
| 417 | xs *rpls = NULL; | ||
| 418 | int status = activitypub_request(user, next, &rpls); | ||
| 419 | |||
| 420 | /* request the Collection of replies */ | ||
| 421 | if (valid_status(status)) { | ||
| 422 | xs_list *items = xs_dict_get(rpls, "items"); | ||
| 423 | |||
| 424 | if (xs_type(items) == XSTYPE_LIST) { | ||
| 425 | xs_val *v; | ||
| 426 | |||
| 427 | /* request them all */ | ||
| 428 | while (xs_list_iter(&items, &v)) { | ||
| 429 | if (xs_type(v) == XSTYPE_DICT) { | ||
| 430 | /* not an id, but the object itself (!) */ | ||
| 431 | const char *c_id = xs_dict_get(v, "id"); | ||
| 432 | |||
| 433 | if (!xs_is_null(id)) { | ||
| 434 | snac_debug(user, 0, xs_fmt("embedded reply %s", c_id)); | ||
| 435 | 377 | ||
| 436 | object_add(c_id, v); | 378 | /* store */ |
| 379 | timeline_add(snac, nid, object); | ||
| 437 | 380 | ||
| 438 | /* get its own children */ | 381 | /* recurse! */ |
| 439 | timeline_request_replies(user, v); | 382 | timeline_request(snac, &in_reply_to, NULL, level + 1); |
| 440 | } | ||
| 441 | } | ||
| 442 | else { | ||
| 443 | snac_debug(user, 0, xs_fmt("request reply %s", v)); | ||
| 444 | timeline_request(user, &v, NULL, 0); | ||
| 445 | } | ||
| 446 | } | 383 | } |
| 447 | } | 384 | } |
| 448 | } | 385 | } |
| 449 | else | ||
| 450 | snac_debug(user, 0, xs_fmt("replies request error %s %d", next, status)); | ||
| 451 | } | 386 | } |
| 452 | } | 387 | } |
| 453 | } | 388 | } |
| 389 | |||
| 390 | return status; | ||
| 454 | } | 391 | } |
| 455 | 392 | ||
| 456 | 393 | ||
| @@ -476,7 +413,7 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg, | |||
| 476 | xs_val **payload, int *p_size, int timeout) | 413 | xs_val **payload, int *p_size, int timeout) |
| 477 | /* sends a message to an Inbox */ | 414 | /* sends a message to an Inbox */ |
| 478 | { | 415 | { |
| 479 | char *seckey = xs_dict_get(snac->key, "secret"); | 416 | const char *seckey = xs_dict_get(snac->key, "secret"); |
| 480 | 417 | ||
| 481 | 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); |
| 482 | } | 419 | } |
| @@ -486,7 +423,7 @@ xs_str *get_actor_inbox(const char *actor) | |||
| 486 | /* gets an actor's inbox */ | 423 | /* gets an actor's inbox */ |
| 487 | { | 424 | { |
| 488 | xs *data = NULL; | 425 | xs *data = NULL; |
| 489 | char *v = NULL; | 426 | const char *v = NULL; |
| 490 | 427 | ||
| 491 | if (valid_status(actor_request(NULL, actor, &data))) { | 428 | if (valid_status(actor_request(NULL, actor, &data))) { |
| 492 | /* try first endpoints/sharedInbox */ | 429 | /* try first endpoints/sharedInbox */ |
| @@ -535,17 +472,17 @@ void post_message(snac *snac, const char *actor, const xs_dict *msg) | |||
| 535 | xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) | 472 | xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) |
| 536 | /* returns the list of recipients for a message */ | 473 | /* returns the list of recipients for a message */ |
| 537 | { | 474 | { |
| 538 | char *to = xs_dict_get(msg, "to"); | 475 | const xs_val *to = xs_dict_get(msg, "to"); |
| 539 | char *cc = xs_dict_get(msg, "cc"); | 476 | const xs_val *cc = xs_dict_get(msg, "cc"); |
| 540 | xs_set rcpts; | 477 | xs_set rcpts; |
| 541 | int n; | 478 | int n; |
| 542 | 479 | ||
| 543 | xs_set_init(&rcpts); | 480 | xs_set_init(&rcpts); |
| 544 | 481 | ||
| 545 | char *lists[] = { to, cc, NULL }; | 482 | const xs_list *lists[] = { to, cc, NULL }; |
| 546 | for (n = 0; lists[n]; n++) { | 483 | for (n = 0; lists[n]; n++) { |
| 547 | char *l = lists[n]; | 484 | xs_list *l = (xs_list *)lists[n]; |
| 548 | char *v; | 485 | const char *v; |
| 549 | xs *tl = NULL; | 486 | xs *tl = NULL; |
| 550 | 487 | ||
| 551 | /* if it's a string, create a list with only one element */ | 488 | /* if it's a string, create a list with only one element */ |
| @@ -560,7 +497,7 @@ xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) | |||
| 560 | if (expand_public && strcmp(v, public_address) == 0) { | 497 | if (expand_public && strcmp(v, public_address) == 0) { |
| 561 | /* iterate the followers and add them */ | 498 | /* iterate the followers and add them */ |
| 562 | xs *fwers = follower_list(snac); | 499 | xs *fwers = follower_list(snac); |
| 563 | char *actor; | 500 | const char *actor; |
| 564 | 501 | ||
| 565 | char *p = fwers; | 502 | char *p = fwers; |
| 566 | while (xs_list_iter(&p, &actor)) | 503 | while (xs_list_iter(&p, &actor)) |
| @@ -667,13 +604,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) | |||
| 667 | 604 | ||
| 668 | /* if it's a Follow, it must be explicitly for us */ | 605 | /* if it's a Follow, it must be explicitly for us */ |
| 669 | if (xs_match(type, "Follow")) { | 606 | if (xs_match(type, "Follow")) { |
| 670 | char *object = xs_dict_get(c_msg, "object"); | 607 | const char *object = xs_dict_get(c_msg, "object"); |
| 671 | return !xs_is_null(object) && strcmp(snac->actor, object) == 0; | 608 | return !xs_is_null(object) && strcmp(snac->actor, object) == 0; |
| 672 | } | 609 | } |
| 673 | 610 | ||
| 674 | /* only accept Ping directed to us */ | 611 | /* only accept Ping directed to us */ |
| 675 | if (xs_match(type, "Ping")) { | 612 | if (xs_match(type, "Ping")) { |
| 676 | char *dest = xs_dict_get(c_msg, "to"); | 613 | const char *dest = xs_dict_get(c_msg, "to"); |
| 677 | return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0; | 614 | return !xs_is_null(dest) && strcmp(snac->actor, dest) == 0; |
| 678 | } | 615 | } |
| 679 | 616 | ||
| @@ -688,10 +625,10 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) | |||
| 688 | if (pub_msg && following_check(snac, actor)) | 625 | if (pub_msg && following_check(snac, actor)) |
| 689 | return 1; | 626 | return 1; |
| 690 | 627 | ||
| 691 | xs_dict *msg = xs_dict_get(c_msg, "object"); | 628 | const xs_dict *msg = xs_dict_get(c_msg, "object"); |
| 692 | xs *rcpts = recipient_list(snac, msg, 0); | 629 | xs *rcpts = recipient_list(snac, msg, 0); |
| 693 | xs_list *p = rcpts; | 630 | xs_list *p = rcpts; |
| 694 | xs_str *v; | 631 | const xs_str *v; |
| 695 | 632 | ||
| 696 | xs *actor_followers = NULL; | 633 | xs *actor_followers = NULL; |
| 697 | 634 | ||
| @@ -700,8 +637,9 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) | |||
| 700 | xs *actor_obj = NULL; | 637 | xs *actor_obj = NULL; |
| 701 | 638 | ||
| 702 | if (valid_status(object_get(actor, &actor_obj))) { | 639 | if (valid_status(object_get(actor, &actor_obj))) { |
| 703 | if ((v = xs_dict_get(actor_obj, "followers"))) | 640 | const xs_val *fw = xs_dict_get(actor_obj, "followers"); |
| 704 | actor_followers = xs_dup(v); | 641 | if (fw) |
| 642 | actor_followers = xs_dup(fw); | ||
| 705 | } | 643 | } |
| 706 | } | 644 | } |
| 707 | 645 | ||
| @@ -724,13 +662,13 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) | |||
| 724 | } | 662 | } |
| 725 | 663 | ||
| 726 | /* accept if it's by someone we follow */ | 664 | /* accept if it's by someone we follow */ |
| 727 | char *atto = get_atto(msg); | 665 | const char *atto = get_atto(msg); |
| 728 | 666 | ||
| 729 | if (pub_msg && !xs_is_null(atto) && following_check(snac, atto)) | 667 | if (pub_msg && !xs_is_null(atto) && following_check(snac, atto)) |
| 730 | return 3; | 668 | return 3; |
| 731 | 669 | ||
| 732 | /* is this message a reply to another? */ | 670 | /* is this message a reply to another? */ |
| 733 | char *irt = xs_dict_get(msg, "inReplyTo"); | 671 | const char *irt = xs_dict_get(msg, "inReplyTo"); |
| 734 | if (!xs_is_null(irt)) { | 672 | if (!xs_is_null(irt)) { |
| 735 | xs *r_msg = NULL; | 673 | xs *r_msg = NULL; |
| 736 | 674 | ||
| @@ -755,7 +693,7 @@ xs_str *process_tags(snac *snac, const char *content, xs_list **tag) | |||
| 755 | xs_list *tl = *tag; | 693 | xs_list *tl = *tag; |
| 756 | xs *split; | 694 | xs *split; |
| 757 | xs_list *p; | 695 | xs_list *p; |
| 758 | xs_val *v; | 696 | const xs_val *v; |
| 759 | int n = 0; | 697 | int n = 0; |
| 760 | 698 | ||
| 761 | /* create a default server for incomplete mentions */ | 699 | /* create a default server for incomplete mentions */ |
| @@ -983,8 +921,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor, | |||
| 983 | 921 | ||
| 984 | /* telegram */ | 922 | /* telegram */ |
| 985 | 923 | ||
| 986 | char *bot = xs_dict_get(snac->config, "telegram_bot"); | 924 | const char *bot = xs_dict_get(snac->config, "telegram_bot"); |
| 987 | char *chat_id = xs_dict_get(snac->config, "telegram_chat_id"); | 925 | const char *chat_id = xs_dict_get(snac->config, "telegram_chat_id"); |
| 988 | 926 | ||
| 989 | 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) |
| 990 | enqueue_telegram(body, bot, chat_id); | 928 | enqueue_telegram(body, bot, chat_id); |
| @@ -997,8 +935,8 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor, | |||
| 997 | objid = actor; | 935 | objid = actor; |
| 998 | 936 | ||
| 999 | /* ntfy */ | 937 | /* ntfy */ |
| 1000 | char *ntfy_server = xs_dict_get(snac->config, "ntfy_server"); | 938 | const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server"); |
| 1001 | char *ntfy_token = xs_dict_get(snac->config, "ntfy_token"); | 939 | const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token"); |
| 1002 | 940 | ||
| 1003 | if (!xs_is_null(ntfy_server) && *ntfy_server) | 941 | if (!xs_is_null(ntfy_server) && *ntfy_server) |
| 1004 | enqueue_ntfy(body, ntfy_server, ntfy_token); | 942 | enqueue_ntfy(body, ntfy_server, ntfy_token); |
| @@ -1084,7 +1022,7 @@ xs_dict *msg_base(snac *snac, const char *type, const char *id, | |||
| 1084 | } | 1022 | } |
| 1085 | 1023 | ||
| 1086 | 1024 | ||
| 1087 | xs_dict *msg_collection(snac *snac, char *id) | 1025 | xs_dict *msg_collection(snac *snac, const char *id) |
| 1088 | /* creates an empty OrderedCollection message */ | 1026 | /* creates an empty OrderedCollection message */ |
| 1089 | { | 1027 | { |
| 1090 | xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL); | 1028 | xs_dict *msg = msg_base(snac, "OrderedCollection", id, NULL, NULL, NULL); |
| @@ -1098,7 +1036,7 @@ xs_dict *msg_collection(snac *snac, char *id) | |||
| 1098 | } | 1036 | } |
| 1099 | 1037 | ||
| 1100 | 1038 | ||
| 1101 | xs_dict *msg_accept(snac *snac, char *object, char *to) | 1039 | xs_dict *msg_accept(snac *snac, const xs_val *object, const char *to) |
| 1102 | /* creates an Accept message (as a response to a Follow) */ | 1040 | /* creates an Accept message (as a response to a Follow) */ |
| 1103 | { | 1041 | { |
| 1104 | 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); |
| @@ -1109,12 +1047,12 @@ xs_dict *msg_accept(snac *snac, char *object, char *to) | |||
| 1109 | } | 1047 | } |
| 1110 | 1048 | ||
| 1111 | 1049 | ||
| 1112 | xs_dict *msg_update(snac *snac, xs_dict *object) | 1050 | xs_dict *msg_update(snac *snac, const xs_dict *object) |
| 1113 | /* creates an Update message */ | 1051 | /* creates an Update message */ |
| 1114 | { | 1052 | { |
| 1115 | 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); |
| 1116 | 1054 | ||
| 1117 | char *type = xs_dict_get(object, "type"); | 1055 | const char *type = xs_dict_get(object, "type"); |
| 1118 | 1056 | ||
| 1119 | if (strcmp(type, "Note") == 0) { | 1057 | if (strcmp(type, "Note") == 0) { |
| 1120 | msg = xs_dict_append(msg, "to", xs_dict_get(object, "to")); | 1058 | msg = xs_dict_append(msg, "to", xs_dict_get(object, "to")); |
| @@ -1137,7 +1075,7 @@ xs_dict *msg_update(snac *snac, xs_dict *object) | |||
| 1137 | } | 1075 | } |
| 1138 | 1076 | ||
| 1139 | 1077 | ||
| 1140 | xs_dict *msg_admiration(snac *snac, char *object, char *type) | 1078 | xs_dict *msg_admiration(snac *snac, const char *object, const char *type) |
| 1141 | /* creates a Like or Announce message */ | 1079 | /* creates a Like or Announce message */ |
| 1142 | { | 1080 | { |
| 1143 | xs *a_msg = NULL; | 1081 | xs *a_msg = NULL; |
| @@ -1168,7 +1106,7 @@ xs_dict *msg_admiration(snac *snac, char *object, char *type) | |||
| 1168 | } | 1106 | } |
| 1169 | 1107 | ||
| 1170 | 1108 | ||
| 1171 | xs_dict *msg_repulsion(snac *user, char *id, char *type) | 1109 | xs_dict *msg_repulsion(snac *user, const char *id, const char *type) |
| 1172 | /* creates an Undo + admiration message */ | 1110 | /* creates an Undo + admiration message */ |
| 1173 | { | 1111 | { |
| 1174 | xs *a_msg = NULL; | 1112 | xs *a_msg = NULL; |
| @@ -1206,7 +1144,7 @@ xs_dict *msg_actor(snac *snac) | |||
| 1206 | xs *kid = NULL; | 1144 | xs *kid = NULL; |
| 1207 | xs *f_bio = NULL; | 1145 | xs *f_bio = NULL; |
| 1208 | 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); |
| 1209 | char *p; | 1147 | const char *p; |
| 1210 | int n; | 1148 | int n; |
| 1211 | 1149 | ||
| 1212 | /* change the @context (is this really necessary?) */ | 1150 | /* change the @context (is this really necessary?) */ |
| @@ -1264,11 +1202,11 @@ xs_dict *msg_actor(snac *snac) | |||
| 1264 | } | 1202 | } |
| 1265 | 1203 | ||
| 1266 | /* add the metadata as attachments of PropertyValue */ | 1204 | /* add the metadata as attachments of PropertyValue */ |
| 1267 | xs_dict *metadata = xs_dict_get(snac->config, "metadata"); | 1205 | const xs_dict *metadata = xs_dict_get(snac->config, "metadata"); |
| 1268 | if (xs_type(metadata) == XSTYPE_DICT) { | 1206 | if (xs_type(metadata) == XSTYPE_DICT) { |
| 1269 | xs *attach = xs_list_new(); | 1207 | xs *attach = xs_list_new(); |
| 1270 | xs_str *k; | 1208 | const xs_str *k; |
| 1271 | xs_str *v; | 1209 | const xs_str *v; |
| 1272 | 1210 | ||
| 1273 | int c = 0; | 1211 | int c = 0; |
| 1274 | while (xs_dict_next(metadata, &k, &v, &c)) { | 1212 | while (xs_dict_next(metadata, &k, &v, &c)) { |
| @@ -1277,7 +1215,7 @@ xs_dict *msg_actor(snac *snac) | |||
| 1277 | xs *k2 = encode_html(k); | 1215 | xs *k2 = encode_html(k); |
| 1278 | xs *v2 = NULL; | 1216 | xs *v2 = NULL; |
| 1279 | 1217 | ||
| 1280 | if (xs_startswith(v, "https:")) { | 1218 | if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) { |
| 1281 | xs *t = encode_html(v); | 1219 | xs *t = encode_html(v); |
| 1282 | v2 = xs_fmt("<a href=\"%s\" rel=\"me\">%s</a>", t, t); | 1220 | v2 = xs_fmt("<a href=\"%s\" rel=\"me\">%s</a>", t, t); |
| 1283 | } | 1221 | } |
| @@ -1310,7 +1248,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object) | |||
| 1310 | /* creates a 'Create' message */ | 1248 | /* creates a 'Create' message */ |
| 1311 | { | 1249 | { |
| 1312 | 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); |
| 1313 | xs_val *v; | 1251 | const xs_val *v; |
| 1314 | 1252 | ||
| 1315 | if ((v = get_atto(object))) | 1253 | if ((v = get_atto(object))) |
| 1316 | msg = xs_dict_append(msg, "attributedTo", v); | 1254 | msg = xs_dict_append(msg, "attributedTo", v); |
| @@ -1327,7 +1265,7 @@ xs_dict *msg_create(snac *snac, const xs_dict *object) | |||
| 1327 | } | 1265 | } |
| 1328 | 1266 | ||
| 1329 | 1267 | ||
| 1330 | xs_dict *msg_undo(snac *snac, char *object) | 1268 | xs_dict *msg_undo(snac *snac, const xs_val *object) |
| 1331 | /* creates an 'Undo' message */ | 1269 | /* creates an 'Undo' message */ |
| 1332 | { | 1270 | { |
| 1333 | 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); |
| @@ -1340,7 +1278,7 @@ xs_dict *msg_undo(snac *snac, char *object) | |||
| 1340 | } | 1278 | } |
| 1341 | 1279 | ||
| 1342 | 1280 | ||
| 1343 | xs_dict *msg_delete(snac *snac, char *id) | 1281 | xs_dict *msg_delete(snac *snac, const char *id) |
| 1344 | /* creates a 'Delete' + 'Tombstone' for a local entry */ | 1282 | /* creates a 'Delete' + 'Tombstone' for a local entry */ |
| 1345 | { | 1283 | { |
| 1346 | xs *tomb = xs_dict_new(); | 1284 | xs *tomb = xs_dict_new(); |
| @@ -1369,7 +1307,7 @@ xs_dict *msg_follow(snac *snac, const char *q) | |||
| 1369 | 1307 | ||
| 1370 | xs *url_or_uid = xs_strip_i(xs_str_new(q)); | 1308 | xs *url_or_uid = xs_strip_i(xs_str_new(q)); |
| 1371 | 1309 | ||
| 1372 | if (xs_startswith(url_or_uid, "https:/")) | 1310 | if (xs_startswith(url_or_uid, "https:/") || xs_startswith(url_or_uid, "http:/")) |
| 1373 | actor = xs_dup(url_or_uid); | 1311 | actor = xs_dup(url_or_uid); |
| 1374 | else | 1312 | else |
| 1375 | if (!valid_status(webfinger_request(url_or_uid, &actor, NULL)) || actor == NULL) { | 1313 | if (!valid_status(webfinger_request(url_or_uid, &actor, NULL)) || actor == NULL) { |
| @@ -1382,7 +1320,7 @@ xs_dict *msg_follow(snac *snac, const char *q) | |||
| 1382 | 1320 | ||
| 1383 | if (valid_status(status)) { | 1321 | if (valid_status(status)) { |
| 1384 | /* check if the actor is an alias */ | 1322 | /* check if the actor is an alias */ |
| 1385 | char *r_actor = xs_dict_get(actor_o, "id"); | 1323 | const char *r_actor = xs_dict_get(actor_o, "id"); |
| 1386 | 1324 | ||
| 1387 | if (r_actor && strcmp(actor, r_actor) != 0) { | 1325 | if (r_actor && strcmp(actor, r_actor) != 0) { |
| 1388 | 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)); |
| @@ -1398,7 +1336,7 @@ xs_dict *msg_follow(snac *snac, const char *q) | |||
| 1398 | 1336 | ||
| 1399 | 1337 | ||
| 1400 | xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | 1338 | xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, |
| 1401 | xs_str *in_reply_to, xs_list *attach, int priv) | 1339 | const xs_str *in_reply_to, const xs_list *attach, int priv) |
| 1402 | /* creates a 'Note' message */ | 1340 | /* creates a 'Note' message */ |
| 1403 | { | 1341 | { |
| 1404 | xs *ntid = tid(0); | 1342 | xs *ntid = tid(0); |
| @@ -1413,7 +1351,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | |||
| 1413 | xs *atls = xs_list_new(); | 1351 | xs *atls = xs_list_new(); |
| 1414 | xs_dict *msg = msg_base(snac, "Note", id, NULL, "@now", NULL); | 1352 | xs_dict *msg = msg_base(snac, "Note", id, NULL, "@now", NULL); |
| 1415 | xs_list *p; | 1353 | xs_list *p; |
| 1416 | xs_val *v; | 1354 | const xs_val *v; |
| 1417 | 1355 | ||
| 1418 | if (rcpts == NULL) | 1356 | if (rcpts == NULL) |
| 1419 | to = xs_list_new(); | 1357 | to = xs_list_new(); |
| @@ -1438,7 +1376,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | |||
| 1438 | 1376 | ||
| 1439 | if (valid_status(object_get(in_reply_to, &p_msg))) { | 1377 | if (valid_status(object_get(in_reply_to, &p_msg))) { |
| 1440 | /* add this author as recipient */ | 1378 | /* add this author as recipient */ |
| 1441 | char *a, *v; | 1379 | const char *a, *v; |
| 1442 | 1380 | ||
| 1443 | 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) |
| 1444 | to = xs_list_append(to, a); | 1382 | to = xs_list_append(to, a); |
| @@ -1449,7 +1387,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | |||
| 1449 | xs *actor_o = NULL; | 1387 | xs *actor_o = NULL; |
| 1450 | 1388 | ||
| 1451 | 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))) { |
| 1452 | char *uname = xs_dict_get(actor_o, "preferredUsername"); | 1390 | const char *uname = xs_dict_get(actor_o, "preferredUsername"); |
| 1453 | 1391 | ||
| 1454 | if (!xs_is_null(uname) && *uname) { | 1392 | if (!xs_is_null(uname) && *uname) { |
| 1455 | 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)); |
| @@ -1488,7 +1426,8 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | |||
| 1488 | 1426 | ||
| 1489 | /* create the attachment list, if there are any */ | 1427 | /* create the attachment list, if there are any */ |
| 1490 | if (!xs_is_null(attach)) { | 1428 | if (!xs_is_null(attach)) { |
| 1491 | while (xs_list_iter(&attach, &v)) { | 1429 | int c = 0; |
| 1430 | while (xs_list_next(attach, &v, &c)) { | ||
| 1492 | xs *d = xs_dict_new(); | 1431 | xs *d = xs_dict_new(); |
| 1493 | const char *url = xs_list_get(v, 0); | 1432 | const char *url = xs_list_get(v, 0); |
| 1494 | const char *alt = xs_list_get(v, 1); | 1433 | const char *alt = xs_list_get(v, 1); |
| @@ -1511,7 +1450,7 @@ xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | |||
| 1511 | p = tag; | 1450 | p = tag; |
| 1512 | while (xs_list_iter(&p, &v)) { | 1451 | while (xs_list_iter(&p, &v)) { |
| 1513 | if (xs_type(v) == XSTYPE_DICT) { | 1452 | if (xs_type(v) == XSTYPE_DICT) { |
| 1514 | char *t; | 1453 | const char *t; |
| 1515 | 1454 | ||
| 1516 | 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) { |
| 1517 | if (!xs_is_null(t = xs_dict_get(v, "href"))) | 1456 | if (!xs_is_null(t = xs_dict_get(v, "href"))) |
| @@ -1589,7 +1528,7 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach, | |||
| 1589 | 1528 | ||
| 1590 | xs *o = xs_list_new(); | 1529 | xs *o = xs_list_new(); |
| 1591 | xs_list *p = (xs_list *)opts; | 1530 | xs_list *p = (xs_list *)opts; |
| 1592 | xs_str *v; | 1531 | const xs_str *v; |
| 1593 | xs *replies = xs_json_loads("{\"type\":\"Collection\",\"totalItems\":0}"); | 1532 | xs *replies = xs_json_loads("{\"type\":\"Collection\",\"totalItems\":0}"); |
| 1594 | 1533 | ||
| 1595 | xs_set_init(&seen); | 1534 | xs_set_init(&seen); |
| @@ -1635,9 +1574,9 @@ int update_question(snac *user, const char *id) | |||
| 1635 | xs *msg = NULL; | 1574 | xs *msg = NULL; |
| 1636 | xs *rcnt = xs_dict_new(); | 1575 | xs *rcnt = xs_dict_new(); |
| 1637 | xs *lopts = xs_list_new(); | 1576 | xs *lopts = xs_list_new(); |
| 1638 | xs_list *opts; | 1577 | const xs_list *opts; |
| 1639 | xs_list *p; | 1578 | xs_list *p; |
| 1640 | xs_val *v; | 1579 | const xs_val *v; |
| 1641 | 1580 | ||
| 1642 | /* get the object */ | 1581 | /* get the object */ |
| 1643 | if (!valid_status(object_get(id, &msg))) | 1582 | if (!valid_status(object_get(id, &msg))) |
| @@ -1653,8 +1592,8 @@ int update_question(snac *user, const char *id) | |||
| 1653 | return -3; | 1592 | return -3; |
| 1654 | 1593 | ||
| 1655 | /* fill the initial count */ | 1594 | /* fill the initial count */ |
| 1656 | p = opts; | 1595 | int c = 0; |
| 1657 | while (xs_list_iter(&p, &v)) { | 1596 | while (xs_list_next(opts, &v, &c)) { |
| 1658 | const char *name = xs_dict_get(v, "name"); | 1597 | const char *name = xs_dict_get(v, "name"); |
| 1659 | if (name) { | 1598 | if (name) { |
| 1660 | lopts = xs_list_append(lopts, name); | 1599 | lopts = xs_list_append(lopts, name); |
| @@ -1760,13 +1699,13 @@ int update_question(snac *user, const char *id) | |||
| 1760 | 1699 | ||
| 1761 | /** queues **/ | 1700 | /** queues **/ |
| 1762 | 1701 | ||
| 1763 | int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | 1702 | int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) |
| 1764 | /* processes an ActivityPub message from the input queue */ | 1703 | /* processes an ActivityPub message from the input queue */ |
| 1765 | /* return values: -1, fatal error; 0, transient error, retry; | 1704 | /* return values: -1, fatal error; 0, transient error, retry; |
| 1766 | 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) */ |
| 1767 | { | 1706 | { |
| 1768 | char *actor = xs_dict_get(msg, "actor"); | 1707 | const char *actor = xs_dict_get(msg, "actor"); |
| 1769 | char *type = xs_dict_get(msg, "type"); | 1708 | const char *type = xs_dict_get(msg, "type"); |
| 1770 | xs *actor_o = NULL; | 1709 | xs *actor_o = NULL; |
| 1771 | int a_status; | 1710 | int a_status; |
| 1772 | int do_notify = 0; | 1711 | int do_notify = 0; |
| @@ -1786,7 +1725,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1786 | return -1; | 1725 | return -1; |
| 1787 | } | 1726 | } |
| 1788 | 1727 | ||
| 1789 | char *object, *utype; | 1728 | const char *object, *utype; |
| 1790 | 1729 | ||
| 1791 | object = xs_dict_get(msg, "object"); | 1730 | object = xs_dict_get(msg, "object"); |
| 1792 | if (object != NULL && xs_type(object) == XSTYPE_DICT) | 1731 | if (object != NULL && xs_type(object) == XSTYPE_DICT) |
| @@ -1809,7 +1748,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1809 | } | 1748 | } |
| 1810 | 1749 | ||
| 1811 | /* also discard if the object to be deleted is not here */ | 1750 | /* also discard if the object to be deleted is not here */ |
| 1812 | char *obj_id = object; | 1751 | const char *obj_id = object; |
| 1813 | if (xs_type(obj_id) == XSTYPE_DICT) | 1752 | if (xs_type(obj_id) == XSTYPE_DICT) |
| 1814 | obj_id = xs_dict_get(obj_id, "id"); | 1753 | obj_id = xs_dict_get(obj_id, "id"); |
| 1815 | 1754 | ||
| @@ -1881,7 +1820,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1881 | 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")); |
| 1882 | 1821 | ||
| 1883 | if (min_account_age > 0) { | 1822 | if (min_account_age > 0) { |
| 1884 | char *actor_date = xs_dict_get(actor_o, "published"); | 1823 | const char *actor_date = xs_dict_get(actor_o, "published"); |
| 1885 | if (!xs_is_null(actor_date)) { | 1824 | if (!xs_is_null(actor_date)) { |
| 1886 | time_t actor_t = xs_parse_iso_date(actor_date, 0); | 1825 | time_t actor_t = xs_parse_iso_date(actor_date, 0); |
| 1887 | 1826 | ||
| @@ -1941,16 +1880,39 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1941 | } | 1880 | } |
| 1942 | else | 1881 | else |
| 1943 | if (strcmp(type, "Undo") == 0) { /** **/ | 1882 | if (strcmp(type, "Undo") == 0) { /** **/ |
| 1883 | const char *id = xs_dict_get(object, "object"); | ||
| 1884 | |||
| 1944 | if (xs_type(object) != XSTYPE_DICT) | 1885 | if (xs_type(object) != XSTYPE_DICT) |
| 1945 | utype = "Follow"; | 1886 | utype = "Follow"; |
| 1946 | 1887 | ||
| 1947 | if (strcmp(utype, "Follow") == 0) { /** **/ | 1888 | if (strcmp(utype, "Follow") == 0) { /** **/ |
| 1948 | if (valid_status(follower_del(snac, actor))) { | 1889 | if (id && strcmp(id, snac->actor) != 0) |
| 1949 | snac_log(snac, xs_fmt("no longer following us %s", actor)); | 1890 | snac_debug(snac, 1, xs_fmt("Undo + Follow from %s not for us (%s)", actor, id)); |
| 1950 | do_notify = 1; | 1891 | else { |
| 1892 | if (valid_status(follower_del(snac, actor))) { | ||
| 1893 | snac_log(snac, xs_fmt("no longer following us %s", actor)); | ||
| 1894 | do_notify = 1; | ||
| 1895 | } | ||
| 1896 | else | ||
| 1897 | snac_log(snac, xs_fmt("error deleting follower %s", actor)); | ||
| 1951 | } | 1898 | } |
| 1952 | else | 1899 | } |
| 1953 | snac_log(snac, xs_fmt("error deleting follower %s", actor)); | 1900 | else |
| 1901 | if (strcmp(utype, "Like") == 0) { /** **/ | ||
| 1902 | int status = object_unadmire(id, actor, 1); | ||
| 1903 | |||
| 1904 | snac_log(snac, xs_fmt("Unlike for %s %d", id, status)); | ||
| 1905 | } | ||
| 1906 | else | ||
| 1907 | if (strcmp(utype, "Announce") == 0) { /** **/ | ||
| 1908 | int status = 200; | ||
| 1909 | |||
| 1910 | /* commented out: if a followed user boosts something that | ||
| 1911 | is requested and then unboosts, the post remains here, | ||
| 1912 | but with no apparent reason, and that is confusing */ | ||
| 1913 | //status = object_unadmire(id, actor, 0); | ||
| 1914 | |||
| 1915 | snac_log(snac, xs_fmt("Unboost for %s %d", id, status)); | ||
| 1954 | } | 1916 | } |
| 1955 | else | 1917 | else |
| 1956 | snac_debug(snac, 1, xs_fmt("ignored 'Undo' for object type '%s'", utype)); | 1918 | snac_debug(snac, 1, xs_fmt("ignored 'Undo' for object type '%s'", utype)); |
| @@ -1963,19 +1925,29 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1963 | } | 1925 | } |
| 1964 | 1926 | ||
| 1965 | if (xs_match(utype, "Note|Article")) { /** **/ | 1927 | if (xs_match(utype, "Note|Article")) { /** **/ |
| 1966 | char *id = xs_dict_get(object, "id"); | 1928 | const char *id = xs_dict_get(object, "id"); |
| 1967 | char *in_reply_to = xs_dict_get(object, "inReplyTo"); | 1929 | const char *in_reply_to = xs_dict_get(object, "inReplyTo"); |
| 1930 | const char *atto = get_atto(object); | ||
| 1968 | xs *wrk = NULL; | 1931 | xs *wrk = NULL; |
| 1969 | 1932 | ||
| 1933 | if (xs_is_null(id)) | ||
| 1934 | snac_log(snac, xs_fmt("malformed message: no 'id' field")); | ||
| 1935 | else | ||
| 1936 | if (xs_is_null(atto)) | ||
| 1937 | snac_log(snac, xs_fmt("malformed message: no 'attributedTo' field")); | ||
| 1938 | else | ||
| 1970 | if (!xs_is_null(in_reply_to) && is_hidden(snac, in_reply_to)) { | 1939 | if (!xs_is_null(in_reply_to) && is_hidden(snac, in_reply_to)) { |
| 1971 | snac_debug(snac, 0, xs_fmt("dropped reply %s to hidden post %s", id, in_reply_to)); | 1940 | snac_debug(snac, 0, xs_fmt("dropped reply %s to hidden post %s", id, in_reply_to)); |
| 1972 | } | 1941 | } |
| 1973 | else { | 1942 | else { |
| 1974 | if (content_check("filter_reject.txt", object)) { | 1943 | if (content_match("filter_reject.txt", object)) { |
| 1975 | snac_log(snac, xs_fmt("rejected by content %s", id)); | 1944 | snac_log(snac, xs_fmt("rejected by content %s", id)); |
| 1976 | return 1; | 1945 | return 1; |
| 1977 | } | 1946 | } |
| 1978 | 1947 | ||
| 1948 | if (strcmp(actor, atto) != 0) | ||
| 1949 | snac_log(snac, xs_fmt("SUSPICIOUS: actor != atto (%s != %s)", actor, atto)); | ||
| 1950 | |||
| 1979 | timeline_request(snac, &in_reply_to, &wrk, 0); | 1951 | timeline_request(snac, &in_reply_to, &wrk, 0); |
| 1980 | 1952 | ||
| 1981 | if (timeline_add(snac, id, object)) { | 1953 | if (timeline_add(snac, id, object)) { |
| @@ -1992,14 +1964,14 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 1992 | } | 1964 | } |
| 1993 | else | 1965 | else |
| 1994 | if (strcmp(utype, "Question") == 0) { /** **/ | 1966 | if (strcmp(utype, "Question") == 0) { /** **/ |
| 1995 | char *id = xs_dict_get(object, "id"); | 1967 | const char *id = xs_dict_get(object, "id"); |
| 1996 | 1968 | ||
| 1997 | if (timeline_add(snac, id, object)) | 1969 | if (timeline_add(snac, id, object)) |
| 1998 | snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id)); | 1970 | snac_log(snac, xs_fmt("new 'Question' %s %s", actor, id)); |
| 1999 | } | 1971 | } |
| 2000 | else | 1972 | else |
| 2001 | if (strcmp(utype, "Video") == 0) { /** **/ | 1973 | if (strcmp(utype, "Video") == 0) { /** **/ |
| 2002 | char *id = xs_dict_get(object, "id"); | 1974 | const char *id = xs_dict_get(object, "id"); |
| 2003 | 1975 | ||
| 2004 | if (timeline_add(snac, id, object)) | 1976 | if (timeline_add(snac, id, object)) |
| 2005 | snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id)); | 1977 | snac_log(snac, xs_fmt("new 'Video' %s %s", actor, id)); |
| @@ -2080,6 +2052,9 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 2080 | snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", | 2052 | snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", |
| 2081 | actor, object)); | 2053 | actor, object)); |
| 2082 | 2054 | ||
| 2055 | /* distribute the post with the actor as 'proxy' */ | ||
| 2056 | list_distribute(snac, actor, a_msg); | ||
| 2057 | |||
| 2083 | do_notify = 1; | 2058 | do_notify = 1; |
| 2084 | } | 2059 | } |
| 2085 | else | 2060 | else |
| @@ -2172,7 +2147,7 @@ int process_input_message(snac *snac, xs_dict *msg, xs_dict *req) | |||
| 2172 | } | 2147 | } |
| 2173 | 2148 | ||
| 2174 | 2149 | ||
| 2175 | int send_email(char *msg) | 2150 | int send_email(const char *msg) |
| 2176 | /* invoke sendmail with email headers and body in msg */ | 2151 | /* invoke sendmail with email headers and body in msg */ |
| 2177 | { | 2152 | { |
| 2178 | FILE *f; | 2153 | FILE *f; |
| @@ -2204,18 +2179,18 @@ int send_email(char *msg) | |||
| 2204 | void process_user_queue_item(snac *snac, xs_dict *q_item) | 2179 | void process_user_queue_item(snac *snac, xs_dict *q_item) |
| 2205 | /* processes an item from the user queue */ | 2180 | /* processes an item from the user queue */ |
| 2206 | { | 2181 | { |
| 2207 | char *type; | 2182 | const char *type; |
| 2208 | 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")); |
| 2209 | 2184 | ||
| 2210 | if ((type = xs_dict_get(q_item, "type")) == NULL) | 2185 | if ((type = xs_dict_get(q_item, "type")) == NULL) |
| 2211 | type = "output"; | 2186 | type = "output"; |
| 2212 | 2187 | ||
| 2213 | if (strcmp(type, "message") == 0) { | 2188 | if (strcmp(type, "message") == 0) { |
| 2214 | xs_dict *msg = xs_dict_get(q_item, "message"); | 2189 | const xs_dict *msg = xs_dict_get(q_item, "message"); |
| 2215 | xs *rcpts = recipient_list(snac, msg, 1); | 2190 | xs *rcpts = recipient_list(snac, msg, 1); |
| 2216 | xs_set inboxes; | 2191 | xs_set inboxes; |
| 2217 | xs_list *p; | 2192 | xs_list *p; |
| 2218 | xs_str *actor; | 2193 | const xs_str *actor; |
| 2219 | 2194 | ||
| 2220 | xs_set_init(&inboxes); | 2195 | xs_set_init(&inboxes); |
| 2221 | 2196 | ||
| @@ -2237,7 +2212,7 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) | |||
| 2237 | if (is_msg_public(msg)) { | 2212 | if (is_msg_public(msg)) { |
| 2238 | if (xs_type(xs_dict_get(srv_config, "disable_inbox_collection")) != XSTYPE_TRUE) { | 2213 | if (xs_type(xs_dict_get(srv_config, "disable_inbox_collection")) != XSTYPE_TRUE) { |
| 2239 | xs *shibx = inbox_list(); | 2214 | xs *shibx = inbox_list(); |
| 2240 | xs_str *inbox; | 2215 | const xs_str *inbox; |
| 2241 | 2216 | ||
| 2242 | p = shibx; | 2217 | p = shibx; |
| 2243 | while (xs_list_iter(&p, &inbox)) { | 2218 | while (xs_list_iter(&p, &inbox)) { |
| @@ -2252,8 +2227,8 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) | |||
| 2252 | else | 2227 | else |
| 2253 | if (strcmp(type, "input") == 0) { | 2228 | if (strcmp(type, "input") == 0) { |
| 2254 | /* process the message */ | 2229 | /* process the message */ |
| 2255 | xs_dict *msg = xs_dict_get(q_item, "message"); | 2230 | const xs_dict *msg = xs_dict_get(q_item, "message"); |
| 2256 | xs_dict *req = xs_dict_get(q_item, "req"); | 2231 | const xs_dict *req = xs_dict_get(q_item, "req"); |
| 2257 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); | 2232 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); |
| 2258 | 2233 | ||
| 2259 | if (xs_is_null(msg)) | 2234 | if (xs_is_null(msg)) |
| @@ -2280,11 +2255,20 @@ void process_user_queue_item(snac *snac, xs_dict *q_item) | |||
| 2280 | update_question(snac, id); | 2255 | update_question(snac, id); |
| 2281 | } | 2256 | } |
| 2282 | else | 2257 | else |
| 2283 | if (strcmp(type, "request_replies") == 0) { | 2258 | if (strcmp(type, "object_request") == 0) { |
| 2284 | const char *id = xs_dict_get(q_item, "message"); | 2259 | const char *id = xs_dict_get(q_item, "message"); |
| 2285 | 2260 | ||
| 2286 | if (!xs_is_null(id)) | 2261 | if (!xs_is_null(id)) { |
| 2287 | timeline_request_replies(snac, id); | 2262 | int status; |
| 2263 | xs *data = NULL; | ||
| 2264 | |||
| 2265 | status = activitypub_request(snac, id, &data); | ||
| 2266 | |||
| 2267 | if (valid_status(status)) | ||
| 2268 | object_add_ow(id, data); | ||
| 2269 | |||
| 2270 | snac_debug(snac, 1, xs_fmt("object_request %s %d", id, status)); | ||
| 2271 | } | ||
| 2288 | } | 2272 | } |
| 2289 | else | 2273 | else |
| 2290 | if (strcmp(type, "verify_links") == 0) { | 2274 | if (strcmp(type, "verify_links") == 0) { |
| @@ -2320,7 +2304,7 @@ int process_user_queue(snac *snac) | |||
| 2320 | xs *list = user_queue(snac); | 2304 | xs *list = user_queue(snac); |
| 2321 | 2305 | ||
| 2322 | xs_list *p = list; | 2306 | xs_list *p = list; |
| 2323 | xs_str *fn; | 2307 | const xs_str *fn; |
| 2324 | 2308 | ||
| 2325 | while (xs_list_iter(&p, &fn)) { | 2309 | while (xs_list_iter(&p, &fn)) { |
| 2326 | xs *q_item = dequeue(fn); | 2310 | xs *q_item = dequeue(fn); |
| @@ -2339,19 +2323,20 @@ int process_user_queue(snac *snac) | |||
| 2339 | void process_queue_item(xs_dict *q_item) | 2323 | void process_queue_item(xs_dict *q_item) |
| 2340 | /* processes an item from the global queue */ | 2324 | /* processes an item from the global queue */ |
| 2341 | { | 2325 | { |
| 2342 | char *type = xs_dict_get(q_item, "type"); | 2326 | const char *type = xs_dict_get(q_item, "type"); |
| 2343 | 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")); |
| 2344 | 2328 | ||
| 2345 | if (strcmp(type, "output") == 0) { | 2329 | if (strcmp(type, "output") == 0) { |
| 2346 | int status; | 2330 | int status; |
| 2347 | xs_str *inbox = xs_dict_get(q_item, "inbox"); | 2331 | const xs_str *inbox = xs_dict_get(q_item, "inbox"); |
| 2348 | xs_str *keyid = xs_dict_get(q_item, "keyid"); | 2332 | const xs_str *keyid = xs_dict_get(q_item, "keyid"); |
| 2349 | xs_str *seckey = xs_dict_get(q_item, "seckey"); | 2333 | const xs_str *seckey = xs_dict_get(q_item, "seckey"); |
| 2350 | xs_dict *msg = xs_dict_get(q_item, "message"); | 2334 | const xs_dict *msg = xs_dict_get(q_item, "message"); |
| 2351 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); | 2335 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); |
| 2352 | 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")); |
| 2353 | xs *payload = NULL; | 2337 | xs *payload = NULL; |
| 2354 | int p_size = 0; | 2338 | int p_size = 0; |
| 2339 | int timeout = 0; | ||
| 2355 | 2340 | ||
| 2356 | if (xs_is_null(inbox) || xs_is_null(msg) || xs_is_null(keyid) || xs_is_null(seckey)) { | 2341 | if (xs_is_null(inbox) || xs_is_null(msg) || xs_is_null(keyid) || xs_is_null(seckey)) { |
| 2357 | srv_log(xs_fmt("output message error: missing fields")); | 2342 | srv_log(xs_fmt("output message error: missing fields")); |
| @@ -2364,8 +2349,15 @@ void process_queue_item(xs_dict *q_item) | |||
| 2364 | } | 2349 | } |
| 2365 | 2350 | ||
| 2366 | /* deliver (if previous error status was a timeout, try now longer) */ | 2351 | /* deliver (if previous error status was a timeout, try now longer) */ |
| 2367 | status = send_to_inbox_raw(keyid, seckey, inbox, msg, | 2352 | if (p_status == 599) |
| 2368 | &payload, &p_size, p_status == 599 ? 8 : 6); | 2353 | timeout = xs_number_get(xs_dict_get_def(srv_config, "queue_timeout_2", "8")); |
| 2354 | else | ||
| 2355 | timeout = xs_number_get(xs_dict_get_def(srv_config, "queue_timeout", "6")); | ||
| 2356 | |||
| 2357 | if (timeout == 0) | ||
| 2358 | timeout = 6; | ||
| 2359 | |||
| 2360 | status = send_to_inbox_raw(keyid, seckey, inbox, msg, &payload, &p_size, timeout); | ||
| 2369 | 2361 | ||
| 2370 | if (payload) { | 2362 | if (payload) { |
| 2371 | if (p_size > 64) { | 2363 | if (p_size > 64) { |
| @@ -2411,7 +2403,7 @@ void process_queue_item(xs_dict *q_item) | |||
| 2411 | else | 2403 | else |
| 2412 | if (strcmp(type, "email") == 0) { | 2404 | if (strcmp(type, "email") == 0) { |
| 2413 | /* send this email */ | 2405 | /* send this email */ |
| 2414 | xs_str *msg = xs_dict_get(q_item, "message"); | 2406 | const xs_str *msg = xs_dict_get(q_item, "message"); |
| 2415 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); | 2407 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); |
| 2416 | 2408 | ||
| 2417 | if (!send_email(msg)) | 2409 | if (!send_email(msg)) |
| @@ -2433,8 +2425,8 @@ void process_queue_item(xs_dict *q_item) | |||
| 2433 | else | 2425 | else |
| 2434 | if (strcmp(type, "telegram") == 0) { | 2426 | if (strcmp(type, "telegram") == 0) { |
| 2435 | /* send this via telegram */ | 2427 | /* send this via telegram */ |
| 2436 | char *bot = xs_dict_get(q_item, "bot"); | 2428 | const char *bot = xs_dict_get(q_item, "bot"); |
| 2437 | char *msg = xs_dict_get(q_item, "message"); | 2429 | const char *msg = xs_dict_get(q_item, "message"); |
| 2438 | 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")); |
| 2439 | int status = 0; | 2431 | int status = 0; |
| 2440 | 2432 | ||
| @@ -2457,9 +2449,9 @@ void process_queue_item(xs_dict *q_item) | |||
| 2457 | else | 2449 | else |
| 2458 | if (strcmp(type, "ntfy") == 0) { | 2450 | if (strcmp(type, "ntfy") == 0) { |
| 2459 | /* send this via ntfy */ | 2451 | /* send this via ntfy */ |
| 2460 | char *ntfy_server = xs_dict_get(q_item, "ntfy_server"); | 2452 | const char *ntfy_server = xs_dict_get(q_item, "ntfy_server"); |
| 2461 | char *msg = xs_dict_get(q_item, "message"); | 2453 | const char *msg = xs_dict_get(q_item, "message"); |
| 2462 | char *ntfy_token = xs_dict_get(q_item, "ntfy_token"); | 2454 | const char *ntfy_token = xs_dict_get(q_item, "ntfy_token"); |
| 2463 | int status = 0; | 2455 | int status = 0; |
| 2464 | 2456 | ||
| 2465 | xs *url = xs_fmt("%s", ntfy_server); | 2457 | xs *url = xs_fmt("%s", ntfy_server); |
| @@ -2488,8 +2480,8 @@ void process_queue_item(xs_dict *q_item) | |||
| 2488 | } | 2480 | } |
| 2489 | else | 2481 | else |
| 2490 | if (strcmp(type, "input") == 0) { | 2482 | if (strcmp(type, "input") == 0) { |
| 2491 | xs_dict *msg = xs_dict_get(q_item, "message"); | 2483 | const xs_dict *msg = xs_dict_get(q_item, "message"); |
| 2492 | xs_dict *req = xs_dict_get(q_item, "req"); | 2484 | const xs_dict *req = xs_dict_get(q_item, "req"); |
| 2493 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); | 2485 | int retries = xs_number_get(xs_dict_get(q_item, "retries")); |
| 2494 | 2486 | ||
| 2495 | /* do some instance-level checks */ | 2487 | /* do some instance-level checks */ |
| @@ -2497,8 +2489,6 @@ void process_queue_item(xs_dict *q_item) | |||
| 2497 | 2489 | ||
| 2498 | if (r == 0) { | 2490 | if (r == 0) { |
| 2499 | /* transient error? retry */ | 2491 | /* transient error? retry */ |
| 2500 | int queue_retry_max = xs_number_get(xs_dict_get(srv_config, "queue_retry_max")); | ||
| 2501 | |||
| 2502 | if (retries > queue_retry_max) | 2492 | if (retries > queue_retry_max) |
| 2503 | srv_log(xs_fmt("shared input giving up")); | 2493 | srv_log(xs_fmt("shared input giving up")); |
| 2504 | else { | 2494 | else { |
| @@ -2510,7 +2500,7 @@ void process_queue_item(xs_dict *q_item) | |||
| 2510 | else | 2500 | else |
| 2511 | if (r == 2) { | 2501 | if (r == 2) { |
| 2512 | /* redistribute the input message to all users */ | 2502 | /* redistribute the input message to all users */ |
| 2513 | char *ntid = xs_dict_get(q_item, "ntid"); | 2503 | const char *ntid = xs_dict_get(q_item, "ntid"); |
| 2514 | xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid); | 2504 | xs *tmpfn = xs_fmt("%s/tmp/%s.json", srv_basedir, ntid); |
| 2515 | FILE *f; | 2505 | FILE *f; |
| 2516 | 2506 | ||
| @@ -2521,7 +2511,7 @@ void process_queue_item(xs_dict *q_item) | |||
| 2521 | 2511 | ||
| 2522 | xs *users = user_list(); | 2512 | xs *users = user_list(); |
| 2523 | xs_list *p = users; | 2513 | xs_list *p = users; |
| 2524 | char *v; | 2514 | const char *v; |
| 2525 | int cnt = 0; | 2515 | int cnt = 0; |
| 2526 | 2516 | ||
| 2527 | while (xs_list_iter(&p, &v)) { | 2517 | while (xs_list_iter(&p, &v)) { |
| @@ -2564,7 +2554,7 @@ int process_queue(void) | |||
| 2564 | xs *list = queue(); | 2554 | xs *list = queue(); |
| 2565 | 2555 | ||
| 2566 | xs_list *p = list; | 2556 | xs_list *p = list; |
| 2567 | xs_str *fn; | 2557 | const xs_str *fn; |
| 2568 | 2558 | ||
| 2569 | while (xs_list_iter(&p, &fn)) { | 2559 | while (xs_list_iter(&p, &fn)) { |
| 2570 | xs *q_item = dequeue(fn); | 2560 | xs *q_item = dequeue(fn); |
| @@ -2585,7 +2575,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, | |||
| 2585 | char **body, int *b_size, char **ctype) | 2575 | char **body, int *b_size, char **ctype) |
| 2586 | { | 2576 | { |
| 2587 | int status = 200; | 2577 | int status = 200; |
| 2588 | char *accept = xs_dict_get(req, "accept"); | 2578 | const char *accept = xs_dict_get(req, "accept"); |
| 2589 | snac snac; | 2579 | snac snac; |
| 2590 | xs *msg = NULL; | 2580 | xs *msg = NULL; |
| 2591 | 2581 | ||
| @@ -2597,7 +2587,8 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, | |||
| 2597 | return 0; | 2587 | return 0; |
| 2598 | 2588 | ||
| 2599 | xs *l = xs_split_n(q_path, "/", 2); | 2589 | xs *l = xs_split_n(q_path, "/", 2); |
| 2600 | char *uid, *p_path; | 2590 | const char *uid; |
| 2591 | const char *p_path; | ||
| 2601 | 2592 | ||
| 2602 | uid = xs_list_get(l, 1); | 2593 | uid = xs_list_get(l, 1); |
| 2603 | if (!user_open(&snac, uid)) { | 2594 | if (!user_open(&snac, uid)) { |
| @@ -2615,7 +2606,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, | |||
| 2615 | msg = msg_actor(&snac); | 2606 | msg = msg_actor(&snac); |
| 2616 | *ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""; | 2607 | *ctype = "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""; |
| 2617 | 2608 | ||
| 2618 | char *ua = xs_dict_get(req, "user-agent"); | 2609 | const char *ua = xs_dict_get(req, "user-agent"); |
| 2619 | 2610 | ||
| 2620 | 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")); |
| 2621 | } | 2612 | } |
| @@ -2625,15 +2616,16 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, | |||
| 2625 | xs *elems = timeline_simple_list(&snac, "public", 0, 20); | 2616 | xs *elems = timeline_simple_list(&snac, "public", 0, 20); |
| 2626 | xs *list = xs_list_new(); | 2617 | xs *list = xs_list_new(); |
| 2627 | msg = msg_collection(&snac, id); | 2618 | msg = msg_collection(&snac, id); |
| 2628 | char *p, *v; | 2619 | char *p; |
| 2620 | const char *v; | ||
| 2629 | 2621 | ||
| 2630 | p = elems; | 2622 | p = elems; |
| 2631 | while (xs_list_iter(&p, &v)) { | 2623 | while (xs_list_iter(&p, &v)) { |
| 2632 | xs *i = NULL; | 2624 | xs *i = NULL; |
| 2633 | 2625 | ||
| 2634 | if (valid_status(object_get_by_md5(v, &i))) { | 2626 | if (valid_status(object_get_by_md5(v, &i))) { |
| 2635 | char *type = xs_dict_get(i, "type"); | 2627 | const char *type = xs_dict_get(i, "type"); |
| 2636 | char *id = xs_dict_get(i, "id"); | 2628 | const char *id = xs_dict_get(i, "id"); |
| 2637 | 2629 | ||
| 2638 | if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) { | 2630 | if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) { |
| 2639 | xs *c_msg = msg_create(&snac, i); | 2631 | xs *c_msg = msg_create(&snac, i); |
| @@ -2686,9 +2678,9 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path, | |||
| 2686 | (void)b_size; | 2678 | (void)b_size; |
| 2687 | 2679 | ||
| 2688 | int status = 202; /* accepted */ | 2680 | int status = 202; /* accepted */ |
| 2689 | char *i_ctype = xs_dict_get(req, "content-type"); | 2681 | const char *i_ctype = xs_dict_get(req, "content-type"); |
| 2690 | snac snac; | 2682 | snac snac; |
| 2691 | char *v; | 2683 | const char *v; |
| 2692 | 2684 | ||
| 2693 | if (i_ctype == NULL) { | 2685 | if (i_ctype == NULL) { |
| 2694 | *body = xs_str_new("no content-type"); | 2686 | *body = xs_str_new("no content-type"); |