diff --git a/libtransmission/rpc-server.cc b/libtransmission/rpc-server.cc index f74b3b2ee..3d776bb7e 100644 --- a/libtransmission/rpc-server.cc +++ b/libtransmission/rpc-server.cc @@ -169,7 +169,7 @@ static evbuffer* make_response(struct evhttp_request* req, tr_rpc_server* server char const* key = "Accept-Encoding"; char const* encoding = evhttp_find_header(req->input_headers, key); - bool const do_compress = encoding != nullptr && strstr(encoding, "gzip") != nullptr; + bool const do_compress = encoding != nullptr && tr_strvContains(encoding, "gzip"sv); if (!do_compress) { @@ -257,24 +257,31 @@ static void handle_web_client(struct evhttp_request* req, tr_rpc_server* server) } else { - // TODO: string_view - char* const subpath = tr_strdup(req->uri + std::size(server->url()) + 4); - if (char* pch = strchr(subpath, '?'); pch != nullptr) + // convert `req->uri` (ex: "/transmission/web/images/favicon.png") + // into a filesystem path (ex: "/usr/share/transmission/web/images/favicon.png") + + // remove the "/transmission/web/" prefix + static auto constexpr Web = "web/"sv; + auto subpath = std::string_view{ req->uri }.substr(std::size(server->url()) + std::size(Web)); + + // remove any trailing query / fragment + subpath = subpath.substr(0, subpath.find_first_of("?#"sv)); + + // if the query is empty, use the default + static auto constexpr DefaultPage = "index.html"sv; + if (std::empty(subpath)) { - *pch = '\0'; + subpath = DefaultPage; } - if (strstr(subpath, "..") != nullptr) + if (tr_strvContains(subpath, ".."sv)) { send_simple_response(req, HTTP_NOTFOUND, "

Tsk, tsk.

"); } else { - auto const filename = tr_pathbuf{ server->web_client_dir_, '/', tr_str_is_empty(subpath) ? "index.html" : subpath }; - serve_file(req, server, filename.sv()); + serve_file(req, server, tr_pathbuf{ server->web_client_dir_, '/', subpath }); } - - tr_free(subpath); } } @@ -293,7 +300,7 @@ static void rpc_response_func(tr_session* /*session*/, tr_variant* content, void evhttp_send_reply(data->req, HTTP_OK, "OK", response); evbuffer_free(response); - tr_free(data); + delete data; } static void handle_rpc_from_json(struct evhttp_request* req, tr_rpc_server* server, std::string_view json) @@ -301,11 +308,11 @@ static void handle_rpc_from_json(struct evhttp_request* req, tr_rpc_server* serv auto top = tr_variant{}; auto const have_content = tr_variantFromBuf(&top, TR_VARIANT_PARSE_JSON | TR_VARIANT_PARSE_INPLACE, json); - auto* const data = tr_new0(struct rpc_response_data, 1); - data->req = req; - data->server = server; - - tr_rpc_request_exec_json(server->session, have_content ? &top : nullptr, rpc_response_func, data); + tr_rpc_request_exec_json( + server->session, + have_content ? &top : nullptr, + rpc_response_func, + new rpc_response_data{ req, server }); if (have_content) { @@ -323,20 +330,6 @@ static void handle_rpc(struct evhttp_request* req, tr_rpc_server* server) return; } - if (req->type == EVHTTP_REQ_GET) - { - char const* q = strchr(req->uri, '?'); - - if (q != nullptr) - { - auto* const data = tr_new0(struct rpc_response_data, 1); - data->req = req; - data->server = server; - tr_rpc_request_exec_uri(server->session, q + 1, rpc_response_func, data); - return; - } - } - send_simple_response(req, 405, nullptr); } diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index bde09ddab..43a4fb77e 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -2605,29 +2605,3 @@ void tr_rpc_parse_list_str(tr_variant* setme, std::string_view str) } } } - -void tr_rpc_request_exec_uri( - tr_session* session, - std::string_view request_uri, - tr_rpc_response_func callback, - void* callback_user_data) -{ - auto top = tr_variant{}; - tr_variantInitDict(&top, 3); - tr_variant* const args = tr_variantDictAddDict(&top, TR_KEY_arguments, 0); - - if (auto const parsed = tr_urlParse(request_uri); parsed) - { - for (auto const& [key, val] : tr_url_query_view(parsed->query)) - { - auto is_arg = key != "method"sv && key != "tag"sv; - auto* const parent = is_arg ? args : ⊤ - tr_rpc_parse_list_str(tr_variantDictAdd(parent, tr_quark_new(key)), val); - } - } - - tr_rpc_request_exec_json(session, &top, callback, callback_user_data); - - // cleanup - tr_variantFree(&top); -} diff --git a/libtransmission/rpcimpl.h b/libtransmission/rpcimpl.h index 0cd271da1..eefb79950 100644 --- a/libtransmission/rpcimpl.h +++ b/libtransmission/rpcimpl.h @@ -24,11 +24,4 @@ void tr_rpc_request_exec_json( tr_rpc_response_func callback, void* callback_user_data); -/* see the RPC spec's "Request URI Notation" section */ -void tr_rpc_request_exec_uri( - tr_session* session, - std::string_view request_uri, - tr_rpc_response_func callback, - void* callback_user_data); - void tr_rpc_parse_list_str(tr_variant* setme, std::string_view str);