diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp index c3a619af44..7440c781ef 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -233,14 +233,14 @@ WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr plain_text_encode(Vector const& pairs) } // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mutate-action -ErrorOr HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector entry_list, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) +ErrorOr HTMLFormElement::mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling) { // 1. Let pairs be the result of converting to a list of name-value pairs with entry list. auto pairs = TRY(convert_to_list_of_name_value_pairs(entry_list)); // 2. Let query be the result of running the application/x-www-form-urlencoded serializer with pairs and encoding. - // FIXME: Pass in encoding. - auto query = TRY(url_encode(pairs, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)); + auto query = TRY(url_encode(pairs, encoding)); // 3. Set parsed action's query component to query. parsed_action.set_query(query.to_deprecated_string()); @@ -642,8 +641,7 @@ ErrorOr HTMLFormElement::submit_as_entity_body(AK::URL parsed_action, Vect auto pairs = TRY(convert_to_list_of_name_value_pairs(entry_list)); // 2. Let body be the result of running the application/x-www-form-urlencoded serializer with pairs and encoding. - // FIXME: Pass in encoding. - body = TRY(ByteBuffer::copy(TRY(url_encode(pairs, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)).bytes())); + body = TRY(ByteBuffer::copy(TRY(url_encode(pairs, encoding)).bytes())); // 3. Set body to the result of encoding body. // NOTE: `encoding` refers to `UTF-8 encode`, which body already is encoded as because it uses AK::String. @@ -713,8 +711,7 @@ ErrorOr HTMLFormElement::mail_with_headers(AK::URL parsed_action, Vector HTMLFormElement::mail_as_body(AK::URL parsed_action, Vector Otherwise // Let body be the result of running the application/x-www-form-urlencoded serializer with pairs and encoding. - // FIXME: Pass in encoding. - body = TRY(url_encode(pairs, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)); + body = TRY(url_encode(pairs, encoding)); break; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h index 9ac43a4608..86e75ef00f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h @@ -96,7 +96,7 @@ private: ErrorOr pick_an_encoding() const; - ErrorOr mutate_action_url(AK::URL parsed_action, Vector entry_list, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); + ErrorOr mutate_action_url(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); ErrorOr submit_as_entity_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); void get_action_url(AK::URL parsed_action, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); ErrorOr mail_with_headers(AK::URL parsed_action, Vector entry_list, String encoding, JS::NonnullGCPtr target_navigable, HistoryHandlingBehavior history_handling); diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp index 851d6863ce..3b80540dc0 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.cpp @@ -1,12 +1,15 @@ /* * Copyright (c) 2021, Idan Horowitz + * Copyright (c) 2023, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include #include +#include #include #include #include @@ -36,17 +39,40 @@ void URLSearchParams::visit_edges(Cell::Visitor& visitor) visitor.visit(m_url); } -ErrorOr url_encode(Vector const& pairs, AK::URL::PercentEncodeSet percent_encode_set) +// https://url.spec.whatwg.org/#concept-urlencoded-serializer +// The application/x-www-form-urlencoded serializer takes a list of name-value tuples tuples, with an optional encoding encoding (default UTF-8), and then runs these steps. They return an ASCII string. +ErrorOr url_encode(Vector const& tuples, StringView encoding) { - StringBuilder builder; - for (size_t i = 0; i < pairs.size(); ++i) { - TRY(builder.try_append(AK::URL::percent_encode(pairs[i].name, percent_encode_set, AK::URL::SpaceAsPlus::Yes))); - TRY(builder.try_append('=')); - TRY(builder.try_append(AK::URL::percent_encode(pairs[i].value, percent_encode_set, AK::URL::SpaceAsPlus::Yes))); - if (i != pairs.size() - 1) - TRY(builder.try_append('&')); + // 1. Set encoding to the result of getting an output encoding from encoding. + encoding = TextCodec::get_output_encoding(encoding); + + // 2. Let output be the empty string. + StringBuilder output; + + // 3. For each tuple of tuples: + for (auto const& tuple : tuples) { + // 1. Assert: tuple’s name and tuple’s value are scalar value strings. + + // 2. Let name be the result of running percent-encode after encoding with encoding, tuple’s name, the application/x-www-form-urlencoded percent-encode set, and true. + // FIXME: URLParser does not currently implement encoding. + auto name = AK::URLParser::percent_encode_after_encoding(tuple.name, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded, true); + + // 3. Let value be the result of running percent-encode after encoding with encoding, tuple’s value, the application/x-www-form-urlencoded percent-encode set, and true. + // FIXME: URLParser does not currently implement encoding. + auto value = AK::URLParser::percent_encode_after_encoding(tuple.value, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded, true); + + // 4. If output is not the empty string, then append U+0026 (&) to output. + if (!output.is_empty()) + TRY(output.try_append('&')); + + // 5. Append name, followed by U+003D (=), followed by value, to output. + TRY(output.try_append(name)); + TRY(output.try_append('=')); + TRY(output.try_append(value)); } - return builder.to_string(); + + // 4. Return output. + return output.to_string(); } // https://url.spec.whatwg.org/#concept-urlencoded-parser @@ -292,7 +318,7 @@ WebIDL::ExceptionOr URLSearchParams::to_string() const auto& vm = realm().vm(); // return the serialization of this’s list. - return TRY_OR_THROW_OOM(vm, url_encode(m_list, AK::URL::PercentEncodeSet::ApplicationXWWWFormUrlencoded)); + return TRY_OR_THROW_OOM(vm, url_encode(m_list)); } JS::ThrowCompletionOr URLSearchParams::for_each(ForEachCallback callback) diff --git a/Userland/Libraries/LibWeb/URL/URLSearchParams.h b/Userland/Libraries/LibWeb/URL/URLSearchParams.h index 5d0d45c402..f251cd7472 100644 --- a/Userland/Libraries/LibWeb/URL/URLSearchParams.h +++ b/Userland/Libraries/LibWeb/URL/URLSearchParams.h @@ -16,7 +16,7 @@ struct QueryParam { String name; String value; }; -ErrorOr url_encode(Vector const&, AK::URL::PercentEncodeSet); +ErrorOr url_encode(Vector const&, StringView encoding = "UTF-8"sv); ErrorOr> url_decode(StringView); class URLSearchParams : public Bindings::PlatformObject {