diff options
Diffstat (limited to '')
| -rw-r--r-- | activitypub.c | 283 | ||||
| -rw-r--r-- | data.c | 130 | ||||
| -rw-r--r-- | html.c | 278 | ||||
| -rw-r--r-- | http.c | 27 | ||||
| -rw-r--r-- | httpd.c | 16 | ||||
| -rw-r--r-- | main.c | 2 | ||||
| -rw-r--r-- | mastoapi.c | 109 | ||||
| -rw-r--r-- | snac.h | 45 | ||||
| -rw-r--r-- | upgrade.c | 40 | ||||
| -rw-r--r-- | utils.c | 2 | ||||
| -rw-r--r-- | webfinger.c | 23 | ||||
| -rw-r--r-- | xs.h | 110 | ||||
| -rw-r--r-- | xs_curl.h | 2 | ||||
| -rw-r--r-- | xs_html.h | 34 | ||||
| -rw-r--r-- | xs_httpd.h | 5 | ||||
| -rw-r--r-- | xs_json.h | 9 | ||||
| -rw-r--r-- | xs_set.h | 2 | ||||
| -rw-r--r-- | xs_unicode.h | 6 | ||||
| -rw-r--r-- | xs_url.h | 4 | ||||
| -rw-r--r-- | xs_version.h | 2 |
20 files changed, 549 insertions, 580 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 | ||
| 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 | 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 | ||
| 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 */ |
| @@ -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 | ||
| 392 | void 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 | |||
| 461 | int send_to_inbox_raw(const char *keyid, const char *seckey, | 394 | int 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) | |||
| 539 | 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) |
| 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 | ||
| 1091 | xs_dict *msg_collection(snac *snac, char *id) | 1025 | xs_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 | ||
| 1105 | xs_dict *msg_accept(snac *snac, char *object, char *to) | 1039 | xs_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 | ||
| 1116 | xs_dict *msg_update(snac *snac, xs_dict *object) | 1050 | xs_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 | ||
| 1144 | xs_dict *msg_admiration(snac *snac, char *object, char *type) | 1078 | xs_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 | ||
| 1175 | xs_dict *msg_repulsion(snac *user, char *id, char *type) | 1109 | xs_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 | ||
| 1334 | xs_dict *msg_undo(snac *snac, char *object) | 1268 | xs_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 | ||
| 1347 | xs_dict *msg_delete(snac *snac, char *id) | 1281 | xs_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 | ||
| 1404 | 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, |
| 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 | ||
| 1767 | 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) |
| 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 | ||
| 2215 | int send_email(char *msg) | 2150 | int 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) | |||
| 2244 | void process_user_queue_item(snac *snac, xs_dict *q_item) | 2179 | void 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) | |||
| 2395 | void process_queue_item(xs_dict *q_item) | 2323 | void 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"); |
| @@ -29,7 +29,7 @@ pthread_mutex_t data_mutex = {0}; | |||
| 29 | int snac_upgrade(xs_str **error); | 29 | int snac_upgrade(xs_str **error); |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | int srv_open(char *basedir, int auto_upgrade) | 32 | int srv_open(const char *basedir, int auto_upgrade) |
| 33 | /* opens a server */ | 33 | /* opens a server */ |
| 34 | { | 34 | { |
| 35 | int ret = 0; | 35 | int ret = 0; |
| @@ -58,10 +58,10 @@ int srv_open(char *basedir, int auto_upgrade) | |||
| 58 | if (srv_config == NULL) | 58 | if (srv_config == NULL) |
| 59 | error = xs_fmt("ERROR: cannot parse '%s'", cfg_file); | 59 | error = xs_fmt("ERROR: cannot parse '%s'", cfg_file); |
| 60 | else { | 60 | else { |
| 61 | char *host; | 61 | const char *host; |
| 62 | char *prefix; | 62 | const char *prefix; |
| 63 | char *dbglvl; | 63 | const char *dbglvl; |
| 64 | char *proto; | 64 | const char *proto; |
| 65 | 65 | ||
| 66 | host = xs_dict_get(srv_config, "host"); | 66 | host = xs_dict_get(srv_config, "host"); |
| 67 | prefix = xs_dict_get(srv_config, "prefix"); | 67 | prefix = xs_dict_get(srv_config, "prefix"); |
| @@ -710,7 +710,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow) | |||
| 710 | fclose(f); | 710 | fclose(f); |
| 711 | 711 | ||
| 712 | /* does this object has a parent? */ | 712 | /* does this object has a parent? */ |
| 713 | char *in_reply_to = xs_dict_get(obj, "inReplyTo"); | 713 | const char *in_reply_to = xs_dict_get(obj, "inReplyTo"); |
| 714 | 714 | ||
| 715 | if (!xs_is_null(in_reply_to) && *in_reply_to) { | 715 | if (!xs_is_null(in_reply_to) && *in_reply_to) { |
| 716 | /* update the children index of the parent */ | 716 | /* update the children index of the parent */ |
| @@ -1124,7 +1124,7 @@ int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg) | |||
| 1124 | } | 1124 | } |
| 1125 | 1125 | ||
| 1126 | 1126 | ||
| 1127 | int timeline_del(snac *snac, char *id) | 1127 | int timeline_del(snac *snac, const char *id) |
| 1128 | /* deletes a message from the timeline */ | 1128 | /* deletes a message from the timeline */ |
| 1129 | { | 1129 | { |
| 1130 | /* delete from the user's caches */ | 1130 | /* delete from the user's caches */ |
| @@ -1192,17 +1192,16 @@ int timeline_admire(snac *snac, const char *id, const char *admirer, int like) | |||
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | 1194 | ||
| 1195 | xs_list *timeline_top_level(snac *snac, xs_list *list) | 1195 | xs_list *timeline_top_level(snac *snac, const xs_list *list) |
| 1196 | /* returns the top level md5 entries from this index */ | 1196 | /* returns the top level md5 entries from this index */ |
| 1197 | { | 1197 | { |
| 1198 | xs_set seen; | 1198 | xs_set seen; |
| 1199 | xs_list *p; | ||
| 1200 | xs_str *v; | 1199 | xs_str *v; |
| 1201 | 1200 | ||
| 1202 | xs_set_init(&seen); | 1201 | xs_set_init(&seen); |
| 1203 | 1202 | ||
| 1204 | p = list; | 1203 | int c = 0; |
| 1205 | while (xs_list_iter(&p, &v)) { | 1204 | while (xs_list_next(list, &v, &c)) { |
| 1206 | char line[256] = ""; | 1205 | char line[256] = ""; |
| 1207 | 1206 | ||
| 1208 | strncpy(line, v, sizeof(line)); | 1207 | strncpy(line, v, sizeof(line)); |
| @@ -1290,7 +1289,7 @@ int following_add(snac *snac, const char *actor, const xs_dict *msg) | |||
| 1290 | /* object already exists; if it's of type Accept, | 1289 | /* object already exists; if it's of type Accept, |
| 1291 | the actor is already being followed and confirmed, | 1290 | the actor is already being followed and confirmed, |
| 1292 | so do nothing */ | 1291 | so do nothing */ |
| 1293 | char *type = xs_dict_get(p_object, "type"); | 1292 | const char *type = xs_dict_get(p_object, "type"); |
| 1294 | 1293 | ||
| 1295 | if (!xs_is_null(type) && strcmp(type, "Accept") == 0) { | 1294 | if (!xs_is_null(type) && strcmp(type, "Accept") == 0) { |
| 1296 | snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor)); | 1295 | snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor)); |
| @@ -1546,8 +1545,9 @@ void hide(snac *snac, const char *id) | |||
| 1546 | 1545 | ||
| 1547 | /* resolve to get the id */ | 1546 | /* resolve to get the id */ |
| 1548 | if (valid_status(object_get_by_md5(v, &co))) { | 1547 | if (valid_status(object_get_by_md5(v, &co))) { |
| 1549 | if ((v = xs_dict_get(co, "id")) != NULL) | 1548 | const char *id = xs_dict_get(co, "id"); |
| 1550 | hide(snac, v); | 1549 | if (id != NULL) |
| 1550 | hide(snac, id); | ||
| 1551 | } | 1551 | } |
| 1552 | } | 1552 | } |
| 1553 | } | 1553 | } |
| @@ -1563,7 +1563,7 @@ int is_hidden(snac *snac, const char *id) | |||
| 1563 | } | 1563 | } |
| 1564 | 1564 | ||
| 1565 | 1565 | ||
| 1566 | int actor_add(const char *actor, xs_dict *msg) | 1566 | int actor_add(const char *actor, const xs_dict *msg) |
| 1567 | /* adds an actor */ | 1567 | /* adds an actor */ |
| 1568 | { | 1568 | { |
| 1569 | return object_add_ow(actor, msg); | 1569 | return object_add_ow(actor, msg); |
| @@ -1687,7 +1687,7 @@ int limited(snac *user, const char *id, int cmd) | |||
| 1687 | void tag_index(const char *id, const xs_dict *obj) | 1687 | void tag_index(const char *id, const xs_dict *obj) |
| 1688 | /* update the tag indexes for this object */ | 1688 | /* update the tag indexes for this object */ |
| 1689 | { | 1689 | { |
| 1690 | xs_list *tags = xs_dict_get(obj, "tag"); | 1690 | const xs_list *tags = xs_dict_get(obj, "tag"); |
| 1691 | 1691 | ||
| 1692 | if (is_msg_public(obj) && xs_type(tags) == XSTYPE_LIST && xs_list_len(tags) > 0) { | 1692 | if (is_msg_public(obj) && xs_type(tags) == XSTYPE_LIST && xs_list_len(tags) > 0) { |
| 1693 | xs *g_tag_dir = xs_fmt("%s/tag", srv_basedir); | 1693 | xs *g_tag_dir = xs_fmt("%s/tag", srv_basedir); |
| @@ -1695,9 +1695,10 @@ void tag_index(const char *id, const xs_dict *obj) | |||
| 1695 | mkdirx(g_tag_dir); | 1695 | mkdirx(g_tag_dir); |
| 1696 | 1696 | ||
| 1697 | xs_dict *v; | 1697 | xs_dict *v; |
| 1698 | while (xs_list_iter(&tags, &v)) { | 1698 | int ct = 0; |
| 1699 | char *type = xs_dict_get(v, "type"); | 1699 | while (xs_list_next(tags, &v, &ct)) { |
| 1700 | char *name = xs_dict_get(v, "name"); | 1700 | const char *type = xs_dict_get(v, "type"); |
| 1701 | const char *name = xs_dict_get(v, "name"); | ||
| 1701 | 1702 | ||
| 1702 | if (!xs_is_null(type) && !xs_is_null(name) && strcmp(type, "Hashtag") == 0) { | 1703 | if (!xs_is_null(type) && !xs_is_null(name) && strcmp(type, "Hashtag") == 0) { |
| 1703 | while (*name == '#' || *name == '@') | 1704 | while (*name == '#' || *name == '@') |
| @@ -1706,7 +1707,7 @@ void tag_index(const char *id, const xs_dict *obj) | |||
| 1706 | if (*name == '\0') | 1707 | if (*name == '\0') |
| 1707 | continue; | 1708 | continue; |
| 1708 | 1709 | ||
| 1709 | name = xs_tolower_i(name); | 1710 | name = xs_tolower_i((xs_str *)name); |
| 1710 | 1711 | ||
| 1711 | xs *md5_tag = xs_md5_hex(name, strlen(name)); | 1712 | xs *md5_tag = xs_md5_hex(name, strlen(name)); |
| 1712 | xs *tag_dir = xs_fmt("%s/%c%c", g_tag_dir, md5_tag[0], md5_tag[1]); | 1713 | xs *tag_dir = xs_fmt("%s/%c%c", g_tag_dir, md5_tag[0], md5_tag[1]); |
| @@ -1729,7 +1730,7 @@ void tag_index(const char *id, const xs_dict *obj) | |||
| 1729 | } | 1730 | } |
| 1730 | 1731 | ||
| 1731 | 1732 | ||
| 1732 | xs_list *tag_search(char *tag, int skip, int show) | 1733 | xs_list *tag_search(const char *tag, int skip, int show) |
| 1733 | /* returns the list of posts tagged with tag */ | 1734 | /* returns the list of posts tagged with tag */ |
| 1734 | { | 1735 | { |
| 1735 | if (*tag == '#') | 1736 | if (*tag == '#') |
| @@ -1912,7 +1913,7 @@ xs_val *list_content(snac *user, const char *list, const char *actor_md5, int op | |||
| 1912 | void list_distribute(snac *user, const char *who, const xs_dict *post) | 1913 | void list_distribute(snac *user, const char *who, const xs_dict *post) |
| 1913 | /* distributes the post to all appropriate lists */ | 1914 | /* distributes the post to all appropriate lists */ |
| 1914 | { | 1915 | { |
| 1915 | char *id = xs_dict_get(post, "id"); | 1916 | const char *id = xs_dict_get(post, "id"); |
| 1916 | 1917 | ||
| 1917 | /* if who is not set, use the attributedTo in the message */ | 1918 | /* if who is not set, use the attributedTo in the message */ |
| 1918 | if (xs_is_null(who)) | 1919 | if (xs_is_null(who)) |
| @@ -2164,7 +2165,7 @@ void inbox_add(const char *inbox) | |||
| 2164 | void inbox_add_by_actor(const xs_dict *actor) | 2165 | void inbox_add_by_actor(const xs_dict *actor) |
| 2165 | /* collects an actor's shared inbox, if it has one */ | 2166 | /* collects an actor's shared inbox, if it has one */ |
| 2166 | { | 2167 | { |
| 2167 | char *v; | 2168 | const char *v; |
| 2168 | 2169 | ||
| 2169 | if (!xs_is_null(v = xs_dict_get(actor, "endpoints")) && | 2170 | if (!xs_is_null(v = xs_dict_get(actor, "endpoints")) && |
| 2170 | !xs_is_null(v = xs_dict_get(v, "sharedInbox"))) { | 2171 | !xs_is_null(v = xs_dict_get(v, "sharedInbox"))) { |
| @@ -2210,7 +2211,7 @@ xs_str *_instance_block_fn(const char *instance) | |||
| 2210 | xs *s = xs_replace(instance, "http:/" "/", ""); | 2211 | xs *s = xs_replace(instance, "http:/" "/", ""); |
| 2211 | xs *s1 = xs_replace(s, "https:/" "/", ""); | 2212 | xs *s1 = xs_replace(s, "https:/" "/", ""); |
| 2212 | xs *l = xs_split(s1, "/"); | 2213 | xs *l = xs_split(s1, "/"); |
| 2213 | char *p = xs_list_get(l, 0); | 2214 | const char *p = xs_list_get(l, 0); |
| 2214 | xs *md5 = xs_md5_hex(p, strlen(p)); | 2215 | xs *md5 = xs_md5_hex(p, strlen(p)); |
| 2215 | 2216 | ||
| 2216 | return xs_fmt("%s/block/%s", srv_basedir, md5); | 2217 | return xs_fmt("%s/block/%s", srv_basedir, md5); |
| @@ -2279,7 +2280,7 @@ int content_match(const char *file, const xs_dict *msg) | |||
| 2279 | xs *fn = xs_fmt("%s/%s", srv_basedir, file); | 2280 | xs *fn = xs_fmt("%s/%s", srv_basedir, file); |
| 2280 | FILE *f; | 2281 | FILE *f; |
| 2281 | int r = 0; | 2282 | int r = 0; |
| 2282 | char *v = xs_dict_get(msg, "content"); | 2283 | const char *v = xs_dict_get(msg, "content"); |
| 2283 | 2284 | ||
| 2284 | if (xs_type(v) == XSTYPE_STRING && *v) { | 2285 | if (xs_type(v) == XSTYPE_STRING && *v) { |
| 2285 | if ((f = fopen(fn, "r")) != NULL) { | 2286 | if ((f = fopen(fn, "r")) != NULL) { |
| @@ -2386,7 +2387,7 @@ xs_list *content_search(snac *user, const char *regex, | |||
| 2386 | if (id == NULL || is_hidden(user, id)) | 2387 | if (id == NULL || is_hidden(user, id)) |
| 2387 | continue; | 2388 | continue; |
| 2388 | 2389 | ||
| 2389 | char *content = xs_dict_get(post, "content"); | 2390 | const char *content = xs_dict_get(post, "content"); |
| 2390 | 2391 | ||
| 2391 | if (xs_is_null(content)) | 2392 | if (xs_is_null(content)) |
| 2392 | continue; | 2393 | continue; |
| @@ -2639,7 +2640,7 @@ void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retri | |||
| 2639 | /* enqueues an input message */ | 2640 | /* enqueues an input message */ |
| 2640 | { | 2641 | { |
| 2641 | xs *qmsg = _new_qmsg("input", msg, retries); | 2642 | xs *qmsg = _new_qmsg("input", msg, retries); |
| 2642 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2643 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2643 | xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid); | 2644 | xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid); |
| 2644 | 2645 | ||
| 2645 | qmsg = xs_dict_append(qmsg, "req", req); | 2646 | qmsg = xs_dict_append(qmsg, "req", req); |
| @@ -2654,7 +2655,7 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries) | |||
| 2654 | /* enqueues an input message from the shared input */ | 2655 | /* enqueues an input message from the shared input */ |
| 2655 | { | 2656 | { |
| 2656 | xs *qmsg = _new_qmsg("input", msg, retries); | 2657 | xs *qmsg = _new_qmsg("input", msg, retries); |
| 2657 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2658 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2658 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); | 2659 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); |
| 2659 | 2660 | ||
| 2660 | qmsg = xs_dict_append(qmsg, "req", req); | 2661 | qmsg = xs_dict_append(qmsg, "req", req); |
| @@ -2666,11 +2667,12 @@ void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries) | |||
| 2666 | 2667 | ||
| 2667 | 2668 | ||
| 2668 | void enqueue_output_raw(const char *keyid, const char *seckey, | 2669 | void enqueue_output_raw(const char *keyid, const char *seckey, |
| 2669 | xs_dict *msg, xs_str *inbox, int retries, int p_status) | 2670 | const xs_dict *msg, const xs_str *inbox, |
| 2671 | int retries, int p_status) | ||
| 2670 | /* enqueues an output message to an inbox */ | 2672 | /* enqueues an output message to an inbox */ |
| 2671 | { | 2673 | { |
| 2672 | xs *qmsg = _new_qmsg("output", msg, retries); | 2674 | xs *qmsg = _new_qmsg("output", msg, retries); |
| 2673 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2675 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2674 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); | 2676 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); |
| 2675 | 2677 | ||
| 2676 | xs *ns = xs_number_new(p_status); | 2678 | xs *ns = xs_number_new(p_status); |
| @@ -2690,7 +2692,8 @@ void enqueue_output_raw(const char *keyid, const char *seckey, | |||
| 2690 | } | 2692 | } |
| 2691 | 2693 | ||
| 2692 | 2694 | ||
| 2693 | void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status) | 2695 | void enqueue_output(snac *snac, const xs_dict *msg, |
| 2696 | const xs_str *inbox, int retries, int p_status) | ||
| 2694 | /* enqueues an output message to an inbox */ | 2697 | /* enqueues an output message to an inbox */ |
| 2695 | { | 2698 | { |
| 2696 | if (xs_startswith(inbox, snac->actor)) { | 2699 | if (xs_startswith(inbox, snac->actor)) { |
| @@ -2698,13 +2701,14 @@ void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_ | |||
| 2698 | return; | 2701 | return; |
| 2699 | } | 2702 | } |
| 2700 | 2703 | ||
| 2701 | char *seckey = xs_dict_get(snac->key, "secret"); | 2704 | const char *seckey = xs_dict_get(snac->key, "secret"); |
| 2702 | 2705 | ||
| 2703 | enqueue_output_raw(snac->actor, seckey, msg, inbox, retries, p_status); | 2706 | enqueue_output_raw(snac->actor, seckey, msg, inbox, retries, p_status); |
| 2704 | } | 2707 | } |
| 2705 | 2708 | ||
| 2706 | 2709 | ||
| 2707 | void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries) | 2710 | void enqueue_output_by_actor(snac *snac, const xs_dict *msg, |
| 2711 | const xs_str *actor, int retries) | ||
| 2708 | /* enqueues an output message for an actor */ | 2712 | /* enqueues an output message for an actor */ |
| 2709 | { | 2713 | { |
| 2710 | xs *inbox = get_actor_inbox(actor); | 2714 | xs *inbox = get_actor_inbox(actor); |
| @@ -2716,11 +2720,11 @@ void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int | |||
| 2716 | } | 2720 | } |
| 2717 | 2721 | ||
| 2718 | 2722 | ||
| 2719 | void enqueue_email(xs_str *msg, int retries) | 2723 | void enqueue_email(const xs_str *msg, int retries) |
| 2720 | /* enqueues an email message to be sent */ | 2724 | /* enqueues an email message to be sent */ |
| 2721 | { | 2725 | { |
| 2722 | xs *qmsg = _new_qmsg("email", msg, retries); | 2726 | xs *qmsg = _new_qmsg("email", msg, retries); |
| 2723 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2727 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2724 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); | 2728 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); |
| 2725 | 2729 | ||
| 2726 | qmsg = _enqueue_put(fn, qmsg); | 2730 | qmsg = _enqueue_put(fn, qmsg); |
| @@ -2733,7 +2737,7 @@ void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id) | |||
| 2733 | /* enqueues a message to be sent via Telegram */ | 2737 | /* enqueues a message to be sent via Telegram */ |
| 2734 | { | 2738 | { |
| 2735 | xs *qmsg = _new_qmsg("telegram", msg, 0); | 2739 | xs *qmsg = _new_qmsg("telegram", msg, 0); |
| 2736 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2740 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2737 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); | 2741 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); |
| 2738 | 2742 | ||
| 2739 | qmsg = xs_dict_append(qmsg, "bot", bot); | 2743 | qmsg = xs_dict_append(qmsg, "bot", bot); |
| @@ -2748,7 +2752,7 @@ void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_t | |||
| 2748 | /* enqueues a message to be sent via ntfy */ | 2752 | /* enqueues a message to be sent via ntfy */ |
| 2749 | { | 2753 | { |
| 2750 | xs *qmsg = _new_qmsg("ntfy", msg, 0); | 2754 | xs *qmsg = _new_qmsg("ntfy", msg, 0); |
| 2751 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2755 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2752 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); | 2756 | xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid); |
| 2753 | 2757 | ||
| 2754 | qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server); | 2758 | qmsg = xs_dict_append(qmsg, "ntfy_server", ntfy_server); |
| @@ -2764,7 +2768,7 @@ void enqueue_message(snac *snac, const xs_dict *msg) | |||
| 2764 | /* enqueues an output message */ | 2768 | /* enqueues an output message */ |
| 2765 | { | 2769 | { |
| 2766 | xs *qmsg = _new_qmsg("message", msg, 0); | 2770 | xs *qmsg = _new_qmsg("message", msg, 0); |
| 2767 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2771 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2768 | xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid); | 2772 | xs *fn = xs_fmt("%s/queue/%s.json", snac->basedir, ntid); |
| 2769 | 2773 | ||
| 2770 | qmsg = _enqueue_put(fn, qmsg); | 2774 | qmsg = _enqueue_put(fn, qmsg); |
| @@ -2807,7 +2811,7 @@ void enqueue_verify_links(snac *user) | |||
| 2807 | /* enqueues a link verification */ | 2811 | /* enqueues a link verification */ |
| 2808 | { | 2812 | { |
| 2809 | xs *qmsg = _new_qmsg("verify_links", "", 0); | 2813 | xs *qmsg = _new_qmsg("verify_links", "", 0); |
| 2810 | char *ntid = xs_dict_get(qmsg, "ntid"); | 2814 | const char *ntid = xs_dict_get(qmsg, "ntid"); |
| 2811 | xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid); | 2815 | xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid); |
| 2812 | 2816 | ||
| 2813 | qmsg = _enqueue_put(fn, qmsg); | 2817 | qmsg = _enqueue_put(fn, qmsg); |
| @@ -2832,42 +2836,6 @@ void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs) | |||
| 2832 | } | 2836 | } |
| 2833 | 2837 | ||
| 2834 | 2838 | ||
| 2835 | void enqueue_request_replies(snac *user, const char *id) | ||
| 2836 | /* enqueues a request for the replies of a message */ | ||
| 2837 | { | ||
| 2838 | /* test first if this precise request is already in the queue */ | ||
| 2839 | xs *queue = user_queue(user); | ||
| 2840 | xs_list *p = queue; | ||
| 2841 | xs_str *v; | ||
| 2842 | |||
| 2843 | while (xs_list_iter(&p, &v)) { | ||
| 2844 | xs *q_item = queue_get(v); | ||
| 2845 | |||
| 2846 | if (q_item != NULL) { | ||
| 2847 | const char *type = xs_dict_get(q_item, "type"); | ||
| 2848 | const char *msg = xs_dict_get(q_item, "message"); | ||
| 2849 | |||
| 2850 | if (type && msg && strcmp(type, "request_replies") == 0 && strcmp(msg, id) == 0) { | ||
| 2851 | /* don't requeue */ | ||
| 2852 | snac_debug(user, 1, xs_fmt("enqueue_request_replies already here %s", id)); | ||
| 2853 | return; | ||
| 2854 | } | ||
| 2855 | } | ||
| 2856 | } | ||
| 2857 | |||
| 2858 | /* not there; enqueue the request with a small delay */ | ||
| 2859 | xs *qmsg = _new_qmsg("request_replies", id, 0); | ||
| 2860 | xs *ntid = tid(10); | ||
| 2861 | xs *fn = xs_fmt("%s/queue/%s.json", user->basedir, ntid); | ||
| 2862 | |||
| 2863 | qmsg = xs_dict_set(qmsg, "ntid", ntid); | ||
| 2864 | |||
| 2865 | qmsg = _enqueue_put(fn, qmsg); | ||
| 2866 | |||
| 2867 | snac_debug(user, 2, xs_fmt("enqueue_request_replies %s", id)); | ||
| 2868 | } | ||
| 2869 | |||
| 2870 | |||
| 2871 | int was_question_voted(snac *user, const char *id) | 2839 | int was_question_voted(snac *user, const char *id) |
| 2872 | /* returns true if the user voted in this poll */ | 2840 | /* returns true if the user voted in this poll */ |
| 2873 | { | 2841 | { |
| @@ -2881,7 +2849,7 @@ int was_question_voted(snac *user, const char *id) | |||
| 2881 | xs *obj = NULL; | 2849 | xs *obj = NULL; |
| 2882 | 2850 | ||
| 2883 | if (valid_status(object_get_by_md5(md5, &obj))) { | 2851 | if (valid_status(object_get_by_md5(md5, &obj))) { |
| 2884 | char *atto = get_atto(obj); | 2852 | const char *atto = get_atto(obj); |
| 2885 | if (atto && strcmp(atto, user->actor) == 0 && | 2853 | if (atto && strcmp(atto, user->actor) == 0 && |
| 2886 | !xs_is_null(xs_dict_get(obj, "name"))) { | 2854 | !xs_is_null(xs_dict_get(obj, "name"))) { |
| 2887 | voted = 1; | 2855 | voted = 1; |
| @@ -3055,7 +3023,7 @@ void purge_server(void) | |||
| 3055 | if (mtime_nl(v2, &n_link) < mt && n_link < 2) { | 3023 | if (mtime_nl(v2, &n_link) < mt && n_link < 2) { |
| 3056 | xs *s1 = xs_replace(v2, ".json", ""); | 3024 | xs *s1 = xs_replace(v2, ".json", ""); |
| 3057 | xs *l = xs_split(s1, "/"); | 3025 | xs *l = xs_split(s1, "/"); |
| 3058 | char *md5 = xs_list_get(l, -1); | 3026 | const char *md5 = xs_list_get(l, -1); |
| 3059 | 3027 | ||
| 3060 | object_del_by_md5(md5); | 3028 | object_del_by_md5(md5); |
| 3061 | cnt++; | 3029 | cnt++; |
| @@ -3147,7 +3115,7 @@ void purge_user(snac *snac) | |||
| 3147 | /* do the purge for this user */ | 3115 | /* do the purge for this user */ |
| 3148 | { | 3116 | { |
| 3149 | int priv_days, pub_days, user_days = 0; | 3117 | int priv_days, pub_days, user_days = 0; |
| 3150 | char *v; | 3118 | const char *v; |
| 3151 | int n; | 3119 | int n; |
| 3152 | 3120 | ||
| 3153 | priv_days = xs_number_get(xs_dict_get(srv_config, "timeline_purge_days")); | 3121 | priv_days = xs_number_get(xs_dict_get(srv_config, "timeline_purge_days")); |
| @@ -3256,7 +3224,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req, | |||
| 3256 | if (p_size && payload) { | 3224 | if (p_size && payload) { |
| 3257 | xs *payload_fn = NULL; | 3225 | xs *payload_fn = NULL; |
| 3258 | xs *payload_fn_raw = NULL; | 3226 | xs *payload_fn_raw = NULL; |
| 3259 | char *v = xs_dict_get(req, "content-type"); | 3227 | const char *v = xs_dict_get(req, "content-type"); |
| 3260 | 3228 | ||
| 3261 | if (v && xs_str_in(v, "json") != -1) { | 3229 | if (v && xs_str_in(v, "json") != -1) { |
| 3262 | payload_fn = xs_fmt("%s/payload.json", dir); | 3230 | payload_fn = xs_fmt("%s/payload.json", dir); |
| @@ -3287,7 +3255,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req, | |||
| 3287 | 3255 | ||
| 3288 | if (b_size && body) { | 3256 | if (b_size && body) { |
| 3289 | xs *body_fn = NULL; | 3257 | xs *body_fn = NULL; |
| 3290 | char *v = xs_dict_get(headers, "content-type"); | 3258 | const char *v = xs_dict_get(headers, "content-type"); |
| 3291 | 3259 | ||
| 3292 | if (v && xs_str_in(v, "json") != -1) { | 3260 | if (v && xs_str_in(v, "json") != -1) { |
| 3293 | body_fn = xs_fmt("%s/body.json", dir); | 3261 | body_fn = xs_fmt("%s/body.json", dir); |
| @@ -3356,7 +3324,7 @@ void srv_archive_error(const char *prefix, const xs_str *err, | |||
| 3356 | } | 3324 | } |
| 3357 | 3325 | ||
| 3358 | 3326 | ||
| 3359 | void srv_archive_qitem(char *prefix, xs_dict *q_item) | 3327 | void srv_archive_qitem(const char *prefix, xs_dict *q_item) |
| 3360 | /* archives a q_item in the error folder */ | 3328 | /* archives a q_item in the error folder */ |
| 3361 | { | 3329 | { |
| 3362 | xs *ntid = tid(0); | 3330 | xs *ntid = tid(0); |
| @@ -41,7 +41,7 @@ int login(snac *snac, const xs_dict *headers) | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems) | 44 | xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems) |
| 45 | /* replaces all the :shortnames: with the emojis in tag */ | 45 | /* replaces all the :shortnames: with the emojis in tag */ |
| 46 | { | 46 | { |
| 47 | if (!xs_is_null(tag)) { | 47 | if (!xs_is_null(tag)) { |
| @@ -57,18 +57,18 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems) | |||
| 57 | 57 | ||
| 58 | xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems); | 58 | xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems); |
| 59 | 59 | ||
| 60 | xs_list *p = tag_list; | ||
| 61 | char *v; | 60 | char *v; |
| 61 | int c = 0; | ||
| 62 | 62 | ||
| 63 | while (xs_list_iter(&p, &v)) { | 63 | while (xs_list_next(tag_list, &v, &c)) { |
| 64 | char *t = xs_dict_get(v, "type"); | 64 | const char *t = xs_dict_get(v, "type"); |
| 65 | 65 | ||
| 66 | if (t && strcmp(t, "Emoji") == 0) { | 66 | if (t && strcmp(t, "Emoji") == 0) { |
| 67 | char *n = xs_dict_get(v, "name"); | 67 | const char *n = xs_dict_get(v, "name"); |
| 68 | char *i = xs_dict_get(v, "icon"); | 68 | const char *i = xs_dict_get(v, "icon"); |
| 69 | 69 | ||
| 70 | if (n && i) { | 70 | if (n && i) { |
| 71 | char *u = xs_dict_get(i, "url"); | 71 | const char *u = xs_dict_get(i, "url"); |
| 72 | xs_html *img = xs_html_sctag("img", | 72 | xs_html *img = xs_html_sctag("img", |
| 73 | xs_html_attr("loading", "lazy"), | 73 | xs_html_attr("loading", "lazy"), |
| 74 | xs_html_attr("src", u), | 74 | xs_html_attr("src", u), |
| @@ -88,7 +88,7 @@ xs_str *replace_shortnames(xs_str *s, xs_list *tag, int ems) | |||
| 88 | xs_str *actor_name(xs_dict *actor) | 88 | xs_str *actor_name(xs_dict *actor) |
| 89 | /* gets the actor name */ | 89 | /* gets the actor name */ |
| 90 | { | 90 | { |
| 91 | char *v; | 91 | const char *v; |
| 92 | 92 | ||
| 93 | if (xs_is_null((v = xs_dict_get(actor, "name"))) || *v == '\0') { | 93 | if (xs_is_null((v = xs_dict_get(actor, "name"))) || *v == '\0') { |
| 94 | if (xs_is_null(v = xs_dict_get(actor, "preferredUsername")) || *v == '\0') { | 94 | if (xs_is_null(v = xs_dict_get(actor, "preferredUsername")) || *v == '\0') { |
| @@ -106,7 +106,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | |||
| 106 | xs_html *actor_icon = xs_html_tag("p", NULL); | 106 | xs_html *actor_icon = xs_html_tag("p", NULL); |
| 107 | 107 | ||
| 108 | xs *avatar = NULL; | 108 | xs *avatar = NULL; |
| 109 | char *v; | 109 | const char *v; |
| 110 | int fwing = 0; | 110 | int fwing = 0; |
| 111 | int fwer = 0; | 111 | int fwer = 0; |
| 112 | 112 | ||
| @@ -125,7 +125,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | |||
| 125 | if (avatar == NULL) | 125 | if (avatar == NULL) |
| 126 | avatar = xs_fmt("data:image/png;base64, %s", default_avatar_base64()); | 126 | avatar = xs_fmt("data:image/png;base64, %s", default_avatar_base64()); |
| 127 | 127 | ||
| 128 | char *actor_id = xs_dict_get(actor, "id"); | 128 | const char *actor_id = xs_dict_get(actor, "id"); |
| 129 | xs *href = NULL; | 129 | xs *href = NULL; |
| 130 | 130 | ||
| 131 | if (user) { | 131 | if (user) { |
| @@ -216,7 +216,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | |||
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | { | 218 | { |
| 219 | char *username, *id; | 219 | const char *username, *id; |
| 220 | 220 | ||
| 221 | if (xs_is_null(username = xs_dict_get(actor, "preferredUsername")) || *username == '\0') { | 221 | if (xs_is_null(username = xs_dict_get(actor, "preferredUsername")) || *username == '\0') { |
| 222 | /* This should never be reached */ | 222 | /* This should never be reached */ |
| @@ -244,15 +244,15 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | |||
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | 246 | ||
| 247 | xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg) | 247 | xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg) |
| 248 | { | 248 | { |
| 249 | xs *actor = NULL; | 249 | xs *actor = NULL; |
| 250 | xs_html *actor_icon = NULL; | 250 | xs_html *actor_icon = NULL; |
| 251 | 251 | ||
| 252 | if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) { | 252 | if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) { |
| 253 | char *date = NULL; | 253 | const char *date = NULL; |
| 254 | char *udate = NULL; | 254 | const char *udate = NULL; |
| 255 | char *url = NULL; | 255 | const char *url = NULL; |
| 256 | int priv = 0; | 256 | int priv = 0; |
| 257 | const char *type = xs_dict_get(msg, "type"); | 257 | const char *type = xs_dict_get(msg, "type"); |
| 258 | 258 | ||
| @@ -271,14 +271,14 @@ xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg) | |||
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | 273 | ||
| 274 | xs_html *html_note(snac *user, char *summary, | 274 | xs_html *html_note(snac *user, const char *summary, |
| 275 | char *div_id, char *form_id, | 275 | const char *div_id, const char *form_id, |
| 276 | char *ta_plh, char *ta_content, | 276 | const char *ta_plh, const char *ta_content, |
| 277 | char *edit_id, char *actor_id, | 277 | const char *edit_id, const char *actor_id, |
| 278 | xs_val *cw_yn, char *cw_text, | 278 | const xs_val *cw_yn, const char *cw_text, |
| 279 | xs_val *mnt_only, char *redir, | 279 | const xs_val *mnt_only, const char *redir, |
| 280 | char *in_reply_to, int poll, | 280 | const char *in_reply_to, int poll, |
| 281 | char *att_file, char *att_alt_text) | 281 | const char *att_file, const char *att_alt_text) |
| 282 | { | 282 | { |
| 283 | xs *action = xs_fmt("%s/admin/note", user->actor); | 283 | xs *action = xs_fmt("%s/admin/note", user->actor); |
| 284 | 284 | ||
| @@ -460,9 +460,11 @@ static xs_html *html_base_head(void) | |||
| 460 | /* add server CSS and favicon */ | 460 | /* add server CSS and favicon */ |
| 461 | xs *f; | 461 | xs *f; |
| 462 | f = xs_fmt("%s/favicon.ico", srv_baseurl); | 462 | f = xs_fmt("%s/favicon.ico", srv_baseurl); |
| 463 | xs_list *p = xs_dict_get(srv_config, "cssurls"); | 463 | const xs_list *p = xs_dict_get(srv_config, "cssurls"); |
| 464 | char *v; | 464 | char *v; |
| 465 | while (xs_list_iter(&p, &v)) { | 465 | int c = 0; |
| 466 | |||
| 467 | while (xs_list_next(p, &v, &c)) { | ||
| 466 | xs_html_add(head, | 468 | xs_html_add(head, |
| 467 | xs_html_sctag("link", | 469 | xs_html_sctag("link", |
| 468 | xs_html_attr("rel", "stylesheet"), | 470 | xs_html_attr("rel", "stylesheet"), |
| @@ -498,8 +500,8 @@ xs_html *html_instance_head(void) | |||
| 498 | } | 500 | } |
| 499 | } | 501 | } |
| 500 | 502 | ||
| 501 | char *host = xs_dict_get(srv_config, "host"); | 503 | const char *host = xs_dict_get(srv_config, "host"); |
| 502 | char *title = xs_dict_get(srv_config, "title"); | 504 | const char *title = xs_dict_get(srv_config, "title"); |
| 503 | 505 | ||
| 504 | xs_html_add(head, | 506 | xs_html_add(head, |
| 505 | xs_html_tag("title", | 507 | xs_html_tag("title", |
| @@ -511,10 +513,10 @@ xs_html *html_instance_head(void) | |||
| 511 | 513 | ||
| 512 | static xs_html *html_instance_body(void) | 514 | static xs_html *html_instance_body(void) |
| 513 | { | 515 | { |
| 514 | char *host = xs_dict_get(srv_config, "host"); | 516 | const char *host = xs_dict_get(srv_config, "host"); |
| 515 | char *sdesc = xs_dict_get(srv_config, "short_description"); | 517 | const char *sdesc = xs_dict_get(srv_config, "short_description"); |
| 516 | char *email = xs_dict_get(srv_config, "admin_email"); | 518 | const char *email = xs_dict_get(srv_config, "admin_email"); |
| 517 | char *acct = xs_dict_get(srv_config, "admin_account"); | 519 | const char *acct = xs_dict_get(srv_config, "admin_account"); |
| 518 | 520 | ||
| 519 | xs *blurb = xs_replace(snac_blurb, "%host%", host); | 521 | xs *blurb = xs_replace(snac_blurb, "%host%", host); |
| 520 | 522 | ||
| @@ -760,7 +762,7 @@ static xs_html *html_user_body(snac *user, int read_only) | |||
| 760 | xs_html_attr("class", "h-card snac-top-user")); | 762 | xs_html_attr("class", "h-card snac-top-user")); |
| 761 | 763 | ||
| 762 | if (read_only) { | 764 | if (read_only) { |
| 763 | char *header = xs_dict_get(user->config, "header"); | 765 | const char *header = xs_dict_get(user->config, "header"); |
| 764 | if (header && *header) { | 766 | if (header && *header) { |
| 765 | xs_html_add(top_user, | 767 | xs_html_add(top_user, |
| 766 | xs_html_tag("div", | 768 | xs_html_tag("div", |
| @@ -797,7 +799,7 @@ static xs_html *html_user_body(snac *user, int read_only) | |||
| 797 | xs_html_add(top_user, | 799 | xs_html_add(top_user, |
| 798 | top_user_bio); | 800 | top_user_bio); |
| 799 | 801 | ||
| 800 | xs_dict *metadata = xs_dict_get(user->config, "metadata"); | 802 | const xs_dict *metadata = xs_dict_get(user->config, "metadata"); |
| 801 | if (xs_type(metadata) == XSTYPE_DICT) { | 803 | if (xs_type(metadata) == XSTYPE_DICT) { |
| 802 | xs_str *k; | 804 | xs_str *k; |
| 803 | xs_str *v; | 805 | xs_str *v; |
| @@ -816,7 +818,7 @@ static xs_html *html_user_body(snac *user, int read_only) | |||
| 816 | if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) { | 818 | if (xs_startswith(v, "https:/") || xs_startswith(v, "http:/")) { |
| 817 | /* is this link validated? */ | 819 | /* is this link validated? */ |
| 818 | xs *verified_link = NULL; | 820 | xs *verified_link = NULL; |
| 819 | xs_number *val_time = xs_dict_get(val_links, v); | 821 | const xs_number *val_time = xs_dict_get(val_links, v); |
| 820 | 822 | ||
| 821 | if (xs_type(val_time) == XSTYPE_NUMBER) { | 823 | if (xs_type(val_time) == XSTYPE_NUMBER) { |
| 822 | time_t t = xs_number_get(val_time); | 824 | time_t t = xs_number_get(val_time); |
| @@ -928,7 +930,7 @@ xs_html *html_top_controls(snac *snac) | |||
| 928 | 930 | ||
| 929 | /** user settings **/ | 931 | /** user settings **/ |
| 930 | 932 | ||
| 931 | char *email = "[disabled by admin]"; | 933 | const char *email = "[disabled by admin]"; |
| 932 | 934 | ||
| 933 | if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) { | 935 | if (xs_type(xs_dict_get(srv_config, "disable_email_notifications")) != XSTYPE_TRUE) { |
| 934 | email = xs_dict_get(snac->config_o, "email"); | 936 | email = xs_dict_get(snac->config_o, "email"); |
| @@ -940,38 +942,38 @@ xs_html *html_top_controls(snac *snac) | |||
| 940 | } | 942 | } |
| 941 | } | 943 | } |
| 942 | 944 | ||
| 943 | char *cw = xs_dict_get(snac->config, "cw"); | 945 | const char *cw = xs_dict_get(snac->config, "cw"); |
| 944 | if (xs_is_null(cw)) | 946 | if (xs_is_null(cw)) |
| 945 | cw = ""; | 947 | cw = ""; |
| 946 | 948 | ||
| 947 | char *telegram_bot = xs_dict_get(snac->config, "telegram_bot"); | 949 | const char *telegram_bot = xs_dict_get(snac->config, "telegram_bot"); |
| 948 | if (xs_is_null(telegram_bot)) | 950 | if (xs_is_null(telegram_bot)) |
| 949 | telegram_bot = ""; | 951 | telegram_bot = ""; |
| 950 | 952 | ||
| 951 | char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id"); | 953 | const char *telegram_chat_id = xs_dict_get(snac->config, "telegram_chat_id"); |
| 952 | if (xs_is_null(telegram_chat_id)) | 954 | if (xs_is_null(telegram_chat_id)) |
| 953 | telegram_chat_id = ""; | 955 | telegram_chat_id = ""; |
| 954 | 956 | ||
| 955 | char *ntfy_server = xs_dict_get(snac->config, "ntfy_server"); | 957 | const char *ntfy_server = xs_dict_get(snac->config, "ntfy_server"); |
| 956 | if (xs_is_null(ntfy_server)) | 958 | if (xs_is_null(ntfy_server)) |
| 957 | ntfy_server = ""; | 959 | ntfy_server = ""; |
| 958 | 960 | ||
| 959 | char *ntfy_token = xs_dict_get(snac->config, "ntfy_token"); | 961 | const char *ntfy_token = xs_dict_get(snac->config, "ntfy_token"); |
| 960 | if (xs_is_null(ntfy_token)) | 962 | if (xs_is_null(ntfy_token)) |
| 961 | ntfy_token = ""; | 963 | ntfy_token = ""; |
| 962 | 964 | ||
| 963 | char *purge_days = xs_dict_get(snac->config, "purge_days"); | 965 | const char *purge_days = xs_dict_get(snac->config, "purge_days"); |
| 964 | if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER) | 966 | if (!xs_is_null(purge_days) && xs_type(purge_days) == XSTYPE_NUMBER) |
| 965 | purge_days = (char *)xs_number_str(purge_days); | 967 | purge_days = (char *)xs_number_str(purge_days); |
| 966 | else | 968 | else |
| 967 | purge_days = "0"; | 969 | purge_days = "0"; |
| 968 | 970 | ||
| 969 | xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown"); | 971 | const xs_val *d_dm_f_u = xs_dict_get(snac->config, "drop_dm_from_unknown"); |
| 970 | xs_val *bot = xs_dict_get(snac->config, "bot"); | 972 | const xs_val *bot = xs_dict_get(snac->config, "bot"); |
| 971 | xs_val *a_private = xs_dict_get(snac->config, "private"); | 973 | const xs_val *a_private = xs_dict_get(snac->config, "private"); |
| 972 | 974 | ||
| 973 | xs *metadata = xs_str_new(NULL); | 975 | xs *metadata = xs_str_new(NULL); |
| 974 | xs_dict *md = xs_dict_get(snac->config, "metadata"); | 976 | const xs_dict *md = xs_dict_get(snac->config, "metadata"); |
| 975 | xs_str *k; | 977 | xs_str *k; |
| 976 | xs_str *v; | 978 | xs_str *v; |
| 977 | 979 | ||
| @@ -1158,13 +1160,14 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg) | |||
| 1158 | /* returns a string with the mentions in msg */ | 1160 | /* returns a string with the mentions in msg */ |
| 1159 | { | 1161 | { |
| 1160 | xs_str *s = xs_str_new(NULL); | 1162 | xs_str *s = xs_str_new(NULL); |
| 1161 | char *list = xs_dict_get(msg, "tag"); | 1163 | const char *list = xs_dict_get(msg, "tag"); |
| 1162 | char *v; | 1164 | char *v; |
| 1165 | int c = 0; | ||
| 1163 | 1166 | ||
| 1164 | while (xs_list_iter(&list, &v)) { | 1167 | while (xs_list_next(list, &v, &c)) { |
| 1165 | char *type = xs_dict_get(v, "type"); | 1168 | const char *type = xs_dict_get(v, "type"); |
| 1166 | char *href = xs_dict_get(v, "href"); | 1169 | const char *href = xs_dict_get(v, "href"); |
| 1167 | char *name = xs_dict_get(v, "name"); | 1170 | const char *name = xs_dict_get(v, "name"); |
| 1168 | 1171 | ||
| 1169 | if (type && strcmp(type, "Mention") == 0 && | 1172 | if (type && strcmp(type, "Mention") == 0 && |
| 1170 | href && strcmp(href, snac->actor) != 0 && name) { | 1173 | href && strcmp(href, snac->actor) != 0 && name) { |
| @@ -1208,10 +1211,11 @@ xs_str *build_mentions(snac *snac, const xs_dict *msg) | |||
| 1208 | } | 1211 | } |
| 1209 | 1212 | ||
| 1210 | 1213 | ||
| 1211 | xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const char *md5) | 1214 | xs_html *html_entry_controls(snac *snac, const char *actor, |
| 1215 | const xs_dict *msg, const char *md5) | ||
| 1212 | { | 1216 | { |
| 1213 | char *id = xs_dict_get(msg, "id"); | 1217 | const char *id = xs_dict_get(msg, "id"); |
| 1214 | char *group = xs_dict_get(msg, "audience"); | 1218 | const char *group = xs_dict_get(msg, "audience"); |
| 1215 | 1219 | ||
| 1216 | xs *likes = object_likes(id); | 1220 | xs *likes = object_likes(id); |
| 1217 | xs *boosts = object_announces(id); | 1221 | xs *boosts = object_announces(id); |
| @@ -1310,7 +1314,7 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const | |||
| 1310 | html_button("delete", L("Delete"), L("Delete this post")), | 1314 | html_button("delete", L("Delete"), L("Delete this post")), |
| 1311 | html_button("hide", L("Hide"), L("Hide this post and its children"))); | 1315 | html_button("hide", L("Hide"), L("Hide this post and its children"))); |
| 1312 | 1316 | ||
| 1313 | char *prev_src = xs_dict_get(msg, "sourceContent"); | 1317 | const char *prev_src = xs_dict_get(msg, "sourceContent"); |
| 1314 | 1318 | ||
| 1315 | if (!xs_is_null(prev_src) && strcmp(actor, snac->actor) == 0) { /** edit **/ | 1319 | if (!xs_is_null(prev_src) && strcmp(actor, snac->actor) == 0) { /** edit **/ |
| 1316 | /* post can be edited */ | 1320 | /* post can be edited */ |
| @@ -1318,13 +1322,13 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const | |||
| 1318 | xs *form_id = xs_fmt("%s_edit_form", md5); | 1322 | xs *form_id = xs_fmt("%s_edit_form", md5); |
| 1319 | xs *redir = xs_fmt("%s_entry", md5); | 1323 | xs *redir = xs_fmt("%s_entry", md5); |
| 1320 | 1324 | ||
| 1321 | char *att_file = ""; | 1325 | const char *att_file = ""; |
| 1322 | char *att_alt_text = ""; | 1326 | const char *att_alt_text = ""; |
| 1323 | xs_list *att_list = xs_dict_get(msg, "attachment"); | 1327 | const xs_list *att_list = xs_dict_get(msg, "attachment"); |
| 1324 | 1328 | ||
| 1325 | /* does it have an attachment? */ | 1329 | /* does it have an attachment? */ |
| 1326 | if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) { | 1330 | if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) { |
| 1327 | xs_dict *d = xs_list_get(att_list, 0); | 1331 | const xs_dict *d = xs_list_get(att_list, 0); |
| 1328 | 1332 | ||
| 1329 | if (xs_type(d) == XSTYPE_DICT) { | 1333 | if (xs_type(d) == XSTYPE_DICT) { |
| 1330 | att_file = xs_dict_get_def(d, "url", ""); | 1334 | att_file = xs_dict_get_def(d, "url", ""); |
| @@ -1370,10 +1374,10 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const | |||
| 1370 | xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | 1374 | xs_html *html_entry(snac *user, xs_dict *msg, int read_only, |
| 1371 | int level, char *md5, int hide_children) | 1375 | int level, char *md5, int hide_children) |
| 1372 | { | 1376 | { |
| 1373 | char *id = xs_dict_get(msg, "id"); | 1377 | const char *id = xs_dict_get(msg, "id"); |
| 1374 | char *type = xs_dict_get(msg, "type"); | 1378 | const char *type = xs_dict_get(msg, "type"); |
| 1375 | char *actor; | 1379 | const char *actor; |
| 1376 | char *v; | 1380 | const char *v; |
| 1377 | int has_title = 0; | 1381 | int has_title = 0; |
| 1378 | 1382 | ||
| 1379 | /* do not show non-public messages in the public timeline */ | 1383 | /* do not show non-public messages in the public timeline */ |
| @@ -1509,7 +1513,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1509 | 1513 | ||
| 1510 | if (xs_list_len(boosts)) { | 1514 | if (xs_list_len(boosts)) { |
| 1511 | /* if somebody boosted this, show as origin */ | 1515 | /* if somebody boosted this, show as origin */ |
| 1512 | char *p = xs_list_get(boosts, -1); | 1516 | const char *p = xs_list_get(boosts, -1); |
| 1513 | xs *actor_r = NULL; | 1517 | xs *actor_r = NULL; |
| 1514 | 1518 | ||
| 1515 | if (user && xs_list_in(boosts, user->md5) != -1) { | 1519 | if (user && xs_list_in(boosts, user->md5) != -1) { |
| @@ -1529,7 +1533,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1529 | 1533 | ||
| 1530 | if (!xs_is_null(name)) { | 1534 | if (!xs_is_null(name)) { |
| 1531 | xs *href = NULL; | 1535 | xs *href = NULL; |
| 1532 | char *id = xs_dict_get(actor_r, "id"); | 1536 | const char *id = xs_dict_get(actor_r, "id"); |
| 1533 | int fwers = 0; | 1537 | int fwers = 0; |
| 1534 | int fwing = 0; | 1538 | int fwing = 0; |
| 1535 | 1539 | ||
| @@ -1558,7 +1562,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1558 | if (strcmp(type, "Note") == 0) { | 1562 | if (strcmp(type, "Note") == 0) { |
| 1559 | if (level == 0) { | 1563 | if (level == 0) { |
| 1560 | /* is the parent not here? */ | 1564 | /* is the parent not here? */ |
| 1561 | char *parent = xs_dict_get(msg, "inReplyTo"); | 1565 | const char *parent = xs_dict_get(msg, "inReplyTo"); |
| 1562 | 1566 | ||
| 1563 | if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { | 1567 | if (user && !xs_is_null(parent) && *parent && !timeline_here(user, parent)) { |
| 1564 | xs_html_add(post_header, | 1568 | xs_html_add(post_header, |
| @@ -1603,7 +1607,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1603 | v = "..."; | 1607 | v = "..."; |
| 1604 | 1608 | ||
| 1605 | /* only show it when not in the public timeline and the config setting is "open" */ | 1609 | /* only show it when not in the public timeline and the config setting is "open" */ |
| 1606 | char *cw = xs_dict_get(user->config, "cw"); | 1610 | const char *cw = xs_dict_get(user->config, "cw"); |
| 1607 | if (xs_is_null(cw) || read_only) | 1611 | if (xs_is_null(cw) || read_only) |
| 1608 | cw = ""; | 1612 | cw = ""; |
| 1609 | 1613 | ||
| @@ -1632,7 +1636,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1632 | 1636 | ||
| 1633 | { | 1637 | { |
| 1634 | /** build the content string **/ | 1638 | /** build the content string **/ |
| 1635 | char *content = xs_dict_get(msg, "content"); | 1639 | const char *content = xs_dict_get(msg, "content"); |
| 1636 | 1640 | ||
| 1637 | xs *c = sanitize(xs_is_null(content) ? "" : content); | 1641 | xs *c = sanitize(xs_is_null(content) ? "" : content); |
| 1638 | 1642 | ||
| @@ -1650,7 +1654,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1650 | c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2); | 1654 | c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2); |
| 1651 | 1655 | ||
| 1652 | /* Peertube videos content is in markdown */ | 1656 | /* Peertube videos content is in markdown */ |
| 1653 | char *mtype = xs_dict_get(msg, "mediaType"); | 1657 | const char *mtype = xs_dict_get(msg, "mediaType"); |
| 1654 | if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "text/markdown") == 0) { | 1658 | if (xs_type(mtype) == XSTYPE_STRING && strcmp(mtype, "text/markdown") == 0) { |
| 1655 | /* a full conversion could be better */ | 1659 | /* a full conversion could be better */ |
| 1656 | c = xs_replace_i(c, "\r", ""); | 1660 | c = xs_replace_i(c, "\r", ""); |
| @@ -1663,12 +1667,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1663 | } | 1667 | } |
| 1664 | 1668 | ||
| 1665 | if (strcmp(type, "Question") == 0) { /** question content **/ | 1669 | if (strcmp(type, "Question") == 0) { /** question content **/ |
| 1666 | xs_list *oo = xs_dict_get(msg, "oneOf"); | 1670 | const xs_list *oo = xs_dict_get(msg, "oneOf"); |
| 1667 | xs_list *ao = xs_dict_get(msg, "anyOf"); | 1671 | const xs_list *ao = xs_dict_get(msg, "anyOf"); |
| 1668 | xs_list *p; | 1672 | const xs_list *p; |
| 1669 | xs_dict *v; | 1673 | xs_dict *v; |
| 1670 | int closed = 0; | 1674 | int closed = 0; |
| 1671 | char *f_closed = NULL; | 1675 | const char *f_closed = NULL; |
| 1672 | 1676 | ||
| 1673 | xs_html *poll = xs_html_tag("div", NULL); | 1677 | xs_html *poll = xs_html_tag("div", NULL); |
| 1674 | 1678 | ||
| @@ -1697,10 +1701,11 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1697 | /* closed poll */ | 1701 | /* closed poll */ |
| 1698 | xs_html *poll_result = xs_html_tag("table", | 1702 | xs_html *poll_result = xs_html_tag("table", |
| 1699 | xs_html_attr("class", "snac-poll-result")); | 1703 | xs_html_attr("class", "snac-poll-result")); |
| 1704 | int c = 0; | ||
| 1700 | 1705 | ||
| 1701 | while (xs_list_iter(&p, &v)) { | 1706 | while (xs_list_next(p, &v, &c)) { |
| 1702 | char *name = xs_dict_get(v, "name"); | 1707 | const char *name = xs_dict_get(v, "name"); |
| 1703 | xs_dict *replies = xs_dict_get(v, "replies"); | 1708 | const xs_dict *replies = xs_dict_get(v, "replies"); |
| 1704 | 1709 | ||
| 1705 | if (name && replies) { | 1710 | if (name && replies) { |
| 1706 | char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems")); | 1711 | char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems")); |
| @@ -1737,9 +1742,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1737 | xs_html_attr("name", "irt"), | 1742 | xs_html_attr("name", "irt"), |
| 1738 | xs_html_attr("value", id)))); | 1743 | xs_html_attr("value", id)))); |
| 1739 | 1744 | ||
| 1740 | while (xs_list_iter(&p, &v)) { | 1745 | int c = 0; |
| 1741 | char *name = xs_dict_get(v, "name"); | 1746 | while (xs_list_next(p, &v, &c)) { |
| 1742 | xs_dict *replies = xs_dict_get(v, "replies"); | 1747 | const char *name = xs_dict_get(v, "name"); |
| 1748 | const xs_dict *replies = xs_dict_get(v, "replies"); | ||
| 1743 | 1749 | ||
| 1744 | if (name) { | 1750 | if (name) { |
| 1745 | char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems")); | 1751 | char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems")); |
| @@ -1777,7 +1783,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1777 | } | 1783 | } |
| 1778 | else { | 1784 | else { |
| 1779 | /* show when the poll closes */ | 1785 | /* show when the poll closes */ |
| 1780 | char *end_time = xs_dict_get(msg, "endTime"); | 1786 | const char *end_time = xs_dict_get(msg, "endTime"); |
| 1781 | 1787 | ||
| 1782 | /* Pleroma does not have an endTime field; | 1788 | /* Pleroma does not have an endTime field; |
| 1783 | it has a closed time in the future */ | 1789 | it has a closed time in the future */ |
| @@ -1820,12 +1826,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1820 | xs_html_add(snac_content, | 1826 | xs_html_add(snac_content, |
| 1821 | content_attachments); | 1827 | content_attachments); |
| 1822 | 1828 | ||
| 1823 | xs_list *p = attach; | 1829 | int c = 0; |
| 1824 | 1830 | xs_dict *a; | |
| 1825 | while (xs_list_iter(&p, &v)) { | 1831 | while (xs_list_next(attach, &a, &c)) { |
| 1826 | char *type = xs_dict_get(v, "type"); | 1832 | const char *type = xs_dict_get(a, "type"); |
| 1827 | char *href = xs_dict_get(v, "href"); | 1833 | const char *href = xs_dict_get(a, "href"); |
| 1828 | char *name = xs_dict_get(v, "name"); | 1834 | const char *name = xs_dict_get(a, "name"); |
| 1829 | 1835 | ||
| 1830 | if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) { | 1836 | if (xs_startswith(type, "image/") || strcmp(type, "Image") == 0) { |
| 1831 | xs_html_add(content_attachments, | 1837 | xs_html_add(content_attachments, |
| @@ -1889,7 +1895,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 1889 | } | 1895 | } |
| 1890 | 1896 | ||
| 1891 | /* has this message an audience (i.e., comes from a channel or community)? */ | 1897 | /* has this message an audience (i.e., comes from a channel or community)? */ |
| 1892 | char *audience = xs_dict_get(msg, "audience"); | 1898 | const char *audience = xs_dict_get(msg, "audience"); |
| 1893 | if (strcmp(type, "Page") == 0 && !xs_is_null(audience)) { | 1899 | if (strcmp(type, "Page") == 0 && !xs_is_null(audience)) { |
| 1894 | xs_html *au_tag = xs_html_tag("p", | 1900 | xs_html *au_tag = xs_html_tag("p", |
| 1895 | xs_html_text("("), | 1901 | xs_html_text("("), |
| @@ -2023,11 +2029,12 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 2023 | 2029 | ||
| 2024 | if (xs_list_len(list) == 1) { | 2030 | if (xs_list_len(list) == 1) { |
| 2025 | /* only one element? pick the description from the source */ | 2031 | /* only one element? pick the description from the source */ |
| 2026 | char *id = xs_list_get(list, 0); | 2032 | const char *id = xs_list_get(list, 0); |
| 2027 | xs *d = NULL; | 2033 | xs *d = NULL; |
| 2028 | object_get_by_md5(id, &d); | 2034 | object_get_by_md5(id, &d); |
| 2029 | if (d && (v = xs_dict_get(d, "sourceContent")) != NULL) | 2035 | const char *sc = xs_dict_get(d, "sourceContent"); |
| 2030 | desc = xs_dup(v); | 2036 | if (d && sc != NULL) |
| 2037 | desc = xs_dup(sc); | ||
| 2031 | 2038 | ||
| 2032 | alternate = xs_dup(xs_dict_get(d, "id")); | 2039 | alternate = xs_dup(xs_dict_get(d, "id")); |
| 2033 | } | 2040 | } |
| @@ -2087,13 +2094,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 2087 | 2094 | ||
| 2088 | /* is this message a non-public reply? */ | 2095 | /* is this message a non-public reply? */ |
| 2089 | if (user != NULL && !is_msg_public(msg)) { | 2096 | if (user != NULL && !is_msg_public(msg)) { |
| 2090 | char *irt = xs_dict_get(msg, "inReplyTo"); | 2097 | const char *irt = xs_dict_get(msg, "inReplyTo"); |
| 2091 | 2098 | ||
| 2092 | /* is it a reply to something not in the storage? */ | 2099 | /* is it a reply to something not in the storage? */ |
| 2093 | if (!xs_is_null(irt) && !object_here(irt)) { | 2100 | if (!xs_is_null(irt) && !object_here(irt)) { |
| 2094 | /* is it for me? */ | 2101 | /* is it for me? */ |
| 2095 | xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST)); | 2102 | const xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST)); |
| 2096 | xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST)); | 2103 | const xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST)); |
| 2097 | 2104 | ||
| 2098 | if (xs_list_in(to, user->actor) == -1 && xs_list_in(cc, user->actor) == -1) { | 2105 | if (xs_list_in(to, user->actor) == -1 && xs_list_in(cc, user->actor) == -1) { |
| 2099 | snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v)); | 2106 | snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v)); |
| @@ -2212,7 +2219,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t) | |||
| 2212 | html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1))); | 2219 | html_actor_icon(snac, actor, xs_dict_get(actor, "published"), NULL, NULL, 0, 1))); |
| 2213 | 2220 | ||
| 2214 | /* content (user bio) */ | 2221 | /* content (user bio) */ |
| 2215 | char *c = xs_dict_get(actor, "summary"); | 2222 | const char *c = xs_dict_get(actor, "summary"); |
| 2216 | 2223 | ||
| 2217 | if (!xs_is_null(c)) { | 2224 | if (!xs_is_null(c)) { |
| 2218 | xs *sc = sanitize(c); | 2225 | xs *sc = sanitize(c); |
| @@ -2364,10 +2371,10 @@ xs_str *html_notifications(snac *user, int skip, int show) | |||
| 2364 | continue; | 2371 | continue; |
| 2365 | 2372 | ||
| 2366 | xs *obj = NULL; | 2373 | xs *obj = NULL; |
| 2367 | char *type = xs_dict_get(noti, "type"); | 2374 | const char *type = xs_dict_get(noti, "type"); |
| 2368 | char *utype = xs_dict_get(noti, "utype"); | 2375 | const char *utype = xs_dict_get(noti, "utype"); |
| 2369 | char *id = xs_dict_get(noti, "objid"); | 2376 | const char *id = xs_dict_get(noti, "objid"); |
| 2370 | char *date = xs_dict_get(noti, "date"); | 2377 | const char *date = xs_dict_get(noti, "date"); |
| 2371 | 2378 | ||
| 2372 | if (xs_is_null(id) || !valid_status(object_get(id, &obj))) | 2379 | if (xs_is_null(id) || !valid_status(object_get(id, &obj))) |
| 2373 | continue; | 2380 | continue; |
| @@ -2375,14 +2382,14 @@ xs_str *html_notifications(snac *user, int skip, int show) | |||
| 2375 | if (is_hidden(user, id)) | 2382 | if (is_hidden(user, id)) |
| 2376 | continue; | 2383 | continue; |
| 2377 | 2384 | ||
| 2378 | char *actor_id = xs_dict_get(noti, "actor"); | 2385 | const char *actor_id = xs_dict_get(noti, "actor"); |
| 2379 | xs *actor = NULL; | 2386 | xs *actor = NULL; |
| 2380 | 2387 | ||
| 2381 | if (!valid_status(actor_get(actor_id, &actor))) | 2388 | if (!valid_status(actor_get(actor_id, &actor))) |
| 2382 | continue; | 2389 | continue; |
| 2383 | 2390 | ||
| 2384 | xs *a_name = actor_name(actor); | 2391 | xs *a_name = actor_name(actor); |
| 2385 | char *label = type; | 2392 | const char *label = type; |
| 2386 | 2393 | ||
| 2387 | if (strcmp(type, "Create") == 0) | 2394 | if (strcmp(type, "Create") == 0) |
| 2388 | label = L("Mention"); | 2395 | label = L("Mention"); |
| @@ -2494,14 +2501,14 @@ xs_str *html_notifications(snac *user, int skip, int show) | |||
| 2494 | int html_get_handler(const xs_dict *req, const char *q_path, | 2501 | int html_get_handler(const xs_dict *req, const char *q_path, |
| 2495 | char **body, int *b_size, char **ctype, xs_str **etag) | 2502 | char **body, int *b_size, char **ctype, xs_str **etag) |
| 2496 | { | 2503 | { |
| 2497 | char *accept = xs_dict_get(req, "accept"); | 2504 | const char *accept = xs_dict_get(req, "accept"); |
| 2498 | int status = 404; | 2505 | int status = 404; |
| 2499 | snac snac; | 2506 | snac snac; |
| 2500 | xs *uid = NULL; | 2507 | xs *uid = NULL; |
| 2501 | char *p_path; | 2508 | const char *p_path; |
| 2502 | int cache = 1; | 2509 | int cache = 1; |
| 2503 | int save = 1; | 2510 | int save = 1; |
| 2504 | char *v; | 2511 | const char *v; |
| 2505 | 2512 | ||
| 2506 | xs *l = xs_split_n(q_path, "/", 2); | 2513 | xs *l = xs_split_n(q_path, "/", 2); |
| 2507 | v = xs_list_get(l, 1); | 2514 | v = xs_list_get(l, 1); |
| @@ -2540,7 +2547,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2540 | 2547 | ||
| 2541 | int skip = 0; | 2548 | int skip = 0; |
| 2542 | int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); | 2549 | int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); |
| 2543 | xs_dict *q_vars = xs_dict_get(req, "q_vars"); | 2550 | const xs_dict *q_vars = xs_dict_get(req, "q_vars"); |
| 2544 | if ((v = xs_dict_get(q_vars, "skip")) != NULL) | 2551 | if ((v = xs_dict_get(q_vars, "skip")) != NULL) |
| 2545 | skip = atoi(v), cache = 0, save = 0; | 2552 | skip = atoi(v), cache = 0, save = 0; |
| 2546 | if ((v = xs_dict_get(q_vars, "show")) != NULL) | 2553 | if ((v = xs_dict_get(q_vars, "show")) != NULL) |
| @@ -2585,7 +2592,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2585 | status = 401; | 2592 | status = 401; |
| 2586 | } | 2593 | } |
| 2587 | else { | 2594 | else { |
| 2588 | char *q = xs_dict_get(q_vars, "q"); | 2595 | const char *q = xs_dict_get(q_vars, "q"); |
| 2589 | 2596 | ||
| 2590 | if (q && *q) { | 2597 | if (q && *q) { |
| 2591 | if (*q == '#') { | 2598 | if (*q == '#') { |
| @@ -2669,7 +2676,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2669 | } | 2676 | } |
| 2670 | else { | 2677 | else { |
| 2671 | xs *l = xs_split(p_path, "/"); | 2678 | xs *l = xs_split(p_path, "/"); |
| 2672 | char *md5 = xs_list_get(l, -1); | 2679 | const char *md5 = xs_list_get(l, -1); |
| 2673 | 2680 | ||
| 2674 | if (md5 && *md5 && timeline_here(&snac, md5)) { | 2681 | if (md5 && *md5 && timeline_here(&snac, md5)) { |
| 2675 | xs *list = xs_list_append(xs_list_new(), md5); | 2682 | xs *list = xs_list_append(xs_list_new(), md5); |
| @@ -2728,7 +2735,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2728 | } | 2735 | } |
| 2729 | else { | 2736 | else { |
| 2730 | xs *l = xs_split(p_path, "/"); | 2737 | xs *l = xs_split(p_path, "/"); |
| 2731 | char *lid = xs_list_get(l, -1); | 2738 | const char *lid = xs_list_get(l, -1); |
| 2732 | 2739 | ||
| 2733 | xs *list = list_timeline(&snac, lid, skip, show); | 2740 | xs *list = list_timeline(&snac, lid, skip, show); |
| 2734 | xs *next = list_timeline(&snac, lid, skip + show, 1); | 2741 | xs *next = list_timeline(&snac, lid, skip + show, 1); |
| @@ -2767,7 +2774,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2767 | else | 2774 | else |
| 2768 | if (xs_startswith(p_path, "s/")) { /** a static file **/ | 2775 | if (xs_startswith(p_path, "s/")) { /** a static file **/ |
| 2769 | xs *l = xs_split(p_path, "/"); | 2776 | xs *l = xs_split(p_path, "/"); |
| 2770 | char *id = xs_list_get(l, 1); | 2777 | const char *id = xs_list_get(l, 1); |
| 2771 | int sz; | 2778 | int sz; |
| 2772 | 2779 | ||
| 2773 | if (id && *id) { | 2780 | if (id && *id) { |
| @@ -2788,8 +2795,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, | |||
| 2788 | if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE) | 2795 | if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE) |
| 2789 | return 403; | 2796 | return 403; |
| 2790 | 2797 | ||
| 2791 | xs *l = xs_split(p_path, "/"); | 2798 | xs *l = xs_split(p_path, "/"); |
| 2792 | char *id = xs_list_get(l, 1); | 2799 | const char *id = xs_list_get(l, 1); |
| 2793 | 2800 | ||
| 2794 | if (id && *id) { | 2801 | if (id && *id) { |
| 2795 | if (xs_endswith(id, "timeline.html_")) { | 2802 | if (xs_endswith(id, "timeline.html_")) { |
| @@ -2845,8 +2852,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2845 | 2852 | ||
| 2846 | int status = 0; | 2853 | int status = 0; |
| 2847 | snac snac; | 2854 | snac snac; |
| 2848 | char *uid, *p_path; | 2855 | const char *uid; |
| 2849 | xs_dict *p_vars; | 2856 | const char *p_path; |
| 2857 | const xs_dict *p_vars; | ||
| 2850 | 2858 | ||
| 2851 | xs *l = xs_split_n(q_path, "/", 2); | 2859 | xs *l = xs_split_n(q_path, "/", 2); |
| 2852 | 2860 | ||
| @@ -2874,15 +2882,15 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2874 | 2882 | ||
| 2875 | if (p_path && strcmp(p_path, "admin/note") == 0) { /** **/ | 2883 | if (p_path && strcmp(p_path, "admin/note") == 0) { /** **/ |
| 2876 | /* post note */ | 2884 | /* post note */ |
| 2877 | xs_str *content = xs_dict_get(p_vars, "content"); | 2885 | const xs_str *content = xs_dict_get(p_vars, "content"); |
| 2878 | xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); | 2886 | const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); |
| 2879 | xs_str *attach_url = xs_dict_get(p_vars, "attach_url"); | 2887 | const xs_str *attach_url = xs_dict_get(p_vars, "attach_url"); |
| 2880 | xs_list *attach_file = xs_dict_get(p_vars, "attach"); | 2888 | const xs_list *attach_file = xs_dict_get(p_vars, "attach"); |
| 2881 | xs_str *to = xs_dict_get(p_vars, "to"); | 2889 | const xs_str *to = xs_dict_get(p_vars, "to"); |
| 2882 | xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); | 2890 | const xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); |
| 2883 | xs_str *summary = xs_dict_get(p_vars, "summary"); | 2891 | const xs_str *summary = xs_dict_get(p_vars, "summary"); |
| 2884 | xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); | 2892 | const xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); |
| 2885 | xs_str *alt_text = xs_dict_get(p_vars, "alt_text"); | 2893 | const xs_str *alt_text = xs_dict_get(p_vars, "alt_text"); |
| 2886 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); | 2894 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); |
| 2887 | xs *attach_list = xs_list_new(); | 2895 | xs *attach_list = xs_list_new(); |
| 2888 | 2896 | ||
| @@ -2902,7 +2910,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2902 | 2910 | ||
| 2903 | /* is attach_file set? */ | 2911 | /* is attach_file set? */ |
| 2904 | if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) { | 2912 | if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) { |
| 2905 | char *fn = xs_list_get(attach_file, 0); | 2913 | const char *fn = xs_list_get(attach_file, 0); |
| 2906 | 2914 | ||
| 2907 | if (*fn != '\0') { | 2915 | if (*fn != '\0') { |
| 2908 | char *ext = strrchr(fn, '.'); | 2916 | char *ext = strrchr(fn, '.'); |
| @@ -2978,7 +2986,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 2978 | int n; | 2986 | int n; |
| 2979 | 2987 | ||
| 2980 | for (n = 0; fields[n]; n++) { | 2988 | for (n = 0; fields[n]; n++) { |
| 2981 | char *v = xs_dict_get(p_msg, fields[n]); | 2989 | const char *v = xs_dict_get(p_msg, fields[n]); |
| 2982 | msg = xs_dict_set(msg, fields[n], v); | 2990 | msg = xs_dict_set(msg, fields[n], v); |
| 2983 | } | 2991 | } |
| 2984 | 2992 | ||
| @@ -3007,10 +3015,10 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3007 | else | 3015 | else |
| 3008 | if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/ | 3016 | if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/ |
| 3009 | /* action on an entry */ | 3017 | /* action on an entry */ |
| 3010 | char *id = xs_dict_get(p_vars, "id"); | 3018 | const char *id = xs_dict_get(p_vars, "id"); |
| 3011 | char *actor = xs_dict_get(p_vars, "actor"); | 3019 | const char *actor = xs_dict_get(p_vars, "actor"); |
| 3012 | char *action = xs_dict_get(p_vars, "action"); | 3020 | const char *action = xs_dict_get(p_vars, "action"); |
| 3013 | char *group = xs_dict_get(p_vars, "group"); | 3021 | const char *group = xs_dict_get(p_vars, "group"); |
| 3014 | 3022 | ||
| 3015 | if (action == NULL) | 3023 | if (action == NULL) |
| 3016 | return 404; | 3024 | return 404; |
| @@ -3134,7 +3142,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3134 | } | 3142 | } |
| 3135 | else | 3143 | else |
| 3136 | if (strcmp(action, L("Delete")) == 0) { /** **/ | 3144 | if (strcmp(action, L("Delete")) == 0) { /** **/ |
| 3137 | char *actor_form = xs_dict_get(p_vars, "actor-form"); | 3145 | const char *actor_form = xs_dict_get(p_vars, "actor-form"); |
| 3138 | if (actor_form != NULL) { | 3146 | if (actor_form != NULL) { |
| 3139 | /* delete follower */ | 3147 | /* delete follower */ |
| 3140 | if (valid_status(follower_del(&snac, actor))) | 3148 | if (valid_status(follower_del(&snac, actor))) |
| @@ -3178,8 +3186,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3178 | else | 3186 | else |
| 3179 | if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/ | 3187 | if (p_path && strcmp(p_path, "admin/user-setup") == 0) { /** **/ |
| 3180 | /* change of user data */ | 3188 | /* change of user data */ |
| 3181 | char *v; | 3189 | const char *v; |
| 3182 | char *p1, *p2; | 3190 | const char *p1, *p2; |
| 3183 | 3191 | ||
| 3184 | if ((v = xs_dict_get(p_vars, "name")) != NULL) | 3192 | if ((v = xs_dict_get(p_vars, "name")) != NULL) |
| 3185 | snac.config = xs_dict_set(snac.config, "name", v); | 3193 | snac.config = xs_dict_set(snac.config, "name", v); |
| @@ -3245,7 +3253,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3245 | for (n = 0; uploads[n]; n++) { | 3253 | for (n = 0; uploads[n]; n++) { |
| 3246 | xs *var_name = xs_fmt("%s_file", uploads[n]); | 3254 | xs *var_name = xs_fmt("%s_file", uploads[n]); |
| 3247 | 3255 | ||
| 3248 | xs_list *uploaded_file = xs_dict_get(p_vars, var_name); | 3256 | const xs_list *uploaded_file = xs_dict_get(p_vars, var_name); |
| 3249 | if (xs_type(uploaded_file) == XSTYPE_LIST) { | 3257 | if (xs_type(uploaded_file) == XSTYPE_LIST) { |
| 3250 | const char *fn = xs_list_get(uploaded_file, 0); | 3258 | const char *fn = xs_list_get(uploaded_file, 0); |
| 3251 | 3259 | ||
| @@ -3310,7 +3318,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3310 | } | 3318 | } |
| 3311 | else | 3319 | else |
| 3312 | if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/ | 3320 | if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/ |
| 3313 | char *irt = xs_dict_get(p_vars, "irt"); | 3321 | const char *irt = xs_dict_get(p_vars, "irt"); |
| 3314 | const char *opt = xs_dict_get(p_vars, "question"); | 3322 | const char *opt = xs_dict_get(p_vars, "question"); |
| 3315 | const char *actor = xs_dict_get(p_vars, "actor"); | 3323 | const char *actor = xs_dict_get(p_vars, "actor"); |
| 3316 | 3324 | ||
| @@ -3345,7 +3353,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3345 | xs *poll = NULL; | 3353 | xs *poll = NULL; |
| 3346 | 3354 | ||
| 3347 | if (valid_status(object_get(irt, &poll))) { | 3355 | if (valid_status(object_get(irt, &poll))) { |
| 3348 | char *date = xs_dict_get(poll, "endTime"); | 3356 | const char *date = xs_dict_get(poll, "endTime"); |
| 3349 | if (xs_is_null(date)) | 3357 | if (xs_is_null(date)) |
| 3350 | date = xs_dict_get(poll, "closed"); | 3358 | date = xs_dict_get(poll, "closed"); |
| 3351 | 3359 | ||
| @@ -3363,7 +3371,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 3363 | } | 3371 | } |
| 3364 | 3372 | ||
| 3365 | if (status == 303) { | 3373 | if (status == 303) { |
| 3366 | char *redir = xs_dict_get(p_vars, "redir"); | 3374 | const char *redir = xs_dict_get(p_vars, "redir"); |
| 3367 | 3375 | ||
| 3368 | if (xs_is_null(redir)) | 3376 | if (xs_is_null(redir)) |
| 3369 | redir = "top"; | 3377 | redir = "top"; |
| @@ -3411,8 +3419,8 @@ xs_str *timeline_to_rss(snac *user, const xs_list *timeline, char *title, char * | |||
| 3411 | continue; | 3419 | continue; |
| 3412 | } | 3420 | } |
| 3413 | 3421 | ||
| 3414 | char *id = xs_dict_get(msg, "id"); | 3422 | const char *id = xs_dict_get(msg, "id"); |
| 3415 | char *content = xs_dict_get(msg, "content"); | 3423 | const char *content = xs_dict_get(msg, "content"); |
| 3416 | 3424 | ||
| 3417 | if (user && !xs_startswith(id, user->actor)) | 3425 | if (user && !xs_startswith(id, user->actor)) |
| 3418 | continue; | 3426 | continue; |
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, | 13 | xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, |
| 14 | const char *method, const char *url, | 14 | const char *method, const char *url, |
| 15 | xs_dict *headers, | 15 | const xs_dict *headers, |
| 16 | const char *body, int b_size, | 16 | const char *body, int b_size, |
| 17 | int *status, xs_str **payload, int *p_size, | 17 | int *status, xs_str **payload, int *p_size, |
| 18 | int timeout) | 18 | int timeout) |
| @@ -24,8 +24,8 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, | |||
| 24 | xs *s64 = NULL; | 24 | xs *s64 = NULL; |
| 25 | xs *signature = NULL; | 25 | xs *signature = NULL; |
| 26 | xs *hdrs = NULL; | 26 | xs *hdrs = NULL; |
| 27 | char *host; | 27 | const char *host; |
| 28 | char *target; | 28 | const char *target; |
| 29 | char *k, *v; | 29 | char *k, *v; |
| 30 | xs_dict *response; | 30 | xs_dict *response; |
| 31 | 31 | ||
| @@ -106,13 +106,13 @@ xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, | |||
| 106 | 106 | ||
| 107 | 107 | ||
| 108 | xs_dict *http_signed_request(snac *snac, const char *method, const char *url, | 108 | xs_dict *http_signed_request(snac *snac, const char *method, const char *url, |
| 109 | xs_dict *headers, | 109 | const xs_dict *headers, |
| 110 | const char *body, int b_size, | 110 | const char *body, int b_size, |
| 111 | int *status, xs_str **payload, int *p_size, | 111 | int *status, xs_str **payload, int *p_size, |
| 112 | int timeout) | 112 | int timeout) |
| 113 | /* does a signed HTTP request */ | 113 | /* does a signed HTTP request */ |
| 114 | { | 114 | { |
| 115 | char *seckey = xs_dict_get(snac->key, "secret"); | 115 | const char *seckey = xs_dict_get(snac->key, "secret"); |
| 116 | xs_dict *response; | 116 | xs_dict *response; |
| 117 | 117 | ||
| 118 | response = http_signed_request_raw(snac->actor, seckey, method, url, | 118 | response = http_signed_request_raw(snac->actor, seckey, method, url, |
| @@ -122,17 +122,18 @@ xs_dict *http_signed_request(snac *snac, const char *method, const char *url, | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | 124 | ||
| 125 | int check_signature(xs_dict *req, xs_str **err) | 125 | int check_signature(const xs_dict *req, xs_str **err) |
| 126 | /* check the signature */ | 126 | /* check the signature */ |
| 127 | { | 127 | { |
| 128 | char *sig_hdr = xs_dict_get(req, "signature"); | 128 | const char *sig_hdr = xs_dict_get(req, "signature"); |
| 129 | xs *keyId = NULL; | 129 | xs *keyId = NULL; |
| 130 | xs *headers = NULL; | 130 | xs *headers = NULL; |
| 131 | xs *signature = NULL; | 131 | xs *signature = NULL; |
| 132 | xs *created = NULL; | 132 | xs *created = NULL; |
| 133 | xs *expires = NULL; | 133 | xs *expires = NULL; |
| 134 | char *pubkey; | ||
| 135 | char *p; | 134 | char *p; |
| 135 | const char *pubkey; | ||
| 136 | const char *k; | ||
| 136 | 137 | ||
| 137 | if (xs_is_null(sig_hdr)) { | 138 | if (xs_is_null(sig_hdr)) { |
| 138 | *err = xs_fmt("missing 'signature' header"); | 139 | *err = xs_fmt("missing 'signature' header"); |
| @@ -142,10 +143,10 @@ int check_signature(xs_dict *req, xs_str **err) | |||
| 142 | { | 143 | { |
| 143 | /* extract the values */ | 144 | /* extract the values */ |
| 144 | xs *l = xs_split(sig_hdr, ","); | 145 | xs *l = xs_split(sig_hdr, ","); |
| 145 | xs_list *p = l; | 146 | int c = 0; |
| 146 | xs_val *v; | 147 | xs_val *v; |
| 147 | 148 | ||
| 148 | while (xs_list_iter(&p, &v)) { | 149 | while (xs_list_next(l, &v, &c)) { |
| 149 | xs *kv = xs_split_n(v, "=", 1); | 150 | xs *kv = xs_split_n(v, "=", 1); |
| 150 | 151 | ||
| 151 | if (xs_list_len(kv) != 2) | 152 | if (xs_list_len(kv) != 2) |
| @@ -192,8 +193,8 @@ int check_signature(xs_dict *req, xs_str **err) | |||
| 192 | return 0; | 193 | return 0; |
| 193 | } | 194 | } |
| 194 | 195 | ||
| 195 | if ((p = xs_dict_get(actor, "publicKey")) == NULL || | 196 | if ((k = xs_dict_get(actor, "publicKey")) == NULL || |
| 196 | ((pubkey = xs_dict_get(p, "publicKeyPem")) == NULL)) { | 197 | ((pubkey = xs_dict_get(k, "publicKeyPem")) == NULL)) { |
| 197 | *err = xs_fmt("cannot get pubkey from %s", keyId); | 198 | *err = xs_fmt("cannot get pubkey from %s", keyId); |
| 198 | return 0; | 199 | return 0; |
| 199 | } | 200 | } |
| @@ -208,7 +209,7 @@ int check_signature(xs_dict *req, xs_str **err) | |||
| 208 | 209 | ||
| 209 | p = l; | 210 | p = l; |
| 210 | while (xs_list_iter(&p, &v)) { | 211 | while (xs_list_iter(&p, &v)) { |
| 211 | char *hc; | 212 | const char *hc; |
| 212 | xs *ss = NULL; | 213 | xs *ss = NULL; |
| 213 | 214 | ||
| 214 | if (*sig_str != '\0') | 215 | if (*sig_str != '\0') |
| @@ -125,7 +125,7 @@ static xs_str *greeting_html(void) | |||
| 125 | 125 | ||
| 126 | /* does it have a %userlist% mark? */ | 126 | /* does it have a %userlist% mark? */ |
| 127 | if (xs_str_in(s, "%userlist%") != -1) { | 127 | if (xs_str_in(s, "%userlist%") != -1) { |
| 128 | char *host = xs_dict_get(srv_config, "host"); | 128 | const char *host = xs_dict_get(srv_config, "host"); |
| 129 | xs *list = user_list(); | 129 | xs *list = user_list(); |
| 130 | xs_list *p = list; | 130 | xs_list *p = list; |
| 131 | xs_str *uid; | 131 | xs_str *uid; |
| @@ -171,14 +171,14 @@ int server_get_handler(xs_dict *req, const char *q_path, | |||
| 171 | 171 | ||
| 172 | /* is it the server root? */ | 172 | /* is it the server root? */ |
| 173 | if (*q_path == '\0') { | 173 | if (*q_path == '\0') { |
| 174 | xs_dict *q_vars = xs_dict_get(req, "q_vars"); | 174 | const xs_dict *q_vars = xs_dict_get(req, "q_vars"); |
| 175 | char *t = NULL; | 175 | const char *t = NULL; |
| 176 | 176 | ||
| 177 | if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) { | 177 | if (xs_type(q_vars) == XSTYPE_DICT && (t = xs_dict_get(q_vars, "t"))) { |
| 178 | /** search by tag **/ | 178 | /** search by tag **/ |
| 179 | int skip = 0; | 179 | int skip = 0; |
| 180 | int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); | 180 | int show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); |
| 181 | char *v; | 181 | const char *v; |
| 182 | 182 | ||
| 183 | if ((v = xs_dict_get(q_vars, "skip")) != NULL) | 183 | if ((v = xs_dict_get(q_vars, "skip")) != NULL) |
| 184 | skip = atoi(v); | 184 | skip = atoi(v); |
| @@ -193,7 +193,7 @@ int server_get_handler(xs_dict *req, const char *q_path, | |||
| 193 | more = 1; | 193 | more = 1; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | char *accept = xs_dict_get(req, "accept"); | 196 | const char *accept = xs_dict_get(req, "accept"); |
| 197 | if (!xs_is_null(accept) && strcmp(accept, "application/rss+xml") == 0) { | 197 | if (!xs_is_null(accept) && strcmp(accept, "application/rss+xml") == 0) { |
| 198 | xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t); | 198 | xs *link = xs_fmt("%s/?t=%s", srv_baseurl, t); |
| 199 | 199 | ||
| @@ -268,7 +268,7 @@ void httpd_connection(FILE *f) | |||
| 268 | /* the connection processor */ | 268 | /* the connection processor */ |
| 269 | { | 269 | { |
| 270 | xs *req; | 270 | xs *req; |
| 271 | char *method; | 271 | const char *method; |
| 272 | int status = 0; | 272 | int status = 0; |
| 273 | xs_str *body = NULL; | 273 | xs_str *body = NULL; |
| 274 | int b_size = 0; | 274 | int b_size = 0; |
| @@ -278,7 +278,7 @@ void httpd_connection(FILE *f) | |||
| 278 | xs *payload = NULL; | 278 | xs *payload = NULL; |
| 279 | xs *etag = NULL; | 279 | xs *etag = NULL; |
| 280 | int p_size = 0; | 280 | int p_size = 0; |
| 281 | char *p; | 281 | const char *p; |
| 282 | int fcgi_id; | 282 | int fcgi_id; |
| 283 | 283 | ||
| 284 | if (p_state->use_fcgi) | 284 | if (p_state->use_fcgi) |
| @@ -411,7 +411,7 @@ void httpd_connection(FILE *f) | |||
| 411 | headers = xs_dict_append(headers, "etag", etag); | 411 | headers = xs_dict_append(headers, "etag", etag); |
| 412 | 412 | ||
| 413 | /* if there are any additional headers, add them */ | 413 | /* if there are any additional headers, add them */ |
| 414 | xs_dict *more_headers = xs_dict_get(srv_config, "http_headers"); | 414 | const xs_dict *more_headers = xs_dict_get(srv_config, "http_headers"); |
| 415 | if (xs_type(more_headers) == XSTYPE_DICT) { | 415 | if (xs_type(more_headers) == XSTYPE_DICT) { |
| 416 | char *k, *v; | 416 | char *k, *v; |
| 417 | int c = 0; | 417 | int c = 0; |
| @@ -315,7 +315,7 @@ int main(int argc, char *argv[]) | |||
| 315 | xs *msg = msg_follow(&snac, url); | 315 | xs *msg = msg_follow(&snac, url); |
| 316 | 316 | ||
| 317 | if (msg != NULL) { | 317 | if (msg != NULL) { |
| 318 | char *actor = xs_dict_get(msg, "object"); | 318 | const char *actor = xs_dict_get(msg, "object"); |
| 319 | 319 | ||
| 320 | following_add(&snac, actor, msg); | 320 | following_add(&snac, actor, msg); |
| 321 | 321 | ||
| @@ -175,7 +175,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path, | |||
| 175 | return 0; | 175 | return 0; |
| 176 | 176 | ||
| 177 | int status = 404; | 177 | int status = 404; |
| 178 | xs_dict *msg = xs_dict_get(req, "q_vars"); | 178 | const xs_dict *msg = xs_dict_get(req, "q_vars"); |
| 179 | xs *cmd = xs_replace_n(q_path, "/oauth", "", 1); | 179 | xs *cmd = xs_replace_n(q_path, "/oauth", "", 1); |
| 180 | 180 | ||
| 181 | srv_debug(1, xs_fmt("oauth_get_handler %s", q_path)); | 181 | srv_debug(1, xs_fmt("oauth_get_handler %s", q_path)); |
| @@ -239,7 +239,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 239 | 239 | ||
| 240 | int status = 404; | 240 | int status = 404; |
| 241 | 241 | ||
| 242 | char *i_ctype = xs_dict_get(req, "content-type"); | 242 | const char *i_ctype = xs_dict_get(req, "content-type"); |
| 243 | xs *args = NULL; | 243 | xs *args = NULL; |
| 244 | 244 | ||
| 245 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { | 245 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { |
| @@ -568,10 +568,10 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 568 | acct = xs_dict_append(acct, "uri", id); | 568 | acct = xs_dict_append(acct, "uri", id); |
| 569 | 569 | ||
| 570 | xs *avatar = NULL; | 570 | xs *avatar = NULL; |
| 571 | xs_dict *av = xs_dict_get(actor, "icon"); | 571 | const xs_dict *av = xs_dict_get(actor, "icon"); |
| 572 | 572 | ||
| 573 | if (xs_type(av) == XSTYPE_DICT) { | 573 | if (xs_type(av) == XSTYPE_DICT) { |
| 574 | char *url = xs_dict_get(av, "url"); | 574 | const char *url = xs_dict_get(av, "url"); |
| 575 | 575 | ||
| 576 | if (url != NULL) | 576 | if (url != NULL) |
| 577 | avatar = xs_dup(url); | 577 | avatar = xs_dup(url); |
| @@ -584,7 +584,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 584 | acct = xs_dict_append(acct, "avatar_static", avatar); | 584 | acct = xs_dict_append(acct, "avatar_static", avatar); |
| 585 | 585 | ||
| 586 | xs *header = NULL; | 586 | xs *header = NULL; |
| 587 | xs_dict *hd = xs_dict_get(actor, "image"); | 587 | const xs_dict *hd = xs_dict_get(actor, "image"); |
| 588 | 588 | ||
| 589 | if (xs_type(hd) == XSTYPE_DICT) | 589 | if (xs_type(hd) == XSTYPE_DICT) |
| 590 | header = xs_dup(xs_dict_get(hd, "url")); | 590 | header = xs_dup(xs_dict_get(hd, "url")); |
| @@ -596,12 +596,13 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 596 | acct = xs_dict_append(acct, "header_static", header); | 596 | acct = xs_dict_append(acct, "header_static", header); |
| 597 | 597 | ||
| 598 | /* emojis */ | 598 | /* emojis */ |
| 599 | xs_list *p; | 599 | const xs_list *p; |
| 600 | if (!xs_is_null(p = xs_dict_get(actor, "tag"))) { | 600 | if (!xs_is_null(p = xs_dict_get(actor, "tag"))) { |
| 601 | xs *eml = xs_list_new(); | 601 | xs *eml = xs_list_new(); |
| 602 | xs_dict *v; | 602 | xs_dict *v; |
| 603 | int c = 0; | ||
| 603 | 604 | ||
| 604 | while (xs_list_iter(&p, &v)) { | 605 | while (xs_list_next(p, &v, &c)) { |
| 605 | const char *type = xs_dict_get(v, "type"); | 606 | const char *type = xs_dict_get(v, "type"); |
| 606 | 607 | ||
| 607 | if (!xs_is_null(type) && strcmp(type, "Emoji") == 0) { | 608 | if (!xs_is_null(type) && strcmp(type, "Emoji") == 0) { |
| @@ -640,7 +641,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 640 | 641 | ||
| 641 | /* dict of validated links */ | 642 | /* dict of validated links */ |
| 642 | xs_dict *val_links = NULL; | 643 | xs_dict *val_links = NULL; |
| 643 | xs_dict *metadata = xs_stock(XSTYPE_DICT); | 644 | const xs_dict *metadata = xs_stock(XSTYPE_DICT); |
| 644 | snac user = {0}; | 645 | snac user = {0}; |
| 645 | 646 | ||
| 646 | if (xs_startswith(id, srv_baseurl)) { | 647 | if (xs_startswith(id, srv_baseurl)) { |
| @@ -654,19 +655,20 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 654 | if (xs_is_null(val_links)) | 655 | if (xs_is_null(val_links)) |
| 655 | val_links = xs_stock(XSTYPE_DICT); | 656 | val_links = xs_stock(XSTYPE_DICT); |
| 656 | 657 | ||
| 657 | while (xs_list_iter(&p, &v)) { | 658 | int c = 0; |
| 658 | char *type = xs_dict_get(v, "type"); | 659 | while (xs_list_next(p, &v, &c)) { |
| 659 | char *name = xs_dict_get(v, "name"); | 660 | const char *type = xs_dict_get(v, "type"); |
| 660 | char *value = xs_dict_get(v, "value"); | 661 | const char *name = xs_dict_get(v, "name"); |
| 662 | const char *value = xs_dict_get(v, "value"); | ||
| 661 | 663 | ||
| 662 | if (!xs_is_null(type) && !xs_is_null(name) && | 664 | if (!xs_is_null(type) && !xs_is_null(name) && |
| 663 | !xs_is_null(value) && strcmp(type, "PropertyValue") == 0) { | 665 | !xs_is_null(value) && strcmp(type, "PropertyValue") == 0) { |
| 664 | xs *val_date = NULL; | 666 | xs *val_date = NULL; |
| 665 | 667 | ||
| 666 | char *url = xs_dict_get(metadata, name); | 668 | const char *url = xs_dict_get(metadata, name); |
| 667 | 669 | ||
| 668 | if (!xs_is_null(url) && xs_startswith(url, "https:/" "/")) { | 670 | if (!xs_is_null(url) && xs_startswith(url, "https:/" "/")) { |
| 669 | xs_number *verified_time = xs_dict_get(val_links, url); | 671 | const xs_number *verified_time = xs_dict_get(val_links, url); |
| 670 | if (xs_type(verified_time) == XSTYPE_NUMBER) { | 672 | if (xs_type(verified_time) == XSTYPE_NUMBER) { |
| 671 | time_t t = xs_number_get(verified_time); | 673 | time_t t = xs_number_get(verified_time); |
| 672 | 674 | ||
| @@ -695,7 +697,7 @@ xs_dict *mastoapi_account(const xs_dict *actor) | |||
| 695 | } | 697 | } |
| 696 | 698 | ||
| 697 | 699 | ||
| 698 | xs_str *mastoapi_date(char *date) | 700 | xs_str *mastoapi_date(const char *date) |
| 699 | /* converts an ISO 8601 date to whatever format Mastodon uses */ | 701 | /* converts an ISO 8601 date to whatever format Mastodon uses */ |
| 700 | { | 702 | { |
| 701 | xs_str *s = xs_crop_i(xs_dup(date), 0, 19); | 703 | xs_str *s = xs_crop_i(xs_dup(date), 0, 19); |
| @@ -710,13 +712,13 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg) | |||
| 710 | { | 712 | { |
| 711 | xs_dict *poll = xs_dict_new(); | 713 | xs_dict *poll = xs_dict_new(); |
| 712 | xs *mid = mastoapi_id(msg); | 714 | xs *mid = mastoapi_id(msg); |
| 713 | xs_list *opts = NULL; | 715 | const xs_list *opts = NULL; |
| 714 | xs_val *v; | 716 | xs_val *v; |
| 715 | int num_votes = 0; | 717 | int num_votes = 0; |
| 716 | xs *options = xs_list_new(); | 718 | xs *options = xs_list_new(); |
| 717 | 719 | ||
| 718 | poll = xs_dict_append(poll, "id", mid); | 720 | poll = xs_dict_append(poll, "id", mid); |
| 719 | char *date = xs_dict_get(msg, "endTime"); | 721 | const char *date = xs_dict_get(msg, "endTime"); |
| 720 | if (date == NULL) | 722 | if (date == NULL) |
| 721 | date = xs_dict_get(msg, "closed"); | 723 | date = xs_dict_get(msg, "closed"); |
| 722 | if (date == NULL) | 724 | if (date == NULL) |
| @@ -741,7 +743,8 @@ xs_dict *mastoapi_poll(snac *snac, const xs_dict *msg) | |||
| 741 | poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_TRUE)); | 743 | poll = xs_dict_append(poll, "multiple", xs_stock(XSTYPE_TRUE)); |
| 742 | } | 744 | } |
| 743 | 745 | ||
| 744 | while (xs_list_iter(&opts, &v)) { | 746 | int c = 0; |
| 747 | while (xs_list_next(opts, &v, &c)) { | ||
| 745 | const char *title = xs_dict_get(v, "name"); | 748 | const char *title = xs_dict_get(v, "name"); |
| 746 | const char *replies = xs_dict_get(v, "replies"); | 749 | const char *replies = xs_dict_get(v, "replies"); |
| 747 | 750 | ||
| @@ -794,7 +797,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 794 | 797 | ||
| 795 | xs *idx = NULL; | 798 | xs *idx = NULL; |
| 796 | xs *ixc = NULL; | 799 | xs *ixc = NULL; |
| 797 | char *tmp; | 800 | const char *tmp; |
| 798 | xs *mid = mastoapi_id(msg); | 801 | xs *mid = mastoapi_id(msg); |
| 799 | 802 | ||
| 800 | xs_dict *st = xs_dict_new(); | 803 | xs_dict *st = xs_dict_new(); |
| @@ -851,9 +854,9 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 851 | xs *matt = xs_list_new(); | 854 | xs *matt = xs_list_new(); |
| 852 | 855 | ||
| 853 | while (xs_list_iter(&p, &v)) { | 856 | while (xs_list_iter(&p, &v)) { |
| 854 | char *type = xs_dict_get(v, "type"); | 857 | const char *type = xs_dict_get(v, "type"); |
| 855 | char *href = xs_dict_get(v, "href"); | 858 | const char *href = xs_dict_get(v, "href"); |
| 856 | char *name = xs_dict_get(v, "name"); | 859 | const char *name = xs_dict_get(v, "name"); |
| 857 | 860 | ||
| 858 | if (xs_match(type, "image/*|video/*|Image|Video")) { /* */ | 861 | if (xs_match(type, "image/*|video/*|Image|Video")) { /* */ |
| 859 | xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt)); | 862 | xs *matteid = xs_fmt("%s_%d", id, xs_list_len(matt)); |
| @@ -879,7 +882,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 879 | xs *ml = xs_list_new(); | 882 | xs *ml = xs_list_new(); |
| 880 | xs *htl = xs_list_new(); | 883 | xs *htl = xs_list_new(); |
| 881 | xs *eml = xs_list_new(); | 884 | xs *eml = xs_list_new(); |
| 882 | xs_list *tag = xs_dict_get(msg, "tag"); | 885 | const xs_list *tag = xs_dict_get(msg, "tag"); |
| 883 | int n = 0; | 886 | int n = 0; |
| 884 | 887 | ||
| 885 | xs *tag_list = NULL; | 888 | xs *tag_list = NULL; |
| @@ -897,7 +900,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 897 | tag = tag_list; | 900 | tag = tag_list; |
| 898 | xs_dict *v; | 901 | xs_dict *v; |
| 899 | 902 | ||
| 900 | while (xs_list_iter(&tag, &v)) { | 903 | int c = 0; |
| 904 | while (xs_list_next(tag, &v, &c)) { | ||
| 901 | const char *type = xs_dict_get(v, "type"); | 905 | const char *type = xs_dict_get(v, "type"); |
| 902 | 906 | ||
| 903 | if (xs_is_null(type)) | 907 | if (xs_is_null(type)) |
| @@ -1006,7 +1010,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 1006 | xs *irt_mid = mastoapi_id(irto); | 1010 | xs *irt_mid = mastoapi_id(irto); |
| 1007 | st = xs_dict_set(st, "in_reply_to_id", irt_mid); | 1011 | st = xs_dict_set(st, "in_reply_to_id", irt_mid); |
| 1008 | 1012 | ||
| 1009 | char *at = NULL; | 1013 | const char *at = NULL; |
| 1010 | if (!xs_is_null(at = get_atto(irto))) { | 1014 | if (!xs_is_null(at = get_atto(irto))) { |
| 1011 | xs *at_md5 = xs_md5_hex(at, strlen(at)); | 1015 | xs *at_md5 = xs_md5_hex(at, strlen(at)); |
| 1012 | st = xs_dict_set(st, "in_reply_to_account_id", at_md5); | 1016 | st = xs_dict_set(st, "in_reply_to_account_id", at_md5); |
| @@ -1118,7 +1122,7 @@ int process_auth_token(snac *snac, const xs_dict *req) | |||
| 1118 | /* processes an authorization token, if there is one */ | 1122 | /* processes an authorization token, if there is one */ |
| 1119 | { | 1123 | { |
| 1120 | int logged_in = 0; | 1124 | int logged_in = 0; |
| 1121 | char *v; | 1125 | const char *v; |
| 1122 | 1126 | ||
| 1123 | /* if there is an authorization field, try to validate it */ | 1127 | /* if there is an authorization field, try to validate it */ |
| 1124 | if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) { | 1128 | if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) { |
| @@ -1156,7 +1160,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1156 | return 0; | 1160 | return 0; |
| 1157 | 1161 | ||
| 1158 | int status = 404; | 1162 | int status = 404; |
| 1159 | xs_dict *args = xs_dict_get(req, "q_vars"); | 1163 | const xs_dict *args = xs_dict_get(req, "q_vars"); |
| 1160 | xs *cmd = xs_replace_n(q_path, "/api", "", 1); | 1164 | xs *cmd = xs_replace_n(q_path, "/api", "", 1); |
| 1161 | 1165 | ||
| 1162 | snac snac1 = {0}; | 1166 | snac snac1 = {0}; |
| @@ -1182,7 +1186,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1182 | acct = xs_dict_append(acct, "source", src); | 1186 | acct = xs_dict_append(acct, "source", src); |
| 1183 | 1187 | ||
| 1184 | xs *avatar = NULL; | 1188 | xs *avatar = NULL; |
| 1185 | char *av = xs_dict_get(snac1.config, "avatar"); | 1189 | const char *av = xs_dict_get(snac1.config, "avatar"); |
| 1186 | 1190 | ||
| 1187 | if (xs_is_null(av) || *av == '\0') | 1191 | if (xs_is_null(av) || *av == '\0') |
| 1188 | avatar = xs_fmt("%s/susie.png", srv_baseurl); | 1192 | avatar = xs_fmt("%s/susie.png", srv_baseurl); |
| @@ -1193,7 +1197,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1193 | acct = xs_dict_append(acct, "avatar_static", avatar); | 1197 | acct = xs_dict_append(acct, "avatar_static", avatar); |
| 1194 | 1198 | ||
| 1195 | xs *header = NULL; | 1199 | xs *header = NULL; |
| 1196 | char *hd = xs_dict_get(snac1.config, "header"); | 1200 | const char *hd = xs_dict_get(snac1.config, "header"); |
| 1197 | 1201 | ||
| 1198 | if (!xs_is_null(hd)) | 1202 | if (!xs_is_null(hd)) |
| 1199 | header = xs_dup(hd); | 1203 | header = xs_dup(hd); |
| @@ -1203,7 +1207,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1203 | acct = xs_dict_append(acct, "header", header); | 1207 | acct = xs_dict_append(acct, "header", header); |
| 1204 | acct = xs_dict_append(acct, "header_static", header); | 1208 | acct = xs_dict_append(acct, "header_static", header); |
| 1205 | 1209 | ||
| 1206 | xs_dict *metadata = xs_dict_get(snac1.config, "metadata"); | 1210 | const xs_dict *metadata = xs_dict_get(snac1.config, "metadata"); |
| 1207 | if (xs_type(metadata) == XSTYPE_DICT) { | 1211 | if (xs_type(metadata) == XSTYPE_DICT) { |
| 1208 | xs *fields = xs_list_new(); | 1212 | xs *fields = xs_list_new(); |
| 1209 | xs_str *k; | 1213 | xs_str *k; |
| @@ -1217,7 +1221,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1217 | while (xs_dict_next(metadata, &k, &v, &c)) { | 1221 | while (xs_dict_next(metadata, &k, &v, &c)) { |
| 1218 | xs *val_date = NULL; | 1222 | xs *val_date = NULL; |
| 1219 | 1223 | ||
| 1220 | xs_number *verified_time = xs_dict_get(val_links, v); | 1224 | const xs_number *verified_time = xs_dict_get(val_links, v); |
| 1221 | if (xs_type(verified_time) == XSTYPE_NUMBER) { | 1225 | if (xs_type(verified_time) == XSTYPE_NUMBER) { |
| 1222 | time_t t = xs_number_get(verified_time); | 1226 | time_t t = xs_number_get(verified_time); |
| 1223 | 1227 | ||
| @@ -1283,13 +1287,13 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1283 | else | 1287 | else |
| 1284 | if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/ | 1288 | if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/ |
| 1285 | /* lookup an account */ | 1289 | /* lookup an account */ |
| 1286 | char *acct = xs_dict_get(args, "acct"); | 1290 | const char *acct = xs_dict_get(args, "acct"); |
| 1287 | 1291 | ||
| 1288 | if (!xs_is_null(acct)) { | 1292 | if (!xs_is_null(acct)) { |
| 1289 | xs *s = xs_strip_chars_i(xs_dup(acct), "@"); | 1293 | xs *s = xs_strip_chars_i(xs_dup(acct), "@"); |
| 1290 | xs *l = xs_split_n(s, "@", 1); | 1294 | xs *l = xs_split_n(s, "@", 1); |
| 1291 | char *uid = xs_list_get(l, 0); | 1295 | const char *uid = xs_list_get(l, 0); |
| 1292 | char *host = xs_list_get(l, 1); | 1296 | const char *host = xs_list_get(l, 1); |
| 1293 | 1297 | ||
| 1294 | if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) { | 1298 | if (uid && (!host || strcmp(host, xs_dict_get(srv_config, "host")) == 0)) { |
| 1295 | snac user; | 1299 | snac user; |
| @@ -1624,7 +1628,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1624 | 1628 | ||
| 1625 | /* get the tag */ | 1629 | /* get the tag */ |
| 1626 | xs *l = xs_split(cmd, "/"); | 1630 | xs *l = xs_split(cmd, "/"); |
| 1627 | char *tag = xs_list_get(l, -1); | 1631 | const char *tag = xs_list_get(l, -1); |
| 1628 | 1632 | ||
| 1629 | xs *timeline = tag_search(tag, 0, limit); | 1633 | xs *timeline = tag_search(tag, 0, limit); |
| 1630 | xs *out = xs_list_new(); | 1634 | xs *out = xs_list_new(); |
| @@ -1664,7 +1668,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1664 | /* get the list id */ | 1668 | /* get the list id */ |
| 1665 | if (logged_in) { | 1669 | if (logged_in) { |
| 1666 | xs *l = xs_split(cmd, "/"); | 1670 | xs *l = xs_split(cmd, "/"); |
| 1667 | char *list = xs_list_get(l, -1); | 1671 | const char *list = xs_list_get(l, -1); |
| 1668 | 1672 | ||
| 1669 | xs *timeline = list_timeline(&snac1, list, 0, 2048); | 1673 | xs *timeline = list_timeline(&snac1, list, 0, 2048); |
| 1670 | xs *out = xs_list_new(); | 1674 | xs *out = xs_list_new(); |
| @@ -1744,7 +1748,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1744 | xs *out = xs_list_new(); | 1748 | xs *out = xs_list_new(); |
| 1745 | xs_list *p = l; | 1749 | xs_list *p = l; |
| 1746 | xs_dict *v; | 1750 | xs_dict *v; |
| 1747 | xs_list *excl = xs_dict_get(args, "exclude_types[]"); | 1751 | const xs_list *excl = xs_dict_get(args, "exclude_types[]"); |
| 1748 | 1752 | ||
| 1749 | while (xs_list_iter(&p, &v)) { | 1753 | while (xs_list_iter(&p, &v)) { |
| 1750 | xs *noti = notify_get(&snac1, v); | 1754 | xs *noti = notify_get(&snac1, v); |
| @@ -1876,7 +1880,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1876 | if (xs_startswith(cmd, "/v1/lists/")) { /** list information **/ | 1880 | if (xs_startswith(cmd, "/v1/lists/")) { /** list information **/ |
| 1877 | if (logged_in) { | 1881 | if (logged_in) { |
| 1878 | xs *l = xs_split(cmd, "/"); | 1882 | xs *l = xs_split(cmd, "/"); |
| 1879 | char *p = xs_list_get(l, -1); | 1883 | const char *p = xs_list_get(l, -1); |
| 1880 | 1884 | ||
| 1881 | if (p) { | 1885 | if (p) { |
| 1882 | if (strcmp(p, "accounts") == 0) { | 1886 | if (strcmp(p, "accounts") == 0) { |
| @@ -1910,7 +1914,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1910 | xs_list *v; | 1914 | xs_list *v; |
| 1911 | 1915 | ||
| 1912 | while (xs_list_next(lol, &v, &c)) { | 1916 | while (xs_list_next(lol, &v, &c)) { |
| 1913 | char *id = xs_list_get(v, 0); | 1917 | const char *id = xs_list_get(v, 0); |
| 1914 | 1918 | ||
| 1915 | if (id && strcmp(id, p) == 0) { | 1919 | if (id && strcmp(id, p) == 0) { |
| 1916 | xs *d = xs_dict_new(); | 1920 | xs *d = xs_dict_new(); |
| @@ -2314,7 +2318,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2314 | 2318 | ||
| 2315 | int status = 404; | 2319 | int status = 404; |
| 2316 | xs *args = NULL; | 2320 | xs *args = NULL; |
| 2317 | char *i_ctype = xs_dict_get(req, "content-type"); | 2321 | const char *i_ctype = xs_dict_get(req, "content-type"); |
| 2318 | 2322 | ||
| 2319 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { | 2323 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { |
| 2320 | if (!xs_is_null(payload)) | 2324 | if (!xs_is_null(payload)) |
| @@ -2487,7 +2491,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2487 | mid = MID_TO_MD5(mid); | 2491 | mid = MID_TO_MD5(mid); |
| 2488 | 2492 | ||
| 2489 | if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) { | 2493 | if (valid_status(timeline_get_by_md5(&snac, mid, &msg))) { |
| 2490 | char *id = xs_dict_get(msg, "id"); | 2494 | const char *id = xs_dict_get(msg, "id"); |
| 2491 | 2495 | ||
| 2492 | if (op == NULL) { | 2496 | if (op == NULL) { |
| 2493 | /* no operation (?) */ | 2497 | /* no operation (?) */ |
| @@ -2593,7 +2597,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2593 | if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/ | 2597 | if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/ |
| 2594 | /* I don't know what I'm doing */ | 2598 | /* I don't know what I'm doing */ |
| 2595 | if (logged_in) { | 2599 | if (logged_in) { |
| 2596 | char *v; | 2600 | const char *v; |
| 2597 | 2601 | ||
| 2598 | xs *wpush = xs_dict_new(); | 2602 | xs *wpush = xs_dict_new(); |
| 2599 | 2603 | ||
| @@ -2765,7 +2769,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2765 | const char *id = xs_dict_get(msg, "id"); | 2769 | const char *id = xs_dict_get(msg, "id"); |
| 2766 | const char *atto = get_atto(msg); | 2770 | const char *atto = get_atto(msg); |
| 2767 | 2771 | ||
| 2768 | xs_list *opts = xs_dict_get(msg, "oneOf"); | 2772 | const xs_list *opts = xs_dict_get(msg, "oneOf"); |
| 2769 | if (opts == NULL) | 2773 | if (opts == NULL) |
| 2770 | opts = xs_dict_get(msg, "anyOf"); | 2774 | opts = xs_dict_get(msg, "anyOf"); |
| 2771 | 2775 | ||
| @@ -2773,7 +2777,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2773 | } | 2777 | } |
| 2774 | else | 2778 | else |
| 2775 | if (strcmp(op, "votes") == 0) { | 2779 | if (strcmp(op, "votes") == 0) { |
| 2776 | xs_list *choices = xs_dict_get(args, "choices[]"); | 2780 | const xs_list *choices = xs_dict_get(args, "choices[]"); |
| 2777 | 2781 | ||
| 2778 | if (xs_is_null(choices)) | 2782 | if (xs_is_null(choices)) |
| 2779 | choices = xs_dict_get(args, "choices"); | 2783 | choices = xs_dict_get(args, "choices"); |
| @@ -2781,7 +2785,8 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2781 | if (xs_type(choices) == XSTYPE_LIST) { | 2785 | if (xs_type(choices) == XSTYPE_LIST) { |
| 2782 | xs_str *v; | 2786 | xs_str *v; |
| 2783 | 2787 | ||
| 2784 | while (xs_list_iter(&choices, &v)) { | 2788 | int c = 0; |
| 2789 | while (xs_list_next(choices, &v, &c)) { | ||
| 2785 | int io = atoi(v); | 2790 | int io = atoi(v); |
| 2786 | const xs_dict *o = xs_list_get(opts, io); | 2791 | const xs_dict *o = xs_list_get(opts, io); |
| 2787 | 2792 | ||
| @@ -2843,12 +2848,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2843 | if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/ | 2848 | if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/ |
| 2844 | if (logged_in) { | 2849 | if (logged_in) { |
| 2845 | xs *l = xs_split(cmd, "/"); | 2850 | xs *l = xs_split(cmd, "/"); |
| 2846 | char *op = xs_list_get(l, -1); | 2851 | const char *op = xs_list_get(l, -1); |
| 2847 | char *id = xs_list_get(l, -2); | 2852 | const char *id = xs_list_get(l, -2); |
| 2848 | 2853 | ||
| 2849 | if (op && id && xs_is_hex(id)) { | 2854 | if (op && id && xs_is_hex(id)) { |
| 2850 | if (strcmp(op, "accounts") == 0) { | 2855 | if (strcmp(op, "accounts") == 0) { |
| 2851 | xs_list *accts = xs_dict_get(args, "account_ids[]"); | 2856 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); |
| 2852 | int c = 0; | 2857 | int c = 0; |
| 2853 | char *v; | 2858 | char *v; |
| 2854 | 2859 | ||
| @@ -2888,7 +2893,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 2888 | 2893 | ||
| 2889 | int status = 404; | 2894 | int status = 404; |
| 2890 | xs *args = NULL; | 2895 | xs *args = NULL; |
| 2891 | char *i_ctype = xs_dict_get(req, "content-type"); | 2896 | const char *i_ctype = xs_dict_get(req, "content-type"); |
| 2892 | 2897 | ||
| 2893 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { | 2898 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { |
| 2894 | if (!xs_is_null(payload)) | 2899 | if (!xs_is_null(payload)) |
| @@ -2921,13 +2926,13 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 2921 | if (xs_startswith(cmd, "/v1/lists/")) { | 2926 | if (xs_startswith(cmd, "/v1/lists/")) { |
| 2922 | if (logged_in) { | 2927 | if (logged_in) { |
| 2923 | xs *l = xs_split(cmd, "/"); | 2928 | xs *l = xs_split(cmd, "/"); |
| 2924 | char *p = xs_list_get(l, -1); | 2929 | const char *p = xs_list_get(l, -1); |
| 2925 | 2930 | ||
| 2926 | if (p) { | 2931 | if (p) { |
| 2927 | if (strcmp(p, "accounts") == 0) { | 2932 | if (strcmp(p, "accounts") == 0) { |
| 2928 | /* delete account from list */ | 2933 | /* delete account from list */ |
| 2929 | p = xs_list_get(l, -2); | 2934 | p = xs_list_get(l, -2); |
| 2930 | xs_list *accts = xs_dict_get(args, "account_ids[]"); | 2935 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); |
| 2931 | int c = 0; | 2936 | int c = 0; |
| 2932 | char *v; | 2937 | char *v; |
| 2933 | 2938 | ||
| @@ -2971,7 +2976,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path, | |||
| 2971 | 2976 | ||
| 2972 | int status = 404; | 2977 | int status = 404; |
| 2973 | xs *args = NULL; | 2978 | xs *args = NULL; |
| 2974 | char *i_ctype = xs_dict_get(req, "content-type"); | 2979 | const char *i_ctype = xs_dict_get(req, "content-type"); |
| 2975 | 2980 | ||
| 2976 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { | 2981 | if (i_ctype && xs_startswith(i_ctype, "application/json")) { |
| 2977 | if (!xs_is_null(payload)) | 2982 | if (!xs_is_null(payload)) |
| @@ -69,7 +69,7 @@ void snac_log(snac *user, xs_str *str); | |||
| 69 | #define snac_debug(user, level, str) do { if (dbglevel >= (level)) \ | 69 | #define snac_debug(user, level, str) do { if (dbglevel >= (level)) \ |
| 70 | { snac_log((user), (str)); } } while (0) | 70 | { snac_log((user), (str)); } } while (0) |
| 71 | 71 | ||
| 72 | int srv_open(char *basedir, int auto_upgrade); | 72 | int srv_open(const char *basedir, int auto_upgrade); |
| 73 | void srv_free(void); | 73 | void srv_free(void); |
| 74 | 74 | ||
| 75 | int user_open(snac *snac, const char *uid); | 75 | int user_open(snac *snac, const char *uid); |
| @@ -88,7 +88,7 @@ void srv_archive(const char *direction, const char *url, xs_dict *req, | |||
| 88 | const char *body, int b_size); | 88 | const char *body, int b_size); |
| 89 | void srv_archive_error(const char *prefix, const xs_str *err, | 89 | void srv_archive_error(const char *prefix, const xs_str *err, |
| 90 | const xs_dict *req, const xs_val *data); | 90 | const xs_dict *req, const xs_val *data); |
| 91 | void srv_archive_qitem(char *prefix, xs_dict *q_item); | 91 | void srv_archive_qitem(const char *prefix, xs_dict *q_item); |
| 92 | 92 | ||
| 93 | double mtime_nl(const char *fn, int *n_link); | 93 | double mtime_nl(const char *fn, int *n_link); |
| 94 | #define mtime(fn) mtime_nl(fn, NULL) | 94 | #define mtime(fn) mtime_nl(fn, NULL) |
| @@ -139,13 +139,13 @@ double timeline_mtime(snac *snac); | |||
| 139 | int timeline_touch(snac *snac); | 139 | int timeline_touch(snac *snac); |
| 140 | int timeline_here(snac *snac, const char *md5); | 140 | int timeline_here(snac *snac, const char *md5); |
| 141 | int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg); | 141 | int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg); |
| 142 | int timeline_del(snac *snac, char *id); | 142 | int timeline_del(snac *snac, const char *id); |
| 143 | xs_list *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show); | 143 | xs_list *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show); |
| 144 | xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show); | 144 | xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show); |
| 145 | int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); | 145 | int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); |
| 146 | int timeline_admire(snac *snac, const char *id, const char *admirer, int like); | 146 | int timeline_admire(snac *snac, const char *id, const char *admirer, int like); |
| 147 | 147 | ||
| 148 | xs_list *timeline_top_level(snac *snac, xs_list *list); | 148 | xs_list *timeline_top_level(snac *snac, const xs_list *list); |
| 149 | xs_list *local_list(snac *snac, int max); | 149 | xs_list *local_list(snac *snac, int max); |
| 150 | xs_list *timeline_instance_list(int skip, int show); | 150 | xs_list *timeline_instance_list(int skip, int show); |
| 151 | 151 | ||
| @@ -174,14 +174,14 @@ void hide(snac *snac, const char *id); | |||
| 174 | int is_hidden(snac *snac, const char *id); | 174 | int is_hidden(snac *snac, const char *id); |
| 175 | 175 | ||
| 176 | void tag_index(const char *id, const xs_dict *obj); | 176 | void tag_index(const char *id, const xs_dict *obj); |
| 177 | xs_list *tag_search(char *tag, int skip, int show); | 177 | xs_list *tag_search(const char *tag, int skip, int show); |
| 178 | 178 | ||
| 179 | xs_val *list_maint(snac *user, const char *list, int op); | 179 | xs_val *list_maint(snac *user, const char *list, int op); |
| 180 | xs_list *list_timeline(snac *user, const char *list, int skip, int show); | 180 | xs_list *list_timeline(snac *user, const char *list, int skip, int show); |
| 181 | xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op); | 181 | xs_val *list_content(snac *user, const char *list_id, const char *actor_md5, int op); |
| 182 | void list_distribute(snac *user, const char *who, const xs_dict *post); | 182 | void list_distribute(snac *user, const char *who, const xs_dict *post); |
| 183 | 183 | ||
| 184 | int actor_add(const char *actor, xs_dict *msg); | 184 | int actor_add(const char *actor, const xs_dict *msg); |
| 185 | int actor_get(const char *actor, xs_dict **data); | 185 | int actor_get(const char *actor, xs_dict **data); |
| 186 | int actor_get_refresh(snac *user, const char *actor, xs_dict **data); | 186 | int actor_get_refresh(snac *user, const char *actor, xs_dict **data); |
| 187 | 187 | ||
| @@ -223,10 +223,13 @@ xs_list *content_search(snac *user, const char *regex, | |||
| 223 | void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retries); | 223 | void enqueue_input(snac *snac, const xs_dict *msg, const xs_dict *req, int retries); |
| 224 | void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries); | 224 | void enqueue_shared_input(const xs_dict *msg, const xs_dict *req, int retries); |
| 225 | void enqueue_output_raw(const char *keyid, const char *seckey, | 225 | void enqueue_output_raw(const char *keyid, const char *seckey, |
| 226 | xs_dict *msg, xs_str *inbox, int retries, int p_status); | 226 | const xs_dict *msg, const xs_str *inbox, |
| 227 | void enqueue_output(snac *snac, xs_dict *msg, xs_str *inbox, int retries, int p_status); | 227 | int retries, int p_status); |
| 228 | void enqueue_output_by_actor(snac *snac, xs_dict *msg, const xs_str *actor, int retries); | 228 | void enqueue_output(snac *snac, const xs_dict *msg, |
| 229 | void enqueue_email(xs_str *msg, int retries); | 229 | const xs_str *inbox, int retries, int p_status); |
| 230 | void enqueue_output_by_actor(snac *snac, const xs_dict *msg, | ||
| 231 | const xs_str *actor, int retries); | ||
| 232 | void enqueue_email(const xs_str *msg, int retries); | ||
| 230 | void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id); | 233 | void enqueue_telegram(const xs_str *msg, const char *bot, const char *chat_id); |
| 231 | void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token); | 234 | void enqueue_ntfy(const xs_str *msg, const char *ntfy_server, const char *ntfy_token); |
| 232 | void enqueue_message(snac *snac, const xs_dict *msg); | 235 | void enqueue_message(snac *snac, const xs_dict *msg); |
| @@ -234,7 +237,6 @@ void enqueue_close_question(snac *user, const char *id, int end_secs); | |||
| 234 | void enqueue_object_request(snac *user, const char *id, int forward_secs); | 237 | void enqueue_object_request(snac *user, const char *id, int forward_secs); |
| 235 | void enqueue_verify_links(snac *user); | 238 | void enqueue_verify_links(snac *user); |
| 236 | void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs); | 239 | void enqueue_actor_refresh(snac *user, const char *actor, int forward_secs); |
| 237 | void enqueue_request_replies(snac *user, const char *id); | ||
| 238 | int was_question_voted(snac *user, const char *id); | 240 | int was_question_voted(snac *user, const char *id); |
| 239 | 241 | ||
| 240 | xs_list *user_queue(snac *snac); | 242 | xs_list *user_queue(snac *snac); |
| @@ -247,16 +249,16 @@ void purge_all(void); | |||
| 247 | 249 | ||
| 248 | xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, | 250 | xs_dict *http_signed_request_raw(const char *keyid, const char *seckey, |
| 249 | const char *method, const char *url, | 251 | const char *method, const char *url, |
| 250 | xs_dict *headers, | 252 | const xs_dict *headers, |
| 251 | const char *body, int b_size, | 253 | const char *body, int b_size, |
| 252 | int *status, xs_str **payload, int *p_size, | 254 | int *status, xs_str **payload, int *p_size, |
| 253 | int timeout); | 255 | int timeout); |
| 254 | xs_dict *http_signed_request(snac *snac, const char *method, const char *url, | 256 | xs_dict *http_signed_request(snac *snac, const char *method, const char *url, |
| 255 | xs_dict *headers, | 257 | const xs_dict *headers, |
| 256 | const char *body, int b_size, | 258 | const char *body, int b_size, |
| 257 | int *status, xs_str **payload, int *p_size, | 259 | int *status, xs_str **payload, int *p_size, |
| 258 | int timeout); | 260 | int timeout); |
| 259 | int check_signature(xs_dict *req, xs_str **err); | 261 | int check_signature(const xs_dict *req, xs_str **err); |
| 260 | 262 | ||
| 261 | srv_state *srv_state_op(xs_str **fname, int op); | 263 | srv_state *srv_state_op(xs_str **fname, int op); |
| 262 | void httpd(void); | 264 | void httpd(void); |
| @@ -270,21 +272,21 @@ const char *default_avatar_base64(void); | |||
| 270 | 272 | ||
| 271 | xs_str *process_tags(snac *snac, const char *content, xs_list **tag); | 273 | xs_str *process_tags(snac *snac, const char *content, xs_list **tag); |
| 272 | 274 | ||
| 273 | char *get_atto(const xs_dict *msg); | 275 | const char *get_atto(const xs_dict *msg); |
| 274 | xs_list *get_attachments(const xs_dict *msg); | 276 | xs_list *get_attachments(const xs_dict *msg); |
| 275 | 277 | ||
| 276 | xs_dict *msg_admiration(snac *snac, char *object, char *type); | 278 | xs_dict *msg_admiration(snac *snac, const char *object, const char *type); |
| 277 | xs_dict *msg_repulsion(snac *user, char *id, char *type); | 279 | xs_dict *msg_repulsion(snac *user, const char *id, const char *type); |
| 278 | xs_dict *msg_create(snac *snac, const xs_dict *object); | 280 | xs_dict *msg_create(snac *snac, const xs_dict *object); |
| 279 | xs_dict *msg_follow(snac *snac, const char *actor); | 281 | xs_dict *msg_follow(snac *snac, const char *actor); |
| 280 | 282 | ||
| 281 | xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, | 283 | xs_dict *msg_note(snac *snac, const xs_str *content, const xs_val *rcpts, |
| 282 | xs_str *in_reply_to, xs_list *attach, int priv); | 284 | const xs_str *in_reply_to, const xs_list *attach, int priv); |
| 283 | 285 | ||
| 284 | xs_dict *msg_undo(snac *snac, char *object); | 286 | xs_dict *msg_undo(snac *snac, const xs_val *object); |
| 285 | xs_dict *msg_delete(snac *snac, char *id); | 287 | xs_dict *msg_delete(snac *snac, const char *id); |
| 286 | xs_dict *msg_actor(snac *snac); | 288 | xs_dict *msg_actor(snac *snac); |
| 287 | xs_dict *msg_update(snac *snac, xs_dict *object); | 289 | xs_dict *msg_update(snac *snac, const xs_dict *object); |
| 288 | xs_dict *msg_ping(snac *user, const char *rcpt); | 290 | xs_dict *msg_ping(snac *user, const char *rcpt); |
| 289 | xs_dict *msg_pong(snac *user, const char *rcpt, const char *object); | 291 | xs_dict *msg_pong(snac *user, const char *rcpt, const char *object); |
| 290 | xs_dict *msg_question(snac *user, const char *content, xs_list *attach, | 292 | xs_dict *msg_question(snac *user, const char *content, xs_list *attach, |
| @@ -292,7 +294,6 @@ xs_dict *msg_question(snac *user, const char *content, xs_list *attach, | |||
| 292 | 294 | ||
| 293 | int activitypub_request(snac *snac, const char *url, xs_dict **data); | 295 | int activitypub_request(snac *snac, const char *url, xs_dict **data); |
| 294 | int actor_request(snac *user, const char *actor, xs_dict **data); | 296 | int actor_request(snac *user, const char *actor, xs_dict **data); |
| 295 | void timeline_request_replies(snac *user, const char *id); | ||
| 296 | int send_to_inbox_raw(const char *keyid, const char *seckey, | 297 | int send_to_inbox_raw(const char *keyid, const char *seckey, |
| 297 | const xs_str *inbox, const xs_dict *msg, | 298 | const xs_str *inbox, const xs_dict *msg, |
| 298 | xs_val **payload, int *p_size, int timeout); | 299 | xs_val **payload, int *p_size, int timeout); |
| @@ -18,7 +18,7 @@ int snac_upgrade(xs_str **error) | |||
| 18 | double f = 0.0; | 18 | double f = 0.0; |
| 19 | 19 | ||
| 20 | for (;;) { | 20 | for (;;) { |
| 21 | char *layout = xs_dict_get(srv_config, "layout"); | 21 | const char *layout = xs_dict_get(srv_config, "layout"); |
| 22 | double nf; | 22 | double nf; |
| 23 | 23 | ||
| 24 | f = nf = xs_number_get(layout); | 24 | f = nf = xs_number_get(layout); |
| @@ -56,8 +56,8 @@ int snac_upgrade(xs_str **error) | |||
| 56 | 56 | ||
| 57 | g = list; | 57 | g = list; |
| 58 | while (xs_list_iter(&g, &fn)) { | 58 | while (xs_list_iter(&g, &fn)) { |
| 59 | xs *l = xs_split(fn, "/"); | 59 | xs *l = xs_split(fn, "/"); |
| 60 | char *b = xs_list_get(l, -1); | 60 | const char *b = xs_list_get(l, -1); |
| 61 | xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]); | 61 | xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]); |
| 62 | xs *nfn = xs_fmt("%s/%s", dir, b); | 62 | xs *nfn = xs_fmt("%s/%s", dir, b); |
| 63 | 63 | ||
| @@ -152,12 +152,12 @@ int snac_upgrade(xs_str **error) | |||
| 152 | xs *o = xs_json_loads(s); | 152 | xs *o = xs_json_loads(s); |
| 153 | fclose(f); | 153 | fclose(f); |
| 154 | 154 | ||
| 155 | char *type = xs_dict_get(o, "type"); | 155 | const char *type = xs_dict_get(o, "type"); |
| 156 | 156 | ||
| 157 | if (!xs_is_null(type) && strcmp(type, "Follow") == 0) { | 157 | if (!xs_is_null(type) && strcmp(type, "Follow") == 0) { |
| 158 | unlink(v); | 158 | unlink(v); |
| 159 | 159 | ||
| 160 | char *actor = xs_dict_get(o, "actor"); | 160 | const char *actor = xs_dict_get(o, "actor"); |
| 161 | 161 | ||
| 162 | if (!xs_is_null(actor)) | 162 | if (!xs_is_null(actor)) |
| 163 | follower_add(&snac, actor); | 163 | follower_add(&snac, actor); |
| @@ -198,22 +198,29 @@ int snac_upgrade(xs_str **error) | |||
| 198 | xs *meta = xs_dup(xs_dict_get(o, "_snac")); | 198 | xs *meta = xs_dup(xs_dict_get(o, "_snac")); |
| 199 | o = xs_dict_del(o, "_snac"); | 199 | o = xs_dict_del(o, "_snac"); |
| 200 | 200 | ||
| 201 | char *id = xs_dict_get(o, "id"); | 201 | const char *id = xs_dict_get(o, "id"); |
| 202 | 202 | ||
| 203 | /* store object */ | 203 | /* store object */ |
| 204 | object_add_ow(id, o); | 204 | object_add_ow(id, o); |
| 205 | 205 | ||
| 206 | /* if it's from us, add to public */ | 206 | /* if it's from us, add to public */ |
| 207 | if (xs_startswith(id, snac.actor)) { | 207 | if (xs_startswith(id, snac.actor)) { |
| 208 | char *p, *v; | 208 | const xs_list *p; |
| 209 | char *v; | ||
| 210 | int c; | ||
| 209 | 211 | ||
| 210 | object_user_cache_add(&snac, id, "public"); | 212 | object_user_cache_add(&snac, id, "public"); |
| 211 | 213 | ||
| 212 | p = xs_dict_get(meta, "announced_by"); | 214 | p = xs_dict_get(meta, "announced_by"); |
| 213 | while (xs_list_iter(&p, &v)) | 215 | |
| 216 | c = 0; | ||
| 217 | while (xs_list_next(p, &v, &c)) | ||
| 214 | object_admire(id, v, 0); | 218 | object_admire(id, v, 0); |
| 219 | |||
| 215 | p = xs_dict_get(meta, "liked_by"); | 220 | p = xs_dict_get(meta, "liked_by"); |
| 216 | while (xs_list_iter(&p, &v)) | 221 | |
| 222 | c = 0; | ||
| 223 | while (xs_list_next(p, &v, &c)) | ||
| 217 | object_admire(id, v, 1); | 224 | object_admire(id, v, 1); |
| 218 | } | 225 | } |
| 219 | 226 | ||
| @@ -257,21 +264,28 @@ int snac_upgrade(xs_str **error) | |||
| 257 | xs *meta = xs_dup(xs_dict_get(o, "_snac")); | 264 | xs *meta = xs_dup(xs_dict_get(o, "_snac")); |
| 258 | o = xs_dict_del(o, "_snac"); | 265 | o = xs_dict_del(o, "_snac"); |
| 259 | 266 | ||
| 260 | char *id = xs_dict_get(o, "id"); | 267 | const char *id = xs_dict_get(o, "id"); |
| 261 | 268 | ||
| 262 | /* store object */ | 269 | /* store object */ |
| 263 | object_add_ow(id, o); | 270 | object_add_ow(id, o); |
| 264 | 271 | ||
| 265 | { | 272 | { |
| 266 | char *p, *v; | 273 | const xs_list *p; |
| 274 | char *v; | ||
| 275 | int c = 0; | ||
| 267 | 276 | ||
| 268 | object_user_cache_add(&snac, id, "private"); | 277 | object_user_cache_add(&snac, id, "private"); |
| 269 | 278 | ||
| 270 | p = xs_dict_get(meta, "announced_by"); | 279 | p = xs_dict_get(meta, "announced_by"); |
| 271 | while (xs_list_iter(&p, &v)) | 280 | |
| 281 | c = 0; | ||
| 282 | while (xs_list_next(p, &v, &c)) | ||
| 272 | object_admire(id, v, 0); | 283 | object_admire(id, v, 0); |
| 284 | |||
| 273 | p = xs_dict_get(meta, "liked_by"); | 285 | p = xs_dict_get(meta, "liked_by"); |
| 274 | while (xs_list_iter(&p, &v)) | 286 | |
| 287 | c = 0; | ||
| 288 | while (xs_list_next(p, &v, &c)) | ||
| 275 | object_admire(id, v, 1); | 289 | object_admire(id, v, 1); |
| 276 | } | 290 | } |
| 277 | 291 | ||
| @@ -418,7 +418,7 @@ int deluser(snac *user) | |||
| 418 | void verify_links(snac *user) | 418 | void verify_links(snac *user) |
| 419 | /* verifies a user's links */ | 419 | /* verifies a user's links */ |
| 420 | { | 420 | { |
| 421 | xs_dict *p = xs_dict_get(user->config, "metadata"); | 421 | const xs_dict *p = xs_dict_get(user->config, "metadata"); |
| 422 | char *k, *v; | 422 | char *k, *v; |
| 423 | int changed = 0; | 423 | int changed = 0; |
| 424 | 424 | ||
diff --git a/webfinger.c b/webfinger.c index 7255ae2..a12134d 100644 --- a/webfinger.c +++ b/webfinger.c | |||
| @@ -16,7 +16,7 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us | |||
| 16 | int p_size = 0; | 16 | int p_size = 0; |
| 17 | xs *headers = xs_dict_new(); | 17 | xs *headers = xs_dict_new(); |
| 18 | xs *l = NULL; | 18 | xs *l = NULL; |
| 19 | xs_str *host = NULL; | 19 | const char *host = NULL; |
| 20 | xs *resource = NULL; | 20 | xs *resource = NULL; |
| 21 | 21 | ||
| 22 | if (xs_startswith(qs, "https:/") || xs_startswith(qs, "http:/")) { | 22 | if (xs_startswith(qs, "https:/") || xs_startswith(qs, "http:/")) { |
| @@ -87,19 +87,20 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us | |||
| 87 | 87 | ||
| 88 | if (obj) { | 88 | if (obj) { |
| 89 | if (user != NULL) { | 89 | if (user != NULL) { |
| 90 | char *subject = xs_dict_get(obj, "subject"); | 90 | const char *subject = xs_dict_get(obj, "subject"); |
| 91 | 91 | ||
| 92 | if (subject) | 92 | if (subject) |
| 93 | *user = xs_replace_n(subject, "acct:", "", 1); | 93 | *user = xs_replace_n(subject, "acct:", "", 1); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | if (actor != NULL) { | 96 | if (actor != NULL) { |
| 97 | char *list = xs_dict_get(obj, "links"); | 97 | const xs_list *list = xs_dict_get(obj, "links"); |
| 98 | int c = 0; | ||
| 98 | char *v; | 99 | char *v; |
| 99 | 100 | ||
| 100 | while (xs_list_iter(&list, &v)) { | 101 | while (xs_list_next(list, &v, &c)) { |
| 101 | if (xs_type(v) == XSTYPE_DICT) { | 102 | if (xs_type(v) == XSTYPE_DICT) { |
| 102 | char *type = xs_dict_get(v, "type"); | 103 | const char *type = xs_dict_get(v, "type"); |
| 103 | 104 | ||
| 104 | if (type && (strcmp(type, "application/activity+json") == 0 || | 105 | if (type && (strcmp(type, "application/activity+json") == 0 || |
| 105 | strcmp(type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") == 0)) { | 106 | strcmp(type, "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"") == 0)) { |
| @@ -133,8 +134,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path, | |||
| 133 | if (strcmp(q_path, "/.well-known/webfinger") != 0) | 134 | if (strcmp(q_path, "/.well-known/webfinger") != 0) |
| 134 | return 0; | 135 | return 0; |
| 135 | 136 | ||
| 136 | char *q_vars = xs_dict_get(req, "q_vars"); | 137 | const char *q_vars = xs_dict_get(req, "q_vars"); |
| 137 | char *resource = xs_dict_get(q_vars, "resource"); | 138 | const char *resource = xs_dict_get(q_vars, "resource"); |
| 138 | 139 | ||
| 139 | if (resource == NULL) | 140 | if (resource == NULL) |
| 140 | return 400; | 141 | return 400; |
| @@ -145,7 +146,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path, | |||
| 145 | if (xs_startswith(resource, "https:/") || xs_startswith(resource, "http:/")) { | 146 | if (xs_startswith(resource, "https:/") || xs_startswith(resource, "http:/")) { |
| 146 | /* actor search: find a user with this actor */ | 147 | /* actor search: find a user with this actor */ |
| 147 | xs *l = xs_split(resource, "/"); | 148 | xs *l = xs_split(resource, "/"); |
| 148 | char *uid = xs_list_get(l, -1); | 149 | const char *uid = xs_list_get(l, -1); |
| 149 | 150 | ||
| 150 | if (uid) | 151 | if (uid) |
| 151 | found = user_open(&snac, uid); | 152 | found = user_open(&snac, uid); |
| @@ -163,8 +164,8 @@ int webfinger_get_handler(xs_dict *req, char *q_path, | |||
| 163 | l = xs_split_n(an, "@", 1); | 164 | l = xs_split_n(an, "@", 1); |
| 164 | 165 | ||
| 165 | if (xs_list_len(l) == 2) { | 166 | if (xs_list_len(l) == 2) { |
| 166 | char *uid = xs_list_get(l, 0); | 167 | const char *uid = xs_list_get(l, 0); |
| 167 | char *host = xs_list_get(l, 1); | 168 | const char *host = xs_list_get(l, 1); |
| 168 | 169 | ||
| 169 | if (strcmp(host, xs_dict_get(srv_config, "host")) == 0) | 170 | if (strcmp(host, xs_dict_get(srv_config, "host")) == 0) |
| 170 | found = user_open(&snac, uid); | 171 | found = user_open(&snac, uid); |
| @@ -194,7 +195,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path, | |||
| 194 | 195 | ||
| 195 | links = xs_list_append(links, prof); | 196 | links = xs_list_append(links, prof); |
| 196 | 197 | ||
| 197 | char *avatar = xs_dict_get(snac.config, "avatar"); | 198 | const char *avatar = xs_dict_get(snac.config, "avatar"); |
| 198 | if (!xs_is_null(avatar) && *avatar) { | 199 | if (!xs_is_null(avatar) && *avatar) { |
| 199 | xs *d = xs_dict_new(); | 200 | xs *d = xs_dict_new(); |
| 200 | 201 | ||
| @@ -21,8 +21,8 @@ typedef enum { | |||
| 21 | XSTYPE_FALSE = 0x15, /* Boolean */ | 21 | XSTYPE_FALSE = 0x15, /* Boolean */ |
| 22 | XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */ | 22 | XSTYPE_LIST = 0x1d, /* Sequence of LITEMs up to EOM (with size) */ |
| 23 | XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */ | 23 | XSTYPE_LITEM = 0x1f, /* Element of a list (any type) */ |
| 24 | XSTYPE_DICT = 0x1c, /* Sequence of DITEMs up to EOM (with size) */ | 24 | XSTYPE_DICT = 0x1c, /* Sequence of KEYVALs up to EOM (with size) */ |
| 25 | XSTYPE_DITEM = 0x1e, /* Element of a dict (STRING key + any type) */ | 25 | XSTYPE_KEYVAL = 0x1e, /* key + value (STRING key + any type) */ |
| 26 | XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */ | 26 | XSTYPE_EOM = 0x19, /* End of Multiple (LIST or DICT) */ |
| 27 | XSTYPE_DATA = 0x10 /* A block of anonymous data */ | 27 | XSTYPE_DATA = 0x10 /* A block of anonymous data */ |
| 28 | } xstype; | 28 | } xstype; |
| @@ -32,6 +32,7 @@ typedef enum { | |||
| 32 | typedef char xs_val; | 32 | typedef char xs_val; |
| 33 | typedef char xs_str; | 33 | typedef char xs_str; |
| 34 | typedef char xs_list; | 34 | typedef char xs_list; |
| 35 | typedef char xs_keyval; | ||
| 35 | typedef char xs_dict; | 36 | typedef char xs_dict; |
| 36 | typedef char xs_number; | 37 | typedef char xs_number; |
| 37 | typedef char xs_data; | 38 | typedef char xs_data; |
| @@ -96,7 +97,7 @@ xs_list *_xs_list_append(xs_list *list, const xs_val *vals[]); | |||
| 96 | int xs_list_iter(xs_list **list, xs_val **value); | 97 | int xs_list_iter(xs_list **list, xs_val **value); |
| 97 | int xs_list_next(const xs_list *list, xs_val **value, int *ctxt); | 98 | int xs_list_next(const xs_list *list, xs_val **value, int *ctxt); |
| 98 | int xs_list_len(const xs_list *list); | 99 | int xs_list_len(const xs_list *list); |
| 99 | xs_val *xs_list_get(const xs_list *list, int num); | 100 | const xs_val *xs_list_get(const xs_list *list, int num); |
| 100 | xs_list *xs_list_del(xs_list *list, int num); | 101 | xs_list *xs_list_del(xs_list *list, int num); |
| 101 | xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data); | 102 | xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data); |
| 102 | xs_list *xs_list_set(xs_list *list, int num, const xs_val *data); | 103 | xs_list *xs_list_set(xs_list *list, int num, const xs_val *data); |
| @@ -109,14 +110,20 @@ xs_list *xs_split_n(const char *str, const char *sep, int times); | |||
| 109 | #define xs_split(str, sep) xs_split_n(str, sep, XS_ALL) | 110 | #define xs_split(str, sep) xs_split_n(str, sep, XS_ALL) |
| 110 | xs_list *xs_list_cat(xs_list *l1, const xs_list *l2); | 111 | xs_list *xs_list_cat(xs_list *l1, const xs_list *l2); |
| 111 | 112 | ||
| 113 | int xs_keyval_size(const xs_str *key, const xs_val *value); | ||
| 114 | xs_str *xs_keyval_key(const xs_keyval *keyval); | ||
| 115 | xs_val *xs_keyval_value(const xs_keyval *keyval); | ||
| 116 | xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value); | ||
| 117 | |||
| 112 | xs_dict *xs_dict_new(void); | 118 | xs_dict *xs_dict_new(void); |
| 113 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value); | 119 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value); |
| 114 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value); | 120 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value); |
| 115 | int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt); | 121 | int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt); |
| 116 | xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def); | 122 | const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def); |
| 117 | #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL) | 123 | #define xs_dict_get(dict, key) xs_dict_get_def(dict, key, NULL) |
| 118 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); | 124 | xs_dict *xs_dict_del(xs_dict *dict, const xs_str *key); |
| 119 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); | 125 | xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data); |
| 126 | xs_dict *xs_dict_gc(xs_dict *dict); | ||
| 120 | 127 | ||
| 121 | xs_val *xs_val_new(xstype t); | 128 | xs_val *xs_val_new(xstype t); |
| 122 | xs_number *xs_number_new(double f); | 129 | xs_number *xs_number_new(double f); |
| @@ -244,7 +251,7 @@ xstype xs_type(const xs_val *data) | |||
| 244 | case XSTYPE_LIST: | 251 | case XSTYPE_LIST: |
| 245 | case XSTYPE_LITEM: | 252 | case XSTYPE_LITEM: |
| 246 | case XSTYPE_DICT: | 253 | case XSTYPE_DICT: |
| 247 | case XSTYPE_DITEM: | 254 | case XSTYPE_KEYVAL: |
| 248 | case XSTYPE_NUMBER: | 255 | case XSTYPE_NUMBER: |
| 249 | case XSTYPE_EOM: | 256 | case XSTYPE_EOM: |
| 250 | case XSTYPE_DATA: | 257 | case XSTYPE_DATA: |
| @@ -262,7 +269,7 @@ xstype xs_type(const xs_val *data) | |||
| 262 | void _xs_put_size(xs_val *ptr, int i) | 269 | void _xs_put_size(xs_val *ptr, int i) |
| 263 | /* must match _XS_TYPE_SIZE */ | 270 | /* must match _XS_TYPE_SIZE */ |
| 264 | { | 271 | { |
| 265 | memcpy(ptr, &i, sizeof(i)); | 272 | memcpy(ptr + 1, &i, sizeof(i)); |
| 266 | } | 273 | } |
| 267 | 274 | ||
| 268 | 275 | ||
| @@ -296,7 +303,7 @@ int xs_size(const xs_val *data) | |||
| 296 | 303 | ||
| 297 | break; | 304 | break; |
| 298 | 305 | ||
| 299 | case XSTYPE_DITEM: | 306 | case XSTYPE_KEYVAL: |
| 300 | /* calculate the size of the key and the value */ | 307 | /* calculate the size of the key and the value */ |
| 301 | p = data + 1; | 308 | p = data + 1; |
| 302 | p += xs_size(p); | 309 | p += xs_size(p); |
| @@ -380,7 +387,7 @@ xs_val *xs_expand(xs_val *data, int offset, int size) | |||
| 380 | if (xs_type(data) == XSTYPE_LIST || | 387 | if (xs_type(data) == XSTYPE_LIST || |
| 381 | xs_type(data) == XSTYPE_DICT || | 388 | xs_type(data) == XSTYPE_DICT || |
| 382 | xs_type(data) == XSTYPE_DATA) | 389 | xs_type(data) == XSTYPE_DATA) |
| 383 | _xs_put_size(data + 1, sz); | 390 | _xs_put_size(data, sz); |
| 384 | 391 | ||
| 385 | return data; | 392 | return data; |
| 386 | } | 393 | } |
| @@ -405,7 +412,7 @@ xs_val *xs_collapse(xs_val *data, int offset, int size) | |||
| 405 | if (xs_type(data) == XSTYPE_LIST || | 412 | if (xs_type(data) == XSTYPE_LIST || |
| 406 | xs_type(data) == XSTYPE_DICT || | 413 | xs_type(data) == XSTYPE_DICT || |
| 407 | xs_type(data) == XSTYPE_DATA) | 414 | xs_type(data) == XSTYPE_DATA) |
| 408 | _xs_put_size(data + 1, sz); | 415 | _xs_put_size(data, sz); |
| 409 | 416 | ||
| 410 | return xs_realloc(data, _xs_blk_size(sz)); | 417 | return xs_realloc(data, _xs_blk_size(sz)); |
| 411 | } | 418 | } |
| @@ -666,10 +673,10 @@ xs_list *xs_list_new(void) | |||
| 666 | { | 673 | { |
| 667 | int sz = 1 + _XS_TYPE_SIZE + 1; | 674 | int sz = 1 + _XS_TYPE_SIZE + 1; |
| 668 | xs_list *l = xs_realloc(NULL, sz); | 675 | xs_list *l = xs_realloc(NULL, sz); |
| 669 | memset(l, '\0', sz); | 676 | memset(l, XSTYPE_EOM, sz); |
| 670 | 677 | ||
| 671 | l[0] = XSTYPE_LIST; | 678 | l[0] = XSTYPE_LIST; |
| 672 | _xs_put_size(&l[1], sz); | 679 | _xs_put_size(l, sz); |
| 673 | 680 | ||
| 674 | return l; | 681 | return l; |
| 675 | } | 682 | } |
| @@ -802,7 +809,7 @@ int xs_list_len(const xs_list *list) | |||
| 802 | } | 809 | } |
| 803 | 810 | ||
| 804 | 811 | ||
| 805 | xs_val *xs_list_get(const xs_list *list, int num) | 812 | const xs_val *xs_list_get(const xs_list *list, int num) |
| 806 | /* returns the element #num */ | 813 | /* returns the element #num */ |
| 807 | { | 814 | { |
| 808 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 815 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| @@ -830,7 +837,7 @@ xs_list *xs_list_del(xs_list *list, int num) | |||
| 830 | { | 837 | { |
| 831 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 838 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 832 | 839 | ||
| 833 | xs_val *v; | 840 | const xs_val *v; |
| 834 | 841 | ||
| 835 | if ((v = xs_list_get(list, num)) != NULL) | 842 | if ((v = xs_list_get(list, num)) != NULL) |
| 836 | list = xs_collapse(list, v - 1 - list, xs_size(v - 1)); | 843 | list = xs_collapse(list, v - 1 - list, xs_size(v - 1)); |
| @@ -844,7 +851,7 @@ xs_list *xs_list_insert(xs_list *list, int num, const xs_val *data) | |||
| 844 | { | 851 | { |
| 845 | XS_ASSERT_TYPE(list, XSTYPE_LIST); | 852 | XS_ASSERT_TYPE(list, XSTYPE_LIST); |
| 846 | 853 | ||
| 847 | xs_val *v; | 854 | const xs_val *v; |
| 848 | int offset; | 855 | int offset; |
| 849 | 856 | ||
| 850 | if ((v = xs_list_get(list, num)) != NULL) | 857 | if ((v = xs_list_get(list, num)) != NULL) |
| @@ -999,6 +1006,40 @@ xs_list *xs_list_cat(xs_list *l1, const xs_list *l2) | |||
| 999 | } | 1006 | } |
| 1000 | 1007 | ||
| 1001 | 1008 | ||
| 1009 | /** keyvals **/ | ||
| 1010 | |||
| 1011 | int xs_keyval_size(const xs_str *key, const xs_val *value) | ||
| 1012 | /* returns the needed size for a keyval */ | ||
| 1013 | { | ||
| 1014 | return 1 + xs_size(key) + xs_size(value); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | |||
| 1018 | xs_str *xs_keyval_key(const xs_keyval *keyval) | ||
| 1019 | /* returns a pointer to the key of the keyval */ | ||
| 1020 | { | ||
| 1021 | return (xs_str *)&keyval[1]; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | |||
| 1025 | xs_val *xs_keyval_value(const xs_keyval *keyval) | ||
| 1026 | /* returns a pointer to the value of the keyval */ | ||
| 1027 | { | ||
| 1028 | return (xs_val *)&keyval[1 + xs_size(xs_keyval_key(keyval))]; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | |||
| 1032 | xs_keyval *xs_keyval_make(xs_keyval *keyval, const xs_str *key, const xs_val *value) | ||
| 1033 | /* builds a keyval into mem (should have enough size) */ | ||
| 1034 | { | ||
| 1035 | keyval[0] = XSTYPE_KEYVAL; | ||
| 1036 | memcpy(xs_keyval_key(keyval), key, xs_size(key)); | ||
| 1037 | memcpy(xs_keyval_value(keyval), value, xs_size(value)); | ||
| 1038 | |||
| 1039 | return keyval; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | |||
| 1002 | /** dicts **/ | 1043 | /** dicts **/ |
| 1003 | 1044 | ||
| 1004 | xs_dict *xs_dict_new(void) | 1045 | xs_dict *xs_dict_new(void) |
| @@ -1006,34 +1047,27 @@ xs_dict *xs_dict_new(void) | |||
| 1006 | { | 1047 | { |
| 1007 | int sz = 1 + _XS_TYPE_SIZE + 1; | 1048 | int sz = 1 + _XS_TYPE_SIZE + 1; |
| 1008 | xs_dict *d = xs_realloc(NULL, sz); | 1049 | xs_dict *d = xs_realloc(NULL, sz); |
| 1009 | memset(d, '\0', sz); | 1050 | memset(d, XSTYPE_EOM, sz); |
| 1010 | 1051 | ||
| 1011 | d[0] = XSTYPE_DICT; | 1052 | d[0] = XSTYPE_DICT; |
| 1012 | _xs_put_size(&d[1], sz); | 1053 | _xs_put_size(d, sz); |
| 1013 | 1054 | ||
| 1014 | return d; | 1055 | return d; |
| 1015 | } | 1056 | } |
| 1016 | 1057 | ||
| 1017 | 1058 | ||
| 1018 | xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key, | 1059 | xs_dict *_xs_dict_write_keyval(xs_dict *dict, int offset, const xs_str *key, const xs_val *value) |
| 1019 | const xs_val *data, int dsz) | 1060 | /* adds a new keyval to the dict */ |
| 1020 | /* inserts a memory block into the dict */ | ||
| 1021 | { | 1061 | { |
| 1022 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); | 1062 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); |
| 1023 | XS_ASSERT_TYPE(key, XSTYPE_STRING); | 1063 | XS_ASSERT_TYPE(key, XSTYPE_STRING); |
| 1024 | 1064 | ||
| 1025 | if (data == NULL) { | 1065 | if (value == NULL) |
| 1026 | data = xs_stock(XSTYPE_NULL); | 1066 | value = xs_stock(XSTYPE_NULL); |
| 1027 | dsz = xs_size(data); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | int ksz = xs_size(key); | ||
| 1031 | 1067 | ||
| 1032 | dict = xs_expand(dict, offset, 1 + ksz + dsz); | 1068 | dict = xs_expand(dict, offset, xs_keyval_size(key, value)); |
| 1033 | 1069 | ||
| 1034 | dict[offset] = XSTYPE_DITEM; | 1070 | xs_keyval_make(&dict[offset], key, value); |
| 1035 | memcpy(&dict[offset + 1], key, ksz); | ||
| 1036 | memcpy(&dict[offset + 1 + ksz], data, dsz); | ||
| 1037 | 1071 | ||
| 1038 | return dict; | 1072 | return dict; |
| 1039 | } | 1073 | } |
| @@ -1042,14 +1076,14 @@ xs_dict *_xs_dict_write_ditem(xs_dict *dict, int offset, const xs_str *key, | |||
| 1042 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value) | 1076 | xs_dict *xs_dict_append(xs_dict *dict, const xs_str *key, const xs_val *value) |
| 1043 | /* appends a memory block to the dict */ | 1077 | /* appends a memory block to the dict */ |
| 1044 | { | 1078 | { |
| 1045 | return _xs_dict_write_ditem(dict, xs_size(dict) - 1, key, value, xs_size(value)); | 1079 | return _xs_dict_write_keyval(dict, xs_size(dict) - 1, key, value); |
| 1046 | } | 1080 | } |
| 1047 | 1081 | ||
| 1048 | 1082 | ||
| 1049 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value) | 1083 | xs_dict *xs_dict_prepend(xs_dict *dict, const xs_str *key, const xs_val *value) |
| 1050 | /* prepends a memory block to the dict */ | 1084 | /* prepends a memory block to the dict */ |
| 1051 | { | 1085 | { |
| 1052 | return _xs_dict_write_ditem(dict, 1 + _XS_TYPE_SIZE, key, value, xs_size(value)); | 1086 | return _xs_dict_write_keyval(dict, 1 + _XS_TYPE_SIZE, key, value); |
| 1053 | } | 1087 | } |
| 1054 | 1088 | ||
| 1055 | 1089 | ||
| @@ -1070,7 +1104,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt) | |||
| 1070 | p += *ctxt; | 1104 | p += *ctxt; |
| 1071 | 1105 | ||
| 1072 | /* an element? */ | 1106 | /* an element? */ |
| 1073 | if (xs_type(p) == XSTYPE_DITEM) { | 1107 | if (xs_type(p) == XSTYPE_KEYVAL) { |
| 1074 | p++; | 1108 | p++; |
| 1075 | 1109 | ||
| 1076 | *key = p; | 1110 | *key = p; |
| @@ -1091,7 +1125,7 @@ int xs_dict_next(const xs_dict *dict, xs_str **key, xs_val **value, int *ctxt) | |||
| 1091 | } | 1125 | } |
| 1092 | 1126 | ||
| 1093 | 1127 | ||
| 1094 | xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def) | 1128 | const xs_val *xs_dict_get_def(const xs_dict *dict, const xs_str *key, const xs_val *def) |
| 1095 | /* returns the value directed by key, or the default value */ | 1129 | /* returns the value directed by key, or the default value */ |
| 1096 | { | 1130 | { |
| 1097 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); | 1131 | XS_ASSERT_TYPE(dict, XSTYPE_DICT); |
| @@ -1150,6 +1184,14 @@ xs_dict *xs_dict_set(xs_dict *dict, const xs_str *key, const xs_val *data) | |||
| 1150 | } | 1184 | } |
| 1151 | 1185 | ||
| 1152 | 1186 | ||
| 1187 | xs_dict *xs_dict_gc(xs_dict *dict) | ||
| 1188 | /* collects garbage (leaked values) inside a dict */ | ||
| 1189 | { | ||
| 1190 | /* this kind of dicts does not get garbage */ | ||
| 1191 | return dict; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | |||
| 1153 | /** other values **/ | 1195 | /** other values **/ |
| 1154 | 1196 | ||
| 1155 | xs_val *xs_val_new(xstype t) | 1197 | xs_val *xs_val_new(xstype t) |
| @@ -1235,7 +1277,7 @@ xs_data *xs_data_new(const void *data, int size) | |||
| 1235 | v = xs_realloc(NULL, _xs_blk_size(total_size)); | 1277 | v = xs_realloc(NULL, _xs_blk_size(total_size)); |
| 1236 | v[0] = XSTYPE_DATA; | 1278 | v[0] = XSTYPE_DATA; |
| 1237 | 1279 | ||
| 1238 | _xs_put_size(v + 1, total_size); | 1280 | _xs_put_size(v, total_size); |
| 1239 | 1281 | ||
| 1240 | memcpy(&v[1 + _XS_TYPE_SIZE], data, size); | 1282 | memcpy(&v[1 + _XS_TYPE_SIZE], data, size); |
| 1241 | 1283 | ||
| @@ -28,7 +28,7 @@ static size_t _header_callback(char *buffer, size_t size, | |||
| 28 | if (xs_str_in(l, ": ") != -1) { | 28 | if (xs_str_in(l, ": ") != -1) { |
| 29 | xs *knv = xs_split_n(l, ": ", 1); | 29 | xs *knv = xs_split_n(l, ": ", 1); |
| 30 | 30 | ||
| 31 | xs_tolower_i(xs_list_get(knv, 0)); | 31 | xs_tolower_i((xs_str *)xs_list_get(knv, 0)); |
| 32 | 32 | ||
| 33 | headers = xs_dict_set(headers, xs_list_get(knv, 0), xs_list_get(knv, 1)); | 33 | headers = xs_dict_set(headers, xs_list_get(knv, 0), xs_list_get(knv, 1)); |
| 34 | } | 34 | } |
| @@ -6,26 +6,26 @@ | |||
| 6 | 6 | ||
| 7 | typedef struct xs_html xs_html; | 7 | typedef struct xs_html xs_html; |
| 8 | 8 | ||
| 9 | xs_str *xs_html_encode(char *str); | 9 | xs_str *xs_html_encode(const char *str); |
| 10 | 10 | ||
| 11 | xs_html *xs_html_attr(char *key, char *value); | 11 | xs_html *xs_html_attr(const char *key, const char *value); |
| 12 | xs_html *xs_html_text(char *content); | 12 | xs_html *xs_html_text(const char *content); |
| 13 | xs_html *xs_html_raw(char *content); | 13 | xs_html *xs_html_raw(const char *content); |
| 14 | 14 | ||
| 15 | xs_html *_xs_html_add(xs_html *tag, xs_html *var[]); | 15 | xs_html *_xs_html_add(xs_html *tag, xs_html *var[]); |
| 16 | #define xs_html_add(tag, ...) _xs_html_add(tag, (xs_html *[]) { __VA_ARGS__, NULL }) | 16 | #define xs_html_add(tag, ...) _xs_html_add(tag, (xs_html *[]) { __VA_ARGS__, NULL }) |
| 17 | 17 | ||
| 18 | xs_html *_xs_html_tag(char *tag, xs_html *var[]); | 18 | xs_html *_xs_html_tag(const char *tag, xs_html *var[]); |
| 19 | #define xs_html_tag(tag, ...) _xs_html_tag(tag, (xs_html *[]) { __VA_ARGS__, NULL }) | 19 | #define xs_html_tag(tag, ...) _xs_html_tag(tag, (xs_html *[]) { __VA_ARGS__, NULL }) |
| 20 | 20 | ||
| 21 | xs_html *_xs_html_sctag(char *tag, xs_html *var[]); | 21 | xs_html *_xs_html_sctag(const char *tag, xs_html *var[]); |
| 22 | #define xs_html_sctag(tag, ...) _xs_html_sctag(tag, (xs_html *[]) { __VA_ARGS__, NULL }) | 22 | #define xs_html_sctag(tag, ...) _xs_html_sctag(tag, (xs_html *[]) { __VA_ARGS__, NULL }) |
| 23 | 23 | ||
| 24 | xs_html *_xs_html_container(xs_html *var[]); | 24 | xs_html *_xs_html_container(xs_html *var[]); |
| 25 | #define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL }) | 25 | #define xs_html_container(...) _xs_html_container((xs_html *[]) { __VA_ARGS__, NULL }) |
| 26 | 26 | ||
| 27 | void xs_html_render_f(xs_html *h, FILE *f); | 27 | void xs_html_render_f(xs_html *h, FILE *f); |
| 28 | xs_str *xs_html_render_s(xs_html *tag, char *prefix); | 28 | xs_str *xs_html_render_s(xs_html *tag, const char *prefix); |
| 29 | #define xs_html_render(tag) xs_html_render_s(tag, NULL) | 29 | #define xs_html_render(tag) xs_html_render_s(tag, NULL) |
| 30 | 30 | ||
| 31 | 31 | ||
| @@ -47,16 +47,16 @@ struct xs_html { | |||
| 47 | xs_html *next; | 47 | xs_html *next; |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | xs_str *xs_html_encode(char *str) | 50 | xs_str *xs_html_encode(const char *str) |
| 51 | /* encodes str using HTML entities */ | 51 | /* encodes str using HTML entities */ |
| 52 | { | 52 | { |
| 53 | xs_str *s = xs_str_new(NULL); | 53 | xs_str *s = xs_str_new(NULL); |
| 54 | int o = 0; | 54 | int o = 0; |
| 55 | char *e = str + strlen(str); | 55 | const char *e = str + strlen(str); |
| 56 | 56 | ||
| 57 | for (;;) { | 57 | for (;;) { |
| 58 | char *ec = "<>\"'&"; /* characters to escape */ | 58 | char *ec = "<>\"'&"; /* characters to escape */ |
| 59 | char *q = e; | 59 | const char *q = e; |
| 60 | int z; | 60 | int z; |
| 61 | 61 | ||
| 62 | /* find the nearest happening of a char */ | 62 | /* find the nearest happening of a char */ |
| @@ -90,7 +90,7 @@ xs_str *xs_html_encode(char *str) | |||
| 90 | 90 | ||
| 91 | #define XS_HTML_NEW() memset(xs_realloc(NULL, sizeof(xs_html)), '\0', sizeof(xs_html)) | 91 | #define XS_HTML_NEW() memset(xs_realloc(NULL, sizeof(xs_html)), '\0', sizeof(xs_html)) |
| 92 | 92 | ||
| 93 | xs_html *xs_html_attr(char *key, char *value) | 93 | xs_html *xs_html_attr(const char *key, const char *value) |
| 94 | /* creates an HTML block with an attribute */ | 94 | /* creates an HTML block with an attribute */ |
| 95 | { | 95 | { |
| 96 | xs_html *a = XS_HTML_NEW(); | 96 | xs_html *a = XS_HTML_NEW(); |
| @@ -108,7 +108,7 @@ xs_html *xs_html_attr(char *key, char *value) | |||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | 110 | ||
| 111 | xs_html *xs_html_text(char *content) | 111 | xs_html *xs_html_text(const char *content) |
| 112 | /* creates an HTML block of text, escaping it previously */ | 112 | /* creates an HTML block of text, escaping it previously */ |
| 113 | { | 113 | { |
| 114 | xs_html *a = XS_HTML_NEW(); | 114 | xs_html *a = XS_HTML_NEW(); |
| @@ -120,7 +120,7 @@ xs_html *xs_html_text(char *content) | |||
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | 122 | ||
| 123 | xs_html *xs_html_raw(char *content) | 123 | xs_html *xs_html_raw(const char *content) |
| 124 | /* creates an HTML block without escaping (for pre-formatted HTML, comments, etc) */ | 124 | /* creates an HTML block without escaping (for pre-formatted HTML, comments, etc) */ |
| 125 | { | 125 | { |
| 126 | xs_html *a = XS_HTML_NEW(); | 126 | xs_html *a = XS_HTML_NEW(); |
| @@ -152,7 +152,7 @@ xs_html *_xs_html_add(xs_html *tag, xs_html *var[]) | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | 154 | ||
| 155 | static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[]) | 155 | static xs_html *_xs_html_tag_t(xs_html_type type, const char *tag, xs_html *var[]) |
| 156 | /* creates a tag with a variable list of attributes and subtags */ | 156 | /* creates a tag with a variable list of attributes and subtags */ |
| 157 | { | 157 | { |
| 158 | xs_html *a = XS_HTML_NEW(); | 158 | xs_html *a = XS_HTML_NEW(); |
| @@ -169,13 +169,13 @@ static xs_html *_xs_html_tag_t(xs_html_type type, char *tag, xs_html *var[]) | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | 171 | ||
| 172 | xs_html *_xs_html_tag(char *tag, xs_html *var[]) | 172 | xs_html *_xs_html_tag(const char *tag, xs_html *var[]) |
| 173 | { | 173 | { |
| 174 | return _xs_html_tag_t(XS_HTML_TAG, tag, var); | 174 | return _xs_html_tag_t(XS_HTML_TAG, tag, var); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | 177 | ||
| 178 | xs_html *_xs_html_sctag(char *tag, xs_html *var[]) | 178 | xs_html *_xs_html_sctag(const char *tag, xs_html *var[]) |
| 179 | { | 179 | { |
| 180 | return _xs_html_tag_t(XS_HTML_SCTAG, tag, var); | 180 | return _xs_html_tag_t(XS_HTML_SCTAG, tag, var); |
| 181 | } | 181 | } |
| @@ -239,7 +239,7 @@ void xs_html_render_f(xs_html *h, FILE *f) | |||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | 241 | ||
| 242 | xs_str *xs_html_render_s(xs_html *tag, char *prefix) | 242 | xs_str *xs_html_render_s(xs_html *tag, const char *prefix) |
| 243 | /* renders to a string */ | 243 | /* renders to a string */ |
| 244 | { | 244 | { |
| 245 | xs_str *s = NULL; | 245 | xs_str *s = NULL; |
| @@ -16,7 +16,7 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size) | |||
| 16 | xs *q_vars = NULL; | 16 | xs *q_vars = NULL; |
| 17 | xs *p_vars = NULL; | 17 | xs *p_vars = NULL; |
| 18 | xs *l1, *l2; | 18 | xs *l1, *l2; |
| 19 | char *v; | 19 | const char *v; |
| 20 | 20 | ||
| 21 | xs_socket_timeout(fileno(f), 2.0, 0.0); | 21 | xs_socket_timeout(fileno(f), 2.0, 0.0); |
| 22 | 22 | ||
| @@ -60,7 +60,8 @@ xs_dict *xs_httpd_request(FILE *f, xs_str **payload, int *p_size) | |||
| 60 | p = xs_split_n(l, ": ", 1); | 60 | p = xs_split_n(l, ": ", 1); |
| 61 | 61 | ||
| 62 | if (xs_list_len(p) == 2) | 62 | if (xs_list_len(p) == 2) |
| 63 | req = xs_dict_append(req, xs_tolower_i(xs_list_get(p, 0)), xs_list_get(p, 1)); | 63 | req = xs_dict_append(req, xs_tolower_i( |
| 64 | (xs_str *)xs_list_get(p, 0)), xs_list_get(p, 1)); | ||
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | xs_socket_timeout(fileno(f), 5.0, 0.0); | 67 | xs_socket_timeout(fileno(f), 5.0, 0.0); |
| @@ -71,12 +71,12 @@ static void _xs_json_indent(int level, int indent, FILE *f) | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | 73 | ||
| 74 | static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f) | 74 | static void _xs_json_dump(const xs_val *data, int level, int indent, FILE *f) |
| 75 | /* dumps partial data as JSON */ | 75 | /* dumps partial data as JSON */ |
| 76 | { | 76 | { |
| 77 | int c = 0; | 77 | int c = 0; |
| 78 | int ct = 0; | ||
| 78 | xs_val *v; | 79 | xs_val *v; |
| 79 | xs_val *data = (xs_val *)s_data; | ||
| 80 | 80 | ||
| 81 | switch (xs_type(data)) { | 81 | switch (xs_type(data)) { |
| 82 | case XSTYPE_NULL: | 82 | case XSTYPE_NULL: |
| @@ -98,7 +98,7 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f) | |||
| 98 | case XSTYPE_LIST: | 98 | case XSTYPE_LIST: |
| 99 | fputc('[', f); | 99 | fputc('[', f); |
| 100 | 100 | ||
| 101 | while (xs_list_iter(&data, &v)) { | 101 | while (xs_list_next(data, &v, &ct)) { |
| 102 | if (c != 0) | 102 | if (c != 0) |
| 103 | fputc(',', f); | 103 | fputc(',', f); |
| 104 | 104 | ||
| @@ -117,9 +117,8 @@ static void _xs_json_dump(const xs_val *s_data, int level, int indent, FILE *f) | |||
| 117 | fputc('{', f); | 117 | fputc('{', f); |
| 118 | 118 | ||
| 119 | xs_str *k; | 119 | xs_str *k; |
| 120 | int ct = 0; | ||
| 121 | 120 | ||
| 122 | while (xs_dict_next(s_data, &k, &v, &ct)) { | 121 | while (xs_dict_next(data, &k, &v, &ct)) { |
| 123 | if (c != 0) | 122 | if (c != 0) |
| 124 | fputc(',', f); | 123 | fputc(',', f); |
| 125 | 124 | ||
| @@ -104,7 +104,7 @@ int xs_set_add(xs_set *s, const xs_val *data) | |||
| 104 | 104 | ||
| 105 | /* if it's new, add the data */ | 105 | /* if it's new, add the data */ |
| 106 | if (ret) | 106 | if (ret) |
| 107 | s->list = xs_list_append_m(s->list, data, xs_size(data)); | 107 | s->list = xs_list_append(s->list, data); |
| 108 | 108 | ||
| 109 | return ret; | 109 | return ret; |
| 110 | } | 110 | } |
diff --git a/xs_unicode.h b/xs_unicode.h index 6654da4..1799d89 100644 --- a/xs_unicode.h +++ b/xs_unicode.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | int _xs_utf8_enc(char buf[4], unsigned int cpoint); | 7 | int _xs_utf8_enc(char buf[4], unsigned int cpoint); |
| 8 | int xs_is_utf8_cont_byte(char c); | 8 | int xs_is_utf8_cont_byte(char c); |
| 9 | unsigned int xs_utf8_dec(char **str); | 9 | unsigned int xs_utf8_dec(const char **str); |
| 10 | int xs_unicode_width(unsigned int cpoint); | 10 | int xs_unicode_width(unsigned int cpoint); |
| 11 | int xs_is_surrogate(unsigned int cpoint); | 11 | int xs_is_surrogate(unsigned int cpoint); |
| 12 | unsigned int xs_surrogate_dec(unsigned int p1, unsigned int p2); | 12 | unsigned int xs_surrogate_dec(unsigned int p1, unsigned int p2); |
| @@ -66,10 +66,10 @@ int xs_is_utf8_cont_byte(char c) | |||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | 68 | ||
| 69 | unsigned int xs_utf8_dec(char **str) | 69 | unsigned int xs_utf8_dec(const char **str) |
| 70 | /* decodes an utf-8 char inside str and updates the pointer */ | 70 | /* decodes an utf-8 char inside str and updates the pointer */ |
| 71 | { | 71 | { |
| 72 | char *p = *str; | 72 | const char *p = *str; |
| 73 | unsigned int cpoint = 0; | 73 | unsigned int cpoint = 0; |
| 74 | unsigned char c = *p++; | 74 | unsigned char c = *p++; |
| 75 | int cb = 0; | 75 | int cb = 0; |
| @@ -119,8 +119,8 @@ xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *hea | |||
| 119 | while ((p = xs_memmem(payload + offset, p_size - offset, boundary, bsz)) != NULL) { | 119 | while ((p = xs_memmem(payload + offset, p_size - offset, boundary, bsz)) != NULL) { |
| 120 | xs *s1 = NULL; | 120 | xs *s1 = NULL; |
| 121 | xs *l1 = NULL; | 121 | xs *l1 = NULL; |
| 122 | char *vn = NULL; | 122 | const char *vn = NULL; |
| 123 | char *fn = NULL; | 123 | const char *fn = NULL; |
| 124 | char *q; | 124 | char *q; |
| 125 | int po, ps; | 125 | int po, ps; |
| 126 | 126 | ||
diff --git a/xs_version.h b/xs_version.h index 16faf2b..9ecf9b8 100644 --- a/xs_version.h +++ b/xs_version.h | |||
| @@ -1 +1 @@ | |||
| /* 6e75e8736f7f1b6ea6c6774d4bd922b3ad56b771 2024-05-15T11:42:19+02:00 */ | /* 34850dcdec50b669a2c0bbe9f16f6d9c4b16eafd 2024-05-21T14:06:02+02:00 */ | ||