summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Louis Brauer2024-05-26 21:45:41 +0200
committerGravatar Louis Brauer2024-05-26 21:45:41 +0200
commit0e21d35e802bf859aa14bce688cd9544458e9e9c (patch)
tree55861603d4f702d56edafe24aa1019484b714fbc
parentEnable deletion of avatar and header image in user settings (diff)
downloadpenes-snac2-0e21d35e802bf859aa14bce688cd9544458e9e9c.tar.gz
penes-snac2-0e21d35e802bf859aa14bce688cd9544458e9e9c.tar.xz
penes-snac2-0e21d35e802bf859aa14bce688cd9544458e9e9c.zip
Use enum instead of numeric status codes for HTTP statuses
-rw-r--r--activitypub.c56
-rw-r--r--data.c68
-rw-r--r--html.c76
-rw-r--r--httpd.c26
-rw-r--r--mastoapi.c184
-rw-r--r--snac.h50
-rw-r--r--webfinger.c8
7 files changed, 262 insertions, 206 deletions
diff --git a/activitypub.c b/activitypub.c
index 6e40a88..4247078 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -96,19 +96,19 @@ int activitypub_request(snac *user, const char *url, xs_dict **data)
96 ctype = xs_dict_get(response, "content-type"); 96 ctype = xs_dict_get(response, "content-type");
97 97
98 if (xs_is_null(ctype)) 98 if (xs_is_null(ctype))
99 status = 400; 99 status = HTTP_STATUS_BAD_REQUEST;
100 else 100 else
101 if (xs_str_in(ctype, "application/activity+json") != -1 || 101 if (xs_str_in(ctype, "application/activity+json") != -1 ||
102 xs_str_in(ctype, "application/ld+json") != -1) { 102 xs_str_in(ctype, "application/ld+json") != -1) {
103 103
104 /* if there is no payload, fail */ 104 /* if there is no payload, fail */
105 if (xs_is_null(payload)) 105 if (xs_is_null(payload))
106 status = 400; 106 status = HTTP_STATUS_BAD_REQUEST;
107 else 107 else
108 *data = xs_json_loads(payload); 108 *data = xs_json_loads(payload);
109 } 109 }
110 else 110 else
111 status = 500; 111 status = HTTP_STATUS_INTERNAL_SERVER_ERROR;
112 } 112 }
113 113
114 return status; 114 return status;
@@ -443,7 +443,7 @@ int send_to_actor(snac *snac, const char *actor, const xs_dict *msg,
443 xs_val **payload, int *p_size, int timeout) 443 xs_val **payload, int *p_size, int timeout)
444/* sends a message to an actor */ 444/* sends a message to an actor */
445{ 445{
446 int status = 400; 446 int status = HTTP_STATUS_BAD_REQUEST;
447 xs *inbox = get_actor_inbox(actor); 447 xs *inbox = get_actor_inbox(actor);
448 448
449 if (!xs_is_null(inbox)) 449 if (!xs_is_null(inbox))
@@ -1762,7 +1762,9 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
1762 a_status = actor_request(snac, actor, &actor_o); 1762 a_status = actor_request(snac, actor, &actor_o);
1763 1763
1764 /* do not retry permanent failures */ 1764 /* do not retry permanent failures */
1765 if (a_status == 404 || a_status == 410 || a_status < 0) { 1765 if (a_status == HTTP_STATUS_NOT_FOUND
1766 || a_status == HTTP_STATUS_GONE
1767 || a_status < 0) {
1766 srv_debug(1, xs_fmt("dropping message due to actor error %s %d", actor, a_status)); 1768 srv_debug(1, xs_fmt("dropping message due to actor error %s %d", actor, a_status));
1767 return -1; 1769 return -1;
1768 } 1770 }
@@ -1905,7 +1907,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
1905 } 1907 }
1906 else 1908 else
1907 if (strcmp(utype, "Announce") == 0) { /** **/ 1909 if (strcmp(utype, "Announce") == 0) { /** **/
1908 int status = 200; 1910 int status = HTTP_STATUS_OK;
1909 1911
1910 /* commented out: if a followed user boosts something that 1912 /* commented out: if a followed user boosts something that
1911 is requested and then unboosts, the post remains here, 1913 is requested and then unboosts, the post remains here,
@@ -2015,7 +2017,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2015 if (xs_type(object) == XSTYPE_DICT) 2017 if (xs_type(object) == XSTYPE_DICT)
2016 object = xs_dict_get(object, "id"); 2018 object = xs_dict_get(object, "id");
2017 2019
2018 if (timeline_admire(snac, object, actor, 1) == 201) 2020 if (timeline_admire(snac, object, actor, 1) == HTTP_STATUS_CREATED)
2019 snac_log(snac, xs_fmt("new 'Like' %s %s", actor, object)); 2021 snac_log(snac, xs_fmt("new 'Like' %s %s", actor, object));
2020 else 2022 else
2021 snac_log(snac, xs_fmt("repeated 'Like' from %s to %s", actor, object)); 2023 snac_log(snac, xs_fmt("repeated 'Like' from %s to %s", actor, object));
@@ -2046,7 +2048,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req)
2046 xs *who_o = NULL; 2048 xs *who_o = NULL;
2047 2049
2048 if (valid_status(actor_request(snac, who, &who_o))) { 2050 if (valid_status(actor_request(snac, who, &who_o))) {
2049 if (timeline_admire(snac, object, actor, 0) == 201) 2051 if (timeline_admire(snac, object, actor, 0) == HTTP_STATUS_CREATED)
2050 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); 2052 snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object));
2051 else 2053 else
2052 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", 2054 snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s",
@@ -2383,11 +2385,15 @@ void process_queue_item(xs_dict *q_item)
2383 2385
2384 /* if it's not the first time it fails with a timeout, 2386 /* if it's not the first time it fails with a timeout,
2385 penalize the server by skipping one retry */ 2387 penalize the server by skipping one retry */
2386 if (p_status == status && status == 499) 2388 if (p_status == status && status == HTTP_STATUS_CLIENT_CLOSED_REQUEST)
2387 retries++; 2389 retries++;
2388 2390
2389 /* error sending; requeue? */ 2391 /* error sending; requeue? */
2390 if (status == 400 || status == 404 || status == 405 || status == 410 || status < 0) 2392 if (status == HTTP_STATUS_BAD_REQUEST
2393 || status == HTTP_STATUS_NOT_FOUND
2394 || status == HTTP_STATUS_METHOD_NOT_ALLOWED
2395 || status == HTTP_STATUS_GONE
2396 || status < 0)
2391 /* explicit error: discard */ 2397 /* explicit error: discard */
2392 srv_log(xs_fmt("output message: fatal error %s %d", inbox, status)); 2398 srv_log(xs_fmt("output message: fatal error %s %d", inbox, status));
2393 else 2399 else
@@ -2574,7 +2580,7 @@ int process_queue(void)
2574int activitypub_get_handler(const xs_dict *req, const char *q_path, 2580int activitypub_get_handler(const xs_dict *req, const char *q_path,
2575 char **body, int *b_size, char **ctype) 2581 char **body, int *b_size, char **ctype)
2576{ 2582{
2577 int status = 200; 2583 int status = HTTP_STATUS_OK;
2578 const char *accept = xs_dict_get(req, "accept"); 2584 const char *accept = xs_dict_get(req, "accept");
2579 snac snac; 2585 snac snac;
2580 xs *msg = NULL; 2586 xs *msg = NULL;
@@ -2594,7 +2600,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2594 if (!user_open(&snac, uid)) { 2600 if (!user_open(&snac, uid)) {
2595 /* invalid user */ 2601 /* invalid user */
2596 srv_debug(1, xs_fmt("activitypub_get_handler bad user %s", uid)); 2602 srv_debug(1, xs_fmt("activitypub_get_handler bad user %s", uid));
2597 return 404; 2603 return HTTP_STATUS_NOT_FOUND;
2598 } 2604 }
2599 2605
2600 p_path = xs_list_get(l, 2); 2606 p_path = xs_list_get(l, 2);
@@ -2652,12 +2658,12 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path,
2652 2658
2653 /* don't return non-public objects */ 2659 /* don't return non-public objects */
2654 if (valid_status(status) && !is_msg_public(msg)) 2660 if (valid_status(status) && !is_msg_public(msg))
2655 status = 404; 2661 status = HTTP_STATUS_NOT_FOUND;
2656 } 2662 }
2657 else 2663 else
2658 status = 404; 2664 status = HTTP_STATUS_NOT_FOUND;
2659 2665
2660 if (status == 200 && msg != NULL) { 2666 if (status == HTTP_STATUS_OK && msg != NULL) {
2661 *body = xs_json_dumps(msg, 4); 2667 *body = xs_json_dumps(msg, 4);
2662 *b_size = strlen(*body); 2668 *b_size = strlen(*body);
2663 } 2669 }
@@ -2677,7 +2683,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2677{ 2683{
2678 (void)b_size; 2684 (void)b_size;
2679 2685
2680 int status = 202; /* accepted */ 2686 int status = HTTP_STATUS_ACCEPTED;
2681 const char *i_ctype = xs_dict_get(req, "content-type"); 2687 const char *i_ctype = xs_dict_get(req, "content-type");
2682 snac snac; 2688 snac snac;
2683 const char *v; 2689 const char *v;
@@ -2685,13 +2691,13 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2685 if (i_ctype == NULL) { 2691 if (i_ctype == NULL) {
2686 *body = xs_str_new("no content-type"); 2692 *body = xs_str_new("no content-type");
2687 *ctype = "text/plain"; 2693 *ctype = "text/plain";
2688 return 400; 2694 return HTTP_STATUS_BAD_REQUEST;
2689 } 2695 }
2690 2696
2691 if (xs_is_null(payload)) { 2697 if (xs_is_null(payload)) {
2692 *body = xs_str_new("no payload"); 2698 *body = xs_str_new("no payload");
2693 *ctype = "text/plain"; 2699 *ctype = "text/plain";
2694 return 400; 2700 return HTTP_STATUS_BAD_REQUEST;
2695 } 2701 }
2696 2702
2697 if (xs_str_in(i_ctype, "application/activity+json") == -1 && 2703 if (xs_str_in(i_ctype, "application/activity+json") == -1 &&
@@ -2709,7 +2715,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2709 2715
2710 *body = xs_str_new("JSON error"); 2716 *body = xs_str_new("JSON error");
2711 *ctype = "text/plain"; 2717 *ctype = "text/plain";
2712 return 400; 2718 return HTTP_STATUS_BAD_REQUEST;
2713 } 2719 }
2714 2720
2715 if (id && is_instance_blocked(id)) { 2721 if (id && is_instance_blocked(id)) {
@@ -2717,7 +2723,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2717 2723
2718 *body = xs_str_new("blocked"); 2724 *body = xs_str_new("blocked");
2719 *ctype = "text/plain"; 2725 *ctype = "text/plain";
2720 return 403; 2726 return HTTP_STATUS_FORBIDDEN;
2721 } 2727 }
2722 2728
2723 /* get the user and path */ 2729 /* get the user and path */
@@ -2725,20 +2731,20 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2725 2731
2726 if (xs_list_len(l) == 2 && strcmp(xs_list_get(l, 1), "shared-inbox") == 0) { 2732 if (xs_list_len(l) == 2 && strcmp(xs_list_get(l, 1), "shared-inbox") == 0) {
2727 enqueue_shared_input(msg, req, 0); 2733 enqueue_shared_input(msg, req, 0);
2728 return 202; 2734 return HTTP_STATUS_ACCEPTED;
2729 } 2735 }
2730 2736
2731 if (xs_list_len(l) != 3 || strcmp(xs_list_get(l, 2), "inbox") != 0) { 2737 if (xs_list_len(l) != 3 || strcmp(xs_list_get(l, 2), "inbox") != 0) {
2732 /* strange q_path */ 2738 /* strange q_path */
2733 srv_debug(1, xs_fmt("activitypub_post_handler unsupported path %s", q_path)); 2739 srv_debug(1, xs_fmt("activitypub_post_handler unsupported path %s", q_path));
2734 return 404; 2740 return HTTP_STATUS_NOT_FOUND;
2735 } 2741 }
2736 2742
2737 const char *uid = xs_list_get(l, 1); 2743 const char *uid = xs_list_get(l, 1);
2738 if (!user_open(&snac, uid)) { 2744 if (!user_open(&snac, uid)) {
2739 /* invalid user */ 2745 /* invalid user */
2740 srv_debug(1, xs_fmt("activitypub_post_handler bad user %s", uid)); 2746 srv_debug(1, xs_fmt("activitypub_post_handler bad user %s", uid));
2741 return 404; 2747 return HTTP_STATUS_NOT_FOUND;
2742 } 2748 }
2743 2749
2744 /* if it has a digest, check it now, because 2750 /* if it has a digest, check it now, because
@@ -2752,7 +2758,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2752 2758
2753 *body = xs_str_new("bad digest"); 2759 *body = xs_str_new("bad digest");
2754 *ctype = "text/plain"; 2760 *ctype = "text/plain";
2755 status = 400; 2761 status = HTTP_STATUS_BAD_REQUEST;
2756 } 2762 }
2757 } 2763 }
2758 2764
@@ -2763,7 +2769,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2763 2769
2764 *body = xs_str_new("rejected"); 2770 *body = xs_str_new("rejected");
2765 *ctype = "text/plain"; 2771 *ctype = "text/plain";
2766 status = 403; 2772 status = HTTP_STATUS_FORBIDDEN;
2767 } 2773 }
2768 } 2774 }
2769 2775
diff --git a/data.c b/data.c
index edbc64f..8fdd292 100644
--- a/data.c
+++ b/data.c
@@ -355,12 +355,12 @@ int is_md5_hex(const char *md5)
355int index_add_md5(const char *fn, const char *md5) 355int index_add_md5(const char *fn, const char *md5)
356/* adds an md5 to an index */ 356/* adds an md5 to an index */
357{ 357{
358 int status = 201; /* Created */ 358 int status = HTTP_STATUS_CREATED;
359 FILE *f; 359 FILE *f;
360 360
361 if (!is_md5_hex(md5)) { 361 if (!is_md5_hex(md5)) {
362 srv_log(xs_fmt("index_add_md5: bad md5 %s %s", fn, md5)); 362 srv_log(xs_fmt("index_add_md5: bad md5 %s %s", fn, md5));
363 return 400; 363 return HTTP_STATUS_BAD_REQUEST;
364 } 364 }
365 365
366 pthread_mutex_lock(&data_mutex); 366 pthread_mutex_lock(&data_mutex);
@@ -375,7 +375,7 @@ int index_add_md5(const char *fn, const char *md5)
375 fclose(f); 375 fclose(f);
376 } 376 }
377 else 377 else
378 status = 500; 378 status = HTTP_STATUS_INTERNAL_SERVER_ERROR;
379 379
380 pthread_mutex_unlock(&data_mutex); 380 pthread_mutex_unlock(&data_mutex);
381 381
@@ -394,7 +394,7 @@ int index_add(const char *fn, const char *id)
394int index_del_md5(const char *fn, const char *md5) 394int index_del_md5(const char *fn, const char *md5)
395/* deletes an md5 from an index */ 395/* deletes an md5 from an index */
396{ 396{
397 int status = 404; 397 int status = HTTP_STATUS_NOT_FOUND;
398 FILE *f; 398 FILE *f;
399 399
400 pthread_mutex_lock(&data_mutex); 400 pthread_mutex_lock(&data_mutex);
@@ -411,7 +411,7 @@ int index_del_md5(const char *fn, const char *md5)
411 [yes: this breaks index_len()] */ 411 [yes: this breaks index_len()] */
412 fseek(f, -33, SEEK_CUR); 412 fseek(f, -33, SEEK_CUR);
413 fwrite("-", 1, 1, f); 413 fwrite("-", 1, 1, f);
414 status = 200; 414 status = HTTP_STATUS_OK;
415 415
416 break; 416 break;
417 } 417 }
@@ -420,7 +420,7 @@ int index_del_md5(const char *fn, const char *md5)
420 fclose(f); 420 fclose(f);
421 } 421 }
422 else 422 else
423 status = 410; 423 status = HTTP_STATUS_GONE;
424 424
425 pthread_mutex_unlock(&data_mutex); 425 pthread_mutex_unlock(&data_mutex);
426 426
@@ -660,7 +660,7 @@ int object_here(const char *id)
660int object_get_by_md5(const char *md5, xs_dict **obj) 660int object_get_by_md5(const char *md5, xs_dict **obj)
661/* returns a stored object, optionally of the requested type */ 661/* returns a stored object, optionally of the requested type */
662{ 662{
663 int status = 404; 663 int status = HTTP_STATUS_NOT_FOUND;
664 xs *fn = _object_fn_by_md5(md5, "object_get_by_md5"); 664 xs *fn = _object_fn_by_md5(md5, "object_get_by_md5");
665 FILE *f; 665 FILE *f;
666 666
@@ -669,7 +669,7 @@ int object_get_by_md5(const char *md5, xs_dict **obj)
669 fclose(f); 669 fclose(f);
670 670
671 if (*obj) 671 if (*obj)
672 status = 200; 672 status = HTTP_STATUS_OK;
673 } 673 }
674 else 674 else
675 *obj = NULL; 675 *obj = NULL;
@@ -689,7 +689,7 @@ int object_get(const char *id, xs_dict **obj)
689int _object_add(const char *id, const xs_dict *obj, int ow) 689int _object_add(const char *id, const xs_dict *obj, int ow)
690/* stores an object */ 690/* stores an object */
691{ 691{
692 int status = 201; /* Created */ 692 int status = HTTP_STATUS_CREATED; /* Created */
693 xs *fn = _object_fn(id); 693 xs *fn = _object_fn(id);
694 FILE *f; 694 FILE *f;
695 695
@@ -697,10 +697,10 @@ int _object_add(const char *id, const xs_dict *obj, int ow)
697 if (!ow) { 697 if (!ow) {
698 /* object already here */ 698 /* object already here */
699 srv_debug(1, xs_fmt("object_add object already here %s", id)); 699 srv_debug(1, xs_fmt("object_add object already here %s", id));
700 return 204; /* No content */ 700 return HTTP_STATUS_NO_CONTENT;
701 } 701 }
702 else 702 else
703 status = 200; 703 status = HTTP_STATUS_OK;
704 } 704 }
705 705
706 if ((f = fopen(fn, "w")) != NULL) { 706 if ((f = fopen(fn, "w")) != NULL) {
@@ -736,7 +736,7 @@ int _object_add(const char *id, const xs_dict *obj, int ow)
736 } 736 }
737 else { 737 else {
738 srv_log(xs_fmt("object_add error writing %s (errno: %d)", fn, errno)); 738 srv_log(xs_fmt("object_add error writing %s (errno: %d)", fn, errno));
739 status = 500; 739 status = HTTP_STATUS_INTERNAL_SERVER_ERROR;
740 } 740 }
741 741
742 srv_debug(1, xs_fmt("object_add %s %s %d", id, fn, status)); 742 srv_debug(1, xs_fmt("object_add %s %s %d", id, fn, status));
@@ -762,11 +762,11 @@ int object_add_ow(const char *id, const xs_dict *obj)
762int object_del_by_md5(const char *md5) 762int object_del_by_md5(const char *md5)
763/* deletes an object by its md5 */ 763/* deletes an object by its md5 */
764{ 764{
765 int status = 404; 765 int status = HTTP_STATUS_NOT_FOUND;
766 xs *fn = _object_fn_by_md5(md5, "object_del_by_md5"); 766 xs *fn = _object_fn_by_md5(md5, "object_del_by_md5");
767 767
768 if (unlink(fn) != -1) { 768 if (unlink(fn) != -1) {
769 status = 200; 769 status = HTTP_STATUS_OK;
770 770
771 /* also delete associated indexes */ 771 /* also delete associated indexes */
772 xs *spec = xs_dup(fn); 772 xs *spec = xs_dup(fn);
@@ -907,7 +907,7 @@ int object_parent(const char *md5, char *buf, int size)
907int object_admire(const char *id, const char *actor, int like) 907int object_admire(const char *id, const char *actor, int like)
908/* actor likes or announces this object */ 908/* actor likes or announces this object */
909{ 909{
910 int status = 200; 910 int status = HTTP_STATUS_OK;
911 xs *fn = _object_fn(id); 911 xs *fn = _object_fn(id);
912 912
913 fn = xs_replace_i(fn, ".json", like ? "_l.idx" : "_a.idx"); 913 fn = xs_replace_i(fn, ".json", like ? "_l.idx" : "_a.idx");
@@ -1007,7 +1007,7 @@ int follower_add(snac *snac, const char *actor)
1007 1007
1008 snac_debug(snac, 2, xs_fmt("follower_add %s", actor)); 1008 snac_debug(snac, 2, xs_fmt("follower_add %s", actor));
1009 1009
1010 return ret == -1 ? 500 : 200; 1010 return ret == -1 ? HTTP_STATUS_INTERNAL_SERVER_ERROR : HTTP_STATUS_OK;
1011} 1011}
1012 1012
1013 1013
@@ -1018,7 +1018,7 @@ int follower_del(snac *snac, const char *actor)
1018 1018
1019 snac_debug(snac, 2, xs_fmt("follower_del %s", actor)); 1019 snac_debug(snac, 2, xs_fmt("follower_del %s", actor));
1020 1020
1021 return ret == -1 ? 404 : 200; 1021 return ret == -1 ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_OK;
1022} 1022}
1023 1023
1024 1024
@@ -1109,7 +1109,7 @@ int timeline_here(snac *snac, const char *md5)
1109int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg) 1109int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg)
1110/* gets a message from the timeline */ 1110/* gets a message from the timeline */
1111{ 1111{
1112 int status = 404; 1112 int status = HTTP_STATUS_NOT_FOUND;
1113 FILE *f = NULL; 1113 FILE *f = NULL;
1114 1114
1115 xs *fn = timeline_fn_by_md5(snac, md5); 1115 xs *fn = timeline_fn_by_md5(snac, md5);
@@ -1119,7 +1119,7 @@ int timeline_get_by_md5(snac *snac, const char *md5, xs_dict **msg)
1119 fclose(f); 1119 fclose(f);
1120 1120
1121 if (*msg != NULL) 1121 if (*msg != NULL)
1122 status = 200; 1122 status = HTTP_STATUS_OK;
1123 } 1123 }
1124 1124
1125 return status; 1125 return status;
@@ -1282,7 +1282,7 @@ xs_str *_following_fn(snac *snac, const char *actor)
1282int following_add(snac *snac, const char *actor, const xs_dict *msg) 1282int following_add(snac *snac, const char *actor, const xs_dict *msg)
1283/* adds to the following list */ 1283/* adds to the following list */
1284{ 1284{
1285 int ret = 201; /* created */ 1285 int ret = HTTP_STATUS_CREATED;
1286 xs *fn = _following_fn(snac, actor); 1286 xs *fn = _following_fn(snac, actor);
1287 FILE *f; 1287 FILE *f;
1288 xs *p_object = NULL; 1288 xs *p_object = NULL;
@@ -1295,7 +1295,7 @@ int following_add(snac *snac, const char *actor, const xs_dict *msg)
1295 1295
1296 if (!xs_is_null(type) && strcmp(type, "Accept") == 0) { 1296 if (!xs_is_null(type) && strcmp(type, "Accept") == 0) {
1297 snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor)); 1297 snac_debug(snac, 1, xs_fmt("following_add actor already confirmed %s", actor));
1298 return 200; 1298 return HTTP_STATUS_OK;
1299 } 1299 }
1300 } 1300 }
1301 1301
@@ -1311,7 +1311,7 @@ int following_add(snac *snac, const char *actor, const xs_dict *msg)
1311 link(actor_fn, fn); 1311 link(actor_fn, fn);
1312 } 1312 }
1313 else 1313 else
1314 ret = 500; 1314 ret = HTTP_STATUS_INTERNAL_SERVER_ERROR;
1315 1315
1316 snac_debug(snac, 2, xs_fmt("following_add %s %s", actor, fn)); 1316 snac_debug(snac, 2, xs_fmt("following_add %s %s", actor, fn));
1317 1317
@@ -1332,7 +1332,7 @@ int following_del(snac *snac, const char *actor)
1332 fn = xs_replace_i(fn, ".json", "_a.json"); 1332 fn = xs_replace_i(fn, ".json", "_a.json");
1333 unlink(fn); 1333 unlink(fn);
1334 1334
1335 return 200; 1335 return HTTP_STATUS_OK;
1336} 1336}
1337 1337
1338 1338
@@ -1350,14 +1350,14 @@ int following_get(snac *snac, const char *actor, xs_dict **data)
1350{ 1350{
1351 xs *fn = _following_fn(snac, actor); 1351 xs *fn = _following_fn(snac, actor);
1352 FILE *f; 1352 FILE *f;
1353 int status = 200; 1353 int status = HTTP_STATUS_OK;
1354 1354
1355 if ((f = fopen(fn, "r")) != NULL) { 1355 if ((f = fopen(fn, "r")) != NULL) {
1356 *data = xs_json_load(f); 1356 *data = xs_json_load(f);
1357 fclose(f); 1357 fclose(f);
1358 } 1358 }
1359 else 1359 else
1360 status = 404; 1360 status = HTTP_STATUS_NOT_FOUND;
1361 1361
1362 return status; 1362 return status;
1363} 1363}
@@ -1576,7 +1576,7 @@ int actor_add(const char *actor, const xs_dict *msg)
1576int actor_get(const char *actor, xs_dict **data) 1576int actor_get(const char *actor, xs_dict **data)
1577/* returns an already downloaded actor */ 1577/* returns an already downloaded actor */
1578{ 1578{
1579 int status = 200; 1579 int status = HTTP_STATUS_OK;
1580 xs_dict *d = NULL; 1580 xs_dict *d = NULL;
1581 1581
1582 if (xs_startswith(actor, srv_baseurl)) { 1582 if (xs_startswith(actor, srv_baseurl)) {
@@ -1590,10 +1590,10 @@ int actor_get(const char *actor, xs_dict **data)
1590 *data = msg_actor(&user); 1590 *data = msg_actor(&user);
1591 1591
1592 user_free(&user); 1592 user_free(&user);
1593 return 200; 1593 return HTTP_STATUS_OK;
1594 } 1594 }
1595 else 1595 else
1596 return 404; 1596 return HTTP_STATUS_NOT_FOUND;
1597 } 1597 }
1598 1598
1599 /* read the object */ 1599 /* read the object */
@@ -1606,7 +1606,7 @@ int actor_get(const char *actor, xs_dict **data)
1606 if (xs_is_null(xs_dict_get(d, "id")) || xs_is_null(xs_dict_get(d, "type"))) { 1606 if (xs_is_null(xs_dict_get(d, "id")) || xs_is_null(xs_dict_get(d, "type"))) {
1607 srv_debug(1, xs_fmt("corrupted actor object %s", actor)); 1607 srv_debug(1, xs_fmt("corrupted actor object %s", actor));
1608 d = xs_free(d); 1608 d = xs_free(d);
1609 return 404; 1609 return HTTP_STATUS_NOT_FOUND;
1610 } 1610 }
1611 1611
1612 if (data) 1612 if (data)
@@ -1622,7 +1622,7 @@ int actor_get(const char *actor, xs_dict **data)
1622 1622
1623 if (mtime(fn) + max_time < (double) time(NULL)) { 1623 if (mtime(fn) + max_time < (double) time(NULL)) {
1624 /* actor data exists but also stinks */ 1624 /* actor data exists but also stinks */
1625 status = 205; /* "205: Reset Content" "110: Response Is Stale" */ 1625 status = HTTP_STATUS_RESET_CONTENT; /* "110: Response Is Stale" */
1626 } 1626 }
1627 1627
1628 return status; 1628 return status;
@@ -1634,7 +1634,7 @@ int actor_get_refresh(snac *user, const char *actor, xs_dict **data)
1634{ 1634{
1635 int status = actor_get(actor, data); 1635 int status = actor_get(actor, data);
1636 1636
1637 if (status == 205 && user && !xs_startswith(actor, srv_baseurl)) 1637 if (status == HTTP_STATUS_RESET_CONTENT && user && !xs_startswith(actor, srv_baseurl))
1638 enqueue_actor_refresh(user, actor, 0); 1638 enqueue_actor_refresh(user, actor, 0);
1639 1639
1640 return status; 1640 return status;
@@ -1953,7 +1953,7 @@ static int _load_raw_file(const char *fn, xs_val **data, int *size,
1953 const char *inm, xs_str **etag) 1953 const char *inm, xs_str **etag)
1954/* loads a cached file */ 1954/* loads a cached file */
1955{ 1955{
1956 int status = 404; 1956 int status = HTTP_STATUS_NOT_FOUND;
1957 1957
1958 if (fn) { 1958 if (fn) {
1959 double tm = mtime(fn); 1959 double tm = mtime(fn);
@@ -1965,7 +1965,7 @@ static int _load_raw_file(const char *fn, xs_val **data, int *size,
1965 /* if if-none-match is set, check if it's the same */ 1965 /* if if-none-match is set, check if it's the same */
1966 if (!xs_is_null(inm) && strcmp(e, inm) == 0) { 1966 if (!xs_is_null(inm) && strcmp(e, inm) == 0) {
1967 /* client has the newest version */ 1967 /* client has the newest version */
1968 status = 304; 1968 status = HTTP_STATUS_NOT_MODIFIED;
1969 } 1969 }
1970 else { 1970 else {
1971 /* newer or never downloaded; read the full file */ 1971 /* newer or never downloaded; read the full file */
@@ -1976,7 +1976,7 @@ static int _load_raw_file(const char *fn, xs_val **data, int *size,
1976 *data = xs_read(f, size); 1976 *data = xs_read(f, size);
1977 fclose(f); 1977 fclose(f);
1978 1978
1979 status = 200; 1979 status = HTTP_STATUS_OK;
1980 } 1980 }
1981 } 1981 }
1982 1982
diff --git a/html.c b/html.c
index 4522050..1840799 100644
--- a/html.c
+++ b/html.c
@@ -2540,7 +2540,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2540 char **body, int *b_size, char **ctype, xs_str **etag) 2540 char **body, int *b_size, char **ctype, xs_str **etag)
2541{ 2541{
2542 const char *accept = xs_dict_get(req, "accept"); 2542 const char *accept = xs_dict_get(req, "accept");
2543 int status = 404; 2543 int status = HTTP_STATUS_NOT_FOUND;
2544 snac snac; 2544 snac snac;
2545 xs *uid = NULL; 2545 xs *uid = NULL;
2546 const char *p_path; 2546 const char *p_path;
@@ -2553,7 +2553,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2553 2553
2554 if (xs_is_null(v)) { 2554 if (xs_is_null(v)) {
2555 srv_log(xs_fmt("html_get_handler bad query '%s'", q_path)); 2555 srv_log(xs_fmt("html_get_handler bad query '%s'", q_path));
2556 return 404; 2556 return HTTP_STATUS_NOT_FOUND;
2557 } 2557 }
2558 2558
2559 uid = xs_dup(v); 2559 uid = xs_dup(v);
@@ -2569,7 +2569,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2569 if (!uid || !user_open(&snac, uid)) { 2569 if (!uid || !user_open(&snac, uid)) {
2570 /* invalid user */ 2570 /* invalid user */
2571 srv_debug(1, xs_fmt("html_get_handler bad user %s", uid)); 2571 srv_debug(1, xs_fmt("html_get_handler bad user %s", uid));
2572 return 404; 2572 return HTTP_STATUS_NOT_FOUND;
2573 } 2573 }
2574 2574
2575 /* return the RSS if requested by Accept header */ 2575 /* return the RSS if requested by Accept header */
@@ -2598,7 +2598,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2598 /** empty public timeline for private users **/ 2598 /** empty public timeline for private users **/
2599 *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1); 2599 *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1);
2600 *b_size = strlen(*body); 2600 *b_size = strlen(*body);
2601 status = 200; 2601 status = HTTP_STATUS_OK;
2602 } 2602 }
2603 else 2603 else
2604 if (cache && history_mtime(&snac, h) > timeline_mtime(&snac)) { 2604 if (cache && history_mtime(&snac, h) > timeline_mtime(&snac)) {
@@ -2617,7 +2617,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2617 *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1); 2617 *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1);
2618 2618
2619 *b_size = strlen(*body); 2619 *b_size = strlen(*body);
2620 status = 200; 2620 status = HTTP_STATUS_OK;
2621 2621
2622 if (save) 2622 if (save)
2623 history_add(&snac, h, *body, *b_size, etag); 2623 history_add(&snac, h, *body, *b_size, etag);
@@ -2627,7 +2627,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2627 if (strcmp(p_path, "admin") == 0) { /** private timeline **/ 2627 if (strcmp(p_path, "admin") == 0) { /** private timeline **/
2628 if (!login(&snac, req)) { 2628 if (!login(&snac, req)) {
2629 *body = xs_dup(uid); 2629 *body = xs_dup(uid);
2630 status = 401; 2630 status = HTTP_STATUS_UNAUTHORIZED;
2631 } 2631 }
2632 else { 2632 else {
2633 const char *q = xs_dict_get(q_vars, "q"); 2633 const char *q = xs_dict_get(q_vars, "q");
@@ -2649,7 +2649,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2649 2649
2650 *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0); 2650 *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0);
2651 *b_size = strlen(*body); 2651 *b_size = strlen(*body);
2652 status = 200; 2652 status = HTTP_STATUS_OK;
2653 } 2653 }
2654 else { 2654 else {
2655 /** search by content **/ 2655 /** search by content **/
@@ -2670,7 +2670,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2670 2670
2671 *body = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show, title, page, 0); 2671 *body = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show, title, page, 0);
2672 *b_size = strlen(*body); 2672 *b_size = strlen(*body);
2673 status = 200; 2673 status = HTTP_STATUS_OK;
2674 } 2674 }
2675 } 2675 }
2676 else { 2676 else {
@@ -2699,7 +2699,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2699 xs_list_len(next), NULL, "/admin", 1); 2699 xs_list_len(next), NULL, "/admin", 1);
2700 2700
2701 *b_size = strlen(*body); 2701 *b_size = strlen(*body);
2702 status = 200; 2702 status = HTTP_STATUS_OK;
2703 2703
2704 if (save) 2704 if (save)
2705 history_add(&snac, "timeline.html_", *body, *b_size, etag); 2705 history_add(&snac, "timeline.html_", *body, *b_size, etag);
@@ -2711,7 +2711,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2711 if (xs_startswith(p_path, "admin/p/")) { /** unique post by md5 **/ 2711 if (xs_startswith(p_path, "admin/p/")) { /** unique post by md5 **/
2712 if (!login(&snac, req)) { 2712 if (!login(&snac, req)) {
2713 *body = xs_dup(uid); 2713 *body = xs_dup(uid);
2714 status = 401; 2714 status = HTTP_STATUS_UNAUTHORIZED;
2715 } 2715 }
2716 else { 2716 else {
2717 xs *l = xs_split(p_path, "/"); 2717 xs *l = xs_split(p_path, "/");
@@ -2722,7 +2722,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2722 2722
2723 *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1); 2723 *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1);
2724 *b_size = strlen(*body); 2724 *b_size = strlen(*body);
2725 status = 200; 2725 status = HTTP_STATUS_OK;
2726 } 2726 }
2727 } 2727 }
2728 } 2728 }
@@ -2730,31 +2730,31 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2730 if (strcmp(p_path, "people") == 0) { /** the list of people **/ 2730 if (strcmp(p_path, "people") == 0) { /** the list of people **/
2731 if (!login(&snac, req)) { 2731 if (!login(&snac, req)) {
2732 *body = xs_dup(uid); 2732 *body = xs_dup(uid);
2733 status = 401; 2733 status = HTTP_STATUS_UNAUTHORIZED;
2734 } 2734 }
2735 else { 2735 else {
2736 *body = html_people(&snac); 2736 *body = html_people(&snac);
2737 *b_size = strlen(*body); 2737 *b_size = strlen(*body);
2738 status = 200; 2738 status = HTTP_STATUS_OK;
2739 } 2739 }
2740 } 2740 }
2741 else 2741 else
2742 if (strcmp(p_path, "notifications") == 0) { /** the list of notifications **/ 2742 if (strcmp(p_path, "notifications") == 0) { /** the list of notifications **/
2743 if (!login(&snac, req)) { 2743 if (!login(&snac, req)) {
2744 *body = xs_dup(uid); 2744 *body = xs_dup(uid);
2745 status = 401; 2745 status = HTTP_STATUS_UNAUTHORIZED;
2746 } 2746 }
2747 else { 2747 else {
2748 *body = html_notifications(&snac, skip, show); 2748 *body = html_notifications(&snac, skip, show);
2749 *b_size = strlen(*body); 2749 *b_size = strlen(*body);
2750 status = 200; 2750 status = HTTP_STATUS_OK;
2751 } 2751 }
2752 } 2752 }
2753 else 2753 else
2754 if (strcmp(p_path, "instance") == 0) { /** instance timeline **/ 2754 if (strcmp(p_path, "instance") == 0) { /** instance timeline **/
2755 if (!login(&snac, req)) { 2755 if (!login(&snac, req)) {
2756 *body = xs_dup(uid); 2756 *body = xs_dup(uid);
2757 status = 401; 2757 status = HTTP_STATUS_UNAUTHORIZED;
2758 } 2758 }
2759 else { 2759 else {
2760 xs *list = timeline_instance_list(skip, show); 2760 xs *list = timeline_instance_list(skip, show);
@@ -2763,14 +2763,14 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2763 *body = html_timeline(&snac, list, 0, skip, show, 2763 *body = html_timeline(&snac, list, 0, skip, show,
2764 xs_list_len(next), L("Showing instance timeline"), "/instance", 0); 2764 xs_list_len(next), L("Showing instance timeline"), "/instance", 0);
2765 *b_size = strlen(*body); 2765 *b_size = strlen(*body);
2766 status = 200; 2766 status = HTTP_STATUS_OK;
2767 } 2767 }
2768 } 2768 }
2769 else 2769 else
2770 if (xs_startswith(p_path, "list/")) { /** list timelines **/ 2770 if (xs_startswith(p_path, "list/")) { /** list timelines **/
2771 if (!login(&snac, req)) { 2771 if (!login(&snac, req)) {
2772 *body = xs_dup(uid); 2772 *body = xs_dup(uid);
2773 status = 401; 2773 status = HTTP_STATUS_UNAUTHORIZED;
2774 } 2774 }
2775 else { 2775 else {
2776 xs *l = xs_split(p_path, "/"); 2776 xs *l = xs_split(p_path, "/");
@@ -2787,14 +2787,14 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2787 *body = html_timeline(&snac, list, 0, skip, show, 2787 *body = html_timeline(&snac, list, 0, skip, show,
2788 xs_list_len(next), title, base, 1); 2788 xs_list_len(next), title, base, 1);
2789 *b_size = strlen(*body); 2789 *b_size = strlen(*body);
2790 status = 200; 2790 status = HTTP_STATUS_OK;
2791 } 2791 }
2792 } 2792 }
2793 } 2793 }
2794 else 2794 else
2795 if (xs_startswith(p_path, "p/")) { /** a timeline with just one entry **/ 2795 if (xs_startswith(p_path, "p/")) { /** a timeline with just one entry **/
2796 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) 2796 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE)
2797 return 403; 2797 return HTTP_STATUS_FORBIDDEN;
2798 2798
2799 xs *id = xs_fmt("%s/%s", snac.actor, p_path); 2799 xs *id = xs_fmt("%s/%s", snac.actor, p_path);
2800 xs *msg = NULL; 2800 xs *msg = NULL;
@@ -2807,7 +2807,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2807 2807
2808 *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1); 2808 *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1);
2809 *b_size = strlen(*body); 2809 *b_size = strlen(*body);
2810 status = 200; 2810 status = HTTP_STATUS_OK;
2811 } 2811 }
2812 } 2812 }
2813 else 2813 else
@@ -2829,10 +2829,10 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2829 else 2829 else
2830 if (xs_startswith(p_path, "h/")) { /** an entry from the history **/ 2830 if (xs_startswith(p_path, "h/")) { /** an entry from the history **/
2831 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) 2831 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE)
2832 return 403; 2832 return HTTP_STATUS_FORBIDDEN;
2833 2833
2834 if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE) 2834 if (xs_type(xs_dict_get(srv_config, "disable_history")) == XSTYPE_TRUE)
2835 return 403; 2835 return HTTP_STATUS_FORBIDDEN;
2836 2836
2837 xs *l = xs_split(p_path, "/"); 2837 xs *l = xs_split(p_path, "/");
2838 const char *id = xs_list_get(l, 1); 2838 const char *id = xs_list_get(l, 1);
@@ -2841,7 +2841,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2841 if (xs_endswith(id, "timeline.html_")) { 2841 if (xs_endswith(id, "timeline.html_")) {
2842 /* Don't let them in */ 2842 /* Don't let them in */
2843 *b_size = 0; 2843 *b_size = 0;
2844 status = 404; 2844 status = HTTP_STATUS_NOT_FOUND;
2845 } 2845 }
2846 else 2846 else
2847 status = history_get(&snac, id, body, b_size, 2847 status = history_get(&snac, id, body, b_size,
@@ -2851,7 +2851,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2851 else 2851 else
2852 if (strcmp(p_path, ".rss") == 0) { /** public timeline in RSS format **/ 2852 if (strcmp(p_path, ".rss") == 0) { /** public timeline in RSS format **/
2853 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) 2853 if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE)
2854 return 403; 2854 return HTTP_STATUS_FORBIDDEN;
2855 2855
2856 xs *elems = timeline_simple_list(&snac, "public", 0, 20); 2856 xs *elems = timeline_simple_list(&snac, "public", 0, 20);
2857 xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL, NULL); 2857 xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL, NULL);
@@ -2865,12 +2865,12 @@ int html_get_handler(const xs_dict *req, const char *q_path,
2865 *body = timeline_to_rss(&snac, elems, rss_title, rss_link, bio); 2865 *body = timeline_to_rss(&snac, elems, rss_title, rss_link, bio);
2866 *b_size = strlen(*body); 2866 *b_size = strlen(*body);
2867 *ctype = "application/rss+xml; charset=utf-8"; 2867 *ctype = "application/rss+xml; charset=utf-8";
2868 status = 200; 2868 status = HTTP_STATUS_OK;
2869 2869
2870 snac_debug(&snac, 1, xs_fmt("serving RSS")); 2870 snac_debug(&snac, 1, xs_fmt("serving RSS"));
2871 } 2871 }
2872 else 2872 else
2873 status = 404; 2873 status = HTTP_STATUS_NOT_FOUND;
2874 2874
2875 user_free(&snac); 2875 user_free(&snac);
2876 2876
@@ -2901,7 +2901,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
2901 if (!uid || !user_open(&snac, uid)) { 2901 if (!uid || !user_open(&snac, uid)) {
2902 /* invalid user */ 2902 /* invalid user */
2903 srv_debug(1, xs_fmt("html_post_handler bad user %s", uid)); 2903 srv_debug(1, xs_fmt("html_post_handler bad user %s", uid));
2904 return 404; 2904 return HTTP_STATUS_NOT_FOUND;
2905 } 2905 }
2906 2906
2907 p_path = xs_list_get(l, 2); 2907 p_path = xs_list_get(l, 2);
@@ -2910,7 +2910,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
2910 if (!login(&snac, req)) { 2910 if (!login(&snac, req)) {
2911 user_free(&snac); 2911 user_free(&snac);
2912 *body = xs_dup(uid); 2912 *body = xs_dup(uid);
2913 return 401; 2913 return HTTP_STATUS_UNAUTHORIZED;
2914 } 2914 }
2915 2915
2916 p_vars = xs_dict_get(req, "p_vars"); 2916 p_vars = xs_dict_get(req, "p_vars");
@@ -3049,7 +3049,7 @@ int html_post_handler(const xs_dict *req, const char *q_path,
3049 history_del(&snac, "timeline.html_"); 3049 history_del(&snac, "timeline.html_");
3050 } 3050 }
3051 3051
3052 status = 303; 3052 status = HTTP_STATUS_SEE_OTHER;
3053 } 3053 }
3054 else 3054 else
3055 if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/ 3055 if (p_path && strcmp(p_path, "admin/action") == 0) { /** **/
@@ -3060,11 +3060,11 @@ int html_post_handler(const xs_dict *req, const char *q_path,
3060 const char *group = xs_dict_get(p_vars, "group"); 3060 const char *group = xs_dict_get(p_vars, "group");
3061 3061
3062 if (action == NULL) 3062 if (action == NULL)
3063 return 404; 3063 return HTTP_STATUS_NOT_FOUND;
3064 3064
3065 snac_debug(&snac, 1, xs_fmt("web action '%s' received", action)); 3065 snac_debug(&snac, 1, xs_fmt("web action '%s' received", action));
3066 3066
3067 status = 303; 3067 status = HTTP_STATUS_SEE_OTHER;
3068 3068
3069 if (strcmp(action, L("Like")) == 0) { /** **/ 3069 if (strcmp(action, L("Like")) == 0) { /** **/
3070 xs *msg = msg_admiration(&snac, id, "Like"); 3070 xs *msg = msg_admiration(&snac, id, "Like");
@@ -3216,10 +3216,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
3216 timeline_touch(&snac); 3216 timeline_touch(&snac);
3217 } 3217 }
3218 else 3218 else
3219 status = 404; 3219 status = HTTP_STATUS_NOT_FOUND;
3220 3220
3221 /* delete the cached timeline */ 3221 /* delete the cached timeline */
3222 if (status == 303) 3222 if (status == HTTP_STATUS_SEE_OTHER)
3223 history_del(&snac, "timeline.html_"); 3223 history_del(&snac, "timeline.html_");
3224 } 3224 }
3225 else 3225 else
@@ -3356,14 +3356,14 @@ int html_post_handler(const xs_dict *req, const char *q_path,
3356 3356
3357 enqueue_verify_links(&snac); 3357 enqueue_verify_links(&snac);
3358 3358
3359 status = 303; 3359 status = HTTP_STATUS_SEE_OTHER;
3360 } 3360 }
3361 else 3361 else
3362 if (p_path && strcmp(p_path, "admin/clear-notifications") == 0) { /** **/ 3362 if (p_path && strcmp(p_path, "admin/clear-notifications") == 0) { /** **/
3363 notify_clear(&snac); 3363 notify_clear(&snac);
3364 timeline_touch(&snac); 3364 timeline_touch(&snac);
3365 3365
3366 status = 303; 3366 status = HTTP_STATUS_SEE_OTHER;
3367 } 3367 }
3368 else 3368 else
3369 if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/ 3369 if (p_path && strcmp(p_path, "admin/vote") == 0) { /** **/
@@ -3416,10 +3416,10 @@ int html_post_handler(const xs_dict *req, const char *q_path,
3416 } 3416 }
3417 } 3417 }
3418 3418
3419 status = 303; 3419 status = HTTP_STATUS_SEE_OTHER;
3420 } 3420 }
3421 3421
3422 if (status == 303) { 3422 if (status == HTTP_STATUS_SEE_OTHER) {
3423 const char *redir = xs_dict_get(p_vars, "redir"); 3423 const char *redir = xs_dict_get(p_vars, "redir");
3424 3424
3425 if (xs_is_null(redir)) 3425 if (xs_is_null(redir))
diff --git a/httpd.c b/httpd.c
index a7396e8..60afe28 100644
--- a/httpd.c
+++ b/httpd.c
@@ -217,17 +217,17 @@ int server_get_handler(xs_dict *req, const char *q_path,
217 *body = greeting_html(); 217 *body = greeting_html();
218 218
219 if (*body) 219 if (*body)
220 status = 200; 220 status = HTTP_STATUS_OK;
221 } 221 }
222 else 222 else
223 if (strcmp(q_path, "/susie.png") == 0 || strcmp(q_path, "/favicon.ico") == 0 ) { 223 if (strcmp(q_path, "/susie.png") == 0 || strcmp(q_path, "/favicon.ico") == 0 ) {
224 status = 200; 224 status = HTTP_STATUS_OK;
225 *body = xs_base64_dec(default_avatar_base64(), b_size); 225 *body = xs_base64_dec(default_avatar_base64(), b_size);
226 *ctype = "image/png"; 226 *ctype = "image/png";
227 } 227 }
228 else 228 else
229 if (strcmp(q_path, "/.well-known/nodeinfo") == 0) { 229 if (strcmp(q_path, "/.well-known/nodeinfo") == 0) {
230 status = 200; 230 status = HTTP_STATUS_OK;
231 *ctype = "application/json; charset=utf-8"; 231 *ctype = "application/json; charset=utf-8";
232 *body = xs_fmt("{\"links\":[" 232 *body = xs_fmt("{\"links\":["
233 "{\"rel\":\"http:/" "/nodeinfo.diaspora.software/ns/schema/2.0\"," 233 "{\"rel\":\"http:/" "/nodeinfo.diaspora.software/ns/schema/2.0\","
@@ -236,7 +236,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
236 } 236 }
237 else 237 else
238 if (strcmp(q_path, "/.well-known/host-meta") == 0) { 238 if (strcmp(q_path, "/.well-known/host-meta") == 0) {
239 status = 200; 239 status = HTTP_STATUS_OK;
240 *ctype = "application/xrd+xml"; 240 *ctype = "application/xrd+xml";
241 *body = xs_fmt("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 241 *body = xs_fmt("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
242 "<XRD>" 242 "<XRD>"
@@ -245,13 +245,13 @@ int server_get_handler(xs_dict *req, const char *q_path,
245 } 245 }
246 else 246 else
247 if (strcmp(q_path, "/nodeinfo_2_0") == 0) { 247 if (strcmp(q_path, "/nodeinfo_2_0") == 0) {
248 status = 200; 248 status = HTTP_STATUS_OK;
249 *ctype = "application/json; charset=utf-8"; 249 *ctype = "application/json; charset=utf-8";
250 *body = nodeinfo_2_0(); 250 *body = nodeinfo_2_0();
251 } 251 }
252 else 252 else
253 if (strcmp(q_path, "/robots.txt") == 0) { 253 if (strcmp(q_path, "/robots.txt") == 0) {
254 status = 200; 254 status = HTTP_STATUS_OK;
255 *ctype = "text/plain"; 255 *ctype = "text/plain";
256 *body = xs_str_new("User-agent: *\n" 256 *body = xs_str_new("User-agent: *\n"
257 "Disallow: /\n"); 257 "Disallow: /\n");
@@ -363,7 +363,7 @@ void httpd_connection(FILE *f)
363 } 363 }
364 else 364 else
365 if (strcmp(method, "OPTIONS") == 0) { 365 if (strcmp(method, "OPTIONS") == 0) {
366 status = 200; 366 status = HTTP_STATUS_OK;
367 } 367 }
368 else 368 else
369 if (strcmp(method, "DELETE") == 0) { 369 if (strcmp(method, "DELETE") == 0) {
@@ -378,22 +378,22 @@ void httpd_connection(FILE *f)
378 if (status == 0) { 378 if (status == 0) {
379 srv_archive_error("unattended_method", "unattended method", req, payload); 379 srv_archive_error("unattended_method", "unattended method", req, payload);
380 srv_debug(1, xs_fmt("httpd_connection unattended %s %s", method, q_path)); 380 srv_debug(1, xs_fmt("httpd_connection unattended %s %s", method, q_path));
381 status = 404; 381 status = HTTP_STATUS_NOT_FOUND;
382 } 382 }
383 383
384 if (status == 403) 384 if (status == HTTP_STATUS_FORBIDDEN)
385 body = xs_str_new("<h1>403 Forbidden</h1>"); 385 body = xs_str_new("<h1>403 Forbidden</h1>");
386 386
387 if (status == 404) 387 if (status == HTTP_STATUS_NOT_FOUND)
388 body = xs_str_new("<h1>404 Not Found</h1>"); 388 body = xs_str_new("<h1>404 Not Found</h1>");
389 389
390 if (status == 400 && body != NULL) 390 if (status == HTTP_STATUS_BAD_REQUEST && body != NULL)
391 body = xs_str_new("<h1>400 Bad Request</h1>"); 391 body = xs_str_new("<h1>400 Bad Request</h1>");
392 392
393 if (status == 303) 393 if (status == HTTP_STATUS_SEE_OTHER)
394 headers = xs_dict_append(headers, "location", body); 394 headers = xs_dict_append(headers, "location", body);
395 395
396 if (status == 401) { 396 if (status == HTTP_STATUS_UNAUTHORIZED) {
397 xs *www_auth = xs_fmt("Basic realm=\"@%s@%s snac login\"", 397 xs *www_auth = xs_fmt("Basic realm=\"@%s@%s snac login\"",
398 body, xs_dict_get(srv_config, "host")); 398 body, xs_dict_get(srv_config, "host"));
399 399
diff --git a/mastoapi.c b/mastoapi.c
index 3936c2a..8a54230 100644
--- a/mastoapi.c
+++ b/mastoapi.c
@@ -32,9 +32,9 @@ int app_add(const char *id, const xs_dict *app)
32/* stores an app */ 32/* stores an app */
33{ 33{
34 if (!xs_is_hex(id)) 34 if (!xs_is_hex(id))
35 return 500; 35 return HTTP_STATUS_INTERNAL_SERVER_ERROR;
36 36
37 int status = 201; 37 int status = HTTP_STATUS_CREATED;
38 xs *fn = xs_fmt("%s/app/", srv_basedir); 38 xs *fn = xs_fmt("%s/app/", srv_basedir);
39 FILE *f; 39 FILE *f;
40 40
@@ -47,7 +47,7 @@ int app_add(const char *id, const xs_dict *app)
47 fclose(f); 47 fclose(f);
48 } 48 }
49 else 49 else
50 status = 500; 50 status = HTTP_STATUS_INTERNAL_SERVER_ERROR;
51 51
52 return status; 52 return status;
53} 53}
@@ -95,9 +95,9 @@ int token_add(const char *id, const xs_dict *token)
95/* stores a token */ 95/* stores a token */
96{ 96{
97 if (!xs_is_hex(id)) 97 if (!xs_is_hex(id))
98 return 500; 98 return HTTP_STATUS_INTERNAL_SERVER_ERROR;
99 99
100 int status = 201; 100 int status = HTTP_STATUS_CREATED;
101 xs *fn = xs_fmt("%s/token/", srv_basedir); 101 xs *fn = xs_fmt("%s/token/", srv_basedir);
102 FILE *f; 102 FILE *f;
103 103
@@ -110,7 +110,7 @@ int token_add(const char *id, const xs_dict *token)
110 fclose(f); 110 fclose(f);
111 } 111 }
112 else 112 else
113 status = 500; 113 status = HTTP_STATUS_INTERNAL_SERVER_ERROR;
114 114
115 return status; 115 return status;
116} 116}
@@ -174,7 +174,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
174 if (!xs_startswith(q_path, "/oauth/")) 174 if (!xs_startswith(q_path, "/oauth/"))
175 return 0; 175 return 0;
176 176
177 int status = 404; 177 int status = HTTP_STATUS_NOT_FOUND;
178 const 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
@@ -186,7 +186,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
186 const char *rtype = xs_dict_get(msg, "response_type"); 186 const char *rtype = xs_dict_get(msg, "response_type");
187 const char *state = xs_dict_get(msg, "state"); 187 const char *state = xs_dict_get(msg, "state");
188 188
189 status = 400; 189 status = HTTP_STATUS_BAD_REQUEST;
190 190
191 if (cid && ruri && rtype && strcmp(rtype, "code") == 0) { 191 if (cid && ruri && rtype && strcmp(rtype, "code") == 0) {
192 xs *app = app_get(cid); 192 xs *app = app_get(cid);
@@ -201,7 +201,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
201 *body = xs_fmt(login_page, host, host, "", proto, host, "oauth/x-snac-login", 201 *body = xs_fmt(login_page, host, host, "", proto, host, "oauth/x-snac-login",
202 ruri, cid, state, USER_AGENT); 202 ruri, cid, state, USER_AGENT);
203 *ctype = "text/html"; 203 *ctype = "text/html";
204 status = 200; 204 status = HTTP_STATUS_OK;
205 205
206 srv_debug(1, xs_fmt("oauth authorize: generating login page")); 206 srv_debug(1, xs_fmt("oauth authorize: generating login page"));
207 } 207 }
@@ -219,7 +219,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path,
219 *body = xs_fmt(login_page, host, host, "", proto, host, "oauth/x-snac-get-token", 219 *body = xs_fmt(login_page, host, host, "", proto, host, "oauth/x-snac-get-token",
220 "", "", "", USER_AGENT); 220 "", "", "", USER_AGENT);
221 *ctype = "text/html"; 221 *ctype = "text/html";
222 status = 200; 222 status = HTTP_STATUS_OK;
223 223
224 } 224 }
225 225
@@ -237,7 +237,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
237 if (!xs_startswith(q_path, "/oauth/")) 237 if (!xs_startswith(q_path, "/oauth/"))
238 return 0; 238 return 0;
239 239
240 int status = 404; 240 int status = HTTP_STATUS_NOT_FOUND;
241 241
242 const 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;
@@ -255,7 +255,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
255 args = xs_dup(xs_dict_get(req, "p_vars")); 255 args = xs_dup(xs_dict_get(req, "p_vars"));
256 256
257 if (args == NULL) 257 if (args == NULL)
258 return 400; 258 return HTTP_STATUS_BAD_REQUEST;
259 259
260 xs *cmd = xs_replace_n(q_path, "/oauth", "", 1); 260 xs *cmd = xs_replace_n(q_path, "/oauth", "", 1);
261 261
@@ -274,7 +274,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
274 *body = xs_fmt(login_page, host, host, "LOGIN INCORRECT", proto, host, "oauth/x-snac-login", 274 *body = xs_fmt(login_page, host, host, "LOGIN INCORRECT", proto, host, "oauth/x-snac-login",
275 redir, cid, state, USER_AGENT); 275 redir, cid, state, USER_AGENT);
276 *ctype = "text/html"; 276 *ctype = "text/html";
277 status = 200; 277 status = HTTP_STATUS_OK;
278 278
279 if (login && passwd && redir && cid) { 279 if (login && passwd && redir && cid) {
280 snac snac; 280 snac snac;
@@ -296,7 +296,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
296 else 296 else
297 *body = xs_fmt("%s?code=%s", redir, code); 297 *body = xs_fmt("%s?code=%s", redir, code);
298 298
299 status = 303; 299 status = HTTP_STATUS_SEE_OTHER;
300 } 300 }
301 301
302 /* if there is a state, add it */ 302 /* if there is a state, add it */
@@ -375,12 +375,12 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
375 xs *app = app_get(cid); 375 xs *app = app_get(cid);
376 376
377 if (app == NULL) { 377 if (app == NULL) {
378 status = 401; 378 status = HTTP_STATUS_UNAUTHORIZED;
379 srv_log(xs_fmt("oauth token: invalid app %s", cid)); 379 srv_log(xs_fmt("oauth token: invalid app %s", cid));
380 } 380 }
381 else 381 else
382 if (strcmp(csec, xs_dict_get(app, "client_secret")) != 0) { 382 if (strcmp(csec, xs_dict_get(app, "client_secret")) != 0) {
383 status = 401; 383 status = HTTP_STATUS_UNAUTHORIZED;
384 srv_log(xs_fmt("oauth token: invalid client_secret for app %s", cid)); 384 srv_log(xs_fmt("oauth token: invalid client_secret for app %s", cid));
385 } 385 }
386 else { 386 else {
@@ -397,7 +397,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
397 397
398 *body = xs_json_dumps(rsp, 4); 398 *body = xs_json_dumps(rsp, 4);
399 *ctype = "application/json"; 399 *ctype = "application/json";
400 status = 200; 400 status = HTTP_STATUS_OK;
401 401
402 const char *uid = xs_dict_get(app, "uid"); 402 const char *uid = xs_dict_get(app, "uid");
403 403
@@ -416,7 +416,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
416 } 416 }
417 else { 417 else {
418 srv_debug(1, xs_fmt("oauth token: invalid or unset arguments")); 418 srv_debug(1, xs_fmt("oauth token: invalid or unset arguments"));
419 status = 400; 419 status = HTTP_STATUS_BAD_REQUEST;
420 } 420 }
421 } 421 }
422 else 422 else
@@ -433,12 +433,12 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
433 433
434 if (token == NULL || strcmp(csec, xs_dict_get(token, "client_secret")) != 0) { 434 if (token == NULL || strcmp(csec, xs_dict_get(token, "client_secret")) != 0) {
435 srv_debug(1, xs_fmt("oauth revoke: bad secret for token %s", tokid)); 435 srv_debug(1, xs_fmt("oauth revoke: bad secret for token %s", tokid));
436 status = 403; 436 status = HTTP_STATUS_FORBIDDEN;
437 } 437 }
438 else { 438 else {
439 token_del(tokid); 439 token_del(tokid);
440 srv_debug(1, xs_fmt("oauth revoke: revoked token %s", tokid)); 440 srv_debug(1, xs_fmt("oauth revoke: revoked token %s", tokid));
441 status = 200; 441 status = HTTP_STATUS_OK;
442 442
443 /* also delete the app, as it serves no purpose from now on */ 443 /* also delete the app, as it serves no purpose from now on */
444 app_del(cid); 444 app_del(cid);
@@ -446,7 +446,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
446 } 446 }
447 else { 447 else {
448 srv_debug(1, xs_fmt("oauth revoke: invalid or unset arguments")); 448 srv_debug(1, xs_fmt("oauth revoke: invalid or unset arguments"));
449 status = 403; 449 status = HTTP_STATUS_FORBIDDEN;
450 } 450 }
451 } 451 }
452 if (strcmp(cmd, "/x-snac-get-token") == 0) { /** **/ 452 if (strcmp(cmd, "/x-snac-get-token") == 0) { /** **/
@@ -459,7 +459,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
459 *body = xs_fmt(login_page, host, host, "LOGIN INCORRECT", proto, host, "oauth/x-snac-get-token", 459 *body = xs_fmt(login_page, host, host, "LOGIN INCORRECT", proto, host, "oauth/x-snac-get-token",
460 "", "", "", USER_AGENT); 460 "", "", "", USER_AGENT);
461 *ctype = "text/html"; 461 *ctype = "text/html";
462 status = 200; 462 status = HTTP_STATUS_OK;
463 463
464 if (login && passwd) { 464 if (login && passwd) {
465 snac user; 465 snac user;
@@ -1159,7 +1159,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1159 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) 1159 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/"))
1160 return 0; 1160 return 0;
1161 1161
1162 int status = 404; 1162 int status = HTTP_STATUS_NOT_FOUND;
1163 const xs_dict *args = xs_dict_get(req, "q_vars"); 1163 const xs_dict *args = xs_dict_get(req, "q_vars");
1164 xs *cmd = xs_replace_n(q_path, "/api", "", 1); 1164 xs *cmd = xs_replace_n(q_path, "/api", "", 1);
1165 1165
@@ -1249,10 +1249,10 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1249 1249
1250 *body = xs_json_dumps(acct, 4); 1250 *body = xs_json_dumps(acct, 4);
1251 *ctype = "application/json"; 1251 *ctype = "application/json";
1252 status = 200; 1252 status = HTTP_STATUS_OK;
1253 } 1253 }
1254 else { 1254 else {
1255 status = 422; // "Unprocessable entity" (no login) 1255 status = HTTP_STATUS_UNPROCESSABLE_CONTENT; // (no login)
1256 } 1256 }
1257 } 1257 }
1258 else 1258 else
@@ -1279,10 +1279,10 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1279 1279
1280 *body = xs_json_dumps(res, 4); 1280 *body = xs_json_dumps(res, 4);
1281 *ctype = "application/json"; 1281 *ctype = "application/json";
1282 status = 200; 1282 status = HTTP_STATUS_OK;
1283 } 1283 }
1284 else 1284 else
1285 status = 422; 1285 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
1286 } 1286 }
1287 else 1287 else
1288 if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/ 1288 if (strcmp(cmd, "/v1/accounts/lookup") == 0) { /** **/
@@ -1304,7 +1304,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1304 1304
1305 *body = xs_json_dumps(macct, 4); 1305 *body = xs_json_dumps(macct, 4);
1306 *ctype = "application/json"; 1306 *ctype = "application/json";
1307 status = 200; 1307 status = HTTP_STATUS_OK;
1308 1308
1309 user_free(&user); 1309 user_free(&user);
1310 } 1310 }
@@ -1450,7 +1450,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1450 if (out != NULL) { 1450 if (out != NULL) {
1451 *body = xs_json_dumps(out, 4); 1451 *body = xs_json_dumps(out, 4);
1452 *ctype = "application/json"; 1452 *ctype = "application/json";
1453 status = 200; 1453 status = HTTP_STATUS_OK;
1454 } 1454 }
1455 } 1455 }
1456 } 1456 }
@@ -1554,12 +1554,12 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1554 1554
1555 *body = xs_json_dumps(out, 4); 1555 *body = xs_json_dumps(out, 4);
1556 *ctype = "application/json"; 1556 *ctype = "application/json";
1557 status = 200; 1557 status = HTTP_STATUS_OK;
1558 1558
1559 srv_debug(2, xs_fmt("mastoapi timeline: returned %d entries", xs_list_len(out))); 1559 srv_debug(2, xs_fmt("mastoapi timeline: returned %d entries", xs_list_len(out)));
1560 } 1560 }
1561 else { 1561 else {
1562 status = 401; // unauthorized 1562 status = HTTP_STATUS_UNAUTHORIZED;
1563 } 1563 }
1564 } 1564 }
1565 else 1565 else
@@ -1612,7 +1612,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1612 1612
1613 *body = xs_json_dumps(out, 4); 1613 *body = xs_json_dumps(out, 4);
1614 *ctype = "application/json"; 1614 *ctype = "application/json";
1615 status = 200; 1615 status = HTTP_STATUS_OK;
1616 } 1616 }
1617 else 1617 else
1618 if (xs_startswith(cmd, "/v1/timelines/tag/")) { /** **/ 1618 if (xs_startswith(cmd, "/v1/timelines/tag/")) { /** **/
@@ -1661,7 +1661,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1661 1661
1662 *body = xs_json_dumps(out, 4); 1662 *body = xs_json_dumps(out, 4);
1663 *ctype = "application/json"; 1663 *ctype = "application/json";
1664 status = 200; 1664 status = HTTP_STATUS_OK;
1665 } 1665 }
1666 else 1666 else
1667 if (xs_startswith(cmd, "/v1/timelines/list/")) { /** **/ 1667 if (xs_startswith(cmd, "/v1/timelines/list/")) { /** **/
@@ -1729,17 +1729,17 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1729 1729
1730 *body = xs_json_dumps(out, 4); 1730 *body = xs_json_dumps(out, 4);
1731 *ctype = "application/json"; 1731 *ctype = "application/json";
1732 status = 200; 1732 status = HTTP_STATUS_OK;
1733 } 1733 }
1734 else 1734 else
1735 status = 421; 1735 status = HTTP_STATUS_MISDIRECTED_REQUEST;
1736 } 1736 }
1737 else 1737 else
1738 if (strcmp(cmd, "/v1/conversations") == 0) { /** **/ 1738 if (strcmp(cmd, "/v1/conversations") == 0) { /** **/
1739 /* TBD */ 1739 /* TBD */
1740 *body = xs_dup("[]"); 1740 *body = xs_dup("[]");
1741 *ctype = "application/json"; 1741 *ctype = "application/json";
1742 status = 200; 1742 status = HTTP_STATUS_OK;
1743 } 1743 }
1744 else 1744 else
1745 if (strcmp(cmd, "/v1/notifications") == 0) { /** **/ 1745 if (strcmp(cmd, "/v1/notifications") == 0) { /** **/
@@ -1817,17 +1817,17 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1817 1817
1818 *body = xs_json_dumps(out, 4); 1818 *body = xs_json_dumps(out, 4);
1819 *ctype = "application/json"; 1819 *ctype = "application/json";
1820 status = 200; 1820 status = HTTP_STATUS_OK;
1821 } 1821 }
1822 else 1822 else
1823 status = 401; 1823 status = HTTP_STATUS_UNAUTHORIZED;
1824 } 1824 }
1825 else 1825 else
1826 if (strcmp(cmd, "/v1/filters") == 0) { /** **/ 1826 if (strcmp(cmd, "/v1/filters") == 0) { /** **/
1827 /* snac will never have filters */ 1827 /* snac will never have filters */
1828 *body = xs_dup("[]"); 1828 *body = xs_dup("[]");
1829 *ctype = "application/json"; 1829 *ctype = "application/json";
1830 status = 200; 1830 status = HTTP_STATUS_OK;
1831 } 1831 }
1832 else 1832 else
1833 if (strcmp(cmd, "/v2/filters") == 0) { /** **/ 1833 if (strcmp(cmd, "/v2/filters") == 0) { /** **/
@@ -1836,21 +1836,21 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1836 * in some apps */ 1836 * in some apps */
1837 *body = xs_dup("[]"); 1837 *body = xs_dup("[]");
1838 *ctype = "application/json"; 1838 *ctype = "application/json";
1839 status = 200; 1839 status = HTTP_STATUS_OK;
1840 } 1840 }
1841 else 1841 else
1842 if (strcmp(cmd, "/v1/favourites") == 0) { /** **/ 1842 if (strcmp(cmd, "/v1/favourites") == 0) { /** **/
1843 /* snac will never support a list of favourites */ 1843 /* snac will never support a list of favourites */
1844 *body = xs_dup("[]"); 1844 *body = xs_dup("[]");
1845 *ctype = "application/json"; 1845 *ctype = "application/json";
1846 status = 200; 1846 status = HTTP_STATUS_OK;
1847 } 1847 }
1848 else 1848 else
1849 if (strcmp(cmd, "/v1/bookmarks") == 0) { /** **/ 1849 if (strcmp(cmd, "/v1/bookmarks") == 0) { /** **/
1850 /* snac does not support bookmarks */ 1850 /* snac does not support bookmarks */
1851 *body = xs_dup("[]"); 1851 *body = xs_dup("[]");
1852 *ctype = "application/json"; 1852 *ctype = "application/json";
1853 status = 200; 1853 status = HTTP_STATUS_OK;
1854 } 1854 }
1855 else 1855 else
1856 if (strcmp(cmd, "/v1/lists") == 0) { /** list of lists **/ 1856 if (strcmp(cmd, "/v1/lists") == 0) { /** list of lists **/
@@ -1873,7 +1873,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1873 1873
1874 *body = xs_json_dumps(l, 4); 1874 *body = xs_json_dumps(l, 4);
1875 *ctype = "application/json"; 1875 *ctype = "application/json";
1876 status = 200; 1876 status = HTTP_STATUS_OK;
1877 } 1877 }
1878 } 1878 }
1879 else 1879 else
@@ -1903,7 +1903,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1903 1903
1904 *body = xs_json_dumps(out, 4); 1904 *body = xs_json_dumps(out, 4);
1905 *ctype = "application/json"; 1905 *ctype = "application/json";
1906 status = 200; 1906 status = HTTP_STATUS_OK;
1907 } 1907 }
1908 } 1908 }
1909 else 1909 else
@@ -1931,7 +1931,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1931 1931
1932 *body = xs_json_dumps(out, 4); 1932 *body = xs_json_dumps(out, 4);
1933 *ctype = "application/json"; 1933 *ctype = "application/json";
1934 status = 200; 1934 status = HTTP_STATUS_OK;
1935 } 1935 }
1936 } 1936 }
1937 } 1937 }
@@ -1941,28 +1941,28 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
1941 /* snac does not schedule notes */ 1941 /* snac does not schedule notes */
1942 *body = xs_dup("[]"); 1942 *body = xs_dup("[]");
1943 *ctype = "application/json"; 1943 *ctype = "application/json";
1944 status = 200; 1944 status = HTTP_STATUS_OK;
1945 } 1945 }
1946 else 1946 else
1947 if (strcmp(cmd, "/v1/follow_requests") == 0) { /** **/ 1947 if (strcmp(cmd, "/v1/follow_requests") == 0) { /** **/
1948 /* snac does not support optional follow confirmations */ 1948 /* snac does not support optional follow confirmations */
1949 *body = xs_dup("[]"); 1949 *body = xs_dup("[]");
1950 *ctype = "application/json"; 1950 *ctype = "application/json";
1951 status = 200; 1951 status = HTTP_STATUS_OK;
1952 } 1952 }
1953 else 1953 else
1954 if (strcmp(cmd, "/v1/announcements") == 0) { /** **/ 1954 if (strcmp(cmd, "/v1/announcements") == 0) { /** **/
1955 /* snac has no announcements (yet?) */ 1955 /* snac has no announcements (yet?) */
1956 *body = xs_dup("[]"); 1956 *body = xs_dup("[]");
1957 *ctype = "application/json"; 1957 *ctype = "application/json";
1958 status = 200; 1958 status = HTTP_STATUS_OK;
1959 } 1959 }
1960 else 1960 else
1961 if (strcmp(cmd, "/v1/custom_emojis") == 0) { /** **/ 1961 if (strcmp(cmd, "/v1/custom_emojis") == 0) { /** **/
1962 /* are you kidding me? */ 1962 /* are you kidding me? */
1963 *body = xs_dup("[]"); 1963 *body = xs_dup("[]");
1964 *ctype = "application/json"; 1964 *ctype = "application/json";
1965 status = 200; 1965 status = HTTP_STATUS_OK;
1966 } 1966 }
1967 else 1967 else
1968 if (strcmp(cmd, "/v1/instance") == 0) { /** **/ 1968 if (strcmp(cmd, "/v1/instance") == 0) { /** **/
@@ -2075,7 +2075,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
2075 2075
2076 *body = xs_json_dumps(ins, 4); 2076 *body = xs_json_dumps(ins, 4);
2077 *ctype = "application/json"; 2077 *ctype = "application/json";
2078 status = 200; 2078 status = HTTP_STATUS_OK;
2079 } 2079 }
2080 else 2080 else
2081 if (xs_startswith(cmd, "/v1/statuses/")) { /** **/ 2081 if (xs_startswith(cmd, "/v1/statuses/")) { /** **/
@@ -2188,30 +2188,30 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
2188 if (out != NULL) { 2188 if (out != NULL) {
2189 *body = xs_json_dumps(out, 4); 2189 *body = xs_json_dumps(out, 4);
2190 *ctype = "application/json"; 2190 *ctype = "application/json";
2191 status = 200; 2191 status = HTTP_STATUS_OK;
2192 } 2192 }
2193 } 2193 }
2194 } 2194 }
2195 else 2195 else
2196 status = 401; 2196 status = HTTP_STATUS_UNAUTHORIZED;
2197 } 2197 }
2198 else 2198 else
2199 if (strcmp(cmd, "/v1/preferences") == 0) { /** **/ 2199 if (strcmp(cmd, "/v1/preferences") == 0) { /** **/
2200 *body = xs_dup("{}"); 2200 *body = xs_dup("{}");
2201 *ctype = "application/json"; 2201 *ctype = "application/json";
2202 status = 200; 2202 status = HTTP_STATUS_OK;
2203 } 2203 }
2204 else 2204 else
2205 if (strcmp(cmd, "/v1/markers") == 0) { /** **/ 2205 if (strcmp(cmd, "/v1/markers") == 0) { /** **/
2206 *body = xs_dup("{}"); 2206 *body = xs_dup("{}");
2207 *ctype = "application/json"; 2207 *ctype = "application/json";
2208 status = 200; 2208 status = HTTP_STATUS_OK;
2209 } 2209 }
2210 else 2210 else
2211 if (strcmp(cmd, "/v1/followed_tags") == 0) { /** **/ 2211 if (strcmp(cmd, "/v1/followed_tags") == 0) { /** **/
2212 *body = xs_dup("[]"); 2212 *body = xs_dup("[]");
2213 *ctype = "application/json"; 2213 *ctype = "application/json";
2214 status = 200; 2214 status = HTTP_STATUS_OK;
2215 } 2215 }
2216 else 2216 else
2217 if (strcmp(cmd, "/v2/search") == 0) { /** **/ 2217 if (strcmp(cmd, "/v2/search") == 0) { /** **/
@@ -2290,10 +2290,10 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
2290 2290
2291 *body = xs_json_dumps(res, 4); 2291 *body = xs_json_dumps(res, 4);
2292 *ctype = "application/json"; 2292 *ctype = "application/json";
2293 status = 200; 2293 status = HTTP_STATUS_OK;
2294 } 2294 }
2295 else 2295 else
2296 status = 401; 2296 status = HTTP_STATUS_UNAUTHORIZED;
2297 } 2297 }
2298 2298
2299 /* user cleanup */ 2299 /* user cleanup */
@@ -2316,7 +2316,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2316 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) 2316 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/"))
2317 return 0; 2317 return 0;
2318 2318
2319 int status = 404; 2319 int status = HTTP_STATUS_NOT_FOUND;
2320 xs *args = NULL; 2320 xs *args = NULL;
2321 const char *i_ctype = xs_dict_get(req, "content-type"); 2321 const char *i_ctype = xs_dict_get(req, "content-type");
2322 2322
@@ -2336,7 +2336,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2336 args = xs_dup(xs_dict_get(req, "p_vars")); 2336 args = xs_dup(xs_dict_get(req, "p_vars"));
2337 2337
2338 if (args == NULL) 2338 if (args == NULL)
2339 return 400; 2339 return HTTP_STATUS_BAD_REQUEST;
2340 2340
2341 xs *cmd = xs_replace_n(q_path, "/api", "", 1); 2341 xs *cmd = xs_replace_n(q_path, "/api", "", 1);
2342 2342
@@ -2378,7 +2378,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2378 2378
2379 *body = xs_json_dumps(app, 4); 2379 *body = xs_json_dumps(app, 4);
2380 *ctype = "application/json"; 2380 *ctype = "application/json";
2381 status = 200; 2381 status = HTTP_STATUS_OK;
2382 2382
2383 app = xs_dict_append(app, "code", ""); 2383 app = xs_dict_append(app, "code", "");
2384 2384
@@ -2470,10 +2470,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2470 2470
2471 *body = xs_json_dumps(st, 4); 2471 *body = xs_json_dumps(st, 4);
2472 *ctype = "application/json"; 2472 *ctype = "application/json";
2473 status = 200; 2473 status = HTTP_STATUS_OK;
2474 } 2474 }
2475 else 2475 else
2476 status = 401; 2476 status = HTTP_STATUS_UNAUTHORIZED;
2477 } 2477 }
2478 else 2478 else
2479 if (xs_startswith(cmd, "/v1/statuses")) { /** **/ 2479 if (xs_startswith(cmd, "/v1/statuses")) { /** **/
@@ -2552,7 +2552,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2552 if (pin(&snac, id)) 2552 if (pin(&snac, id))
2553 out = mastoapi_status(&snac, msg); 2553 out = mastoapi_status(&snac, msg);
2554 else 2554 else
2555 status = 422; 2555 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
2556 } 2556 }
2557 else 2557 else
2558 if (strcmp(op, "unpin") == 0) { /** **/ 2558 if (strcmp(op, "unpin") == 0) { /** **/
@@ -2573,12 +2573,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2573 if (out != NULL) { 2573 if (out != NULL) {
2574 *body = xs_json_dumps(out, 4); 2574 *body = xs_json_dumps(out, 4);
2575 *ctype = "application/json"; 2575 *ctype = "application/json";
2576 status = 200; 2576 status = HTTP_STATUS_OK;
2577 } 2577 }
2578 } 2578 }
2579 } 2579 }
2580 else 2580 else
2581 status = 401; 2581 status = HTTP_STATUS_UNAUTHORIZED;
2582 } 2582 }
2583 else 2583 else
2584 if (strcmp(cmd, "/v1/notifications/clear") == 0) { /** **/ 2584 if (strcmp(cmd, "/v1/notifications/clear") == 0) { /** **/
@@ -2588,10 +2588,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2588 2588
2589 *body = xs_dup("{}"); 2589 *body = xs_dup("{}");
2590 *ctype = "application/json"; 2590 *ctype = "application/json";
2591 status = 200; 2591 status = HTTP_STATUS_OK;
2592 } 2592 }
2593 else 2593 else
2594 status = 401; 2594 status = HTTP_STATUS_UNAUTHORIZED;
2595 } 2595 }
2596 else 2596 else
2597 if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/ 2597 if (strcmp(cmd, "/v1/push/subscription") == 0) { /** **/
@@ -2616,10 +2616,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2616 2616
2617 *body = xs_json_dumps(wpush, 4); 2617 *body = xs_json_dumps(wpush, 4);
2618 *ctype = "application/json"; 2618 *ctype = "application/json";
2619 status = 200; 2619 status = HTTP_STATUS_OK;
2620 } 2620 }
2621 else 2621 else
2622 status = 401; 2622 status = HTTP_STATUS_UNAUTHORIZED;
2623 } 2623 }
2624 else 2624 else
2625 if (strcmp(cmd, "/v1/media") == 0 || strcmp(cmd, "/v2/media") == 0) { /** **/ 2625 if (strcmp(cmd, "/v1/media") == 0 || strcmp(cmd, "/v2/media") == 0) { /** **/
@@ -2630,7 +2630,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2630 if (xs_is_null(desc)) 2630 if (xs_is_null(desc))
2631 desc = ""; 2631 desc = "";
2632 2632
2633 status = 400; 2633 status = HTTP_STATUS_BAD_REQUEST;
2634 2634
2635 if (xs_type(file) == XSTYPE_LIST) { 2635 if (xs_type(file) == XSTYPE_LIST) {
2636 const char *fn = xs_list_get(file, 0); 2636 const char *fn = xs_list_get(file, 0);
@@ -2659,12 +2659,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2659 2659
2660 *body = xs_json_dumps(rsp, 4); 2660 *body = xs_json_dumps(rsp, 4);
2661 *ctype = "application/json"; 2661 *ctype = "application/json";
2662 status = 200; 2662 status = HTTP_STATUS_OK;
2663 } 2663 }
2664 } 2664 }
2665 } 2665 }
2666 else 2666 else
2667 status = 401; 2667 status = HTTP_STATUS_UNAUTHORIZED;
2668 } 2668 }
2669 else 2669 else
2670 if (xs_startswith(cmd, "/v1/accounts")) { /** **/ 2670 if (xs_startswith(cmd, "/v1/accounts")) { /** **/
@@ -2744,11 +2744,11 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2744 if (rsp != NULL) { 2744 if (rsp != NULL) {
2745 *body = xs_json_dumps(rsp, 4); 2745 *body = xs_json_dumps(rsp, 4);
2746 *ctype = "application/json"; 2746 *ctype = "application/json";
2747 status = 200; 2747 status = HTTP_STATUS_OK;
2748 } 2748 }
2749 } 2749 }
2750 else 2750 else
2751 status = 401; 2751 status = HTTP_STATUS_UNAUTHORIZED;
2752 } 2752 }
2753 else 2753 else
2754 if (xs_startswith(cmd, "/v1/polls")) { /** **/ 2754 if (xs_startswith(cmd, "/v1/polls")) { /** **/
@@ -2810,12 +2810,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2810 if (out != NULL) { 2810 if (out != NULL) {
2811 *body = xs_json_dumps(out, 4); 2811 *body = xs_json_dumps(out, 4);
2812 *ctype = "application/json"; 2812 *ctype = "application/json";
2813 status = 200; 2813 status = HTTP_STATUS_OK;
2814 } 2814 }
2815 } 2815 }
2816 } 2816 }
2817 else 2817 else
2818 status = 401; 2818 status = HTTP_STATUS_UNAUTHORIZED;
2819 } 2819 }
2820 else 2820 else
2821 if (strcmp(cmd, "/v1/lists") == 0) { 2821 if (strcmp(cmd, "/v1/lists") == 0) {
@@ -2831,18 +2831,18 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2831 out = xs_dict_append(out, "replies_policy", xs_dict_get_def(args, "replies_policy", "list")); 2831 out = xs_dict_append(out, "replies_policy", xs_dict_get_def(args, "replies_policy", "list"));
2832 out = xs_dict_append(out, "exclusive", xs_stock(XSTYPE_FALSE)); 2832 out = xs_dict_append(out, "exclusive", xs_stock(XSTYPE_FALSE));
2833 2833
2834 status = 200; 2834 status = HTTP_STATUS_OK;
2835 } 2835 }
2836 else { 2836 else {
2837 out = xs_dict_append(out, "error", "cannot create list"); 2837 out = xs_dict_append(out, "error", "cannot create list");
2838 status = 422; 2838 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
2839 } 2839 }
2840 2840
2841 *body = xs_json_dumps(out, 4); 2841 *body = xs_json_dumps(out, 4);
2842 *ctype = "application/json"; 2842 *ctype = "application/json";
2843 } 2843 }
2844 else 2844 else
2845 status = 422; 2845 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
2846 } 2846 }
2847 } 2847 }
2848 if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/ 2848 if (xs_startswith(cmd, "/v1/lists/")) { /** list maintenance **/
@@ -2861,12 +2861,12 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path,
2861 list_content(&snac, id, v, 1); 2861 list_content(&snac, id, v, 1);
2862 } 2862 }
2863 2863
2864 status = 200; 2864 status = HTTP_STATUS_OK;
2865 } 2865 }
2866 } 2866 }
2867 } 2867 }
2868 else 2868 else
2869 status = 422; 2869 status = HTTP_STATUS_UNPROCESSABLE_CONTENT;
2870 } 2870 }
2871 2871
2872 /* user cleanup */ 2872 /* user cleanup */
@@ -2891,7 +2891,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
2891 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) 2891 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/"))
2892 return 0; 2892 return 0;
2893 2893
2894 int status = 404; 2894 int status = HTTP_STATUS_NOT_FOUND;
2895 xs *args = NULL; 2895 xs *args = NULL;
2896 const char *i_ctype = xs_dict_get(req, "content-type"); 2896 const char *i_ctype = xs_dict_get(req, "content-type");
2897 2897
@@ -2911,7 +2911,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
2911 args = xs_dup(xs_dict_get(req, "p_vars")); 2911 args = xs_dup(xs_dict_get(req, "p_vars"));
2912 2912
2913 if (args == NULL) 2913 if (args == NULL)
2914 return 400; 2914 return HTTP_STATUS_BAD_REQUEST;
2915 2915
2916 snac snac = {0}; 2916 snac snac = {0};
2917 int logged_in = process_auth_token(&snac, req); 2917 int logged_in = process_auth_token(&snac, req);
@@ -2920,7 +2920,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
2920 2920
2921 if (xs_startswith(cmd, "/v1/push/subscription") || xs_startswith(cmd, "/v2/push/subscription")) { /** **/ 2921 if (xs_startswith(cmd, "/v1/push/subscription") || xs_startswith(cmd, "/v2/push/subscription")) { /** **/
2922 // pretend we deleted it, since it doesn't exist anyway 2922 // pretend we deleted it, since it doesn't exist anyway
2923 status = 200; 2923 status = HTTP_STATUS_OK;
2924 } 2924 }
2925 else 2925 else
2926 if (xs_startswith(cmd, "/v1/lists/")) { 2926 if (xs_startswith(cmd, "/v1/lists/")) {
@@ -2948,10 +2948,10 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path,
2948 } 2948 }
2949 } 2949 }
2950 2950
2951 status = 200; 2951 status = HTTP_STATUS_OK;
2952 } 2952 }
2953 else 2953 else
2954 status = 401; 2954 status = HTTP_STATUS_UNAUTHORIZED;
2955 } 2955 }
2956 2956
2957 /* user cleanup */ 2957 /* user cleanup */
@@ -2974,7 +2974,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
2974 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) 2974 if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/"))
2975 return 0; 2975 return 0;
2976 2976
2977 int status = 404; 2977 int status = HTTP_STATUS_NOT_FOUND;
2978 xs *args = NULL; 2978 xs *args = NULL;
2979 const char *i_ctype = xs_dict_get(req, "content-type"); 2979 const char *i_ctype = xs_dict_get(req, "content-type");
2980 2980
@@ -2986,7 +2986,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
2986 args = xs_dup(xs_dict_get(req, "p_vars")); 2986 args = xs_dup(xs_dict_get(req, "p_vars"));
2987 2987
2988 if (args == NULL) 2988 if (args == NULL)
2989 return 400; 2989 return HTTP_STATUS_BAD_REQUEST;
2990 2990
2991 xs *cmd = xs_replace_n(q_path, "/api", "", 1); 2991 xs *cmd = xs_replace_n(q_path, "/api", "", 1);
2992 2992
@@ -3017,11 +3017,11 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
3017 3017
3018 *body = xs_json_dumps(rsp, 4); 3018 *body = xs_json_dumps(rsp, 4);
3019 *ctype = "application/json"; 3019 *ctype = "application/json";
3020 status = 200; 3020 status = HTTP_STATUS_OK;
3021 } 3021 }
3022 } 3022 }
3023 else 3023 else
3024 status = 401; 3024 status = HTTP_STATUS_UNAUTHORIZED;
3025 } 3025 }
3026 else 3026 else
3027 if (xs_startswith(cmd, "/v1/statuses")) { 3027 if (xs_startswith(cmd, "/v1/statuses")) {
@@ -3060,12 +3060,12 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
3060 if (rsp != NULL) { 3060 if (rsp != NULL) {
3061 *body = xs_json_dumps(rsp, 4); 3061 *body = xs_json_dumps(rsp, 4);
3062 *ctype = "application/json"; 3062 *ctype = "application/json";
3063 status = 200; 3063 status = HTTP_STATUS_OK;
3064 } 3064 }
3065 } 3065 }
3066 } 3066 }
3067 else 3067 else
3068 status = 401; 3068 status = HTTP_STATUS_UNAUTHORIZED;
3069 } 3069 }
3070 3070
3071 /* user cleanup */ 3071 /* user cleanup */
diff --git a/snac.h b/snac.h
index 79e144a..d79f3ea 100644
--- a/snac.h
+++ b/snac.h
@@ -361,3 +361,53 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path,
361void mastoapi_purge(void); 361void mastoapi_purge(void);
362 362
363void verify_links(snac *user); 363void verify_links(snac *user);
364
365/* HTTP responses RFC 9110 plus some extensions */
366
367typedef enum {
368 HTTP_STATUS_CONTINUE = 100,
369 HTTP_STATUS_SWITCHTING_PROTOCOLS = 101,
370 HTTP_STATUS_PROCESSING = 102,
371 HTTP_STATUS_EARLY_HINTS = 103,
372 HTTP_STATUS_OK = 200,
373 HTTP_STATUS_CREATED = 201,
374 HTTP_STATUS_ACCEPTED = 202,
375 HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203,
376 HTTP_STATUS_NO_CONTENT = 204,
377 HTTP_STATUS_RESET_CONTENT = 205,
378 HTTP_STATUS_PARTIAL_CONTENT = 206,
379 HTTP_STATUS_MULTI_STATUS = 207,
380 HTTP_STATUS_ALREADY_REPORTED = 208,
381 HTTP_STATUS_THIS_IS_FINE = 218,
382 HTTP_STATUS_IM_USED = 226,
383 HTTP_STATUS_MULTIPLE_CHOICES = 300,
384 HTTP_STATUS_MOVED_PERMANENTLY = 301,
385 HTTP_STATUS_FOUND = 302,
386 HTTP_STATUS_SEE_OTHER = 303,
387 HTTP_STATUS_NOT_MODIFIED = 304,
388 HTTP_STATUS_USE_PROXY = 305,
389 HTTP_STATUS_SWITCH_PROXY = 306,
390 HTTP_STATUS_TEMPORARY_REDIRECT = 307,
391 HTTP_STATUS_PERMANENT_REDIRECT = 308,
392 HTTP_STATUS_BAD_REQUEST = 400,
393 HTTP_STATUS_UNAUTHORIZED = 401,
394 HTTP_STATUS_PAYMENT_REQUIRED = 402,
395 HTTP_STATUS_FORBIDDEN = 403,
396 HTTP_STATUS_NOT_FOUND = 404,
397 HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
398 HTTP_STATUS_NOT_ACCEPTABLE = 406,
399 HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407,
400 HTTP_STATUS_REQUEST_TIMEOUT = 408,
401 HTTP_STATUS_CONFLICT = 409,
402 HTTP_STATUS_GONE = 410,
403 HTTP_STATUS_MISDIRECTED_REQUEST = 421,
404 HTTP_STATUS_UNPROCESSABLE_CONTENT = 422,
405 HTTP_STATUS_CLIENT_CLOSED_REQUEST = 499,
406 HTTP_STATUS_INTERNAL_SERVER_ERROR = 500,
407 HTTP_STATUS_NOT_IMPLEMENTED = 501,
408 HTTP_STATUS_BAD_GATEWAY = 502,
409 HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
410 HTTP_STATUS_GATEWAY_TIMEOUT = 504,
411 HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505,
412 HTTP_STATUS_INSUFFICIENT_STORAGE = 507
413} http_status;
diff --git a/webfinger.c b/webfinger.c
index c79fd44..0c18362 100644
--- a/webfinger.c
+++ b/webfinger.c
@@ -42,7 +42,7 @@ int webfinger_request_signed(snac *snac, const char *qs, char **actor, char **us
42 } 42 }
43 43
44 if (host == NULL || resource == NULL) 44 if (host == NULL || resource == NULL)
45 return 400; 45 return HTTP_STATUS_BAD_REQUEST;
46 46
47 headers = xs_dict_append(headers, "accept", "application/json"); 47 headers = xs_dict_append(headers, "accept", "application/json");
48 headers = xs_dict_append(headers, "user-agent", USER_AGENT); 48 headers = xs_dict_append(headers, "user-agent", USER_AGENT);
@@ -139,7 +139,7 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
139 const char *resource = xs_dict_get(q_vars, "resource"); 139 const char *resource = xs_dict_get(q_vars, "resource");
140 140
141 if (resource == NULL) 141 if (resource == NULL)
142 return 400; 142 return HTTP_STATUS_BAD_REQUEST;
143 143
144 snac snac; 144 snac snac;
145 int found = 0; 145 int found = 0;
@@ -220,12 +220,12 @@ int webfinger_get_handler(xs_dict *req, char *q_path,
220 220
221 user_free(&snac); 221 user_free(&snac);
222 222
223 status = 200; 223 status = HTTP_STATUS_OK;
224 *body = j; 224 *body = j;
225 *ctype = "application/jrd+json"; 225 *ctype = "application/jrd+json";
226 } 226 }
227 else 227 else
228 status = 404; 228 status = HTTP_STATUS_NOT_FOUND;
229 229
230 srv_debug(1, xs_fmt("webfinger_get_handler resource=%s %d", resource, status)); 230 srv_debug(1, xs_fmt("webfinger_get_handler resource=%s %d", resource, status));
231 231