diff options
| -rw-r--r-- | RELEASE_NOTES.md | 2 | ||||
| -rw-r--r-- | mastoapi.c | 57 |
2 files changed, 46 insertions, 13 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b0d37f4..e3cefa4 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md | |||
| @@ -10,7 +10,7 @@ The avatar and/or the header images can now be deleted (contributed by louis77). | |||
| 10 | 10 | ||
| 11 | Code cleaning: HTTP status codes use names instead of hardcoded integers (contributed by louis77). | 11 | Code cleaning: HTTP status codes use names instead of hardcoded integers (contributed by louis77). |
| 12 | 12 | ||
| 13 | Mastodon API: some fixes for Mona and Tokodon apps, user credentials can now be edited from apps (contributed by louis77). | 13 | Mastodon API: fixed login problems with the official Mastodon API, IceCube and Toot! on iOS, some fixes for Mona and Tokodon apps, user credentials can now be edited from apps (contributed by louis77). |
| 14 | 14 | ||
| 15 | The webfinger content-type response header is now RFC-compliant (contributed by steve-bate). | 15 | The webfinger content-type response header is now RFC-compliant (contributed by steve-bate). |
| 16 | 16 | ||
| @@ -152,6 +152,7 @@ const char *login_page = "" | |||
| 152 | "<html>\n" | 152 | "<html>\n" |
| 153 | "<head>\n" | 153 | "<head>\n" |
| 154 | "<title>%s OAuth - Snac2</title>\n" | 154 | "<title>%s OAuth - Snac2</title>\n" |
| 155 | "<meta content=\"width=device-width, initial-scale=1, minimum-scale=1, user-scalable=no\" name=\"viewport\">" | ||
| 155 | "<style>:root {color-scheme: light dark}</style>\n" | 156 | "<style>:root {color-scheme: light dark}</style>\n" |
| 156 | "</head>\n" | 157 | "</head>\n" |
| 157 | "<body><h1>%s OAuth identify</h1>\n" | 158 | "<body><h1>%s OAuth identify</h1>\n" |
| @@ -338,11 +339,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 338 | const char *cid = xs_dict_get(args, "client_id"); | 339 | const char *cid = xs_dict_get(args, "client_id"); |
| 339 | const char *csec = xs_dict_get(args, "client_secret"); | 340 | const char *csec = xs_dict_get(args, "client_secret"); |
| 340 | const char *ruri = xs_dict_get(args, "redirect_uri"); | 341 | const char *ruri = xs_dict_get(args, "redirect_uri"); |
| 341 | /* FIXME: this 'scope' parameter is mandatory for the official Mastodon API, | 342 | const char *scope = xs_dict_get(args, "scope"); |
| 342 | but if it's enabled, it makes it crash after some more steps, which | ||
| 343 | is FAR WORSE */ | ||
| 344 | const char *scope = NULL; | ||
| 345 | // scope = xs_dict_get(args, "scope"); | ||
| 346 | 343 | ||
| 347 | /* no client_secret? check if it's inside an authorization header | 344 | /* no client_secret? check if it's inside an authorization header |
| 348 | (AndStatus does it this way) */ | 345 | (AndStatus does it this way) */ |
| @@ -1164,8 +1161,10 @@ void credentials_get(char **body, char **ctype, int *status, snac snac) | |||
| 1164 | acct = xs_dict_append(acct, "url", snac.actor); | 1161 | acct = xs_dict_append(acct, "url", snac.actor); |
| 1165 | acct = xs_dict_append(acct, "locked", xs_stock(XSTYPE_FALSE)); | 1162 | acct = xs_dict_append(acct, "locked", xs_stock(XSTYPE_FALSE)); |
| 1166 | acct = xs_dict_append(acct, "bot", xs_dict_get(snac.config, "bot")); | 1163 | acct = xs_dict_append(acct, "bot", xs_dict_get(snac.config, "bot")); |
| 1164 | acct = xs_dict_append(acct, "emojis", xs_stock(XSTYPE_LIST)); | ||
| 1167 | 1165 | ||
| 1168 | xs *src = xs_json_loads("{\"privacy\":\"public\"," | 1166 | xs *src = xs_json_loads("{\"privacy\":\"public\", \"language\":\"en\"," |
| 1167 | "\"follow_requests_count\": 0," | ||
| 1169 | "\"sensitive\":false,\"fields\":[],\"note\":\"\"}"); | 1168 | "\"sensitive\":false,\"fields\":[],\"note\":\"\"}"); |
| 1170 | /* some apps take the note from the source object */ | 1169 | /* some apps take the note from the source object */ |
| 1171 | src = xs_dict_set(src, "note", xs_dict_get(snac.config, "bio")); | 1170 | src = xs_dict_set(src, "note", xs_dict_get(snac.config, "bio")); |
| @@ -1447,9 +1446,27 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1447 | if (strcmp(opt, "featured_tags") == 0) { | 1446 | if (strcmp(opt, "featured_tags") == 0) { |
| 1448 | /* snac doesn't have features tags, yet? */ | 1447 | /* snac doesn't have features tags, yet? */ |
| 1449 | /* implement empty response so apps like Tokodon don't show an error */ | 1448 | /* implement empty response so apps like Tokodon don't show an error */ |
| 1450 | *body = xs_dup("[]"); | 1449 | out = xs_list_new(); |
| 1451 | *ctype = "application/json"; | 1450 | } |
| 1452 | status = HTTP_STATUS_OK; | 1451 | else |
| 1452 | if (strcmp(opt, "following") == 0) { | ||
| 1453 | xs *wing = following_list(&snac1); | ||
| 1454 | out = xs_list_new(); | ||
| 1455 | int c = 0; | ||
| 1456 | const char *v; | ||
| 1457 | |||
| 1458 | while (xs_list_next(wing, &v, &c)) { | ||
| 1459 | xs *actor = NULL; | ||
| 1460 | |||
| 1461 | if (valid_status(object_get(v, &actor))) { | ||
| 1462 | xs *acct = mastoapi_account(actor); | ||
| 1463 | out = xs_list_append(out, acct); | ||
| 1464 | } | ||
| 1465 | } | ||
| 1466 | } | ||
| 1467 | else | ||
| 1468 | if (strcmp(opt, "followers") == 0) { | ||
| 1469 | out = xs_list_new(); | ||
| 1453 | } | 1470 | } |
| 1454 | 1471 | ||
| 1455 | user_free(&snac2); | 1472 | user_free(&snac2); |
| @@ -1470,9 +1487,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1470 | if (strcmp(opt, "featured_tags") == 0) { | 1487 | if (strcmp(opt, "featured_tags") == 0) { |
| 1471 | /* snac doesn't have features tags, yet? */ | 1488 | /* snac doesn't have features tags, yet? */ |
| 1472 | /* implement empty response so apps like Tokodon don't show an error */ | 1489 | /* implement empty response so apps like Tokodon don't show an error */ |
| 1473 | *body = xs_dup("[]"); | 1490 | out = xs_list_new(); |
| 1474 | *ctype = "application/json"; | ||
| 1475 | status = HTTP_STATUS_OK; | ||
| 1476 | } | 1491 | } |
| 1477 | } | 1492 | } |
| 1478 | } | 1493 | } |
| @@ -2408,6 +2423,14 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2408 | const char *ruri = xs_dict_get(args, "redirect_uris"); | 2423 | const char *ruri = xs_dict_get(args, "redirect_uris"); |
| 2409 | const char *scope = xs_dict_get(args, "scope"); | 2424 | const char *scope = xs_dict_get(args, "scope"); |
| 2410 | 2425 | ||
| 2426 | /* Ice Cubes sends these values as query parameters, so try these */ | ||
| 2427 | if (name == NULL && ruri == NULL && scope == NULL) { | ||
| 2428 | args = xs_dup(xs_dict_get(req, "q_vars")); | ||
| 2429 | name = xs_dict_get(args, "client_name"); | ||
| 2430 | ruri = xs_dict_get(args, "redirect_uris"); | ||
| 2431 | scope = xs_dict_get(args, "scope"); | ||
| 2432 | } | ||
| 2433 | |||
| 2411 | if (xs_type(ruri) == XSTYPE_LIST) | 2434 | if (xs_type(ruri) == XSTYPE_LIST) |
| 2412 | ruri = xs_dict_get(ruri, 0); | 2435 | ruri = xs_dict_get(ruri, 0); |
| 2413 | 2436 | ||
| @@ -2914,6 +2937,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2914 | if (op && id && xs_is_hex(id)) { | 2937 | if (op && id && xs_is_hex(id)) { |
| 2915 | if (strcmp(op, "accounts") == 0) { | 2938 | if (strcmp(op, "accounts") == 0) { |
| 2916 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); | 2939 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); |
| 2940 | |||
| 2941 | if (xs_is_null(accts)) | ||
| 2942 | accts = xs_dict_get(args, "account_ids"); | ||
| 2943 | |||
| 2917 | int c = 0; | 2944 | int c = 0; |
| 2918 | const char *v; | 2945 | const char *v; |
| 2919 | 2946 | ||
| @@ -2921,6 +2948,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 2921 | list_content(&snac, id, v, 1); | 2948 | list_content(&snac, id, v, 1); |
| 2922 | } | 2949 | } |
| 2923 | 2950 | ||
| 2951 | *ctype = "application/json"; | ||
| 2924 | status = HTTP_STATUS_OK; | 2952 | status = HTTP_STATUS_OK; |
| 2925 | } | 2953 | } |
| 2926 | } | 2954 | } |
| @@ -2993,6 +3021,10 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 2993 | /* delete account from list */ | 3021 | /* delete account from list */ |
| 2994 | p = xs_list_get(l, -2); | 3022 | p = xs_list_get(l, -2); |
| 2995 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); | 3023 | const xs_list *accts = xs_dict_get(args, "account_ids[]"); |
| 3024 | |||
| 3025 | if (xs_is_null(accts)) | ||
| 3026 | accts = xs_dict_get(args, "account_ids"); | ||
| 3027 | |||
| 2996 | int c = 0; | 3028 | int c = 0; |
| 2997 | const char *v; | 3029 | const char *v; |
| 2998 | 3030 | ||
| @@ -3008,6 +3040,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, | |||
| 3008 | } | 3040 | } |
| 3009 | } | 3041 | } |
| 3010 | 3042 | ||
| 3043 | *ctype = "application/json"; | ||
| 3011 | status = HTTP_STATUS_OK; | 3044 | status = HTTP_STATUS_OK; |
| 3012 | } | 3045 | } |
| 3013 | else | 3046 | else |