From 0226e0ca0dc70f9a0310b3eef045ee1c1e0ca3ac Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 13 Dec 2022 20:00:46 +0300 Subject: split into a separate repo --- vendor/league/uri-interfaces/LICENSE | 20 ++ vendor/league/uri-interfaces/composer.json | 68 +++++ .../src/Contracts/AuthorityInterface.php | 87 ++++++ .../src/Contracts/DataPathInterface.php | 92 +++++++ .../src/Contracts/DomainHostInterface.php | 107 ++++++++ .../src/Contracts/FragmentInterface.php | 22 ++ .../uri-interfaces/src/Contracts/HostInterface.php | 51 ++++ .../src/Contracts/IpHostInterface.php | 48 ++++ .../uri-interfaces/src/Contracts/PathInterface.php | 90 +++++++ .../uri-interfaces/src/Contracts/PortInterface.php | 22 ++ .../src/Contracts/QueryInterface.php | 227 ++++++++++++++++ .../src/Contracts/SegmentedPathInterface.php | 147 +++++++++++ .../src/Contracts/UriComponentInterface.php | 88 +++++++ .../uri-interfaces/src/Contracts/UriException.php | 20 ++ .../uri-interfaces/src/Contracts/UriInterface.php | 292 +++++++++++++++++++++ .../src/Contracts/UserInfoInterface.php | 40 +++ .../src/Exceptions/FileinfoSupportMissing.php | 20 ++ .../src/Exceptions/IdnSupportMissing.php | 20 ++ .../src/Exceptions/IdnaConversionFailed.php | 46 ++++ .../uri-interfaces/src/Exceptions/SyntaxError.php | 20 ++ vendor/league/uri-interfaces/src/Idna/Idna.php | 212 +++++++++++++++ vendor/league/uri-interfaces/src/Idna/IdnaInfo.php | 113 ++++++++ 22 files changed, 1852 insertions(+) create mode 100644 vendor/league/uri-interfaces/LICENSE create mode 100644 vendor/league/uri-interfaces/composer.json create mode 100644 vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/HostInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/PathInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/PortInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/QueryInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/UriException.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/UriInterface.php create mode 100644 vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php create mode 100644 vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php create mode 100644 vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php create mode 100644 vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php create mode 100644 vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php create mode 100644 vendor/league/uri-interfaces/src/Idna/Idna.php create mode 100644 vendor/league/uri-interfaces/src/Idna/IdnaInfo.php (limited to 'vendor/league/uri-interfaces') diff --git a/vendor/league/uri-interfaces/LICENSE b/vendor/league/uri-interfaces/LICENSE new file mode 100644 index 0000000..14c82cd --- /dev/null +++ b/vendor/league/uri-interfaces/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2016 ignace nyamagana butera + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/league/uri-interfaces/composer.json b/vendor/league/uri-interfaces/composer.json new file mode 100644 index 0000000..fc34cfe --- /dev/null +++ b/vendor/league/uri-interfaces/composer.json @@ -0,0 +1,68 @@ +{ + "name": "league/uri-interfaces", + "description" : "Common interface for URI representation", + "keywords": [ + "url", + "uri", + "rfc3986", + "rfc3987" + ], + "license": "MIT", + "homepage": "http://github.com/thephpleague/uri-interfaces", + "authors": [ + { + "name" : "Ignace Nyamagana Butera", + "email" : "nyamsprod@gmail.com", + "homepage" : "https://nyamsprod.com" + } + ], + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nyamsprod" + } + ], + "require": { + "php" : "^7.2 || ^8.0", + "ext-json": "*" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.19", + "phpstan/phpstan": "^0.12.90", + "phpstan/phpstan-strict-rules": "^0.12.9", + "phpstan/phpstan-phpunit": "^0.12.19", + "phpunit/phpunit": "^8.5.15 || ^9.5" + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "src/" + } + }, + "scripts": { + "phpunit": "phpunit --coverage-text", + "phpcs": "php-cs-fixer fix --dry-run --diff -vvv --allow-risky=yes --ansi", + "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi", + "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit 192M", + "test": [ + "@phpunit", + "@phpstan", + "@phpcs:fix" + ] + }, + "scripts-descriptions": { + "phpunit": "Runs package test suite", + "phpstan": "Runs complete codebase static analysis", + "phpcs": "Runs coding style testing", + "phpcs:fix": "Fix coding style issues", + "test": "Runs all tests" + }, + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "suggest": { + "ext-intl": "to use the IDNA feature", + "symfony/intl": "to use the IDNA feature via Symfony Polyfill" + } +} diff --git a/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php b/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php new file mode 100644 index 0000000..ed6c2b8 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface AuthorityInterface extends UriComponentInterface +{ + /** + * Returns the host component of the authority. + */ + public function getHost(): ?string; + + /** + * Returns the port component of the authority. + */ + public function getPort(): ?int; + + /** + * Returns the user information component of the authority. + */ + public function getUserInfo(): ?string; + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * A null value provided for the host is equivalent to removing the host + * information. + * + * @param ?string $host + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withHost(?string $host): self; + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param ?int $port + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPort(?int $port): self; + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; a null value for the user is equivalent to removing user + * information. + * + * @param ?string $user + * @param ?string $password + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withUserInfo(?string $user, ?string $password = null): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php b/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php new file mode 100644 index 0000000..1e4f385 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/DataPathInterface.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface DataPathInterface extends PathInterface +{ + /** + * Retrieve the data mime type associated to the URI. + * + * If no mimetype is present, this method MUST return the default mimetype 'text/plain'. + * + * @see http://tools.ietf.org/html/rfc2397#section-2 + */ + public function getMimeType(): string; + + /** + * Retrieve the parameters associated with the Mime Type of the URI. + * + * If no parameters is present, this method MUST return the default parameter 'charset=US-ASCII'. + * + * @see http://tools.ietf.org/html/rfc2397#section-2 + */ + public function getParameters(): string; + + /** + * Retrieve the mediatype associated with the URI. + * + * If no mediatype is present, this method MUST return the default parameter 'text/plain;charset=US-ASCII'. + * + * @see http://tools.ietf.org/html/rfc2397#section-3 + * + * @return string The URI scheme. + */ + public function getMediaType(): string; + + /** + * Retrieves the data string. + * + * Retrieves the data part of the path. If no data part is provided return + * a empty string + */ + public function getData(): string; + + /** + * Tells whether the data is binary safe encoded. + */ + public function isBinaryData(): bool; + + /** + * Save the data to a specific file. + */ + public function save(string $path, string $mode = 'w'): \SplFileObject; + + /** + * Returns an instance where the data part is base64 encoded. + * + * This method MUST retain the state of the current instance, and return + * an instance where the data part is base64 encoded + */ + public function toBinary(): self; + + /** + * Returns an instance where the data part is url encoded following RFC3986 rules. + * + * This method MUST retain the state of the current instance, and return + * an instance where the data part is url encoded + */ + public function toAscii(): self; + + /** + * Return an instance with the specified mediatype parameters. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified mediatype parameters. + * + * Users must provide encoded characters. + * + * An empty parameters value is equivalent to removing the parameter. + */ + public function withParameters(string $parameters): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php b/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php new file mode 100644 index 0000000..2490310 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +/** + * @extends \IteratorAggregate + */ +interface DomainHostInterface extends \Countable, HostInterface, \IteratorAggregate +{ + /** + * Returns the labels total number. + */ + public function count(): int; + + /** + * Iterate over the Domain labels. + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Retrieves a single host label. + * + * If the label offset has not been set, returns the null value. + */ + public function get(int $offset): ?string; + + /** + * Returns the associated key for a specific label or all the keys. + * + * @param ?string $label + * + * @return int[] + */ + public function keys(?string $label = null): array; + + /** + * Tells whether the domain is absolute. + */ + public function isAbsolute(): bool; + + /** + * Prepends a label to the host. + */ + public function prepend(string $label): self; + + /** + * Appends a label to the host. + */ + public function append(string $label): self; + + /** + * Returns an instance with its Root label. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function withRootLabel(): self; + + /** + * Returns an instance without its Root label. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function withoutRootLabel(): self; + + /** + * Returns an instance with the modified label. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the new label + * + * If $key is non-negative, the added label will be the label at $key position from the start. + * If $key is negative, the added label will be the label at $key position from the end. + * + * @throws SyntaxError If the key is invalid + */ + public function withLabel(int $key, string $label): self; + + /** + * Returns an instance without the specified label. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * If $key is non-negative, the removed label will be the label at $key position from the start. + * If $key is negative, the removed label will be the label at $key position from the end. + * + * @param int ...$keys + * + * @throws SyntaxError If the key is invalid + */ + public function withoutLabel(int ...$keys): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php b/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php new file mode 100644 index 0000000..3d80f06 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/FragmentInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface FragmentInterface extends UriComponentInterface +{ + /** + * Returns the decoded fragment. + */ + public function decoded(): ?string; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/HostInterface.php b/vendor/league/uri-interfaces/src/Contracts/HostInterface.php new file mode 100644 index 0000000..a8b8bb3 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/HostInterface.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface HostInterface extends UriComponentInterface +{ + /** + * Returns the ascii representation. + */ + public function toAscii(): ?string; + + /** + * Returns the unicode representation. + */ + public function toUnicode(): ?string; + + /** + * Returns the IP version. + * + * If the host is a not an IP this method will return null + */ + public function getIpVersion(): ?string; + + /** + * Returns the IP component If the Host is an IP address. + * + * If the host is a not an IP this method will return null + */ + public function getIp(): ?string; + + /** + * Tells whether the host is a domain name. + */ + public function isDomain(): bool; + + /** + * Tells whether the host is an IP Address. + */ + public function isIp(): bool; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php b/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php new file mode 100644 index 0000000..1e2242a --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/IpHostInterface.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface IpHostInterface extends HostInterface +{ + /** + * Returns whether or not the host is an IPv4 address. + */ + public function isIpv4(): bool; + /** + * Returns whether or not the host is an IPv6 address. + */ + public function isIpv6(): bool; + + /** + * Returns whether or not the host is an IPv6 address. + */ + public function isIpFuture(): bool; + + /** + * Returns whether or not the host has a ZoneIdentifier. + * + * @see http://tools.ietf.org/html/rfc6874#section-4 + */ + public function hasZoneIdentifier(): bool; + + /** + * Returns an host without its zone identifier according to RFC6874. + * + * This method MUST retain the state of the current instance, and return + * an instance without the host zone identifier according to RFC6874 + * + * @see http://tools.ietf.org/html/rfc6874#section-4 + */ + public function withoutZoneIdentifier(): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/PathInterface.php b/vendor/league/uri-interfaces/src/Contracts/PathInterface.php new file mode 100644 index 0000000..389c0ff --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/PathInterface.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +interface PathInterface extends UriComponentInterface +{ + /** + * Returns the decoded path. + */ + public function decoded(): string; + + /** + * Returns whether or not the path is absolute or relative. + */ + public function isAbsolute(): bool; + + /** + * Returns whether or not the path has a trailing delimiter. + */ + public function hasTrailingSlash(): bool; + + /** + * Returns an instance without dot segments. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component normalized by removing + * the dot segment. + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutDotSegments(): self; + + /** + * Returns an instance with a leading slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component with a leading slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withLeadingSlash(): self; + + /** + * Returns an instance without a leading slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component without a leading slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutLeadingSlash(): self; + + /** + * Returns an instance with a trailing slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component with a trailing slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withTrailingSlash(): self; + + /** + * Returns an instance without a trailing slash. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component without a trailing slash + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withoutTrailingSlash(): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/PortInterface.php b/vendor/league/uri-interfaces/src/Contracts/PortInterface.php new file mode 100644 index 0000000..7230c4a --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/PortInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface PortInterface extends UriComponentInterface +{ + /** + * Returns the integer representation of the Port. + */ + public function toInt(): ?int; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php b/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php new file mode 100644 index 0000000..f7081ea --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/QueryInterface.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +/** + * @extends \IteratorAggregate + */ +interface QueryInterface extends \Countable, \IteratorAggregate, UriComponentInterface +{ + /** + * Returns the query separator. + */ + public function getSeparator(): string; + + /** + * Returns the number of key/value pairs present in the object. + */ + public function count(): int; + + /** + * Returns an iterator allowing to go through all key/value pairs contained in this object. + * + * The pair is represented as an array where the first value is the pair key + * and the second value the pair value. + * + * The key of each pair is a string + * The value of each pair is a scalar or the null value + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Returns an iterator allowing to go through all key/value pairs contained in this object. + * + * The return type is as a Iterator where its offset is the pair key and its value the pair value. + * + * The key of each pair is a string + * The value of each pair is a scalar or the null value + * + * @return iterable + */ + public function pairs(): iterable; + + /** + * Tells whether a pair with a specific name exists. + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-has + */ + public function has(string $key): bool; + + /** + * Returns the first value associated to the given pair name. + * + * If no value is found null is returned + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-get + */ + public function get(string $key): ?string; + + /** + * Returns all the values associated to the given pair name as an array or all + * the instance pairs. + * + * If no value is found an empty array is returned + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-getall + * + * @return array + */ + public function getAll(string $key): array; + + /** + * Returns the store PHP variables as elements of an array. + * + * The result is similar as PHP parse_str when used with its + * second argument with the difference that variable names are + * not mangled. + * + * If a key is submitted it will returns the value attached to it or null + * + * @see http://php.net/parse_str + * @see https://wiki.php.net/rfc/on_demand_name_mangling + * + * @param ?string $key + * @return mixed the collection of stored PHP variables or the empty array if no input is given, + * the single value of a stored PHP variable or null if the variable is not present in the collection + */ + public function params(?string $key = null); + + /** + * Returns the RFC1738 encoded query. + */ + public function toRFC1738(): ?string; + + /** + * Returns the RFC3986 encoded query. + * + * @see ::getContent + */ + public function toRFC3986(): ?string; + + /** + * Returns an instance with a different separator. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component with a different separator + */ + public function withSeparator(string $separator): self; + + /** + * Sorts the query string by offset, maintaining offset to data correlations. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-sort + */ + public function sort(): self; + + /** + * Returns an instance without duplicate key/value pair. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized by removing + * duplicate pairs whose key/value are the same. + */ + public function withoutDuplicates(): self; + + /** + * Returns an instance without empty key/value where the value is the null value. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized by removing + * empty pairs. + * + * A pair is considered empty if its value is equal to the null value + */ + public function withoutEmptyPairs(): self; + + /** + * Returns an instance where numeric indices associated to PHP's array like key are removed. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the query component normalized so that numeric indexes + * are removed from the pair key value. + * + * ie.: toto[3]=bar[3]&foo=bar becomes toto[]=bar[3]&foo=bar + */ + public function withoutNumericIndices(): self; + + /** + * Returns an instance with the a new key/value pair added to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * If the pair already exists the value will replace the existing value. + * + * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set + * + * @param ?string $value + */ + public function withPair(string $key, ?string $value): self; + + /** + * Returns an instance with the new pairs set to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @see ::withPair + */ + public function merge(string $query): self; + + /** + * Returns an instance without the specified keys. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * @param string ...$keys + */ + public function withoutPair(string ...$keys): self; + + /** + * Returns a new instance with a specified key/value pair appended as a new pair. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * @param ?string $value + */ + public function appendTo(string $key, ?string $value): self; + + /** + * Returns an instance with the new pairs appended to it. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified query + * + * If the pair already exists the value will be added to it. + */ + public function append(string $query): self; + + /** + * Returns an instance without the specified params. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component without PHP's value. + * PHP's mangled is not taken into account. + * + * @param string ...$keys + */ + public function withoutParam(string ...$keys): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php b/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php new file mode 100644 index 0000000..53065ff --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\SyntaxError; + +/** + * @extends \IteratorAggregate + */ +interface SegmentedPathInterface extends \Countable, \IteratorAggregate, PathInterface +{ + /** + * Returns the total number of segments in the path. + */ + public function count(): int; + + /** + * Iterate over the path segment. + * + * @return \Iterator + */ + public function getIterator(): \Iterator; + + /** + * Returns parent directory's path. + */ + public function getDirname(): string; + + /** + * Returns the path basename. + */ + public function getBasename(): string; + + /** + * Returns the basename extension. + */ + public function getExtension(): string; + + /** + * Retrieves a single path segment. + * + * If the segment offset has not been set, returns null. + */ + public function get(int $offset): ?string; + + /** + * Returns the associated key for a specific segment. + * + * If a value is specified only the keys associated with + * the given value will be returned + * + * @param ?string $segment + * + * @return int[] + */ + public function keys(?string $segment = null): array; + + /** + * Appends a segment to the path. + */ + public function append(string $segment): self; + + /** + * Prepends a segment to the path. + */ + public function prepend(string $segment): self; + + /** + * Returns an instance with the modified segment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the new segment + * + * If $key is non-negative, the added segment will be the segment at $key position from the start. + * If $key is negative, the added segment will be the segment at $key position from the end. + * + * @param ?string $segment + * + * @throws SyntaxError If the key is invalid + */ + public function withSegment(int $key, ?string $segment): self; + + /** + * Returns an instance without the specified segment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the modified component + * + * If $key is non-negative, the removed segment will be the segment at $key position from the start. + * If $key is negative, the removed segment will be the segment at $key position from the end. + * + * @param int ...$keys remaining keys to remove + * + * @throws SyntaxError If the key is invalid + */ + public function withoutSegment(int ...$keys): self; + + /** + * Returns an instance without duplicate delimiters. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the path component normalized by removing + * multiple consecutive empty segment + */ + public function withoutEmptySegments(): self; + + /** + * Returns an instance with the specified parent directory's path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $path + */ + public function withDirname(?string $path): self; + + /** + * Returns an instance with the specified basename. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $basename + */ + public function withBasename(?string $basename): self; + + /** + * Returns an instance with the specified basename extension. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the extension basename modified. + * + * @param ?string $extension + */ + public function withExtension(?string $extension): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php b/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php new file mode 100644 index 0000000..c7b39bb --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface UriComponentInterface extends \JsonSerializable +{ + /** + * Returns the instance content. + * + * If the instance is defined, the value returned MUST be encoded according to the + * selected encoding algorithm. In any case, the value MUST NOT double-encode any character + * depending on the selected encoding algorithm. + * + * To determine what characters to encode, please refer to RFC 3986, Sections 2 and 3. + * or RFC 3987 Section 3. By default the content is encoded according to RFC3986 + * + * If the instance is not defined null is returned + */ + public function getContent(): ?string; + + /** + * Returns the instance string representation. + * + * If the instance is defined, the value returned MUST be percent-encoded, + * but MUST NOT double-encode any characters. To determine what characters + * to encode, please refer to RFC 3986, Sections 2 and 3. + * + * If the instance is not defined an empty string is returned + */ + public function __toString(): string; + + /** + * Returns the instance json representation. + * + * If the instance is defined, the value returned MUST be percent-encoded, + * but MUST NOT double-encode any characters. To determine what characters + * to encode, please refer to RFC 3986 or RFC 1738. + * + * If the instance is not defined null is returned + */ + public function jsonSerialize(): ?string; + + /** + * Returns the instance string representation with its optional URI delimiters. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode any + * characters. To determine what characters to encode, please refer to RFC 3986, + * Sections 2 and 3. + * + * If the instance is not defined an empty string is returned + */ + public function getUriComponent(): string; + + /** + * Returns an instance with the specified content. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified content. + * + * Users can provide both encoded and decoded content characters. + * + * A null value is equivalent to removing the component content. + * + * + * @param ?string $content + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withContent(?string $content): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/UriException.php b/vendor/league/uri-interfaces/src/Contracts/UriException.php new file mode 100644 index 0000000..c0fec2a --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/UriException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use Throwable; + +interface UriException extends Throwable +{ +} diff --git a/vendor/league/uri-interfaces/src/Contracts/UriInterface.php b/vendor/league/uri-interfaces/src/Contracts/UriInterface.php new file mode 100644 index 0000000..b6eb6a1 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/UriInterface.php @@ -0,0 +1,292 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; + +interface UriInterface extends \JsonSerializable +{ + /** + * Returns the string representation as a URI reference. + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + */ + public function __toString(): string; + + /** + * Returns the string representation as a URI reference. + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @see ::__toString + */ + public function jsonSerialize(): string; + + /** + * Retrieve the scheme component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.1. + * + * The trailing ":" character is not part of the scheme and MUST NOT be + * added. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.1 + */ + public function getScheme(): ?string; + + /** + * Retrieve the authority component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + */ + public function getAuthority(): ?string; + + /** + * Retrieve the user information component of the URI. + * + * If no scheme is present, this method MUST return a null value. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + */ + public function getUserInfo(): ?string; + + /** + * Retrieve the host component of the URI. + * + * If no host is present this method MUST return a null value. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + */ + public function getHost(): ?string; + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + */ + public function getPort(): ?int; + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + */ + public function getPath(): string; + + /** + * Retrieve the query string of the URI. + * + * If no host is present this method MUST return a null value. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + */ + public function getQuery(): ?string; + + /** + * Retrieve the fragment component of the URI. + * + * If no host is present this method MUST return a null value. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + */ + public function getFragment(): ?string; + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * A null value provided for the scheme is equivalent to removing the scheme + * information. + * + * @param ?string $scheme + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withScheme(?string $scheme): self; + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; a null value for the user is equivalent to removing user + * information. + * + * @param ?string $user + * @param ?string $password + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withUserInfo(?string $user, ?string $password = null): self; + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * A null value provided for the host is equivalent to removing the host + * information. + * + * @param ?string $host + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + * @throws IdnSupportMissing for component or transformations + * requiring IDN support when IDN support is not present + * or misconfigured. + */ + public function withHost(?string $host): self; + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param ?int $port + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPort(?int $port): self; + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withPath(string $path): self; + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * A null value provided for the query is equivalent to removing the query + * information. + * + * @param ?string $query + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withQuery(?string $query): self; + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * A null value provided for the fragment is equivalent to removing the fragment + * information. + * + * @param ?string $fragment + * + * @throws SyntaxError for invalid component or transformations + * that would result in a object in invalid state. + */ + public function withFragment(?string $fragment): self; +} diff --git a/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php b/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php new file mode 100644 index 0000000..6411f9b --- /dev/null +++ b/vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Contracts; + +interface UserInfoInterface extends UriComponentInterface +{ + /** + * Returns the user component part. + */ + public function getUser(): ?string; + + /** + * Returns the pass component part. + */ + public function getPass(): ?string; + + /** + * Returns an instance with the specified user and/or pass. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user. + * + * An empty user is equivalent to removing the user information. + * + * @param ?string $user + * @param ?string $pass + */ + public function withUserInfo(?string $user, ?string $pass = null): self; +} diff --git a/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php b/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php new file mode 100644 index 0000000..0105b2d --- /dev/null +++ b/vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class FileinfoSupportMissing extends \RuntimeException implements UriException +{ +} diff --git a/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php b/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php new file mode 100644 index 0000000..8ff3b53 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class IdnSupportMissing extends \RuntimeException implements UriException +{ +} diff --git a/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php b/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php new file mode 100644 index 0000000..80259f3 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Idna\IdnaInfo; + +final class IdnaConversionFailed extends SyntaxError +{ + /** @var IdnaInfo|null */ + private $idnaInfo; + + private function __construct(string $message, IdnaInfo $idnaInfo = null) + { + parent::__construct($message); + $this->idnaInfo = $idnaInfo; + } + + public static function dueToIDNAError(string $domain, IdnaInfo $idnaInfo): self + { + return new self( + 'The host `'.$domain.'` is invalid : '.implode(', ', $idnaInfo->errorList()).' .', + $idnaInfo + ); + } + + public static function dueToInvalidHost(string $domain): self + { + return new self('The host `'.$domain.'` is not a valid IDN host'); + } + + public function idnaInfo(): ?IdnaInfo + { + return $this->idnaInfo; + } +} diff --git a/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php b/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php new file mode 100644 index 0000000..1b5e4cb --- /dev/null +++ b/vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Exceptions; + +use League\Uri\Contracts\UriException; + +class SyntaxError extends \InvalidArgumentException implements UriException +{ +} diff --git a/vendor/league/uri-interfaces/src/Idna/Idna.php b/vendor/league/uri-interfaces/src/Idna/Idna.php new file mode 100644 index 0000000..5930687 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Idna/Idna.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Idna; + +use League\Uri\Exceptions\IdnaConversionFailed; +use League\Uri\Exceptions\IdnSupportMissing; +use League\Uri\Exceptions\SyntaxError; +use function defined; +use function function_exists; +use function idn_to_ascii; +use function idn_to_utf8; +use function rawurldecode; +use const INTL_IDNA_VARIANT_UTS46; + +/** + * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html + */ +final class Idna +{ + private const REGEXP_IDNA_PATTERN = '/[^\x20-\x7f]/'; + private const MAX_DOMAIN_LENGTH = 253; + private const MAX_LABEL_LENGTH = 63; + + /** + * General registered name regular expression. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2.2 + * @see https://regex101.com/r/fptU8V/1 + */ + private const REGEXP_REGISTERED_NAME = '/ + (?(DEFINE) + (?[a-z0-9_~\-]) # . is missing as it is used to separate labels + (?[!$&\'()*+,;=]) + (?%[A-F0-9]{2}) + (?(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*) + ) + ^(?:(?®_name)\.)*(?®_name)\.?$ + /ix'; + + /** + * IDNA options. + */ + public const IDNA_DEFAULT = 0; + public const IDNA_ALLOW_UNASSIGNED = 1; + public const IDNA_USE_STD3_RULES = 2; + public const IDNA_CHECK_BIDI = 4; + public const IDNA_CHECK_CONTEXTJ = 8; + public const IDNA_NONTRANSITIONAL_TO_ASCII = 0x10; + public const IDNA_NONTRANSITIONAL_TO_UNICODE = 0x20; + public const IDNA_CHECK_CONTEXTO = 0x40; + + /** + * IDNA errors. + */ + public const ERROR_NONE = 0; + public const ERROR_EMPTY_LABEL = 1; + public const ERROR_LABEL_TOO_LONG = 2; + public const ERROR_DOMAIN_NAME_TOO_LONG = 4; + public const ERROR_LEADING_HYPHEN = 8; + public const ERROR_TRAILING_HYPHEN = 0x10; + public const ERROR_HYPHEN_3_4 = 0x20; + public const ERROR_LEADING_COMBINING_MARK = 0x40; + public const ERROR_DISALLOWED = 0x80; + public const ERROR_PUNYCODE = 0x100; + public const ERROR_LABEL_HAS_DOT = 0x200; + public const ERROR_INVALID_ACE_LABEL = 0x400; + public const ERROR_BIDI = 0x800; + public const ERROR_CONTEXTJ = 0x1000; + public const ERROR_CONTEXTO_PUNCTUATION = 0x2000; + public const ERROR_CONTEXTO_DIGITS = 0x4000; + + /** + * IDNA default options. + */ + public const IDNA2008_ASCII = self::IDNA_NONTRANSITIONAL_TO_ASCII + | self::IDNA_CHECK_BIDI + | self::IDNA_USE_STD3_RULES + | self::IDNA_CHECK_CONTEXTJ; + public const IDNA2008_UNICODE = self::IDNA_NONTRANSITIONAL_TO_UNICODE + | self::IDNA_CHECK_BIDI + | self::IDNA_USE_STD3_RULES + | self::IDNA_CHECK_CONTEXTJ; + + /** + * @codeCoverageIgnore + */ + private static function supportsIdna(): void + { + static $idnSupport; + if (null === $idnSupport) { + $idnSupport = function_exists('\idn_to_ascii') && defined('\INTL_IDNA_VARIANT_UTS46'); + } + + if (!$idnSupport) { + throw new IdnSupportMissing('IDN host can not be processed. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.'); + } + } + + /** + * Converts the input to its IDNA ASCII form. + * + * This method returns the string converted to IDN ASCII form + * + * @throws SyntaxError if the string can not be converted to ASCII using IDN UTS46 algorithm + */ + public static function toAscii(string $domain, int $options): IdnaInfo + { + $domain = rawurldecode($domain); + + if (1 === preg_match(self::REGEXP_IDNA_PATTERN, $domain)) { + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + if ([] === $idnaInfo) { + return IdnaInfo::fromIntl([ + 'result' => strtolower($domain), + 'isTransitionalDifferent' => false, + 'errors' => self::validateDomainAndLabelLength($domain), + ]); + } + + /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + return IdnaInfo::fromIntl($idnaInfo); + } + + $error = self::ERROR_NONE; + if (1 !== preg_match(self::REGEXP_REGISTERED_NAME, $domain)) { + $error |= self::ERROR_DISALLOWED; + } + + return IdnaInfo::fromIntl([ + 'result' => strtolower($domain), + 'isTransitionalDifferent' => false, + 'errors' => self::validateDomainAndLabelLength($domain) | $error, + ]); + } + + /** + * Converts the input to its IDNA UNICODE form. + * + * This method returns the string converted to IDN UNICODE form + * + * @throws SyntaxError if the string can not be converted to UNICODE using IDN UTS46 algorithm + */ + public static function toUnicode(string $domain, int $options): IdnaInfo + { + $domain = rawurldecode($domain); + + if (false === stripos($domain, 'xn--')) { + return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => self::ERROR_NONE]); + } + + self::supportsIdna(); + + /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + idn_to_utf8($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo); + if ([] === $idnaInfo) { + throw IdnaConversionFailed::dueToInvalidHost($domain); + } + + /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */ + return IdnaInfo::fromIntl($idnaInfo); + } + + /** + * Adapted from https://github.com/TRowbotham/idna. + * + * @see https://github.com/TRowbotham/idna/blob/master/src/Idna.php#L236 + */ + private static function validateDomainAndLabelLength(string $domain): int + { + $error = self::ERROR_NONE; + $labels = explode('.', $domain); + $maxDomainSize = self::MAX_DOMAIN_LENGTH; + $length = count($labels); + + // If the last label is empty and it is not the first label, then it is the root label. + // Increase the max size by 1, making it 254, to account for the root label's "." + // delimiter. This also means we don't need to check the last label's length for being too + // long. + if ($length > 1 && $labels[$length - 1] === '') { + ++$maxDomainSize; + array_pop($labels); + } + + if (strlen($domain) > $maxDomainSize) { + $error |= self::ERROR_DOMAIN_NAME_TOO_LONG; + } + + foreach ($labels as $label) { + if (strlen($label) > self::MAX_LABEL_LENGTH) { + $error |= self::ERROR_LABEL_TOO_LONG; + + break; + } + } + + return $error; + } +} diff --git a/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php b/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php new file mode 100644 index 0000000..73610a2 --- /dev/null +++ b/vendor/league/uri-interfaces/src/Idna/IdnaInfo.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace League\Uri\Idna; + +use function array_filter; +use const ARRAY_FILTER_USE_KEY; + +/** + * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html + */ +final class IdnaInfo +{ + private const ERRORS = [ + Idna::ERROR_EMPTY_LABEL => 'a non-final domain name label (or the whole domain name) is empty', + Idna::ERROR_LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', + Idna::ERROR_DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', + Idna::ERROR_LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', + Idna::ERROR_TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', + Idna::ERROR_HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', + Idna::ERROR_LEADING_COMBINING_MARK => 'a label starts with a combining mark', + Idna::ERROR_DISALLOWED => 'a label or domain name contains disallowed characters', + Idna::ERROR_PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', + Idna::ERROR_LABEL_HAS_DOT => 'a label contains a dot=full stop', + Idna::ERROR_INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', + Idna::ERROR_BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', + Idna::ERROR_CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', + Idna::ERROR_CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', + Idna::ERROR_CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts', + ]; + + /** @var string */ + private $result; + + /** @var bool */ + private $isTransitionalDifferent; + + /** @var int */ + private $errors; + + /** + * @var array + */ + private $errorList; + + private function __construct(string $result, bool $isTransitionalDifferent, int $errors) + { + $this->result = $result; + $this->errors = $errors; + $this->isTransitionalDifferent = $isTransitionalDifferent; + $this->errorList = array_filter( + self::ERRORS, + function (int $error): bool { + return 0 !== ($error & $this->errors); + }, + ARRAY_FILTER_USE_KEY + ); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $infos + */ + public static function fromIntl(array $infos): self + { + return new self($infos['result'], $infos['isTransitionalDifferent'], $infos['errors']); + } + + /** + * @param array{result:string, isTransitionalDifferent:bool, errors:int} $properties + */ + public static function __set_state(array $properties): self + { + return self::fromIntl($properties); + } + + public function result(): string + { + return $this->result; + } + + public function isTransitionalDifferent(): bool + { + return $this->isTransitionalDifferent; + } + + public function errors(): int + { + return $this->errors; + } + + public function error(int $error): ?string + { + return $this->errorList[$error] ?? null; + } + + /** + * @return array + */ + public function errorList(): array + { + return $this->errorList; + } +} -- cgit v1.2.3