From 545d4085124e9131f03abb9f8a86b72de672ad39 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Fri, 21 Feb 2025 16:51:22 -0500 Subject: [PATCH] Everywhere: Make session->path(), session->path_count() callable --- Slon/Api/V1/Accounts.HC | 54 +++++++++++++------------------------ Slon/Api/V1/Statuses.HC | 10 ++----- Slon/Api/V1/Timelines.HC | 38 +++++++++----------------- Slon/Http/Server.HC | 36 ++++++++++++++++++++++--- Slon/Modules/ActivityPub.HC | 21 ++++----------- Slon/Modules/Http.HC | 28 +++++++++++++++++-- 6 files changed, 97 insertions(+), 90 deletions(-) diff --git a/Slon/Api/V1/Accounts.HC b/Slon/Api/V1/Accounts.HC index 4978d60..2849a43 100644 --- a/Slon/Api/V1/Accounts.HC +++ b/Slon/Api/V1/Accounts.HC @@ -104,26 +104,22 @@ U0 @slon_api_v1_accounts_post(SlonHttpSession* session) I64 i; - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - if (2 == 3) { // placeholder for other methods } else { // Work with account :id - U8* some_account_id = path_segments[3]; + U8* some_account_id = session->path(3); JsonObject* acct = @slon_api_account_by_id(some_account_id); if (!acct) { session->status(404); - goto slon_api_v1_accounts_post_return; + return; } - if (path_segments_count > 5) { - U8* method = path_segments[4]; + if (session->path_count() > 5) { + U8* method = session->path(4); if (!StrICmp("follow", method)) { if (!acct->@("remote_actor")) { session->status(404); - goto slon_api_v1_accounts_post_return; + return; } // add to my following if (!db->o("following")->a(my_acct->@("username"))) { @@ -158,15 +154,13 @@ U0 @slon_api_v1_accounts_post(SlonHttpSession* session) relationship->set("domain_blocking", FALSE, JSON_BOOLEAN); relationship->set("endorsed", FALSE, JSON_BOOLEAN); session->send(relationship); - goto slon_api_v1_accounts_post_return; + return; } session->status(404); } else { session->status(404); } } -slon_api_v1_accounts_post_return: - @slon_free(session, path); } U0 @slon_api_v1_accounts_get(SlonHttpSession* session) @@ -176,12 +170,8 @@ U0 @slon_api_v1_accounts_get(SlonHttpSession* session) I64 i; - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - JsonObject* acct = NULL; - if (!StrICmp("relationships", path_segments[3])) { + if (!StrICmp("relationships", session->path(3))) { if (@slon_api_authorized(session)) { // FIXME: handle array of id[]= @@ -231,11 +221,11 @@ U0 @slon_api_v1_accounts_get(SlonHttpSession* session) session->send(relationships); Json.Delete(relationships); - goto slon_api_v1_accounts_get_return; + return; } else { session->status(401); } - } else if (!StrICmp("verify_credentials", path_segments[3])) { + } else if (!StrICmp("verify_credentials", session->path(3))) { if (@slon_api_authorized(session)) { SLON_AUTH_ACCOUNT_ID acct = @slon_api_account_by_id(account_id); @@ -249,18 +239,18 @@ U0 @slon_api_v1_accounts_get(SlonHttpSession* session) } } else { // Work with account :id - U8* some_account_id = path_segments[3]; + U8* some_account_id = session->path(3); acct = @slon_api_account_by_id(some_account_id); if (!acct) { session->status(404); - goto slon_api_v1_accounts_get_return; + return; } - if (path_segments_count > 5) { - U8* method = path_segments[4]; + if (session->path_count() > 5) { + U8* method = session->path(4); if (!StrICmp("following", method)) { // FIXME: Implement this session->send(SLON_EMPTY_JSON_ARRAY); - goto slon_api_v1_accounts_get_return; + return; } if (!StrICmp("statuses", method)) { // Return the Account's Statuses @@ -332,7 +322,7 @@ U0 @slon_api_v1_accounts_get(SlonHttpSession* session) session->send(statuses); Json.Delete(statuses); - goto slon_api_v1_accounts_get_return; + return; } session->status(404); } else { @@ -343,8 +333,6 @@ U0 @slon_api_v1_accounts_get(SlonHttpSession* session) Json.Delete(profile_object); } } -slon_api_v1_accounts_get_return: - @slon_free(session, path); } Bool @slon_api_v1_accounts_key_is_boolean(U8* name) @@ -356,26 +344,22 @@ U0 @slon_api_v1_accounts_patch(SlonHttpSession* session) { SLON_SCRATCH_BUFFER_AND_REQUEST_JSON - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - JsonObject* acct = NULL; - if (!StrICmp("update_credentials", path_segments[3])) { + if (!StrICmp("update_credentials", session->path(3))) { if (@slon_api_authorized(session)) { SLON_AUTH_ACCOUNT_ID if (!request_json || !request_json->keys) { session->status(400); - goto slon_api_v1_accounts_patch_return; + return; } // FIXME: Support avatars/banners acct = @slon_api_account_by_id(account_id); if (!acct) { session->status(404); - goto slon_api_v1_accounts_patch_return; + return; } JsonObject* source = acct->@("source"); @@ -494,6 +478,4 @@ U0 @slon_api_v1_accounts_patch(SlonHttpSession* session) } else { session->status(404); } -slon_api_v1_accounts_patch_return: - @slon_free(session, path); } diff --git a/Slon/Api/V1/Statuses.HC b/Slon/Api/V1/Statuses.HC index 0e51192..a1ae529 100644 --- a/Slon/Api/V1/Statuses.HC +++ b/Slon/Api/V1/Statuses.HC @@ -12,15 +12,11 @@ U0 @slon_api_v1_statuses_delete(SlonHttpSession* session) return; } - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - - if (path_segments_count < 4) { + if (session->path_count() < 4) { goto slon_api_v1_statuses_delete_return; } - U8* id = path_segments[3]; + U8* id = session->path(3); JsonObject* status; JsonObject* fedi_status; @@ -41,8 +37,6 @@ U0 @slon_api_v1_statuses_delete(SlonHttpSession* session) } slon_api_v1_statuses_delete_return: - Free(path_segments); - @slon_free(session, path); session->send(SLON_EMPTY_JSON_OBJECT); } else { session->status(401); diff --git a/Slon/Api/V1/Timelines.HC b/Slon/Api/V1/Timelines.HC index 0d76555..95ec959 100644 --- a/Slon/Api/V1/Timelines.HC +++ b/Slon/Api/V1/Timelines.HC @@ -84,50 +84,38 @@ U0 @slon_api_v1_timelines_get(SlonHttpSession* session) if (@slon_api_authorized(session)) { SLON_AUTH_ACCOUNT_ID - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - - if (path_segments_count < 4) { - goto slon_api_v1_timelines_get_return; + if (session->path_count() < 4) { + return; } - - if (!StrICmp("public", path_segments[3])) { + U8* timeline = session->path(3); + if (!StrICmp("public", timeline)) { // FIXME: Implement this session->send(SLON_EMPTY_JSON_ARRAY); - goto slon_api_v1_timelines_get_return; + return; } - - if (!StrICmp("tag", path_segments[3])) { + if (!StrICmp("tag", timeline)) { // FIXME: Implement this session->send(SLON_EMPTY_JSON_ARRAY); - goto slon_api_v1_timelines_get_return; + return; } - - if (!StrICmp("home", path_segments[3])) { + if (!StrICmp("home", timeline)) { // FIXME: Implement this @slon_api_v1_timelines_home(session, account_id); - goto slon_api_v1_timelines_get_return; + return; } - - if (!StrICmp("link", path_segments[3])) { + if (!StrICmp("link", timeline)) { // FIXME: Implement this session->send(SLON_EMPTY_JSON_ARRAY); - goto slon_api_v1_timelines_get_return; + return; } - - if (!StrICmp("list", path_segments[3])) { + if (!StrICmp("list", timeline)) { // FIXME: Implement this session->send(SLON_EMPTY_JSON_ARRAY); - goto slon_api_v1_timelines_get_return; + return; } - session->status(404); } else { session->status(401); return; } -slon_api_v1_timelines_get_return: - Free(path_segments); - @slon_free(session, path); } diff --git a/Slon/Http/Server.HC b/Slon/Http/Server.HC index 56739fa..a36ab85 100644 --- a/Slon/Http/Server.HC +++ b/Slon/Http/Server.HC @@ -32,6 +32,10 @@ U0 @slon_http_free_request(SlonHttpSession* session, SlonHttpRequest* request) @slon_free(session, session->request->raw_path); if (request->path) @slon_free(session, session->request->path); + if (request->path_segments_src) { + @slon_free(session, session->request->path_segments_src); + Free(session->request->path_segments); + } @slon_free(session, request); } } @@ -47,6 +51,8 @@ U0 @slon_http_free_session(SlonHttpSession* session) Free(session->header); Free(session->status); Free(session->send); + Free(session->path_count); + Free(session->path); Free(session); if (bytes_used) { AdamLog("*** Session leaked %d bytes of memory ***\n", bytes_used); @@ -138,6 +144,28 @@ SlonHttpSession* @slon_http_init_session(TcpSocket* s) a += 0x1b; @patch_call_rel32(a, &@slon_http_request_verb); + // Create a copy of function and patch path + code_size = MSize(&@slon_session_path_wrapper_function); + session->path = CAlloc(code_size, adam_task->code_heap); + MemCpy(session->path, &@slon_session_path_wrapper_function, code_size); + + a = session->path; + a += 0x10; + MemSetI64(a, session, 1); + + a = session->path; + a += 0x1a; + @patch_call_rel32(a, &@slon_http_request_path); + + // Create a copy of function and patch path_count + code_size = MSize(&@slon_session_path_count_wrapper_function); + session->path_count = CAlloc(code_size, adam_task->code_heap); + MemCpy(session->path_count, &@slon_session_path_count_wrapper_function, code_size); + + a = session->path_count; + a += 0x0b; + MemSetI64(a, session, 1); + return session; } @@ -241,11 +269,13 @@ slon_http_parse_request_headers: session->request->verb = @slon_strnew(session, request_first_line_segments[0]); session->request->raw_path = @slon_strnew(session, request_first_line_segments[1]); + session->request->path = @slon_strnew(session, session->request->raw_path); if (StrFind("?", session->request->raw_path)) { - session->request->path = @slon_strnew(session, session->request->raw_path); *(StrFind("?", session->request->path)) = NULL; - } else { - session->request->path = @slon_strnew(session, session->request->raw_path); + } + if (StrFind("/", session->request->path)) { + session->request->path_segments_src = @slon_strnew(session, session->request->path); + session->request->path_segments = String.Split(session->request->path_segments_src, '/', &session->request->path_segments_count); } U8* key; diff --git a/Slon/Modules/ActivityPub.HC b/Slon/Modules/ActivityPub.HC index bc9b0b6..e1e7081 100644 --- a/Slon/Modules/ActivityPub.HC +++ b/Slon/Modules/ActivityPub.HC @@ -250,11 +250,8 @@ Bool @slon_activitypub_http_signature_is_valid(SlonHttpSession* session) U0 @slon_activitypub_users_get(SlonHttpSession* session) { - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - if (path_segments_count == 3) { - JsonObject* actor = db->o("actors")->@(path_segments[1]); + if (session->path_count() == 3) { + JsonObject* actor = db->o("actors")->@(session->path(1)); if (actor) { @slon_http_send_ap_json(session, actor); } else { @@ -263,8 +260,6 @@ U0 @slon_activitypub_users_get(SlonHttpSession* session) } else { session->status(400); } -slon_activitypub_users_get_return: - @slon_free(session, path); } U0 @slon_activitypub_async_accept_request(JsonObject* o) @@ -958,23 +953,19 @@ U0 @slon_activitypub_users_post(SlonHttpSession* session) SLON_SCRATCH_BUFFER_AND_REQUEST_JSON no_warn scratch_buffer; - U8* path = @slon_strnew(session, @slon_http_request_path(session)); - I64 path_segments_count = 0; - U8** path_segments = String.Split(path, '/', &path_segments_count); - - if (path_segments_count < 3) { + if (session->path_count() < 3) { session->status(400); goto slon_activitypub_users_post_return; } - U8* user = path_segments[1]; + U8* user = session->path(1); JsonObject* actor = db->o("actors")->@(user); if (!actor) { session->status(404); goto slon_activitypub_users_post_return; } - U8* method = path_segments[2]; + U8* method = session->path(2); if (!StrICmp("inbox", method)) { if (!request_json) { session->status(400); @@ -1002,6 +993,4 @@ slon_activitypub_users_post_return: if (session->actor_for_key_id) { @slon_free(session, session->actor_for_key_id); } - Free(path_segments); - @slon_free(session, path); } diff --git a/Slon/Modules/Http.HC b/Slon/Modules/Http.HC index 33d41f6..74ca805 100644 --- a/Slon/Modules/Http.HC +++ b/Slon/Modules/Http.HC @@ -45,6 +45,9 @@ class SlonHttpRequest { U8* verb; U8* raw_path; U8* path; + I64 path_segments_count; + U8* path_segments_src; + U8** path_segments; Bool headers_have_been_parsed; }; @@ -66,6 +69,8 @@ class SlonHttpSession { U8* (*header)(U8* key, U8* value = NULL); U0 (*send)(U64 payload, I64 size = NULL); + U8* (*path)(I64 segment = NULL); + I64 (*path_count)(); I64 (*status)(I64 code = NULL); I64 (*verb)(Bool return_str = FALSE); }; @@ -228,9 +233,16 @@ U0 @slon_http_send_json_file(SlonHttpSession* session, U8* path, U8* content_typ @slon_http_send_file(session, path); } -U8* @slon_http_request_path(SlonHttpSession* session) +U8* @slon_http_request_path(SlonHttpSession* session, I64 segment = NULL) { - return session->request->path; + if (segment) { + if (!session->request->path_segments_count || segment >= session->request->path_segments_count) { + return NULL; + } + return session->request->path_segments[segment]; + } else { + return session->request->path; + } } I64 @slon_http_request_verb(SlonHttpSession* session, Bool return_str = FALSE) @@ -321,3 +333,15 @@ I64 @slon_session_verb_wrapper_function(Bool return_str = FALSE) SlonHttpSession* session = SLON_WRAPPER_MAGIC_NUMBER; return @slon_http_request_verb(session, return_str); } + +U8* @slon_session_path_wrapper_function(I64 segment = NULL) +{ + SlonHttpSession* session = SLON_WRAPPER_MAGIC_NUMBER; + return @slon_http_request_path(session, segment); +} + +I64 @slon_session_path_count_wrapper_function() +{ + SlonHttpSession* session = SLON_WRAPPER_MAGIC_NUMBER; + return session->request->path_segments_count; +}