/* * Copyright (C) 2014-2020 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "URLDecomposition.h" #include "wtf/text/StringToIntegerConversion.h" namespace WebCore { String URLDecomposition::origin() const { auto fullURL = this->fullURL(); if (fullURL.protocolIsInHTTPFamily() or fullURL.protocolIsInFTPFamily() or fullURL.protocolIs("ws"_s) or fullURL.protocolIs("wss"_s)) return fullURL.protocolHostAndPort(); return "null"_s; } String URLDecomposition::protocol() const { auto fullURL = this->fullURL(); if (WTF::protocolIsJavaScript(fullURL.string())) return "javascript:"_s; return makeString(fullURL.protocol(), ':'); } void URLDecomposition::setProtocol(StringView value) { URL copy = fullURL(); copy.setProtocol(value); setFullURL(copy); } String URLDecomposition::username() const { return fullURL().encodedUser().toString(); } void URLDecomposition::setUsername(StringView user) { auto fullURL = this->fullURL(); if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s)) return; fullURL.setUser(user); setFullURL(fullURL); } String URLDecomposition::password() const { return fullURL().encodedPassword().toString(); } void URLDecomposition::setPassword(StringView password) { auto fullURL = this->fullURL(); if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s)) return; fullURL.setPassword(password); setFullURL(fullURL); } String URLDecomposition::host() const { return fullURL().hostAndPort(); } static unsigned countASCIIDigits(StringView string) { unsigned length = string.length(); for (unsigned count = 0; count < length; ++count) { if (!isASCIIDigit(string[count])) return count; } return length; } void URLDecomposition::setHost(StringView value) { auto fullURL = this->fullURL(); if (value.isEmpty() && !fullURL.protocolIs("file"_s) && fullURL.hasSpecialScheme()) return; size_t separator = value.reverseFind(':'); if (!separator) return; if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort()) return; // No port if no colon or rightmost colon is within the IPv6 section. size_t ipv6Separator = value.reverseFind(']'); if (separator == notFound || (ipv6Separator != notFound && ipv6Separator > separator)) fullURL.setHost(value); else { // Multiple colons are acceptable only in case of IPv6. if (value.find(':') != separator && ipv6Separator == notFound) return; unsigned portLength = countASCIIDigits(value.substring(separator + 1)); if (!portLength) { fullURL.setHost(value.substring(0, separator)); } else { auto portNumber = parseInteger(value.substring(separator + 1, portLength)); if (portNumber && WTF::isDefaultPortForProtocol(*portNumber, fullURL.protocol())) fullURL.setHostAndPort(value.substring(0, separator)); else fullURL.setHostAndPort(value.substring(0, separator + 1 + portLength)); } } if (fullURL.isValid()) setFullURL(fullURL); } String URLDecomposition::hostname() const { return fullURL().host().toString(); } static StringView removeAllLeadingSolidusCharacters(StringView string) { unsigned i; unsigned length = string.length(); for (i = 0; i < length; ++i) { if (string[i] != '/') break; } return string.substring(i); } void URLDecomposition::setHostname(StringView value) { auto fullURL = this->fullURL(); auto host = removeAllLeadingSolidusCharacters(value); if (host.isEmpty() && !fullURL.protocolIs("file"_s) && fullURL.hasSpecialScheme()) return; if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort()) return; fullURL.setHost(host); if (fullURL.isValid()) setFullURL(fullURL); } String URLDecomposition::port() const { auto port = fullURL().port(); if (!port) return emptyString(); return String::number(*port); } // Outer optional is whether we could parse at all. Inner optional is "no port specified". static std::optional> parsePort(StringView string, StringView protocol) { // https://url.spec.whatwg.org/#port-state with state override given. uint32_t port { 0 }; bool foundDigit = false; for (size_t i = 0; i < string.length(); ++i) { auto c = string[i]; // https://infra.spec.whatwg.org/#ascii-tab-or-newline if (c == 0x0009 || c == 0x000A || c == 0x000D) continue; if (isASCIIDigit(c)) { port = port * 10 + c - '0'; foundDigit = true; if (port > std::numeric_limits::max()) return std::nullopt; continue; } if (!foundDigit) return std::nullopt; break; } if (!foundDigit || WTF::isDefaultPortForProtocol(static_cast(port), protocol)) return std::optional { std::nullopt }; return { { static_cast(port) } }; } void URLDecomposition::setPort(StringView value) { auto fullURL = this->fullURL(); if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s) || !fullURL.canSetHostOrPort()) return; auto port = parsePort(value, fullURL.protocol()); if (!port) return; fullURL.setPort(*port); setFullURL(fullURL); } String URLDecomposition::pathname() const { return fullURL().path().toString(); } void URLDecomposition::setPathname(StringView value) { auto fullURL = this->fullURL(); if (fullURL.cannotBeABaseURL() || !fullURL.canSetPathname()) return; fullURL.setPath(value); setFullURL(fullURL); } String URLDecomposition::search() const { auto fullURL = this->fullURL(); return fullURL.query().isEmpty() ? emptyString() : fullURL.queryWithLeadingQuestionMark().toString(); } void URLDecomposition::setSearch(const String& value) { auto fullURL = this->fullURL(); if (value.isEmpty()) { // If the given value is the empty string, set url's query to null. fullURL.setQuery({}); } else { String newSearch = value; // Make sure that '#' in the query does not leak to the hash. fullURL.setQuery(makeStringByReplacingAll(value, '#', "%23"_s)); } setFullURL(fullURL); } String URLDecomposition::hash() const { auto fullURL = this->fullURL(); return fullURL.fragmentIdentifier().isEmpty() ? emptyString() : fullURL.fragmentIdentifierWithLeadingNumberSign().toString(); } void URLDecomposition::setHash(StringView value) { auto fullURL = this->fullURL(); if (value.isEmpty()) fullURL.removeFragmentIdentifier(); else fullURL.setFragmentIdentifier(value.startsWith('#') ? value.substring(1) : value); setFullURL(fullURL); } } red/isolation Unnamed repository; edit this file 'description' to name the repository.
aboutsummaryrefslogtreecommitdiff
AgeCommit message (Expand)AuthorFilesLines
2023-01-21Handle string subclasses and new String() in new BufferGravatar Jarred Sumner 1-2/+11
2023-01-21Make Buffer.alloc* 3ns fasterGravatar Jarred Sumner 1-11/+17
2023-01-21[buffer] Make Buffer.from pass more testsGravatar Jarred Sumner 4-92/+179
2023-01-20constructor parameter properties in class expressions (#1867)Gravatar Dylan Conway 2-8/+48
2023-01-20Update transpiler.test.jsbun-v0.5.1Gravatar Jarred Sumner 1-1/+1
2023-01-20Update transpiler.test.jsGravatar Jarred Sumner 1-1/+1
2023-01-20push super before generated statements (#1856)Gravatar Dylan Conway 2-29/+53
2023-01-20Clear the errorsGravatar Jarred Sumner 1-0/+2
2023-01-20one less hash tableGravatar Jarred Sumner 1-2/+13
2023-01-20Add another testGravatar Jarred Sumner 2-1/+11
2023-01-20fix hanging testGravatar Jarred Sumner 1-38/+42
2023-01-20Further cleanup buffer encodingGravatar Jarred Sumner 1-48/+26
2023-01-20Fixes #1855Gravatar Jarred Sumner 2-5/+57
2023-01-20Fix assertion failure with boringssl messagesGravatar Jarred Sumner 3-5/+132
2023-01-19Revert "ignore sighup"Gravatar Jarred Sumner 1-45/+10
2023-01-19ignore sighupGravatar Jarred Sumner 1-10/+45
2023-01-19make this code easier to readGravatar Jarred Sumner 3-29/+26
2023-01-19Update types.zigGravatar Jarred Sumner 1-4/+0
2023-01-19BumpGravatar Jarred Sumner 2-2/+2
2023-01-19Fix buffer encoding bugGravatar Jarred Sumner 2-4/+17
2023-01-19use `String.from()` (#1850)Gravatar Alex Lam S.L 4-5/+12
2023-01-19Bump zigGravatar Jarred Sumner 2-2/+2
2023-01-19make it packedGravatar Jarred Sumner 1-2/+2
2023-01-20Bugfixes to install (#1848)Gravatar Jarred Sumner 5-26/+119
2023-01-19repopulate `alias_map` correctly (#1847)Gravatar Alex Lam S.L 5-70/+240
2023-01-19Add a commentGravatar Jarred Sumner 1-0/+6
2023-01-19Add a debug safety check for UAF in AST nodesGravatar Jarred Sumner 1-0/+5
2023-01-19Fix UAF when opening workspacesGravatar Jarred Sumner 1-2/+0
2023-01-19Improve error message when a workspace is not foundGravatar Jarred Sumner 2-9/+97