mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:34:59 +00:00
AK: Don't store parts of URLs percent decoded
As noted in serval comments doing this goes against the WC3 spec, and breaks parsing then re-serializing URLs that contain percent encoded data, that was not encoded using the same character set as the serializer. For example, previously if you had a URL like: https:://foo.com/what%2F%2F (the path is what + '//' percent encoded) Creating URL("https:://foo.com/what%2F%2F").serialize() would return: https://foo.com/what// Which is incorrect and not the same as the URL we passed. This is because the re-serializing uses the PercentEncodeSet::Path which does not include '/'. Only doing the percent encoding in the setters fixes this, which is required to navigate to Google Street View (which includes a percent encoded URL in its URL). Seems to fix #13477 too
This commit is contained in:
parent
d2fc8efd9e
commit
8283e8b88c
5 changed files with 85 additions and 51 deletions
69
AK/URL.cpp
69
AK/URL.cpp
|
@ -47,20 +47,32 @@ URL URL::complete_url(StringView relative_url) const
|
|||
return URLParser::parse(relative_url, *this);
|
||||
}
|
||||
|
||||
// NOTE: This only exists for compatibility with the existing URL tests which check for both .is_null() and .is_empty().
|
||||
static DeprecatedString deprecated_string_percent_encode(DeprecatedString const& input, URL::PercentEncodeSet set = URL::PercentEncodeSet::Userinfo, URL::SpaceAsPlus space_as_plus = URL::SpaceAsPlus::No)
|
||||
{
|
||||
if (input.is_null() || input.is_empty())
|
||||
return input;
|
||||
return URL::percent_encode(input.view(), set, space_as_plus);
|
||||
}
|
||||
|
||||
void URL::set_scheme(DeprecatedString scheme)
|
||||
{
|
||||
m_scheme = move(scheme);
|
||||
m_valid = compute_validity();
|
||||
}
|
||||
|
||||
void URL::set_username(DeprecatedString username)
|
||||
void URL::set_username(DeprecatedString username, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes)
|
||||
username = deprecated_string_percent_encode(username, PercentEncodeSet::Userinfo);
|
||||
m_username = move(username);
|
||||
m_valid = compute_validity();
|
||||
}
|
||||
|
||||
void URL::set_password(DeprecatedString password)
|
||||
void URL::set_password(DeprecatedString password, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes)
|
||||
password = deprecated_string_percent_encode(password, PercentEncodeSet::Userinfo);
|
||||
m_password = move(password);
|
||||
m_valid = compute_validity();
|
||||
}
|
||||
|
@ -81,19 +93,38 @@ void URL::set_port(Optional<u16> port)
|
|||
m_valid = compute_validity();
|
||||
}
|
||||
|
||||
void URL::set_paths(Vector<DeprecatedString> paths)
|
||||
void URL::set_paths(Vector<DeprecatedString> paths, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
m_paths = move(paths);
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes) {
|
||||
Vector<DeprecatedString> encoded_paths;
|
||||
encoded_paths.ensure_capacity(paths.size());
|
||||
for (auto& segment : paths)
|
||||
encoded_paths.unchecked_append(deprecated_string_percent_encode(segment, PercentEncodeSet::Path));
|
||||
m_paths = move(encoded_paths);
|
||||
} else {
|
||||
m_paths = move(paths);
|
||||
}
|
||||
m_valid = compute_validity();
|
||||
}
|
||||
|
||||
void URL::set_query(DeprecatedString query)
|
||||
void URL::append_path(DeprecatedString path, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes)
|
||||
path = deprecated_string_percent_encode(path, PercentEncodeSet::Path);
|
||||
m_paths.append(path);
|
||||
}
|
||||
|
||||
void URL::set_query(DeprecatedString query, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes)
|
||||
query = deprecated_string_percent_encode(query, is_special() ? PercentEncodeSet::SpecialQuery : PercentEncodeSet::Query);
|
||||
m_query = move(query);
|
||||
}
|
||||
|
||||
void URL::set_fragment(DeprecatedString fragment)
|
||||
void URL::set_fragment(DeprecatedString fragment, ApplyPercentEncoding apply_percent_encoding)
|
||||
{
|
||||
if (apply_percent_encoding == ApplyPercentEncoding::Yes)
|
||||
fragment = deprecated_string_percent_encode(fragment, PercentEncodeSet::Fragment);
|
||||
m_fragment = move(fragment);
|
||||
}
|
||||
|
||||
|
@ -171,9 +202,8 @@ URL URL::create_with_file_scheme(DeprecatedString const& path, DeprecatedString
|
|||
// This is because a file URL always needs a non-null hostname.
|
||||
url.set_host(hostname.is_null() || hostname == "localhost" ? DeprecatedString::empty() : hostname);
|
||||
url.set_paths(lexical_path.parts());
|
||||
// NOTE: To indicate that we want to end the path with a slash, we have to append an empty path segment.
|
||||
if (path.ends_with('/'))
|
||||
url.append_path("");
|
||||
url.append_slash();
|
||||
url.set_fragment(fragment);
|
||||
return url;
|
||||
}
|
||||
|
@ -188,9 +218,8 @@ URL URL::create_with_help_scheme(DeprecatedString const& path, DeprecatedString
|
|||
// This is because a file URL always needs a non-null hostname.
|
||||
url.set_host(hostname.is_null() || hostname == "localhost" ? DeprecatedString::empty() : hostname);
|
||||
url.set_paths(lexical_path.parts());
|
||||
// NOTE: To indicate that we want to end the path with a slash, we have to append an empty path segment.
|
||||
if (path.ends_with('/'))
|
||||
url.append_path("");
|
||||
url.append_slash();
|
||||
url.set_fragment(fragment);
|
||||
return url;
|
||||
}
|
||||
|
@ -242,10 +271,10 @@ DeprecatedString URL::serialize(ExcludeFragment exclude_fragment) const
|
|||
builder.append("//"sv);
|
||||
|
||||
if (includes_credentials()) {
|
||||
builder.append(percent_encode(m_username, PercentEncodeSet::Userinfo));
|
||||
builder.append(m_username);
|
||||
if (!m_password.is_empty()) {
|
||||
builder.append(':');
|
||||
builder.append(percent_encode(m_password, PercentEncodeSet::Userinfo));
|
||||
builder.append(m_password);
|
||||
}
|
||||
builder.append('@');
|
||||
}
|
||||
|
@ -256,24 +285,24 @@ DeprecatedString URL::serialize(ExcludeFragment exclude_fragment) const
|
|||
}
|
||||
|
||||
if (cannot_be_a_base_url()) {
|
||||
builder.append(percent_encode(m_paths[0], PercentEncodeSet::Path));
|
||||
builder.append(m_paths[0]);
|
||||
} else {
|
||||
if (m_host.is_null() && m_paths.size() > 1 && m_paths[0].is_empty())
|
||||
builder.append("/."sv);
|
||||
for (auto& segment : m_paths) {
|
||||
builder.append('/');
|
||||
builder.append(percent_encode(segment, PercentEncodeSet::Path));
|
||||
builder.append(segment);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_query.is_null()) {
|
||||
builder.append('?');
|
||||
builder.append(percent_encode(m_query, is_special() ? URL::PercentEncodeSet::SpecialQuery : URL::PercentEncodeSet::Query));
|
||||
builder.append(m_query);
|
||||
}
|
||||
|
||||
if (exclude_fragment == ExcludeFragment::No && !m_fragment.is_null()) {
|
||||
builder.append('#');
|
||||
builder.append(percent_encode(m_fragment, PercentEncodeSet::Fragment));
|
||||
builder.append(m_fragment);
|
||||
}
|
||||
|
||||
return builder.to_deprecated_string();
|
||||
|
@ -300,24 +329,24 @@ DeprecatedString URL::serialize_for_display() const
|
|||
}
|
||||
|
||||
if (cannot_be_a_base_url()) {
|
||||
builder.append(percent_encode(m_paths[0], PercentEncodeSet::Path));
|
||||
builder.append(m_paths[0]);
|
||||
} else {
|
||||
if (m_host.is_null() && m_paths.size() > 1 && m_paths[0].is_empty())
|
||||
builder.append("/."sv);
|
||||
for (auto& segment : m_paths) {
|
||||
builder.append('/');
|
||||
builder.append(percent_encode(segment, PercentEncodeSet::Path));
|
||||
builder.append(segment);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_query.is_null()) {
|
||||
builder.append('?');
|
||||
builder.append(percent_encode(m_query, is_special() ? URL::PercentEncodeSet::SpecialQuery : URL::PercentEncodeSet::Query));
|
||||
builder.append(m_query);
|
||||
}
|
||||
|
||||
if (!m_fragment.is_null()) {
|
||||
builder.append('#');
|
||||
builder.append(percent_encode(m_fragment, PercentEncodeSet::Fragment));
|
||||
builder.append(m_fragment);
|
||||
}
|
||||
|
||||
return builder.to_deprecated_string();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue