diff options
Diffstat (limited to 'mastoapi.c')
| -rw-r--r-- | mastoapi.c | 201 |
1 files changed, 121 insertions, 80 deletions
| @@ -162,7 +162,7 @@ const char *login_page = "" | |||
| 162 | "<!DOCTYPE html>\n" | 162 | "<!DOCTYPE html>\n" |
| 163 | "<body><h1>%s OAuth identify</h1>\n" | 163 | "<body><h1>%s OAuth identify</h1>\n" |
| 164 | "<div style=\"background-color: red; color: white\">%s</div>\n" | 164 | "<div style=\"background-color: red; color: white\">%s</div>\n" |
| 165 | "<form method=\"post\" action=\"https:/" "/%s/oauth/x-snac-login\">\n" | 165 | "<form method=\"post\" action=\"https:/" "/%s/%s\">\n" |
| 166 | "<p>Login: <input type=\"text\" name=\"login\"></p>\n" | 166 | "<p>Login: <input type=\"text\" name=\"login\"></p>\n" |
| 167 | "<p>Password: <input type=\"password\" name=\"passwd\"></p>\n" | 167 | "<p>Password: <input type=\"password\" name=\"passwd\"></p>\n" |
| 168 | "<input type=\"hidden\" name=\"redir\" value=\"%s\">\n" | 168 | "<input type=\"hidden\" name=\"redir\" value=\"%s\">\n" |
| @@ -175,6 +175,8 @@ const char *login_page = "" | |||
| 175 | int oauth_get_handler(const xs_dict *req, const char *q_path, | 175 | int oauth_get_handler(const xs_dict *req, const char *q_path, |
| 176 | char **body, int *b_size, char **ctype) | 176 | char **body, int *b_size, char **ctype) |
| 177 | { | 177 | { |
| 178 | (void)b_size; | ||
| 179 | |||
| 178 | if (!xs_startswith(q_path, "/oauth/")) | 180 | if (!xs_startswith(q_path, "/oauth/")) |
| 179 | return 0; | 181 | return 0; |
| 180 | 182 | ||
| @@ -185,7 +187,7 @@ int oauth_get_handler(const xs_dict *req, const char *q_path, | |||
| 185 | 187 | ||
| 186 | int status = 404; | 188 | int status = 404; |
| 187 | xs_dict *msg = xs_dict_get(req, "q_vars"); | 189 | xs_dict *msg = xs_dict_get(req, "q_vars"); |
| 188 | xs *cmd = xs_replace(q_path, "/oauth", ""); | 190 | xs *cmd = xs_replace_n(q_path, "/oauth", "", 1); |
| 189 | 191 | ||
| 190 | srv_debug(1, xs_fmt("oauth_get_handler %s", q_path)); | 192 | srv_debug(1, xs_fmt("oauth_get_handler %s", q_path)); |
| 191 | 193 | ||
| @@ -206,17 +208,28 @@ int oauth_get_handler(const xs_dict *req, const char *q_path, | |||
| 206 | if (xs_is_null(state)) | 208 | if (xs_is_null(state)) |
| 207 | state = ""; | 209 | state = ""; |
| 208 | 210 | ||
| 209 | *body = xs_fmt(login_page, host, "", host, ruri, cid, state, USER_AGENT); | 211 | *body = xs_fmt(login_page, host, "", host, "oauth/x-snac-login", |
| 212 | ruri, cid, state, USER_AGENT); | ||
| 210 | *ctype = "text/html"; | 213 | *ctype = "text/html"; |
| 211 | status = 200; | 214 | status = 200; |
| 212 | 215 | ||
| 213 | srv_debug(0, xs_fmt("oauth authorize: generating login page")); | 216 | srv_debug(1, xs_fmt("oauth authorize: generating login page")); |
| 214 | } | 217 | } |
| 215 | else | 218 | else |
| 216 | srv_debug(0, xs_fmt("oauth authorize: bad client_id %s", cid)); | 219 | srv_debug(1, xs_fmt("oauth authorize: bad client_id %s", cid)); |
| 217 | } | 220 | } |
| 218 | else | 221 | else |
| 219 | srv_debug(0, xs_fmt("oauth authorize: invalid or unset arguments")); | 222 | srv_debug(1, xs_fmt("oauth authorize: invalid or unset arguments")); |
| 223 | } | ||
| 224 | else | ||
| 225 | if (strcmp(cmd, "/x-snac-get-token") == 0) { | ||
| 226 | const char *host = xs_dict_get(srv_config, "host"); | ||
| 227 | |||
| 228 | *body = xs_fmt(login_page, host, "", host, "oauth/x-snac-get-token", | ||
| 229 | "", "", "", USER_AGENT); | ||
| 230 | *ctype = "text/html"; | ||
| 231 | status = 200; | ||
| 232 | |||
| 220 | } | 233 | } |
| 221 | 234 | ||
| 222 | return status; | 235 | return status; |
| @@ -227,6 +240,9 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 227 | const char *payload, int p_size, | 240 | const char *payload, int p_size, |
| 228 | char **body, int *b_size, char **ctype) | 241 | char **body, int *b_size, char **ctype) |
| 229 | { | 242 | { |
| 243 | (void)p_size; | ||
| 244 | (void)b_size; | ||
| 245 | |||
| 230 | if (!xs_startswith(q_path, "/oauth/")) | 246 | if (!xs_startswith(q_path, "/oauth/")) |
| 231 | return 0; | 247 | return 0; |
| 232 | 248 | ||
| @@ -245,7 +261,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 245 | else | 261 | else |
| 246 | args = xs_dup(xs_dict_get(req, "p_vars")); | 262 | args = xs_dup(xs_dict_get(req, "p_vars")); |
| 247 | 263 | ||
| 248 | xs *cmd = xs_replace(q_path, "/oauth", ""); | 264 | xs *cmd = xs_replace_n(q_path, "/oauth", "", 1); |
| 249 | 265 | ||
| 250 | srv_debug(1, xs_fmt("oauth_post_handler %s", q_path)); | 266 | srv_debug(1, xs_fmt("oauth_post_handler %s", q_path)); |
| 251 | 267 | ||
| @@ -259,7 +275,8 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 259 | const char *host = xs_dict_get(srv_config, "host"); | 275 | const char *host = xs_dict_get(srv_config, "host"); |
| 260 | 276 | ||
| 261 | /* by default, generate another login form with an error */ | 277 | /* by default, generate another login form with an error */ |
| 262 | *body = xs_fmt(login_page, host, "LOGIN INCORRECT", host, redir, cid, state, USER_AGENT); | 278 | *body = xs_fmt(login_page, host, "LOGIN INCORRECT", host, "oauth/x-snac-login", |
| 279 | redir, cid, state, USER_AGENT); | ||
| 263 | *ctype = "text/html"; | 280 | *ctype = "text/html"; |
| 264 | status = 200; | 281 | status = 200; |
| 265 | 282 | ||
| @@ -268,8 +285,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 268 | 285 | ||
| 269 | if (user_open(&snac, login)) { | 286 | if (user_open(&snac, login)) { |
| 270 | /* check the login + password */ | 287 | /* check the login + password */ |
| 271 | if (check_password(login, passwd, | 288 | if (check_password(login, passwd, xs_dict_get(snac.config, "passwd"))) { |
| 272 | xs_dict_get(snac.config, "passwd"))) { | ||
| 273 | /* success! redirect to the desired uri */ | 289 | /* success! redirect to the desired uri */ |
| 274 | xs *code = random_str(); | 290 | xs *code = random_str(); |
| 275 | 291 | ||
| @@ -328,7 +344,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 328 | const char *auhdr = xs_dict_get(req, "authorization"); | 344 | const char *auhdr = xs_dict_get(req, "authorization"); |
| 329 | 345 | ||
| 330 | if (!xs_is_null(auhdr) && xs_startswith(auhdr, "Basic ")) { | 346 | if (!xs_is_null(auhdr) && xs_startswith(auhdr, "Basic ")) { |
| 331 | xs *s1 = xs_replace(auhdr, "Basic ", ""); | 347 | xs *s1 = xs_replace_n(auhdr, "Basic ", "", 1); |
| 332 | int size; | 348 | int size; |
| 333 | xs *s2 = xs_base64_dec(s1, &size); | 349 | xs *s2 = xs_base64_dec(s1, &size); |
| 334 | 350 | ||
| @@ -373,7 +389,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 373 | 389 | ||
| 374 | const char *uid = xs_dict_get(app, "uid"); | 390 | const char *uid = xs_dict_get(app, "uid"); |
| 375 | 391 | ||
| 376 | srv_debug(0, xs_fmt("oauth token: " | 392 | srv_debug(1, xs_fmt("oauth token: " |
| 377 | "successful login for %s, new token %s", uid, tokid)); | 393 | "successful login for %s, new token %s", uid, tokid)); |
| 378 | 394 | ||
| 379 | xs *token = xs_dict_new(); | 395 | xs *token = xs_dict_new(); |
| @@ -387,7 +403,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 387 | } | 403 | } |
| 388 | } | 404 | } |
| 389 | else { | 405 | else { |
| 390 | srv_debug(0, xs_fmt("oauth token: invalid or unset arguments")); | 406 | srv_debug(1, xs_fmt("oauth token: invalid or unset arguments")); |
| 391 | status = 400; | 407 | status = 400; |
| 392 | } | 408 | } |
| 393 | } | 409 | } |
| @@ -409,7 +425,7 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 409 | } | 425 | } |
| 410 | else { | 426 | else { |
| 411 | token_del(tokid); | 427 | token_del(tokid); |
| 412 | srv_debug(0, xs_fmt("oauth revoke: revoked token %s", tokid)); | 428 | srv_debug(1, xs_fmt("oauth revoke: revoked token %s", tokid)); |
| 413 | status = 200; | 429 | status = 200; |
| 414 | 430 | ||
| 415 | /* also delete the app, as it serves no purpose from now on */ | 431 | /* also delete the app, as it serves no purpose from now on */ |
| @@ -417,10 +433,52 @@ int oauth_post_handler(const xs_dict *req, const char *q_path, | |||
| 417 | } | 433 | } |
| 418 | } | 434 | } |
| 419 | else { | 435 | else { |
| 420 | srv_debug(0, xs_fmt("oauth revoke: invalid or unset arguments")); | 436 | srv_debug(1, xs_fmt("oauth revoke: invalid or unset arguments")); |
| 421 | status = 403; | 437 | status = 403; |
| 422 | } | 438 | } |
| 423 | } | 439 | } |
| 440 | if (strcmp(cmd, "/x-snac-get-token") == 0) { | ||
| 441 | const char *login = xs_dict_get(args, "login"); | ||
| 442 | const char *passwd = xs_dict_get(args, "passwd"); | ||
| 443 | |||
| 444 | const char *host = xs_dict_get(srv_config, "host"); | ||
| 445 | |||
| 446 | /* by default, generate another login form with an error */ | ||
| 447 | *body = xs_fmt(login_page, host, "LOGIN INCORRECT", host, "oauth/x-snac-get-token", | ||
| 448 | "", "", "", USER_AGENT); | ||
| 449 | *ctype = "text/html"; | ||
| 450 | status = 200; | ||
| 451 | |||
| 452 | if (login && passwd) { | ||
| 453 | snac user; | ||
| 454 | |||
| 455 | if (user_open(&user, login)) { | ||
| 456 | /* check the login + password */ | ||
| 457 | if (check_password(login, passwd, xs_dict_get(user.config, "passwd"))) { | ||
| 458 | /* success! create a new token */ | ||
| 459 | xs *tokid = random_str(); | ||
| 460 | |||
| 461 | srv_debug(1, xs_fmt("x-snac-new-token: " | ||
| 462 | "successful login for %s, new token %s", login, tokid)); | ||
| 463 | |||
| 464 | xs *token = xs_dict_new(); | ||
| 465 | token = xs_dict_append(token, "token", tokid); | ||
| 466 | token = xs_dict_append(token, "client_id", "snac-client"); | ||
| 467 | token = xs_dict_append(token, "client_secret", ""); | ||
| 468 | token = xs_dict_append(token, "uid", login); | ||
| 469 | token = xs_dict_append(token, "code", ""); | ||
| 470 | |||
| 471 | token_add(tokid, token); | ||
| 472 | |||
| 473 | *ctype = "text/plain"; | ||
| 474 | xs_free(*body); | ||
| 475 | *body = xs_dup(tokid); | ||
| 476 | } | ||
| 477 | |||
| 478 | user_free(&user); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | } | ||
| 424 | 482 | ||
| 425 | return status; | 483 | return status; |
| 426 | } | 484 | } |
| @@ -537,7 +595,6 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) | |||
| 537 | xs *f = xs_val_new(XSTYPE_FALSE); | 595 | xs *f = xs_val_new(XSTYPE_FALSE); |
| 538 | xs *t = xs_val_new(XSTYPE_TRUE); | 596 | xs *t = xs_val_new(XSTYPE_TRUE); |
| 539 | xs *n = xs_val_new(XSTYPE_NULL); | 597 | xs *n = xs_val_new(XSTYPE_NULL); |
| 540 | xs *el = xs_list_new(); | ||
| 541 | xs *idx = NULL; | 598 | xs *idx = NULL; |
| 542 | xs *ixc = NULL; | 599 | xs *ixc = NULL; |
| 543 | 600 | ||
| @@ -787,7 +844,7 @@ int process_auth_token(snac *snac, const xs_dict *req) | |||
| 787 | 844 | ||
| 788 | /* if there is an authorization field, try to validate it */ | 845 | /* if there is an authorization field, try to validate it */ |
| 789 | if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) { | 846 | if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) { |
| 790 | xs *tokid = xs_replace(v, "Bearer ", ""); | 847 | xs *tokid = xs_replace_n(v, "Bearer ", "", 1); |
| 791 | xs *token = token_get(tokid); | 848 | xs *token = token_get(tokid); |
| 792 | 849 | ||
| 793 | if (token != NULL) { | 850 | if (token != NULL) { |
| @@ -815,6 +872,8 @@ int process_auth_token(snac *snac, const xs_dict *req) | |||
| 815 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, | 872 | int mastoapi_get_handler(const xs_dict *req, const char *q_path, |
| 816 | char **body, int *b_size, char **ctype) | 873 | char **body, int *b_size, char **ctype) |
| 817 | { | 874 | { |
| 875 | (void)b_size; | ||
| 876 | |||
| 818 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) | 877 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) |
| 819 | return 0; | 878 | return 0; |
| 820 | 879 | ||
| @@ -826,7 +885,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 826 | 885 | ||
| 827 | int status = 404; | 886 | int status = 404; |
| 828 | xs_dict *args = xs_dict_get(req, "q_vars"); | 887 | xs_dict *args = xs_dict_get(req, "q_vars"); |
| 829 | xs *cmd = xs_replace(q_path, "/api", ""); | 888 | xs *cmd = xs_replace_n(q_path, "/api", "", 1); |
| 830 | 889 | ||
| 831 | snac snac1 = {0}; | 890 | snac snac1 = {0}; |
| 832 | int logged_in = process_auth_token(&snac1, req); | 891 | int logged_in = process_auth_token(&snac1, req); |
| @@ -1036,11 +1095,14 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1036 | } | 1095 | } |
| 1037 | else | 1096 | else |
| 1038 | if (strcmp(cmd, "/v1/timelines/public") == 0) { | 1097 | if (strcmp(cmd, "/v1/timelines/public") == 0) { |
| 1039 | /* the public timeline (public timelines for all users) */ | 1098 | /* the instance public timeline (public timelines for all users) */ |
| 1040 | 1099 | ||
| 1041 | /* this is an ugly kludge: first users in the list get all the fame */ | 1100 | /* NOTE: this api call needs no authorization; but, |
| 1101 | I need a logged-in user in mastoapi_status() for | ||
| 1102 | is_msg_public() and the liked/boosted flags, | ||
| 1103 | so it will silently fail for pure public access */ | ||
| 1042 | 1104 | ||
| 1043 | const char *limit_s = xs_dict_get(args, "limit"); | 1105 | const char *limit_s = xs_dict_get(args, "limit"); |
| 1044 | int limit = 0; | 1106 | int limit = 0; |
| 1045 | int cnt = 0; | 1107 | int cnt = 0; |
| 1046 | 1108 | ||
| @@ -1050,44 +1112,28 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1050 | if (limit == 0) | 1112 | if (limit == 0) |
| 1051 | limit = 20; | 1113 | limit = 20; |
| 1052 | 1114 | ||
| 1053 | xs *out = xs_list_new(); | 1115 | xs *timeline = timeline_instance_list(0, limit); |
| 1054 | xs *users = user_list(); | 1116 | xs *out = xs_list_new(); |
| 1055 | xs_list *p = users; | 1117 | xs_list *p = timeline; |
| 1056 | xs_str *uid; | 1118 | xs_str *md5; |
| 1057 | |||
| 1058 | while (xs_list_iter(&p, &uid) && cnt < limit) { | ||
| 1059 | snac user; | ||
| 1060 | |||
| 1061 | if (user_open(&user, uid)) { | ||
| 1062 | xs *timeline = timeline_simple_list(&user, "public", 0, 4); | ||
| 1063 | xs_list *p2 = timeline; | ||
| 1064 | xs_str *v; | ||
| 1065 | |||
| 1066 | while (xs_list_iter(&p2, &v) && cnt < limit) { | ||
| 1067 | xs *msg = NULL; | ||
| 1068 | 1119 | ||
| 1069 | /* get the entry */ | 1120 | while (logged_in && xs_list_iter(&p, &md5) && cnt < limit) { |
| 1070 | if (!valid_status(timeline_get_by_md5(&user, v, &msg))) | 1121 | xs *msg = NULL; |
| 1071 | continue; | ||
| 1072 | |||
| 1073 | /* discard non-Notes */ | ||
| 1074 | if (strcmp(xs_dict_get(msg, "type"), "Note") != 0) | ||
| 1075 | continue; | ||
| 1076 | 1122 | ||
| 1077 | /* discard entries not by this user */ | 1123 | /* get the entry */ |
| 1078 | if (!xs_startswith(xs_dict_get(msg, "id"), user.actor)) | 1124 | if (!valid_status(object_get_by_md5(md5, &msg))) |
| 1079 | continue; | 1125 | continue; |
| 1080 | 1126 | ||
| 1081 | /* convert the Note into a Mastodon status */ | 1127 | /* discard non-Notes */ |
| 1082 | xs *st = mastoapi_status(&user, msg); | 1128 | if (strcmp(xs_dict_get(msg, "type"), "Note") != 0) |
| 1129 | continue; | ||
| 1083 | 1130 | ||
| 1084 | if (st != NULL) { | 1131 | /* convert the Note into a Mastodon status */ |
| 1085 | out = xs_list_append(out, st); | 1132 | xs *st = mastoapi_status(&snac1, msg); |
| 1086 | cnt++; | ||
| 1087 | } | ||
| 1088 | } | ||
| 1089 | 1133 | ||
| 1090 | user_free(&user); | 1134 | if (st != NULL) { |
| 1135 | out = xs_list_append(out, st); | ||
| 1136 | cnt++; | ||
| 1091 | } | 1137 | } |
| 1092 | } | 1138 | } |
| 1093 | 1139 | ||
| @@ -1121,7 +1167,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1121 | xs *actor = NULL; | 1167 | xs *actor = NULL; |
| 1122 | xs *entry = NULL; | 1168 | xs *entry = NULL; |
| 1123 | 1169 | ||
| 1124 | if (!valid_status(object_get(xs_dict_get(noti, "actor"), &actor))) | 1170 | if (!valid_status(actor_get(&snac1, xs_dict_get(noti, "actor"), &actor))) |
| 1125 | continue; | 1171 | continue; |
| 1126 | 1172 | ||
| 1127 | if (objid != NULL && !valid_status(object_get(objid, &entry))) | 1173 | if (objid != NULL && !valid_status(object_get(objid, &entry))) |
| @@ -1287,25 +1333,6 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1287 | cfg = xs_dict_append(cfg, "statuses", d11); | 1333 | cfg = xs_dict_append(cfg, "statuses", d11); |
| 1288 | } | 1334 | } |
| 1289 | 1335 | ||
| 1290 | { | ||
| 1291 | xs *d11 = xs_dict_new(); | ||
| 1292 | xs *mt = xs_list_new(); | ||
| 1293 | |||
| 1294 | mt = xs_list_append(mt, "image/jpeg"); | ||
| 1295 | mt = xs_list_append(mt, "image/png"); | ||
| 1296 | mt = xs_list_append(mt, "image/gif"); | ||
| 1297 | |||
| 1298 | d11 = xs_dict_append(d11, "supported_mime_types", mt); | ||
| 1299 | |||
| 1300 | d11 = xs_dict_append(d11, "image_size_limit", z); | ||
| 1301 | d11 = xs_dict_append(d11, "image_matrix_limit", z); | ||
| 1302 | d11 = xs_dict_append(d11, "video_size_limit", z); | ||
| 1303 | d11 = xs_dict_append(d11, "video_matrix_limit", z); | ||
| 1304 | d11 = xs_dict_append(d11, "video_frame_rate_limit", z); | ||
| 1305 | |||
| 1306 | cfg = xs_dict_append(cfg, "media_attachments", d11); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | ins = xs_dict_append(ins, "configuration", cfg); | 1336 | ins = xs_dict_append(ins, "configuration", cfg); |
| 1310 | 1337 | ||
| 1311 | *body = xs_json_dumps_pp(ins, 4); | 1338 | *body = xs_json_dumps_pp(ins, 4); |
| @@ -1326,7 +1353,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, | |||
| 1326 | /* skip the 'fake' part of the id */ | 1353 | /* skip the 'fake' part of the id */ |
| 1327 | id = MID_TO_MD5(id); | 1354 | id = MID_TO_MD5(id); |
| 1328 | 1355 | ||
| 1329 | if (valid_status(timeline_get_by_md5(&snac1, id, &msg))) { | 1356 | if (valid_status(object_get_by_md5(id, &msg))) { |
| 1330 | if (op == NULL) { | 1357 | if (op == NULL) { |
| 1331 | if (!is_muted(&snac1, xs_dict_get(msg, "attributedTo"))) { | 1358 | if (!is_muted(&snac1, xs_dict_get(msg, "attributedTo"))) { |
| 1332 | /* return the status itself */ | 1359 | /* return the status itself */ |
| @@ -1487,6 +1514,9 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1487 | const char *payload, int p_size, | 1514 | const char *payload, int p_size, |
| 1488 | char **body, int *b_size, char **ctype) | 1515 | char **body, int *b_size, char **ctype) |
| 1489 | { | 1516 | { |
| 1517 | (void)p_size; | ||
| 1518 | (void)b_size; | ||
| 1519 | |||
| 1490 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) | 1520 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) |
| 1491 | return 0; | 1521 | return 0; |
| 1492 | 1522 | ||
| @@ -1513,7 +1543,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1513 | printf("%s\n", j); | 1543 | printf("%s\n", j); |
| 1514 | }*/ | 1544 | }*/ |
| 1515 | 1545 | ||
| 1516 | xs *cmd = xs_replace(q_path, "/api", ""); | 1546 | xs *cmd = xs_replace_n(q_path, "/api", "", 1); |
| 1517 | 1547 | ||
| 1518 | snac snac = {0}; | 1548 | snac snac = {0}; |
| 1519 | int logged_in = process_auth_token(&snac, req); | 1549 | int logged_in = process_auth_token(&snac, req); |
| @@ -1562,7 +1592,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1562 | 1592 | ||
| 1563 | app_add(cid, app); | 1593 | app_add(cid, app); |
| 1564 | 1594 | ||
| 1565 | srv_debug(0, xs_fmt("mastoapi apps: new app %s", cid)); | 1595 | srv_debug(1, xs_fmt("mastoapi apps: new app %s", cid)); |
| 1566 | } | 1596 | } |
| 1567 | } | 1597 | } |
| 1568 | else | 1598 | else |
| @@ -1582,6 +1612,9 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1582 | if (xs_is_null(media_ids)) | 1612 | if (xs_is_null(media_ids)) |
| 1583 | media_ids = xs_dict_get(args, "media_ids[]"); | 1613 | media_ids = xs_dict_get(args, "media_ids[]"); |
| 1584 | 1614 | ||
| 1615 | if (xs_is_null(visibility)) | ||
| 1616 | visibility = "public"; | ||
| 1617 | |||
| 1585 | xs *attach_list = xs_list_new(); | 1618 | xs *attach_list = xs_list_new(); |
| 1586 | xs *irt = NULL; | 1619 | xs *irt = NULL; |
| 1587 | 1620 | ||
| @@ -1683,7 +1716,11 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1683 | } | 1716 | } |
| 1684 | else | 1717 | else |
| 1685 | if (strcmp(op, "unfavourite") == 0) { | 1718 | if (strcmp(op, "unfavourite") == 0) { |
| 1686 | /* snac does not support Undo+Like */ | 1719 | /* partial support: as the original Like message |
| 1720 | is not stored anywhere here, it's not possible | ||
| 1721 | to send an Undo + Like; the only thing done here | ||
| 1722 | is to delete the actor from the list of likes */ | ||
| 1723 | object_unadmire(id, snac.actor, 1); | ||
| 1687 | } | 1724 | } |
| 1688 | else | 1725 | else |
| 1689 | if (strcmp(op, "reblog") == 0) { | 1726 | if (strcmp(op, "reblog") == 0) { |
| @@ -1698,7 +1735,8 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, | |||
| 1698 | } | 1735 | } |
| 1699 | else | 1736 | else |
| 1700 | if (strcmp(op, "unreblog") == 0) { | 1737 | if (strcmp(op, "unreblog") == 0) { |
| 1701 | /* snac does not support Undo+Announce */ | 1738 | /* partial support: see comment in 'unfavourite' */ |
| 1739 | object_unadmire(id, snac.actor, 0); | ||
| 1702 | } | 1740 | } |
| 1703 | else | 1741 | else |
| 1704 | if (strcmp(op, "bookmark") == 0) { | 1742 | if (strcmp(op, "bookmark") == 0) { |
| @@ -1903,6 +1941,9 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path, | |||
| 1903 | const char *payload, int p_size, | 1941 | const char *payload, int p_size, |
| 1904 | char **body, int *b_size, char **ctype) | 1942 | char **body, int *b_size, char **ctype) |
| 1905 | { | 1943 | { |
| 1944 | (void)p_size; | ||
| 1945 | (void)b_size; | ||
| 1946 | |||
| 1906 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) | 1947 | if (!xs_startswith(q_path, "/api/v1/") && !xs_startswith(q_path, "/api/v2/")) |
| 1907 | return 0; | 1948 | return 0; |
| 1908 | 1949 | ||
| @@ -1924,7 +1965,7 @@ int mastoapi_put_handler(const xs_dict *req, const char *q_path, | |||
| 1924 | if (args == NULL) | 1965 | if (args == NULL) |
| 1925 | return 400; | 1966 | return 400; |
| 1926 | 1967 | ||
| 1927 | xs *cmd = xs_replace(q_path, "/api", ""); | 1968 | xs *cmd = xs_replace_n(q_path, "/api", "", 1); |
| 1928 | 1969 | ||
| 1929 | snac snac = {0}; | 1970 | snac snac = {0}; |
| 1930 | int logged_in = process_auth_token(&snac, req); | 1971 | int logged_in = process_auth_token(&snac, req); |