diff --git a/Tests/LibURL/TestURL.cpp b/Tests/LibURL/TestURL.cpp index 7548aa8ff3..72d9e1a99c 100644 --- a/Tests/LibURL/TestURL.cpp +++ b/Tests/LibURL/TestURL.cpp @@ -456,8 +456,8 @@ TEST_CASE(username_and_password) URL::URL url(url_with_username_and_password); EXPECT(url.is_valid()); EXPECT_EQ(MUST(url.serialized_host()), "test.com"sv); - EXPECT_EQ(MUST(url.username()), "username"sv); - EXPECT_EQ(MUST(url.password()), "password"sv); + EXPECT_EQ(url.username(), "username"sv); + EXPECT_EQ(url.password(), "password"sv); } { @@ -465,8 +465,10 @@ TEST_CASE(username_and_password) URL::URL url(url_with_percent_encoded_credentials); EXPECT(url.is_valid()); EXPECT_EQ(MUST(url.serialized_host()), "test.com"sv); - EXPECT_EQ(MUST(url.username()), "username!$%"sv); - EXPECT_EQ(MUST(url.password()), "password!$%"sv); + EXPECT_EQ(url.username(), "username%21%24%25"); + EXPECT_EQ(url.password(), "password%21%24%25"); + EXPECT_EQ(URL::percent_decode(url.username()), "username!$%"sv); + EXPECT_EQ(URL::percent_decode(url.password()), "password!$%"sv); } { @@ -475,8 +477,8 @@ TEST_CASE(username_and_password) URL::URL url(url_with_long_username); EXPECT(url.is_valid()); EXPECT_EQ(MUST(url.serialized_host()), "test.com"sv); - EXPECT_EQ(MUST(url.username()), username); - EXPECT(MUST(url.password()).is_empty()); + EXPECT_EQ(url.username(), username); + EXPECT(url.password().is_empty()); } { @@ -485,8 +487,8 @@ TEST_CASE(username_and_password) URL::URL url(url_with_long_password); EXPECT(url.is_valid()); EXPECT_EQ(MUST(url.serialized_host()), "test.com"sv); - EXPECT(MUST(url.username()).is_empty()); - EXPECT_EQ(MUST(url.password()), password); + EXPECT(url.username().is_empty()); + EXPECT_EQ(url.password(), password); } } diff --git a/Tests/LibWeb/Text/expected/HTML/link-element-username-password-percent-encoded.txt b/Tests/LibWeb/Text/expected/HTML/link-element-username-password-percent-encoded.txt new file mode 100644 index 0000000000..a427f8e6ef --- /dev/null +++ b/Tests/LibWeb/Text/expected/HTML/link-element-username-password-percent-encoded.txt @@ -0,0 +1,2 @@ + user%20name +pa%40ss%3Aword diff --git a/Tests/LibWeb/Text/expected/URL/url.txt b/Tests/LibWeb/Text/expected/URL/url.txt index f5744299e8..391aa406b5 100644 --- a/Tests/LibWeb/Text/expected/URL/url.txt +++ b/Tests/LibWeb/Text/expected/URL/url.txt @@ -88,6 +88,16 @@ port => '' pathname => '/p' search => '' hash => '' +new URL('http://user%20name:pa%40ss%3Aword@www.ladybird.org', undefined) +protocol => 'http:' +username => 'user%20name' +password => 'pa%40ss%3Aword' +host => 'www.ladybird.org' +hostname => 'www.ladybird.org' +port => '' +pathname => '/' +search => '' +hash => '' ========================================= URL.parse('ftp://serenityos.org:21', undefined) protocol => 'ftp:' @@ -179,3 +189,13 @@ port => '' pathname => '/p' search => '' hash => '' +URL.parse('http://user%20name:pa%40ss%3Aword@www.ladybird.org', undefined) +protocol => 'http:' +username => 'user%20name' +password => 'pa%40ss%3Aword' +host => 'www.ladybird.org' +hostname => 'www.ladybird.org' +port => '' +pathname => '/' +search => '' +hash => '' diff --git a/Tests/LibWeb/Text/input/HTML/link-element-username-password-percent-encoded.html b/Tests/LibWeb/Text/input/HTML/link-element-username-password-percent-encoded.html new file mode 100644 index 0000000000..cc726c853d --- /dev/null +++ b/Tests/LibWeb/Text/input/HTML/link-element-username-password-percent-encoded.html @@ -0,0 +1,9 @@ + + + diff --git a/Tests/LibWeb/Text/input/URL/url.html b/Tests/LibWeb/Text/input/URL/url.html index 1ec4e8970e..dbb6392941 100644 --- a/Tests/LibWeb/Text/input/URL/url.html +++ b/Tests/LibWeb/Text/input/URL/url.html @@ -23,6 +23,7 @@ { input: '/hello', base: 'file://friends/' }, { input: '//d:/..', base: 'file:///C:/a/b' }, { input: 'file://a%C2%ADb/p' }, + { input: 'http://user%20name:pa%40ss%3Aword@www.ladybird.org' }, ]; for (url of urls) { diff --git a/Userland/Libraries/LibHTTP/HttpRequest.cpp b/Userland/Libraries/LibHTTP/HttpRequest.cpp index 6d08b7f292..51e86f1e5c 100644 --- a/Userland/Libraries/LibHTTP/HttpRequest.cpp +++ b/Userland/Libraries/LibHTTP/HttpRequest.cpp @@ -271,12 +271,12 @@ Optional
HttpRequest::get_http_basic_authentication_header(URL::URL cons if (!url.includes_credentials()) return {}; StringBuilder builder; - builder.append(url.username().release_value_but_fixme_should_propagate_errors()); + builder.append(URL::percent_decode(url.username())); builder.append(':'); - builder.append(url.password().release_value_but_fixme_should_propagate_errors()); + builder.append(URL::percent_decode(url.password())); // FIXME: change to TRY() and make method fallible - auto token = MUST(encode_base64(MUST(builder.to_string()).bytes())); + auto token = MUST(encode_base64(builder.string_view().bytes())); builder.clear(); builder.append("Basic "sv); builder.append(token); diff --git a/Userland/Libraries/LibURL/URL.cpp b/Userland/Libraries/LibURL/URL.cpp index d739419764..352abcee80 100644 --- a/Userland/Libraries/LibURL/URL.cpp +++ b/Userland/Libraries/LibURL/URL.cpp @@ -36,16 +36,6 @@ URL URL::complete_url(StringView relative_url) const return Parser::basic_parse(relative_url, *this); } -ErrorOr URL::username() const -{ - return String::from_byte_string(percent_decode(m_data->username)); -} - -ErrorOr URL::password() const -{ - return String::from_byte_string(percent_decode(m_data->password)); -} - ByteString URL::path_segment_at_index(size_t index) const { VERIFY(index < path_segment_count()); diff --git a/Userland/Libraries/LibURL/URL.h b/Userland/Libraries/LibURL/URL.h index 1f696bc8f3..4193684ca9 100644 --- a/Userland/Libraries/LibURL/URL.h +++ b/Userland/Libraries/LibURL/URL.h @@ -126,8 +126,8 @@ public: bool is_valid() const { return m_data->valid; } String const& scheme() const { return m_data->scheme; } - ErrorOr username() const; - ErrorOr password() const; + String const& username() const { return m_data->username; } + String const& password() const { return m_data->password; } Host const& host() const { return m_data->host; } ErrorOr serialized_host() const; ByteString basename() const; @@ -180,9 +180,6 @@ public: return equals(other, ExcludeFragment::No); } - String const& raw_username() const { return m_data->username; } - String const& raw_password() const { return m_data->password; } - Optional const& blob_url_entry() const { return m_data->blob_url_entry; } void set_blob_url_entry(Optional entry) { m_data->blob_url_entry = move(entry); } diff --git a/Userland/Libraries/LibWeb/DOMURL/DOMURL.cpp b/Userland/Libraries/LibWeb/DOMURL/DOMURL.cpp index 80bd62f92d..ab2bf80943 100644 --- a/Userland/Libraries/LibWeb/DOMURL/DOMURL.cpp +++ b/Userland/Libraries/LibWeb/DOMURL/DOMURL.cpp @@ -246,12 +246,10 @@ WebIDL::ExceptionOr DOMURL::set_protocol(String const& protocol) } // https://url.spec.whatwg.org/#dom-url-username -WebIDL::ExceptionOr DOMURL::username() const +String const& DOMURL::username() const { - auto& vm = realm().vm(); - // The username getter steps are to return this’s URL’s username. - return TRY_OR_THROW_OOM(vm, m_url.username()); + return m_url.username(); } // https://url.spec.whatwg.org/#ref-for-dom-url-username%E2%91%A0 @@ -266,12 +264,10 @@ void DOMURL::set_username(String const& username) } // https://url.spec.whatwg.org/#dom-url-password -WebIDL::ExceptionOr DOMURL::password() const +String const& DOMURL::password() const { - auto& vm = realm().vm(); - // The password getter steps are to return this’s URL’s password. - return TRY_OR_THROW_OOM(vm, m_url.password()); + return m_url.password(); } // https://url.spec.whatwg.org/#ref-for-dom-url-password%E2%91%A0 diff --git a/Userland/Libraries/LibWeb/DOMURL/DOMURL.h b/Userland/Libraries/LibWeb/DOMURL/DOMURL.h index a122b936c9..e12f47fb64 100644 --- a/Userland/Libraries/LibWeb/DOMURL/DOMURL.h +++ b/Userland/Libraries/LibWeb/DOMURL/DOMURL.h @@ -40,10 +40,10 @@ public: WebIDL::ExceptionOr protocol() const; WebIDL::ExceptionOr set_protocol(String const&); - WebIDL::ExceptionOr username() const; + String const& username() const; void set_username(String const&); - WebIDL::ExceptionOr password() const; + String const& password() const; void set_password(String const&); WebIDL::ExceptionOr host() const; diff --git a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index 94139797ef..4c3105d668 100644 --- a/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Userland/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -1810,7 +1810,7 @@ WebIDL::ExceptionOr> http_network_or_cache_fet // true, set authorizationValue to httpRequest’s current URL, converted to an `Authorization` value. else if (http_request->current_url().includes_credentials() && is_authentication_fetch == IsAuthenticationFetch::Yes) { auto const& url = http_request->current_url(); - auto payload = MUST(String::formatted("{}:{}", MUST(url.username()), MUST(url.password()))); + auto payload = MUST(String::formatted("{}:{}", URL::percent_decode(url.username()), URL::percent_decode(url.password()))); authorization_value = TRY_OR_THROW_OOM(vm, encode_base64(payload.bytes())); } diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index 722f6890bd..e834c9b646 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -41,8 +41,8 @@ bool url_matches_about_blank(URL::URL const& url) // A URL matches about:blank if its scheme is "about", its path contains a single string "blank", its username and password are the empty string, and its host is null. return url.scheme() == "about"sv && url.serialize_path() == "blank"sv - && url.raw_username().is_empty() - && url.raw_password().is_empty() + && url.username().is_empty() + && url.password().is_empty() && url.host().has(); } @@ -53,8 +53,8 @@ bool url_matches_about_srcdoc(URL::URL const& url) return url.scheme() == "about"sv && url.serialize_path() == "srcdoc"sv && !url.query().has_value() - && url.raw_username().is_empty() - && url.raw_password().is_empty() + && url.username().is_empty() + && url.password().is_empty() && url.host().has(); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp b/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp index 47265b608c..69bc15a1eb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLHyperlinkElementUtils.cpp @@ -97,7 +97,7 @@ String HTMLHyperlinkElementUtils::username() const return String {}; // 3. Return this element's url's username. - return m_url->username().release_value(); + return m_url->username(); } // https://html.spec.whatwg.org/multipage/links.html#dom-hyperlink-username @@ -134,7 +134,7 @@ String HTMLHyperlinkElementUtils::password() const return String {}; // 4. Return url's password. - return url->password().release_value(); + return url->password(); } // https://html.spec.whatwg.org/multipage/links.html#dom-hyperlink-password diff --git a/Userland/Libraries/LibWeb/HTML/History.cpp b/Userland/Libraries/LibWeb/HTML/History.cpp index f9dcd889ce..b998878766 100644 --- a/Userland/Libraries/LibWeb/HTML/History.cpp +++ b/Userland/Libraries/LibWeb/HTML/History.cpp @@ -135,8 +135,8 @@ bool can_have_its_url_rewritten(DOM::Document const& document, URL::URL const& t // 2. If targetURL and documentURL differ in their scheme, username, password, host, or port components, // then return false. if (target_url.scheme() != document_url.scheme() - || target_url.raw_username() != document_url.raw_username() - || target_url.raw_password() != document_url.raw_password() + || target_url.username() != document_url.username() + || target_url.password() != document_url.password() || target_url.host() != document_url.host() || target_url.port() != document_url.port()) return false;