From b3b1718d621ed6bd6fc445f3472272d38fab11be Mon Sep 17 00:00:00 2001 From: bdnugget <1001337108312v3@gmail.com> Date: Sun, 4 Jan 2026 19:55:27 +0100 Subject: [PATCH] gitignore vendor --- .gitignore | 2 + vendor/autoload.php | 22 - vendor/composer/ClassLoader.php | 579 ----- vendor/composer/InstalledVersions.php | 396 --- vendor/composer/LICENSE | 21 - vendor/composer/autoload_classmap.php | 10 - vendor/composer/autoload_files.php | 10 - vendor/composer/autoload_namespaces.php | 9 - vendor/composer/autoload_psr4.php | 11 - vendor/composer/autoload_real.php | 50 - vendor/composer/autoload_static.php | 45 - vendor/composer/installed.json | 172 -- vendor/composer/installed.php | 41 - vendor/composer/platform_check.php | 25 - .../symfony/http-foundation/AcceptHeader.php | 304 --- .../http-foundation/AcceptHeaderItem.php | 159 -- .../http-foundation/BinaryFileResponse.php | 396 --- vendor/symfony/http-foundation/CHANGELOG.md | 422 ---- .../http-foundation/ChainRequestMatcher.php | 38 - vendor/symfony/http-foundation/Cookie.php | 405 --- .../http-foundation/EventStreamResponse.php | 110 - .../Exception/BadRequestException.php | 19 - .../Exception/ConflictingHeadersException.php | 21 - .../Exception/ExceptionInterface.php | 16 - .../Exception/ExpiredSignedUriException.php | 29 - .../Exception/JsonException.php | 21 - .../Exception/LogicException.php | 19 - .../Exception/RequestExceptionInterface.php | 21 - .../Exception/SessionNotFoundException.php | 27 - .../Exception/SignedUriException.php | 22 - .../SuspiciousOperationException.php | 20 - .../Exception/UnexpectedValueException.php | 16 - .../Exception/UnsignedUriException.php | 26 - .../UnverifiedSignedUriException.php | 26 - .../File/Exception/AccessDeniedException.php | 25 - .../Exception/CannotWriteFileException.php | 21 - .../File/Exception/ExtensionFileException.php | 21 - .../File/Exception/FileException.php | 21 - .../File/Exception/FileNotFoundException.php | 25 - .../File/Exception/FormSizeFileException.php | 21 - .../File/Exception/IniSizeFileException.php | 21 - .../File/Exception/NoFileException.php | 21 - .../File/Exception/NoTmpDirFileException.php | 21 - .../File/Exception/PartialFileException.php | 21 - .../Exception/UnexpectedTypeException.php | 20 - .../File/Exception/UploadException.php | 21 - vendor/symfony/http-foundation/File/File.php | 141 -- .../symfony/http-foundation/File/Stream.php | 25 - .../http-foundation/File/UploadedFile.php | 289 --- vendor/symfony/http-foundation/FileBag.php | 127 - vendor/symfony/http-foundation/HeaderBag.php | 273 -- .../symfony/http-foundation/HeaderUtils.php | 298 --- vendor/symfony/http-foundation/InputBag.php | 152 -- vendor/symfony/http-foundation/IpUtils.php | 270 -- .../symfony/http-foundation/JsonResponse.php | 187 -- vendor/symfony/http-foundation/LICENSE | 19 - .../symfony/http-foundation/ParameterBag.php | 271 -- vendor/symfony/http-foundation/README.md | 14 - .../AbstractRequestRateLimiter.php | 81 - .../PeekableRequestRateLimiterInterface.php | 35 - .../RequestRateLimiterInterface.php | 30 - .../http-foundation/RedirectResponse.php | 92 - vendor/symfony/http-foundation/Request.php | 2214 ----------------- .../AttributesRequestMatcher.php | 45 - .../ExpressionRequestMatcher.php | 43 - .../RequestMatcher/HeaderRequestMatcher.php | 52 - .../RequestMatcher/HostRequestMatcher.php | 32 - .../RequestMatcher/IpsRequestMatcher.php | 44 - .../RequestMatcher/IsJsonRequestMatcher.php | 28 - .../RequestMatcher/MethodRequestMatcher.php | 46 - .../RequestMatcher/PathRequestMatcher.php | 32 - .../RequestMatcher/PortRequestMatcher.php | 32 - .../QueryParameterRequestMatcher.php | 46 - .../RequestMatcher/SchemeRequestMatcher.php | 46 - .../RequestMatcherInterface.php | 25 - .../symfony/http-foundation/RequestStack.php | 124 - vendor/symfony/http-foundation/Response.php | 1322 ---------- .../http-foundation/ResponseHeaderBag.php | 267 -- vendor/symfony/http-foundation/ServerBag.php | 97 - .../symfony/http-foundation/ServerEvent.php | 145 -- .../Session/Attribute/AttributeBag.php | 117 - .../Attribute/AttributeBagInterface.php | 53 - .../Session/Flash/AutoExpireFlashBag.php | 121 - .../Session/Flash/FlashBag.php | 112 - .../Session/Flash/FlashBagInterface.php | 72 - .../Session/FlashBagAwareSessionInterface.php | 22 - .../http-foundation/Session/Session.php | 223 -- .../Session/SessionBagInterface.php | 42 - .../Session/SessionBagProxy.php | 86 - .../Session/SessionFactory.php | 39 - .../Session/SessionFactoryInterface.php | 20 - .../Session/SessionInterface.php | 140 -- .../http-foundation/Session/SessionUtils.php | 59 - .../Handler/AbstractSessionHandler.php | 111 - .../Storage/Handler/IdentityMarshaller.php | 36 - .../Handler/MarshallingSessionHandler.php | 73 - .../Handler/MemcachedSessionHandler.php | 110 - .../Handler/MigratingSessionHandler.php | 100 - .../Storage/Handler/MongoDbSessionHandler.php | 186 -- .../Handler/NativeFileSessionHandler.php | 55 - .../Storage/Handler/NullSessionHandler.php | 55 - .../Storage/Handler/PdoSessionHandler.php | 919 ------- .../Storage/Handler/RedisSessionHandler.php | 103 - .../Storage/Handler/SessionHandlerFactory.php | 97 - .../Storage/Handler/StrictSessionHandler.php | 87 - .../Session/Storage/MetadataBag.php | 131 - .../Storage/MockArraySessionStorage.php | 188 -- .../Storage/MockFileSessionStorage.php | 149 -- .../Storage/MockFileSessionStorageFactory.php | 38 - .../Session/Storage/NativeSessionStorage.php | 389 --- .../Storage/NativeSessionStorageFactory.php | 45 - .../Storage/PhpBridgeSessionStorage.php | 55 - .../PhpBridgeSessionStorageFactory.php | 41 - .../Session/Storage/Proxy/AbstractProxy.php | 98 - .../Storage/Proxy/SessionHandlerProxy.php | 74 - .../SessionStorageFactoryInterface.php | 25 - .../Storage/SessionStorageInterface.php | 116 - .../http-foundation/StreamedJsonResponse.php | 162 -- .../http-foundation/StreamedResponse.php | 150 -- .../Constraint/RequestAttributeValueSame.php | 45 - .../Constraint/ResponseCookieValueSame.php | 70 - .../Test/Constraint/ResponseFormatSame.php | 60 - .../Test/Constraint/ResponseHasCookie.php | 64 - .../Test/Constraint/ResponseHasHeader.php | 44 - .../Constraint/ResponseHeaderLocationSame.php | 65 - .../Test/Constraint/ResponseHeaderSame.php | 45 - .../Test/Constraint/ResponseIsRedirected.php | 54 - .../Test/Constraint/ResponseIsSuccessful.php | 54 - .../Constraint/ResponseIsUnprocessable.php | 54 - .../Constraint/ResponseStatusCodeSame.php | 53 - vendor/symfony/http-foundation/UriSigner.php | 206 -- vendor/symfony/http-foundation/UrlHelper.php | 108 - vendor/symfony/http-foundation/composer.json | 43 - vendor/symfony/polyfill-mbstring/LICENSE | 19 - vendor/symfony/polyfill-mbstring/Mbstring.php | 1045 -------- vendor/symfony/polyfill-mbstring/README.md | 13 - .../Resources/unidata/caseFolding.php | 119 - .../Resources/unidata/lowerCase.php | 1397 ----------- .../Resources/unidata/titleCaseRegexp.php | 5 - .../Resources/unidata/upperCase.php | 1489 ----------- .../symfony/polyfill-mbstring/bootstrap.php | 172 -- .../symfony/polyfill-mbstring/bootstrap80.php | 167 -- .../symfony/polyfill-mbstring/composer.json | 38 - 143 files changed, 2 insertions(+), 20839 deletions(-) create mode 100644 .gitignore delete mode 100644 vendor/autoload.php delete mode 100644 vendor/composer/ClassLoader.php delete mode 100644 vendor/composer/InstalledVersions.php delete mode 100644 vendor/composer/LICENSE delete mode 100644 vendor/composer/autoload_classmap.php delete mode 100644 vendor/composer/autoload_files.php delete mode 100644 vendor/composer/autoload_namespaces.php delete mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/composer/autoload_real.php delete mode 100644 vendor/composer/autoload_static.php delete mode 100644 vendor/composer/installed.json delete mode 100644 vendor/composer/installed.php delete mode 100644 vendor/composer/platform_check.php delete mode 100644 vendor/symfony/http-foundation/AcceptHeader.php delete mode 100644 vendor/symfony/http-foundation/AcceptHeaderItem.php delete mode 100644 vendor/symfony/http-foundation/BinaryFileResponse.php delete mode 100644 vendor/symfony/http-foundation/CHANGELOG.md delete mode 100644 vendor/symfony/http-foundation/ChainRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/Cookie.php delete mode 100644 vendor/symfony/http-foundation/EventStreamResponse.php delete mode 100644 vendor/symfony/http-foundation/Exception/BadRequestException.php delete mode 100644 vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php delete mode 100644 vendor/symfony/http-foundation/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/http-foundation/Exception/ExpiredSignedUriException.php delete mode 100644 vendor/symfony/http-foundation/Exception/JsonException.php delete mode 100644 vendor/symfony/http-foundation/Exception/LogicException.php delete mode 100644 vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php delete mode 100644 vendor/symfony/http-foundation/Exception/SessionNotFoundException.php delete mode 100644 vendor/symfony/http-foundation/Exception/SignedUriException.php delete mode 100644 vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php delete mode 100644 vendor/symfony/http-foundation/Exception/UnexpectedValueException.php delete mode 100644 vendor/symfony/http-foundation/Exception/UnsignedUriException.php delete mode 100644 vendor/symfony/http-foundation/Exception/UnverifiedSignedUriException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/NoFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/PartialFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/UploadException.php delete mode 100644 vendor/symfony/http-foundation/File/File.php delete mode 100644 vendor/symfony/http-foundation/File/Stream.php delete mode 100644 vendor/symfony/http-foundation/File/UploadedFile.php delete mode 100644 vendor/symfony/http-foundation/FileBag.php delete mode 100644 vendor/symfony/http-foundation/HeaderBag.php delete mode 100644 vendor/symfony/http-foundation/HeaderUtils.php delete mode 100644 vendor/symfony/http-foundation/InputBag.php delete mode 100644 vendor/symfony/http-foundation/IpUtils.php delete mode 100644 vendor/symfony/http-foundation/JsonResponse.php delete mode 100644 vendor/symfony/http-foundation/LICENSE delete mode 100644 vendor/symfony/http-foundation/ParameterBag.php delete mode 100644 vendor/symfony/http-foundation/README.md delete mode 100644 vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php delete mode 100644 vendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php delete mode 100644 vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php delete mode 100644 vendor/symfony/http-foundation/RedirectResponse.php delete mode 100644 vendor/symfony/http-foundation/Request.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/HeaderRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/QueryParameterRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcherInterface.php delete mode 100644 vendor/symfony/http-foundation/RequestStack.php delete mode 100644 vendor/symfony/http-foundation/Response.php delete mode 100644 vendor/symfony/http-foundation/ResponseHeaderBag.php delete mode 100644 vendor/symfony/http-foundation/ServerBag.php delete mode 100644 vendor/symfony/http-foundation/ServerEvent.php delete mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/Session.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionBagProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionFactoryInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionUtils.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MetadataBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php delete mode 100644 vendor/symfony/http-foundation/StreamedJsonResponse.php delete mode 100644 vendor/symfony/http-foundation/StreamedResponse.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php delete mode 100644 vendor/symfony/http-foundation/UriSigner.php delete mode 100644 vendor/symfony/http-foundation/UrlHelper.php delete mode 100644 vendor/symfony/http-foundation/composer.json delete mode 100644 vendor/symfony/polyfill-mbstring/LICENSE delete mode 100644 vendor/symfony/polyfill-mbstring/Mbstring.php delete mode 100644 vendor/symfony/polyfill-mbstring/README.md delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php delete mode 100644 vendor/symfony/polyfill-mbstring/bootstrap.php delete mode 100644 vendor/symfony/polyfill-mbstring/bootstrap80.php delete mode 100644 vendor/symfony/polyfill-mbstring/composer.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5650dce --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor + diff --git a/vendor/autoload.php b/vendor/autoload.php deleted file mode 100644 index 31f24a9..0000000 --- a/vendor/autoload.php +++ /dev/null @@ -1,22 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - * @see https://www.php-fig.org/psr/psr-0/ - * @see https://www.php-fig.org/psr/psr-4/ - */ -class ClassLoader -{ - /** @var \Closure(string):void */ - private static $includeFile; - - /** @var string|null */ - private $vendorDir; - - // PSR-4 - /** - * @var array> - */ - private $prefixLengthsPsr4 = array(); - /** - * @var array> - */ - private $prefixDirsPsr4 = array(); - /** - * @var list - */ - private $fallbackDirsPsr4 = array(); - - // PSR-0 - /** - * List of PSR-0 prefixes - * - * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) - * - * @var array>> - */ - private $prefixesPsr0 = array(); - /** - * @var list - */ - private $fallbackDirsPsr0 = array(); - - /** @var bool */ - private $useIncludePath = false; - - /** - * @var array - */ - private $classMap = array(); - - /** @var bool */ - private $classMapAuthoritative = false; - - /** - * @var array - */ - private $missingClasses = array(); - - /** @var string|null */ - private $apcuPrefix; - - /** - * @var array - */ - private static $registeredLoaders = array(); - - /** - * @param string|null $vendorDir - */ - public function __construct($vendorDir = null) - { - $this->vendorDir = $vendorDir; - self::initializeIncludeClosure(); - } - - /** - * @return array> - */ - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); - } - - return array(); - } - - /** - * @return array> - */ - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - /** - * @return list - */ - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - /** - * @return list - */ - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - /** - * @return array Array of classname => path - */ - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param array $classMap Class to filename map - * - * @return void - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param list|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - * - * @return void - */ - public function add($prefix, $paths, $prepend = false) - { - $paths = (array) $paths; - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param list|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - $paths = (array) $paths; - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param list|string $paths The PSR-0 base directories - * - * @return void - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param list|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - * - * @return void - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - * - * @return void - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - * - * @return void - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * APCu prefix to use to cache found/not-found classes, if the extension is enabled. - * - * @param string|null $apcuPrefix - * - * @return void - */ - public function setApcuPrefix($apcuPrefix) - { - $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; - } - - /** - * The APCu prefix in use, or null if APCu caching is not enabled. - * - * @return string|null - */ - public function getApcuPrefix() - { - return $this->apcuPrefix; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - * - * @return void - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - - if (null === $this->vendorDir) { - return; - } - - if ($prepend) { - self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; - } else { - unset(self::$registeredLoaders[$this->vendorDir]); - self::$registeredLoaders[$this->vendorDir] = $this; - } - } - - /** - * Unregisters this instance as an autoloader. - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - - if (null !== $this->vendorDir) { - unset(self::$registeredLoaders[$this->vendorDir]); - } - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return true|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - $includeFile = self::$includeFile; - $includeFile($file); - - return true; - } - - return null; - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { - return false; - } - if (null !== $this->apcuPrefix) { - $file = apcu_fetch($this->apcuPrefix.$class, $hit); - if ($hit) { - return $file; - } - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if (false === $file && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if (null !== $this->apcuPrefix) { - apcu_add($this->apcuPrefix.$class, $file); - } - - if (false === $file) { - // Remember that this class does not exist. - $this->missingClasses[$class] = true; - } - - return $file; - } - - /** - * Returns the currently registered loaders keyed by their corresponding vendor directories. - * - * @return array - */ - public static function getRegisteredLoaders() - { - return self::$registeredLoaders; - } - - /** - * @param string $class - * @param string $ext - * @return string|false - */ - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - $subPath = $class; - while (false !== $lastPos = strrpos($subPath, '\\')) { - $subPath = substr($subPath, 0, $lastPos); - $search = $subPath . '\\'; - if (isset($this->prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); - foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - - return false; - } - - /** - * @return void - */ - private static function initializeIncludeClosure() - { - if (self::$includeFile !== null) { - return; - } - - /** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - */ - self::$includeFile = \Closure::bind(static function($file) { - include $file; - }, null, null); - } -} diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php deleted file mode 100644 index 2052022..0000000 --- a/vendor/composer/InstalledVersions.php +++ /dev/null @@ -1,396 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer; - -use Composer\Autoload\ClassLoader; -use Composer\Semver\VersionParser; - -/** - * This class is copied in every Composer installed project and available to all - * - * See also https://getcomposer.org/doc/07-runtime.md#installed-versions - * - * To require its presence, you can require `composer-runtime-api ^2.0` - * - * @final - */ -class InstalledVersions -{ - /** - * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to - * @internal - */ - private static $selfDir = null; - - /** - * @var mixed[]|null - * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null - */ - private static $installed; - - /** - * @var bool - */ - private static $installedIsLocalDir; - - /** - * @var bool|null - */ - private static $canGetVendors; - - /** - * @var array[] - * @psalm-var array}> - */ - private static $installedByVendor = array(); - - /** - * Returns a list of all package names which are present, either by being installed, replaced or provided - * - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackages() - { - $packages = array(); - foreach (self::getInstalled() as $installed) { - $packages[] = array_keys($installed['versions']); - } - - if (1 === \count($packages)) { - return $packages[0]; - } - - return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); - } - - /** - * Returns a list of all package names with a specific type e.g. 'library' - * - * @param string $type - * @return string[] - * @psalm-return list - */ - public static function getInstalledPackagesByType($type) - { - $packagesByType = array(); - - foreach (self::getInstalled() as $installed) { - foreach ($installed['versions'] as $name => $package) { - if (isset($package['type']) && $package['type'] === $type) { - $packagesByType[] = $name; - } - } - } - - return $packagesByType; - } - - /** - * Checks whether the given package is installed - * - * This also returns true if the package name is provided or replaced by another package - * - * @param string $packageName - * @param bool $includeDevRequirements - * @return bool - */ - public static function isInstalled($packageName, $includeDevRequirements = true) - { - foreach (self::getInstalled() as $installed) { - if (isset($installed['versions'][$packageName])) { - return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; - } - } - - return false; - } - - /** - * Checks whether the given package satisfies a version constraint - * - * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: - * - * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') - * - * @param VersionParser $parser Install composer/semver to have access to this class and functionality - * @param string $packageName - * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package - * @return bool - */ - public static function satisfies(VersionParser $parser, $packageName, $constraint) - { - $constraint = $parser->parseConstraints((string) $constraint); - $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); - - return $provided->matches($constraint); - } - - /** - * Returns a version constraint representing all the range(s) which are installed for a given package - * - * It is easier to use this via isInstalled() with the $constraint argument if you need to check - * whether a given version of a package is installed, and not just whether it exists - * - * @param string $packageName - * @return string Version constraint usable with composer/semver - */ - public static function getVersionRanges($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - $ranges = array(); - if (isset($installed['versions'][$packageName]['pretty_version'])) { - $ranges[] = $installed['versions'][$packageName]['pretty_version']; - } - if (array_key_exists('aliases', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); - } - if (array_key_exists('replaced', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); - } - if (array_key_exists('provided', $installed['versions'][$packageName])) { - $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); - } - - return implode(' || ', $ranges); - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['version'])) { - return null; - } - - return $installed['versions'][$packageName]['version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present - */ - public static function getPrettyVersion($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['pretty_version'])) { - return null; - } - - return $installed['versions'][$packageName]['pretty_version']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference - */ - public static function getReference($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - if (!isset($installed['versions'][$packageName]['reference'])) { - return null; - } - - return $installed['versions'][$packageName]['reference']; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @param string $packageName - * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. - */ - public static function getInstallPath($packageName) - { - foreach (self::getInstalled() as $installed) { - if (!isset($installed['versions'][$packageName])) { - continue; - } - - return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; - } - - throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); - } - - /** - * @return array - * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} - */ - public static function getRootPackage() - { - $installed = self::getInstalled(); - - return $installed[0]['root']; - } - - /** - * Returns the raw installed.php data for custom implementations - * - * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. - * @return array[] - * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} - */ - public static function getRawData() - { - @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - self::$installed = include __DIR__ . '/installed.php'; - } else { - self::$installed = array(); - } - } - - return self::$installed; - } - - /** - * Returns the raw data of all installed.php which are currently loaded for custom implementations - * - * @return array[] - * @psalm-return list}> - */ - public static function getAllRawData() - { - return self::getInstalled(); - } - - /** - * Lets you reload the static array from another file - * - * This is only useful for complex integrations in which a project needs to use - * this class but then also needs to execute another project's autoloader in process, - * and wants to ensure both projects have access to their version of installed.php. - * - * A typical case would be PHPUnit, where it would need to make sure it reads all - * the data it needs from this class, then call reload() with - * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure - * the project in which it runs can then also use this class safely, without - * interference between PHPUnit's dependencies and the project's dependencies. - * - * @param array[] $data A vendor/composer/installed.php data set - * @return void - * - * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data - */ - public static function reload($data) - { - self::$installed = $data; - self::$installedByVendor = array(); - - // when using reload, we disable the duplicate protection to ensure that self::$installed data is - // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, - // so we have to assume it does not, and that may result in duplicate data being returned when listing - // all installed packages for example - self::$installedIsLocalDir = false; - } - - /** - * @return string - */ - private static function getSelfDir() - { - if (self::$selfDir === null) { - self::$selfDir = strtr(__DIR__, '\\', '/'); - } - - return self::$selfDir; - } - - /** - * @return array[] - * @psalm-return list}> - */ - private static function getInstalled() - { - if (null === self::$canGetVendors) { - self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); - } - - $installed = array(); - $copiedLocalDir = false; - - if (self::$canGetVendors) { - $selfDir = self::getSelfDir(); - foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { - $vendorDir = strtr($vendorDir, '\\', '/'); - if (isset(self::$installedByVendor[$vendorDir])) { - $installed[] = self::$installedByVendor[$vendorDir]; - } elseif (is_file($vendorDir.'/composer/installed.php')) { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require $vendorDir.'/composer/installed.php'; - self::$installedByVendor[$vendorDir] = $required; - $installed[] = $required; - if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { - self::$installed = $required; - self::$installedIsLocalDir = true; - } - } - if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { - $copiedLocalDir = true; - } - } - } - - if (null === self::$installed) { - // only require the installed.php file if this file is loaded from its dumped location, - // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 - if (substr(__DIR__, -8, 1) !== 'C') { - /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ - $required = require __DIR__ . '/installed.php'; - self::$installed = $required; - } else { - self::$installed = array(); - } - } - - if (self::$installed !== array() && !$copiedLocalDir) { - $installed[] = self::$installed; - } - - return $installed; - } -} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE deleted file mode 100644 index f27399a..0000000 --- a/vendor/composer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -Copyright (c) Nils Adermann, Jordi Boggiano - -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/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php deleted file mode 100644 index 0fb0a2c..0000000 --- a/vendor/composer/autoload_classmap.php +++ /dev/null @@ -1,10 +0,0 @@ - $vendorDir . '/composer/InstalledVersions.php', -); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php deleted file mode 100644 index ee3a2d6..0000000 --- a/vendor/composer/autoload_files.php +++ /dev/null @@ -1,10 +0,0 @@ - $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', -); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php deleted file mode 100644 index 15a2ff3..0000000 --- a/vendor/composer/autoload_namespaces.php +++ /dev/null @@ -1,9 +0,0 @@ - array($vendorDir . '/symfony/polyfill-mbstring'), - 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), -); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php deleted file mode 100644 index 0ab77ad..0000000 --- a/vendor/composer/autoload_real.php +++ /dev/null @@ -1,50 +0,0 @@ -register(true); - - $filesToLoad = \Composer\Autoload\ComposerStaticInitefde9833fcaa12ff1811e00a7a077255::$files; - $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - - require $file; - } - }, null, null); - foreach ($filesToLoad as $fileIdentifier => $file) { - $requireFile($fileIdentifier, $file); - } - - return $loader; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php deleted file mode 100644 index 4e0d6be..0000000 --- a/vendor/composer/autoload_static.php +++ /dev/null @@ -1,45 +0,0 @@ - __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', - ); - - public static $prefixLengthsPsr4 = array ( - 'S' => - array ( - 'Symfony\\Polyfill\\Mbstring\\' => 26, - 'Symfony\\Component\\HttpFoundation\\' => 33, - ), - ); - - public static $prefixDirsPsr4 = array ( - 'Symfony\\Polyfill\\Mbstring\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', - ), - 'Symfony\\Component\\HttpFoundation\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/http-foundation', - ), - ); - - public static $classMap = array ( - 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', - ); - - public static function getInitializer(ClassLoader $loader) - { - return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitefde9833fcaa12ff1811e00a7a077255::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitefde9833fcaa12ff1811e00a7a077255::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitefde9833fcaa12ff1811e00a7a077255::$classMap; - - }, null, ClassLoader::class); - } -} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json deleted file mode 100644 index 90ae758..0000000 --- a/vendor/composer/installed.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "packages": [ - { - "name": "symfony/http-foundation", - "version": "v8.0.3", - "version_normalized": "8.0.3.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "514ec3aa7982f296b0ad0825f75b6be5779ae9e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/514ec3aa7982f296b0ad0825f75b6be5779ae9e7", - "reference": "514ec3aa7982f296b0ad0825f75b6be5779ae9e7", - "shasum": "" - }, - "require": { - "php": ">=8.4", - "symfony/polyfill-mbstring": "^1.1" - }, - "conflict": { - "doctrine/dbal": "<4.3" - }, - "require-dev": { - "doctrine/dbal": "^4.3", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^7.4|^8.0", - "symfony/clock": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/mime": "^7.4|^8.0", - "symfony/rate-limiter": "^7.4|^8.0" - }, - "time": "2025-12-23T14:52:06+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Defines an object-oriented layer for the HTTP specification", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/http-foundation/tree/v8.0.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/http-foundation" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2024-09-09T11:45:10+00:00", - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-mbstring" - } - ], - "dev": true, - "dev-package-names": [] -} diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php deleted file mode 100644 index 2a8263b..0000000 --- a/vendor/composer/installed.php +++ /dev/null @@ -1,41 +0,0 @@ - array( - 'name' => '__root__', - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '24b4960fc8f133d1fb2527058501884ee3391395', - 'type' => 'library', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'dev' => true, - ), - 'versions' => array( - '__root__' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '24b4960fc8f133d1fb2527058501884ee3391395', - 'type' => 'library', - 'install_path' => __DIR__ . '/../../', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/http-foundation' => array( - 'pretty_version' => 'v8.0.3', - 'version' => '8.0.3.0', - 'reference' => '514ec3aa7982f296b0ad0825f75b6be5779ae9e7', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/http-foundation', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', - 'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', - 'aliases' => array(), - 'dev_requirement' => false, - ), - ), -); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php deleted file mode 100644 index 5ece5bc..0000000 --- a/vendor/composer/platform_check.php +++ /dev/null @@ -1,25 +0,0 @@ -= 80400)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 8.4.0". You are running ' . PHP_VERSION . '.'; -} - -if ($issues) { - if (!headers_sent()) { - header('HTTP/1.1 500 Internal Server Error'); - } - if (!ini_get('display_errors')) { - if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { - fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); - } elseif (!headers_sent()) { - echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; - } - } - throw new \RuntimeException( - 'Composer detected issues in your platform: ' . implode(' ', $issues) - ); -} diff --git a/vendor/symfony/http-foundation/AcceptHeader.php b/vendor/symfony/http-foundation/AcceptHeader.php deleted file mode 100644 index e735c75..0000000 --- a/vendor/symfony/http-foundation/AcceptHeader.php +++ /dev/null @@ -1,304 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeaderItem::class); - -/** - * Represents an Accept-* header. - * - * An accept header is compound with a list of items, - * sorted by descending quality. - * - * @author Jean-François Simon - */ -class AcceptHeader -{ - /** - * @var array - */ - private array $items = []; - - private bool $sorted = true; - - /** - * @param AcceptHeaderItem[] $items - */ - public function __construct(array $items) - { - foreach ($items as $item) { - $this->add($item); - } - } - - /** - * Builds an AcceptHeader instance from a string. - */ - public static function fromString(?string $headerValue): self - { - $items = []; - foreach (HeaderUtils::split($headerValue ?? '', ',;=') as $i => $parts) { - $part = array_shift($parts); - $item = new AcceptHeaderItem($part[0], HeaderUtils::combine($parts)); - - $items[] = $item->setIndex($i); - } - - return new self($items); - } - - /** - * Returns header value's string representation. - */ - public function __toString(): string - { - return implode(',', $this->items); - } - - /** - * Tests if header has given value. - */ - public function has(string $value): bool - { - $canonicalKey = $this->getCanonicalKey(AcceptHeaderItem::fromString($value)); - - return isset($this->items[$canonicalKey]); - } - - /** - * Returns given value's item, if exists. - */ - public function get(string $value): ?AcceptHeaderItem - { - $queryItem = AcceptHeaderItem::fromString($value.';q=1'); - $canonicalKey = $this->getCanonicalKey($queryItem); - - if (isset($this->items[$canonicalKey])) { - return $this->items[$canonicalKey]; - } - - // Collect and filter matching candidates - if (!$candidates = array_filter($this->items, fn (AcceptHeaderItem $item) => $this->matches($item, $queryItem))) { - return null; - } - - usort( - $candidates, - fn ($a, $b) => $this->getSpecificity($b, $queryItem) <=> $this->getSpecificity($a, $queryItem) // Descending specificity - ?: $b->getQuality() <=> $a->getQuality() // Descending quality - ?: $a->getIndex() <=> $b->getIndex() // Ascending index (stability) - ); - - return reset($candidates); - } - - /** - * Adds an item. - * - * @return $this - */ - public function add(AcceptHeaderItem $item): static - { - $this->items[$this->getCanonicalKey($item)] = $item; - $this->sorted = false; - - return $this; - } - - /** - * Returns all items. - * - * @return AcceptHeaderItem[] - */ - public function all(): array - { - $this->sort(); - - return $this->items; - } - - /** - * Filters items on their value using given regex. - */ - public function filter(string $pattern): self - { - return new self(array_filter($this->items, static fn ($item) => preg_match($pattern, $item->getValue()))); - } - - /** - * Returns first item. - */ - public function first(): ?AcceptHeaderItem - { - $this->sort(); - - return $this->items ? reset($this->items) : null; - } - - /** - * Sorts items by descending quality. - */ - private function sort(): void - { - if (!$this->sorted) { - uasort($this->items, static fn ($a, $b) => $b->getQuality() <=> $a->getQuality() ?: $a->getIndex() <=> $b->getIndex()); - - $this->sorted = true; - } - } - - /** - * Generates the canonical key for storing/retrieving an item. - */ - private function getCanonicalKey(AcceptHeaderItem $item): string - { - $parts = []; - - // Normalize and sort attributes for consistent key generation - $attributes = $this->getMediaParams($item); - ksort($attributes); - - foreach ($attributes as $name => $value) { - if (null === $value) { - $parts[] = $name; // Flag parameter (e.g., "flowed") - continue; - } - - // Quote values containing spaces, commas, semicolons, or equals per RFC 9110 - // This handles cases like 'format="value with space"' or similar. - $quotedValue = \is_string($value) && preg_match('/[\s;,=]/', $value) ? '"'.addcslashes($value, '"\\').'"' : $value; - - $parts[] = $name.'='.$quotedValue; - } - - return $item->getValue().($parts ? ';'.implode(';', $parts) : ''); - } - - /** - * Checks if a given header item (range) matches a queried item (value). - * - * @param AcceptHeaderItem $rangeItem The item from the Accept header (e.g., text/*;format=flowed) - * @param AcceptHeaderItem $queryItem The item being queried (e.g., text/plain;format=flowed;charset=utf-8) - */ - private function matches(AcceptHeaderItem $rangeItem, AcceptHeaderItem $queryItem): bool - { - $rangeValue = strtolower($rangeItem->getValue()); - $queryValue = strtolower($queryItem->getValue()); - - // Handle universal wildcard ranges - if ('*' === $rangeValue || '*/*' === $rangeValue) { - return $this->rangeParametersMatch($rangeItem, $queryItem); - } - - // Queries for '*' only match wildcard ranges (handled above) - if ('*' === $queryValue) { - return false; - } - - // Ensure media vs. non-media consistency - $isQueryMedia = str_contains($queryValue, '/'); - $isRangeMedia = str_contains($rangeValue, '/'); - - if ($isQueryMedia !== $isRangeMedia) { - return false; - } - - // Non-media: exact match only (wildcards handled above) - if (!$isQueryMedia) { - return $rangeValue === $queryValue && $this->rangeParametersMatch($rangeItem, $queryItem); - } - - // Media type: type/subtype with wildcards - [$queryType, $querySubtype] = explode('/', $queryValue, 2); - [$rangeType, $rangeSubtype] = explode('/', $rangeValue, 2) + [1 => '*']; - - if ('*' !== $rangeType && $rangeType !== $queryType) { - return false; - } - - if ('*' !== $rangeSubtype && $rangeSubtype !== $querySubtype) { - return false; - } - - // Parameters must match - return $this->rangeParametersMatch($rangeItem, $queryItem); - } - - /** - * Checks if the parameters of a range item are satisfied by the query item. - * - * Parameters are case-insensitive; range params must be a subset of query params. - */ - private function rangeParametersMatch(AcceptHeaderItem $rangeItem, AcceptHeaderItem $queryItem): bool - { - $queryAttributes = $this->getMediaParams($queryItem); - $rangeAttributes = $this->getMediaParams($rangeItem); - - foreach ($rangeAttributes as $name => $rangeValue) { - if (!\array_key_exists($name, $queryAttributes)) { - return false; // Missing required param - } - - $queryValue = $queryAttributes[$name]; - - if (null === $rangeValue) { - return null === $queryValue; // Both flags or neither - } - - if (null === $queryValue || strtolower($queryValue) !== strtolower($rangeValue)) { - return false; - } - } - - return true; - } - - /** - * Calculates a specificity score for sorting: media precision + param count. - */ - private function getSpecificity(AcceptHeaderItem $item, AcceptHeaderItem $queryItem): int - { - $rangeValue = strtolower($item->getValue()); - $queryValue = strtolower($queryItem->getValue()); - - $paramCount = \count($this->getMediaParams($item)); - - $isQueryMedia = str_contains($queryValue, '/'); - $isRangeMedia = str_contains($rangeValue, '/'); - - if (!$isQueryMedia && !$isRangeMedia) { - return ('*' !== $rangeValue ? 2000 : 1000) + $paramCount; - } - - [$rangeType, $rangeSubtype] = explode('/', $rangeValue, 2) + [1 => '*']; - - $specificity = match (true) { - '*' !== $rangeSubtype => 3000, // Exact subtype (text/plain) - '*' !== $rangeType => 2000, // Type wildcard (text/*) - default => 1000, // Full wildcard (*/* or *) - }; - - return $specificity + $paramCount; - } - - /** - * Returns normalized attributes: keys lowercased, excluding 'q'. - */ - private function getMediaParams(AcceptHeaderItem $item): array - { - $attributes = array_change_key_case($item->getAttributes(), \CASE_LOWER); - unset($attributes['q']); - - return $attributes; - } -} diff --git a/vendor/symfony/http-foundation/AcceptHeaderItem.php b/vendor/symfony/http-foundation/AcceptHeaderItem.php deleted file mode 100644 index b8b2b8a..0000000 --- a/vendor/symfony/http-foundation/AcceptHeaderItem.php +++ /dev/null @@ -1,159 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents an Accept-* header item. - * - * @author Jean-François Simon - */ -class AcceptHeaderItem -{ - private float $quality = 1.0; - private int $index = 0; - private array $attributes = []; - - public function __construct( - private string $value, - array $attributes = [], - ) { - foreach ($attributes as $name => $value) { - $this->setAttribute($name, $value); - } - } - - /** - * Builds an AcceptHeaderInstance instance from a string. - */ - public static function fromString(?string $itemValue): self - { - $parts = HeaderUtils::split($itemValue ?? '', ';='); - - $part = array_shift($parts); - $attributes = HeaderUtils::combine($parts); - - return new self($part[0], $attributes); - } - - /** - * Returns header value's string representation. - */ - public function __toString(): string - { - $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); - if (\count($this->attributes) > 0) { - $string .= '; '.HeaderUtils::toString($this->attributes, ';'); - } - - return $string; - } - - /** - * Set the item value. - * - * @return $this - */ - public function setValue(string $value): static - { - $this->value = $value; - - return $this; - } - - /** - * Returns the item value. - */ - public function getValue(): string - { - return $this->value; - } - - /** - * Set the item quality. - * - * @return $this - */ - public function setQuality(float $quality): static - { - $this->quality = $quality; - - return $this; - } - - /** - * Returns the item quality. - */ - public function getQuality(): float - { - return $this->quality; - } - - /** - * Set the item index. - * - * @return $this - */ - public function setIndex(int $index): static - { - $this->index = $index; - - return $this; - } - - /** - * Returns the item index. - */ - public function getIndex(): int - { - return $this->index; - } - - /** - * Tests if an attribute exists. - */ - public function hasAttribute(string $name): bool - { - return isset($this->attributes[$name]); - } - - /** - * Returns an attribute by its name. - */ - public function getAttribute(string $name, mixed $default = null): mixed - { - return $this->attributes[$name] ?? $default; - } - - /** - * Returns all attributes. - */ - public function getAttributes(): array - { - return $this->attributes; - } - - /** - * Set an attribute. - * - * @return $this - */ - public function setAttribute(string $name, string $value): static - { - if ('q' === $name) { - $this->quality = (float) $value; - } else { - $this->attributes[$name] = $value; - } - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php deleted file mode 100644 index 6a6679e..0000000 --- a/vendor/symfony/http-foundation/BinaryFileResponse.php +++ /dev/null @@ -1,396 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\File; - -/** - * BinaryFileResponse represents an HTTP response delivering a file. - * - * @author Niklas Fiekas - * @author stealth35 - * @author Igor Wiedler - * @author Jordan Alliot - * @author Sergey Linnik - */ -class BinaryFileResponse extends Response -{ - protected static bool $trustXSendfileTypeHeader = false; - - protected File $file; - protected ?\SplTempFileObject $tempFileObject = null; - protected int $offset = 0; - protected int $maxlen = -1; - protected bool $deleteFileAfterSend = false; - protected int $chunkSize = 16 * 1024; - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code (200 "OK" by default) - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - */ - public function __construct(\SplFileInfo|string $file, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - parent::__construct(null, $status, $headers); - - $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); - - if ($public) { - $this->setPublic(); - } - } - - /** - * Sets the file to stream. - * - * @return $this - * - * @throws FileException - */ - public function setFile(\SplFileInfo|string $file, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true): static - { - $isTemporaryFile = $file instanceof \SplTempFileObject; - $this->tempFileObject = $isTemporaryFile ? $file : null; - - if (!$file instanceof File) { - if ($file instanceof \SplFileInfo) { - $file = new File($file->getPathname(), !$isTemporaryFile); - } else { - $file = new File($file); - } - } - - if (!$file->isReadable() && !$isTemporaryFile) { - throw new FileException('File must be readable.'); - } - - $this->file = $file; - - if ($autoEtag) { - $this->setAutoEtag(); - } - - if ($autoLastModified && !$isTemporaryFile) { - $this->setAutoLastModified(); - } - - if ($contentDisposition) { - $this->setContentDisposition($contentDisposition); - } - - return $this; - } - - /** - * Gets the file. - */ - public function getFile(): File - { - return $this->file; - } - - /** - * Sets the response stream chunk size. - * - * @return $this - */ - public function setChunkSize(int $chunkSize): static - { - if ($chunkSize < 1) { - throw new \InvalidArgumentException('The chunk size of a BinaryFileResponse cannot be less than 1.'); - } - - $this->chunkSize = $chunkSize; - - return $this; - } - - /** - * Automatically sets the Last-Modified header according the file modification date. - * - * @return $this - */ - public function setAutoLastModified(): static - { - $this->setLastModified(\DateTimeImmutable::createFromFormat('U', $this->tempFileObject ? time() : $this->file->getMTime())); - - return $this; - } - - /** - * Automatically sets the ETag header according to the checksum of the file. - * - * @return $this - */ - public function setAutoEtag(): static - { - $this->setEtag(base64_encode(hash_file('xxh128', $this->file->getPathname(), true))); - - return $this; - } - - /** - * Sets the Content-Disposition header with the given filename. - * - * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT - * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file - * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename - * - * @return $this - */ - public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = ''): static - { - if ('' === $filename) { - $filename = $this->file->getFilename(); - } - - if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || str_contains($filename, '%'))) { - $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; - - for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { - $char = mb_substr($filename, $i, 1, $encoding); - - if ('%' === $char || \ord($char[0]) < 32 || \ord($char[0]) > 126) { - $filenameFallback .= '_'; - } else { - $filenameFallback .= $char; - } - } - } - - $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); - $this->headers->set('Content-Disposition', $dispositionHeader); - - return $this; - } - - public function prepare(Request $request): static - { - if ($this->isInformational() || $this->isEmpty()) { - parent::prepare($request); - - $this->maxlen = 0; - - return $this; - } - - if (!$this->headers->has('Content-Type')) { - $mimeType = null; - if (!$this->tempFileObject) { - $mimeType = $this->file->getMimeType(); - } - - $this->headers->set('Content-Type', $mimeType ?: 'application/octet-stream'); - } - - parent::prepare($request); - - $this->offset = 0; - $this->maxlen = -1; - - if ($this->tempFileObject) { - $fileSize = $this->tempFileObject->fstat()['size']; - } elseif (false === $fileSize = $this->file->getSize()) { - return $this; - } - $this->headers->remove('Transfer-Encoding'); - $this->headers->set('Content-Length', $fileSize); - - if (!$this->headers->has('Accept-Ranges')) { - // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); - } - - if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { - // Use X-Sendfile, do not send any content. - $type = $request->headers->get('X-Sendfile-Type'); - $path = $this->file->getRealPath(); - // Fall back to scheme://path for stream wrapped locations. - if (false === $path) { - $path = $this->file->getPathname(); - } - if ('x-accel-redirect' === strtolower($type)) { - // Do X-Accel-Mapping substitutions. - // @link https://github.com/rack/rack/blob/main/lib/rack/sendfile.rb - // @link https://mattbrictson.com/blog/accelerated-rails-downloads - if (!$request->headers->has('X-Accel-Mapping')) { - throw new \LogicException('The "X-Accel-Mapping" header must be set when "X-Sendfile-Type" is set to "X-Accel-Redirect".'); - } - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping'), ',='); - foreach ($parts as $part) { - [$pathPrefix, $location] = $part; - if (str_starts_with($path, $pathPrefix)) { - $path = $location.substr($path, \strlen($pathPrefix)); - // Only set X-Accel-Redirect header if a valid URI can be produced - // as nginx does not serve arbitrary file paths. - $this->headers->set($type, rawurlencode($path)); - $this->maxlen = 0; - break; - } - } - } else { - $this->headers->set($type, $path); - $this->maxlen = 0; - } - } elseif ($request->headers->has('Range') && $request->isMethod('GET')) { - // Process the range headers. - if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { - $range = $request->headers->get('Range'); - - if (str_starts_with($range, 'bytes=')) { - [$start, $end] = explode('-', substr($range, 6), 2) + [1 => 0]; - - $end = ('' === $end) ? $fileSize - 1 : (int) $end; - - if ('' === $start) { - $start = $fileSize - $end; - $end = $fileSize - 1; - } else { - $start = (int) $start; - } - - if ($start <= $end) { - $end = min($end, $fileSize - 1); - if ($start < 0 || $start > $end) { - $this->setStatusCode(416); - $this->headers->set('Content-Range', \sprintf('bytes */%s', $fileSize)); - } elseif ($end - $start < $fileSize - 1) { - $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; - $this->offset = $start; - - $this->setStatusCode(206); - $this->headers->set('Content-Range', \sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); - $this->headers->set('Content-Length', $end - $start + 1); - } - } - } - } - } - - if ($request->isMethod('HEAD')) { - $this->maxlen = 0; - } - - return $this; - } - - private function hasValidIfRangeHeader(?string $header): bool - { - if ($this->getEtag() === $header) { - return true; - } - - if (null === $lastModified = $this->getLastModified()) { - return false; - } - - return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; - } - - public function sendContent(): static - { - try { - if (!$this->isSuccessful()) { - return $this; - } - - if (0 === $this->maxlen) { - return $this; - } - - $out = fopen('php://output', 'w'); - - if ($this->tempFileObject) { - $file = $this->tempFileObject; - $file->rewind(); - } else { - $file = new \SplFileObject($this->file->getPathname(), 'r'); - } - - ignore_user_abort(true); - - if (0 !== $this->offset) { - $file->fseek($this->offset); - } - - $length = $this->maxlen; - while ($length && !$file->eof()) { - $read = $length > $this->chunkSize || 0 > $length ? $this->chunkSize : $length; - - if (false === $data = $file->fread($read)) { - break; - } - while ('' !== $data) { - $read = fwrite($out, $data); - if (false === $read || connection_aborted()) { - break 2; - } - if (0 < $length) { - $length -= $read; - } - $data = substr($data, $read); - } - } - - fclose($out); - } finally { - if (null === $this->tempFileObject && $this->deleteFileAfterSend && is_file($this->file->getPathname())) { - unlink($this->file->getPathname()); - } - } - - return $this; - } - - /** - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content): static - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); - } - - return $this; - } - - public function getContent(): string|false - { - return false; - } - - /** - * Trust X-Sendfile-Type header. - */ - public static function trustXSendfileTypeHeader(): void - { - self::$trustXSendfileTypeHeader = true; - } - - /** - * If this is set to true, the file will be unlinked after the request is sent - * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. - * - * @return $this - */ - public function deleteFileAfterSend(bool $shouldDelete = true): static - { - $this->deleteFileAfterSend = $shouldDelete; - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/CHANGELOG.md b/vendor/symfony/http-foundation/CHANGELOG.md deleted file mode 100644 index 4fc5cbf..0000000 --- a/vendor/symfony/http-foundation/CHANGELOG.md +++ /dev/null @@ -1,422 +0,0 @@ -CHANGELOG -========= - -8.0 ---- - - * Drop HTTP method override support for methods GET, HEAD, CONNECT and TRACE - * Add argument `$subtypeFallback` to `Request::getFormat()` - * Remove the following deprecated session options from `NativeSessionStorage`: `referer_check`, `use_only_cookies`, `use_trans_sid`, `sid_length`, `sid_bits_per_character`, `trans_sid_hosts`, `trans_sid_tags` - * Trigger PHP warning when using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead - * Add arguments `$v4Bytes` and `$v6Bytes` to `IpUtils::anonymize()` - * Add argument `$partitioned` to `ResponseHeaderBag::clearCookie()` - * Add argument `$expiration` to `UriSigner::sign()` - * Remove `Request::get()`, use properties `->attributes`, `query` or `request` directly instead - * Remove accepting null `$format` argument to `Request::setFormat()` - -7.4 ---- - - * Add `#[WithHttpStatus]` to define status codes: 404 for `SignedUriException` and 403 for `ExpiredSignedUriException` - * Add support for the `QUERY` HTTP method - * Add support for structured MIME suffix - * Add `Request::set/getAllowedHttpMethodOverride()` to list which HTTP methods can be overridden - * Deprecate using `Request::sendHeaders()` after headers have already been sent; use a `StreamedResponse` instead - * Deprecate method `Request::get()`, use properties `->attributes`, `query` or `request` directly instead - * Make `Request::createFromGlobals()` parse the body of PUT, DELETE, PATCH and QUERY requests - * Deprecate HTTP method override for methods GET, HEAD, CONNECT and TRACE; it will be ignored in Symfony 8.0 - * Deprecate accepting null `$format` argument to `Request::setFormat()` - -7.3 ---- - - * Add support for iterable of string in `StreamedResponse` - * Add `EventStreamResponse` and `ServerEvent` classes to streamline server event streaming - * Add support for `valkey:` / `valkeys:` schemes for sessions - * `Request::getPreferredLanguage()` now favors a more preferred language above exactly matching a locale - * Allow `UriSigner` to use a `ClockInterface` - * Add `UriSigner::verify()` - -7.2 ---- - - * Add optional `$requests` parameter to `RequestStack::__construct()` - * Add optional `$v4Bytes` and `$v6Bytes` parameters to `IpUtils::anonymize()` - * Add `PRIVATE_SUBNETS` as a shortcut for private IP address ranges to `Request::setTrustedProxies()` - * Deprecate passing `referer_check`, `use_only_cookies`, `use_trans_sid`, `trans_sid_hosts`, `trans_sid_tags`, `sid_bits_per_character` and `sid_length` options to `NativeSessionStorage` - -7.1 ---- - - * Add optional `$expirationParameter` argument to `UriSigner::__construct()` - * Add optional `$expiration` argument to `UriSigner::sign()` - * Rename `$parameter` argument of `UriSigner::__construct()` to `$hashParameter` - * Add `UploadedFile::getClientOriginalPath()` - * Add `QueryParameterRequestMatcher` - * Add `HeaderRequestMatcher` - * Add support for `\SplTempFileObject` in `BinaryFileResponse` - * Add `verbose` argument to response test constraints - -7.0 ---- - - * Calling `ParameterBag::filter()` throws an `UnexpectedValueException` on invalid value, unless flag `FILTER_NULL_ON_FAILURE` is set - * Calling `ParameterBag::getInt()` and `ParameterBag::getBool()` throws an `UnexpectedValueException` on invalid value - * Remove classes `RequestMatcher` and `ExpressionRequestMatcher` - * Remove `Request::getContentType()`, use `Request::getContentTypeFormat()` instead - * Throw an `InvalidArgumentException` when calling `Request::create()` with a malformed URI - * Require explicit argument when calling `JsonResponse::setCallback()`, `Response::setExpires/setLastModified/setEtag()`, `MockArraySessionStorage/NativeSessionStorage::setMetadataBag()`, `NativeSessionStorage::setSaveHandler()` - * Add argument `$statusCode` to `Response::sendHeaders()` and `StreamedResponse::sendHeaders()` - -6.4 ---- - - * Make `HeaderBag::getDate()`, `Response::getDate()`, `getExpires()` and `getLastModified()` return a `DateTimeImmutable` - * Support root-level `Generator` in `StreamedJsonResponse` - * Add `UriSigner` from the HttpKernel component - * Add `partitioned` flag to `Cookie` (CHIPS Cookie) - * Add argument `bool $flush = true` to `Response::send()` - * Make `MongoDbSessionHandler` instantiable with the mongodb extension directly - -6.3 ---- - - * Calling `ParameterBag::getDigit()`, `getAlnum()`, `getAlpha()` on an `array` throws a `UnexpectedValueException` instead of a `TypeError` - * Add `ParameterBag::getString()` to convert a parameter into string and throw an exception if the value is invalid - * Add `ParameterBag::getEnum()` - * Create migration for session table when pdo handler is used - * Add support for Relay PHP extension for Redis - * The `Response::sendHeaders()` method now takes an optional HTTP status code as parameter, allowing to send informational responses such as Early Hints responses (103 status code) - * Add `IpUtils::isPrivateIp()` - * Add `Request::getPayload(): InputBag` - * Deprecate conversion of invalid values in `ParameterBag::getInt()` and `ParameterBag::getBoolean()`, - * Deprecate ignoring invalid values when using `ParameterBag::filter()`, unless flag `FILTER_NULL_ON_FAILURE` is set - -6.2 ---- - - * Add `StreamedJsonResponse` class for efficient JSON streaming - * The HTTP cache store uses the `xxh128` algorithm - * Deprecate calling `JsonResponse::setCallback()`, `Response::setExpires/setLastModified/setEtag()`, `MockArraySessionStorage/NativeSessionStorage::setMetadataBag()`, `NativeSessionStorage::setSaveHandler()` without arguments - * Add request matchers under the `Symfony\Component\HttpFoundation\RequestMatcher` namespace - * Deprecate `RequestMatcher` in favor of `ChainRequestMatcher` - * Deprecate `Symfony\Component\HttpFoundation\ExpressionRequestMatcher` in favor of `Symfony\Component\HttpFoundation\RequestMatcher\ExpressionRequestMatcher` - -6.1 ---- - - * Add stale while revalidate and stale if error cache header - * Allow dynamic session "ttl" when using a remote storage - * Deprecate `Request::getContentType()`, use `Request::getContentTypeFormat()` instead - -6.0 ---- - - * Remove the `NamespacedAttributeBag` class - * Removed `Response::create()`, `JsonResponse::create()`, - `RedirectResponse::create()`, `StreamedResponse::create()` and - `BinaryFileResponse::create()` methods (use `__construct()` instead) - * Not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()` throws an `\InvalidArgumentException`; wrap your filter in a closure instead - * Not passing a `Closure` together with `FILTER_CALLBACK` to `InputBag::filter()` throws an `\InvalidArgumentException`; wrap your filter in a closure instead - * Removed the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead - * Rename `RequestStack::getMasterRequest()` to `getMainRequest()` - * Not passing `FILTER_REQUIRE_ARRAY` or `FILTER_FORCE_ARRAY` flags to `InputBag::filter()` when filtering an array will throw `BadRequestException` - * Removed the `Request::HEADER_X_FORWARDED_ALL` constant - * Retrieving non-scalar values using `InputBag::get()` will throw `BadRequestException` (use `InputBad::all()` instead to retrieve an array) - * Passing non-scalar default value as the second argument `InputBag::get()` will throw `\InvalidArgumentException` - * Passing non-scalar, non-array value as the second argument `InputBag::set()` will throw `\InvalidArgumentException` - * Passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()` is not supported anymore. - -5.4 ---- - - * Deprecate passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()`, pass an empty string instead. - * Add the `litespeed_finish_request` method to work with Litespeed - * Deprecate `upload_progress.*` and `url_rewriter.tags` session options - * Allow setting session options via DSN - -5.3 ---- - - * Add the `SessionFactory`, `NativeSessionStorageFactory`, `PhpBridgeSessionStorageFactory` and `MockFileSessionStorageFactory` classes - * Calling `Request::getSession()` when there is no available session throws a `SessionNotFoundException` - * Add the `RequestStack::getSession` method - * Deprecate the `NamespacedAttributeBag` class - * Add `ResponseFormatSame` PHPUnit constraint - * Deprecate the `RequestStack::getMasterRequest()` method and add `getMainRequest()` as replacement - -5.2.0 ------ - - * added support for `X-Forwarded-Prefix` header - * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names - * added `File::getContent()` - * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` - * added `Request::toArray()` to parse a JSON request body to an array - * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter` - * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. - * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead. - * Deprecated `BinaryFileResponse::create()`, use `__construct()` instead - -5.1.0 ------ - - * added `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpires`, - `Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`, - `Cookie::withRaw`, `Cookie::withSameSite` - * Deprecate `Response::create()`, `JsonResponse::create()`, - `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use - `__construct()` instead) - * added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference - according to [RFC 8674](https://tools.ietf.org/html/rfc8674) - * made the Mime component an optional dependency - * added `MarshallingSessionHandler`, `IdentityMarshaller` - * made `Session` accept a callback to report when the session is being used - * Add support for all core cache control directives - * Added `Symfony\Component\HttpFoundation\InputBag` - * Deprecated retrieving non-string values using `InputBag::get()`, use `InputBag::all()` if you need access to the collection of values - -5.0.0 ------ - - * made `Cookie` auto-secure and lax by default - * removed classes in the `MimeType` namespace, use the Symfony Mime component instead - * removed method `UploadedFile::getClientSize()` and the related constructor argument - * made `Request::getSession()` throw if the session has not been set before - * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` - * passing a null url when instantiating a `RedirectResponse` is not allowed - -4.4.0 ------ - - * passing arguments to `Request::isMethodSafe()` is deprecated. - * `ApacheRequest` is deprecated, use the `Request` class instead. - * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead - * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, - make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to - update your database. - * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, - make sure to run `CREATE INDEX expiry ON sessions (sess_lifetime)` to update your database - to speed up garbage collection of expired sessions. - * added `SessionHandlerFactory` to create session handlers with a DSN - * added `IpUtils::anonymize()` to help with GDPR compliance. - -4.3.0 ------ - - * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, - `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` - * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. - * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. - * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. - * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. - * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path - -4.2.0 ------ - - * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor - will respectively change from "false" to "null" and from "null" to "lax" in Symfony - 5.0, you should define their values explicitly or use "Cookie::create()" instead. - * added `matchPort()` in RequestMatcher - -4.1.3 ------ - - * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` - HTTP headers has been dropped for security reasons. - -4.1.0 ------ - - * Query string normalization uses `parse_str()` instead of custom parsing logic. - * Passing the file size to the constructor of the `UploadedFile` class is deprecated. - * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. - * added `RedisSessionHandler` to use Redis as a session storage - * The `get()` method of the `AcceptHeader` class now takes into account the - `*` and `*/*` default values (if they are present in the Accept HTTP header) - when looking for items. - * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. - * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, - `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to - handle failed `UploadedFile`. - * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions - * added `HeaderUtils`. - -4.0.0 ------ - - * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` - methods have been removed - * the `Request::HEADER_CLIENT_IP` constant has been removed, use - `Request::HEADER_X_FORWARDED_FOR` instead - * the `Request::HEADER_CLIENT_HOST` constant has been removed, use - `Request::HEADER_X_FORWARDED_HOST` instead - * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use - `Request::HEADER_X_FORWARDED_PROTO` instead - * the `Request::HEADER_CLIENT_PORT` constant has been removed, use - `Request::HEADER_X_FORWARDED_PORT` instead - * checking for cacheable HTTP methods using the `Request::isMethodSafe()` - method (by not passing `false` as its argument) is not supported anymore and - throws a `\BadMethodCallException` - * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed - * setting session save handlers that do not implement `\SessionHandlerInterface` in - `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a - `\TypeError` - -3.4.0 ------ - - * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new - `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper - * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes - * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` - * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead - * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead - -3.3.0 ------ - - * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, - see https://symfony.com/doc/current/deployment/proxies.html for more info, - * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, - * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, - disabling `Range` and `Content-Length` handling, switching to chunked encoding instead - * added the `Cookie::fromString()` method that allows to create a cookie from a - raw header string - -3.1.0 ------ - - * Added support for creating `JsonResponse` with a string of JSON data - -3.0.0 ------ - - * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" - -2.8.0 ------ - - * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and - will be removed in 3.0. - -2.6.0 ------ - - * PdoSessionHandler changes - - implemented different session locking strategies to prevent loss of data by concurrent access to the same session - - [BC BREAK] save session data in a binary column without base64_encode - - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session - - implemented lazy connections that are only opened when a session is used by either passing a dsn string - explicitly or falling back to session.save_path ini setting - - added a createTable method that initializes a correctly defined table depending on the database vendor - -2.5.0 ------ - - * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation - of the options used while encoding data to JSON format. - -2.4.0 ------ - - * added RequestStack - * added Request::getEncodings() - * added accessors methods to session handlers - -2.3.0 ------ - - * added support for ranges of IPs in trusted proxies - * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) - * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` - to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases - to verify that Exceptions are properly thrown when the PDO queries fail. - -2.2.0 ------ - - * fixed the Request::create() precedence (URI information always take precedence now) - * added Request::getTrustedProxies() - * deprecated Request::isProxyTrusted() - * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects - * added a IpUtils class to check if an IP belongs to a CIDR - * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) - * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to - enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) - * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 - * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 - -2.1.0 ------ - - * added Request::getSchemeAndHttpHost() and Request::getUserInfo() - * added a fluent interface to the Response class - * added Request::isProxyTrusted() - * added JsonResponse - * added a getTargetUrl method to RedirectResponse - * added support for streamed responses - * made Response::prepare() method the place to enforce HTTP specification - * [BC BREAK] moved management of the locale from the Session class to the Request class - * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() - * made FileBinaryMimeTypeGuesser command configurable - * added Request::getUser() and Request::getPassword() - * added support for the PATCH method in Request - * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 - * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) - * made mimetype to extension conversion configurable - * [BC BREAK] Moved all session related classes and interfaces into own namespace, as - `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. - Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. - * SessionHandlers must implement `\SessionHandlerInterface` or extend from the - `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. - * Added internal storage driver proxy mechanism for forward compatibility with - PHP 5.4 `\SessionHandler` class. - * Added session handlers for custom Memcache, Memcached and Null session save handlers. - * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. - * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and - `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class - is a mediator for the session storage internals including the session handlers - which do the real work of participating in the internal PHP session workflow. - * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit - and functional testing without starting real PHP sessions. Removed - `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit - tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` - for functional tests. These do not interact with global session ini - configuration values, session functions or `$_SESSION` superglobal. This means - they can be configured directly allowing multiple instances to work without - conflicting in the same PHP process. - * [BC BREAK] Removed the `close()` method from the `Session` class, as this is - now redundant. - * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` - `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead - which returns a `FlashBagInterface`. - * `Session->clear()` now only clears session attributes as before it cleared - flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. - * Session data is now managed by `SessionBagInterface` to better encapsulate - session data. - * Refactored session attribute and flash messages system to their own - `SessionBagInterface` implementations. - * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This - implementation is ESI compatible. - * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire - behavior of messages auto expiring after one page page load. Messages must - be retrieved by `get()` or `all()`. - * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate - attributes storage behavior from 2.0.x (default). - * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for - namespace session attributes. - * Flash API can stores messages in an array so there may be multiple messages - per flash type. The old `Session` class API remains without BC break as it - will allow single messages as before. - * Added basic session meta-data to the session to record session create time, - last updated time, and the lifetime of the session cookie that was provided - to the client. - * Request::getClientIp() method doesn't take a parameter anymore but bases - itself on the trustProxy parameter. - * Added isMethod() to Request object. - * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of - a `Request` now all return a raw value (vs a urldecoded value before). Any call - to one of these methods must be checked and wrapped in a `rawurldecode()` if - needed. diff --git a/vendor/symfony/http-foundation/ChainRequestMatcher.php b/vendor/symfony/http-foundation/ChainRequestMatcher.php deleted file mode 100644 index 29486fc..0000000 --- a/vendor/symfony/http-foundation/ChainRequestMatcher.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ChainRequestMatcher verifies that all checks match against a Request instance. - * - * @author Fabien Potencier - */ -class ChainRequestMatcher implements RequestMatcherInterface -{ - /** - * @param iterable $matchers - */ - public function __construct(private iterable $matchers) - { - } - - public function matches(Request $request): bool - { - foreach ($this->matchers as $matcher) { - if (!$matcher->matches($request)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/http-foundation/Cookie.php b/vendor/symfony/http-foundation/Cookie.php deleted file mode 100644 index 1992870..0000000 --- a/vendor/symfony/http-foundation/Cookie.php +++ /dev/null @@ -1,405 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents a cookie. - * - * @author Johannes M. Schmitt - */ -class Cookie -{ - public const SAMESITE_NONE = 'none'; - public const SAMESITE_LAX = 'lax'; - public const SAMESITE_STRICT = 'strict'; - - protected int $expire; - protected string $path; - - private ?string $sameSite = null; - private bool $secureDefault = false; - - private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f"; - private const RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; - private const RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; - - /** - * Creates cookie from raw header string. - */ - public static function fromString(string $cookie, bool $decode = false): static - { - $data = [ - 'expires' => 0, - 'path' => '/', - 'domain' => null, - 'secure' => false, - 'httponly' => false, - 'raw' => !$decode, - 'samesite' => null, - 'partitioned' => false, - ]; - - $parts = HeaderUtils::split($cookie, ';='); - $part = array_shift($parts); - - $name = $decode ? urldecode($part[0]) : $part[0]; - $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; - - $data = HeaderUtils::combine($parts) + $data; - $data['expires'] = self::expiresTimestamp($data['expires']); - - if (isset($data['max-age']) && ($data['max-age'] > 0 || $data['expires'] > time())) { - $data['expires'] = time() + (int) $data['max-age']; - } - - return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite'], $data['partitioned']); - } - - /** - * @see self::__construct - * - * @param self::SAMESITE_*|''|null $sameSite - */ - public static function create(string $name, ?string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX, bool $partitioned = false): self - { - return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite, $partitioned); - } - - /** - * @param string $name The name of the cookie - * @param string|null $value The value of the cookie - * @param int|string|\DateTimeInterface $expire The time the cookie expires - * @param string|null $path The path on the server in which the cookie will be available on - * @param string|null $domain The domain that the cookie is available to - * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS - * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol - * @param bool $raw Whether the cookie value should be sent with no url encoding - * @param self::SAMESITE_*|''|null $sameSite Whether the cookie will be available for cross-site requests - * - * @throws \InvalidArgumentException - */ - public function __construct( - protected string $name, - protected ?string $value = null, - int|string|\DateTimeInterface $expire = 0, - ?string $path = '/', - protected ?string $domain = null, - protected ?bool $secure = null, - protected bool $httpOnly = true, - private bool $raw = false, - ?string $sameSite = self::SAMESITE_LAX, - private bool $partitioned = false, - ) { - // from PHP source code - if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(\sprintf('The cookie name "%s" contains invalid characters.', $name)); - } - - if (!$name) { - throw new \InvalidArgumentException('The cookie name cannot be empty.'); - } - - $this->expire = self::expiresTimestamp($expire); - $this->path = $path ?: '/'; - $this->sameSite = $this->withSameSite($sameSite)->sameSite; - } - - /** - * Creates a cookie copy with a new value. - */ - public function withValue(?string $value): static - { - $cookie = clone $this; - $cookie->value = $value; - - return $cookie; - } - - /** - * Creates a cookie copy with a new domain that the cookie is available to. - */ - public function withDomain(?string $domain): static - { - $cookie = clone $this; - $cookie->domain = $domain; - - return $cookie; - } - - /** - * Creates a cookie copy with a new time the cookie expires. - */ - public function withExpires(int|string|\DateTimeInterface $expire = 0): static - { - $cookie = clone $this; - $cookie->expire = self::expiresTimestamp($expire); - - return $cookie; - } - - /** - * Converts expires formats to a unix timestamp. - */ - private static function expiresTimestamp(int|string|\DateTimeInterface $expire = 0): int - { - // convert expiration time to a Unix timestamp - if ($expire instanceof \DateTimeInterface) { - $expire = $expire->format('U'); - } elseif (!is_numeric($expire)) { - $expire = strtotime($expire); - - if (false === $expire) { - throw new \InvalidArgumentException('The cookie expiration time is not valid.'); - } - } - - return 0 < $expire ? (int) $expire : 0; - } - - /** - * Creates a cookie copy with a new path on the server in which the cookie will be available on. - */ - public function withPath(string $path): static - { - $cookie = clone $this; - $cookie->path = '' === $path ? '/' : $path; - - return $cookie; - } - - /** - * Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client. - */ - public function withSecure(bool $secure = true): static - { - $cookie = clone $this; - $cookie->secure = $secure; - - return $cookie; - } - - /** - * Creates a cookie copy that be accessible only through the HTTP protocol. - */ - public function withHttpOnly(bool $httpOnly = true): static - { - $cookie = clone $this; - $cookie->httpOnly = $httpOnly; - - return $cookie; - } - - /** - * Creates a cookie copy that uses no url encoding. - */ - public function withRaw(bool $raw = true): static - { - if ($raw && false !== strpbrk($this->name, self::RESERVED_CHARS_LIST)) { - throw new \InvalidArgumentException(\sprintf('The cookie name "%s" contains invalid characters.', $this->name)); - } - - $cookie = clone $this; - $cookie->raw = $raw; - - return $cookie; - } - - /** - * Creates a cookie copy with SameSite attribute. - * - * @param self::SAMESITE_*|''|null $sameSite - */ - public function withSameSite(?string $sameSite): static - { - if ('' === $sameSite) { - $sameSite = null; - } elseif (null !== $sameSite) { - $sameSite = strtolower($sameSite); - } - - if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { - throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); - } - - $cookie = clone $this; - $cookie->sameSite = $sameSite; - - return $cookie; - } - - /** - * Creates a cookie copy that is tied to the top-level site in cross-site context. - */ - public function withPartitioned(bool $partitioned = true): static - { - $cookie = clone $this; - $cookie->partitioned = $partitioned; - - return $cookie; - } - - /** - * Returns the cookie as a string. - */ - public function __toString(): string - { - if ($this->isRaw()) { - $str = $this->getName(); - } else { - $str = str_replace(self::RESERVED_CHARS_FROM, self::RESERVED_CHARS_TO, $this->getName()); - } - - $str .= '='; - - if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d M Y H:i:s T', time() - 31536001).'; Max-Age=0'; - } else { - $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); - - if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d M Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); - } - } - - if ($this->getPath()) { - $str .= '; path='.$this->getPath(); - } - - if ($this->getDomain()) { - $str .= '; domain='.$this->getDomain(); - } - - if ($this->isSecure()) { - $str .= '; secure'; - } - - if ($this->isHttpOnly()) { - $str .= '; httponly'; - } - - if (null !== $this->getSameSite()) { - $str .= '; samesite='.$this->getSameSite(); - } - - if ($this->isPartitioned()) { - $str .= '; partitioned'; - } - - return $str; - } - - /** - * Gets the name of the cookie. - */ - public function getName(): string - { - return $this->name; - } - - /** - * Gets the value of the cookie. - */ - public function getValue(): ?string - { - return $this->value; - } - - /** - * Gets the domain that the cookie is available to. - */ - public function getDomain(): ?string - { - return $this->domain; - } - - /** - * Gets the time the cookie expires. - */ - public function getExpiresTime(): int - { - return $this->expire; - } - - /** - * Gets the max-age attribute. - */ - public function getMaxAge(): int - { - $maxAge = $this->expire - time(); - - return max(0, $maxAge); - } - - /** - * Gets the path on the server in which the cookie will be available on. - */ - public function getPath(): string - { - return $this->path; - } - - /** - * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. - */ - public function isSecure(): bool - { - return $this->secure ?? $this->secureDefault; - } - - /** - * Checks whether the cookie will be made accessible only through the HTTP protocol. - */ - public function isHttpOnly(): bool - { - return $this->httpOnly; - } - - /** - * Whether this cookie is about to be cleared. - */ - public function isCleared(): bool - { - return 0 !== $this->expire && $this->expire < time(); - } - - /** - * Checks if the cookie value should be sent with no url encoding. - */ - public function isRaw(): bool - { - return $this->raw; - } - - /** - * Checks whether the cookie should be tied to the top-level site in cross-site context. - */ - public function isPartitioned(): bool - { - return $this->partitioned; - } - - /** - * @return self::SAMESITE_*|null - */ - public function getSameSite(): ?string - { - return $this->sameSite; - } - - /** - * @param bool $default The default value of the "secure" flag when it is set to null - */ - public function setSecureDefault(bool $default): void - { - $this->secureDefault = $default; - } -} diff --git a/vendor/symfony/http-foundation/EventStreamResponse.php b/vendor/symfony/http-foundation/EventStreamResponse.php deleted file mode 100644 index e739c30..0000000 --- a/vendor/symfony/http-foundation/EventStreamResponse.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents a streaming HTTP response for sending server events - * as part of the Server-Sent Events (SSE) streaming technique. - * - * To broadcast events to multiple users at once, for long-running - * connections and for high-traffic websites, prefer using the Mercure - * Symfony Component, which relies on Software designed for these use - * cases: https://symfony.com/doc/current/mercure.html - * - * @see ServerEvent - * - * @author Yonel Ceruto - * - * Example usage: - * - * return new EventStreamResponse(function () { - * yield new ServerEvent(time()); - * - * sleep(1); - * - * yield new ServerEvent(time()); - * }); - */ -class EventStreamResponse extends StreamedResponse -{ - /** - * @param int|null $retry The number of milliseconds the client should wait - * before reconnecting in case of network failure - */ - public function __construct(?callable $callback = null, int $status = 200, array $headers = [], private ?int $retry = null) - { - $headers += [ - 'Connection' => 'keep-alive', - 'Content-Type' => 'text/event-stream', - 'Cache-Control' => 'private, no-cache, no-store, must-revalidate, max-age=0', - 'X-Accel-Buffering' => 'no', - 'Pragma' => 'no-cache', - 'Expires' => '0', - ]; - - parent::__construct($callback, $status, $headers); - } - - public function setCallback(callable $callback): static - { - if ($this->callback) { - return parent::setCallback($callback); - } - - $this->callback = function () use ($callback) { - if (is_iterable($events = $callback($this))) { - foreach ($events as $event) { - $this->sendEvent($event); - - if (connection_aborted()) { - break; - } - } - } - }; - - return $this; - } - - /** - * Sends a server event to the client. - * - * @return $this - */ - public function sendEvent(ServerEvent $event): static - { - if ($this->retry > 0 && !$event->getRetry()) { - $event->setRetry($this->retry); - } - - foreach ($event as $part) { - echo $part; - - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { - static::closeOutputBuffers(0, true); - flush(); - } - } - - return $this; - } - - public function getRetry(): ?int - { - return $this->retry; - } - - public function setRetry(int $retry): void - { - $this->retry = $retry; - } -} diff --git a/vendor/symfony/http-foundation/Exception/BadRequestException.php b/vendor/symfony/http-foundation/Exception/BadRequestException.php deleted file mode 100644 index 505e1cf..0000000 --- a/vendor/symfony/http-foundation/Exception/BadRequestException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user sends a malformed request. - */ -class BadRequestException extends UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php b/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php deleted file mode 100644 index 77aa0e1..0000000 --- a/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * The HTTP request contains headers with conflicting information. - * - * @author Magnus Nordlander - */ -class ConflictingHeadersException extends UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/ExceptionInterface.php b/vendor/symfony/http-foundation/Exception/ExceptionInterface.php deleted file mode 100644 index e77c94f..0000000 --- a/vendor/symfony/http-foundation/Exception/ExceptionInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/http-foundation/Exception/ExpiredSignedUriException.php b/vendor/symfony/http-foundation/Exception/ExpiredSignedUriException.php deleted file mode 100644 index 46907a3..0000000 --- a/vendor/symfony/http-foundation/Exception/ExpiredSignedUriException.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -use Symfony\Component\HttpKernel\Attribute\WithHttpStatus; - -/** - * @author Kevin Bond - */ -#[WithHttpStatus(403)] -final class ExpiredSignedUriException extends SignedUriException -{ - /** - * @internal - */ - public function __construct() - { - parent::__construct('The URI has expired.'); - } -} diff --git a/vendor/symfony/http-foundation/Exception/JsonException.php b/vendor/symfony/http-foundation/Exception/JsonException.php deleted file mode 100644 index 6d1e0ae..0000000 --- a/vendor/symfony/http-foundation/Exception/JsonException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Thrown by Request::toArray() when the content cannot be JSON-decoded. - * - * @author Tobias Nyholm - */ -final class JsonException extends UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/LogicException.php b/vendor/symfony/http-foundation/Exception/LogicException.php deleted file mode 100644 index 2d3021f..0000000 --- a/vendor/symfony/http-foundation/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Base LogicException for Http Foundation component. - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php b/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php deleted file mode 100644 index 478d0dc..0000000 --- a/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Interface for Request exceptions. - * - * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. - */ -interface RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php b/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php deleted file mode 100644 index 80a21bf..0000000 --- a/vendor/symfony/http-foundation/Exception/SessionNotFoundException.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a session does not exist. This happens in the following cases: - * - the session is not enabled - * - attempt to read a session outside a request context (ie. cli script). - * - * @author Jérémy Derussé - */ -class SessionNotFoundException extends \LogicException implements RequestExceptionInterface -{ - public function __construct(string $message = 'There is currently no session available.', int $code = 0, ?\Throwable $previous = null) - { - parent::__construct($message, $code, $previous); - } -} diff --git a/vendor/symfony/http-foundation/Exception/SignedUriException.php b/vendor/symfony/http-foundation/Exception/SignedUriException.php deleted file mode 100644 index 09c8065..0000000 --- a/vendor/symfony/http-foundation/Exception/SignedUriException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -use Symfony\Component\HttpKernel\Attribute\WithHttpStatus; - -/** - * @author Kevin Bond - */ -#[WithHttpStatus(404)] -abstract class SignedUriException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php b/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php deleted file mode 100644 index 4818ef2..0000000 --- a/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user has performed an operation that should be considered - * suspicious from a security perspective. - */ -class SuspiciousOperationException extends UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/UnexpectedValueException.php b/vendor/symfony/http-foundation/Exception/UnexpectedValueException.php deleted file mode 100644 index c3e6c9d..0000000 --- a/vendor/symfony/http-foundation/Exception/UnexpectedValueException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -class UnexpectedValueException extends \UnexpectedValueException -{ -} diff --git a/vendor/symfony/http-foundation/Exception/UnsignedUriException.php b/vendor/symfony/http-foundation/Exception/UnsignedUriException.php deleted file mode 100644 index 5eabb80..0000000 --- a/vendor/symfony/http-foundation/Exception/UnsignedUriException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * @author Kevin Bond - */ -final class UnsignedUriException extends SignedUriException -{ - /** - * @internal - */ - public function __construct() - { - parent::__construct('The URI is not signed.'); - } -} diff --git a/vendor/symfony/http-foundation/Exception/UnverifiedSignedUriException.php b/vendor/symfony/http-foundation/Exception/UnverifiedSignedUriException.php deleted file mode 100644 index cc7e98b..0000000 --- a/vendor/symfony/http-foundation/Exception/UnverifiedSignedUriException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * @author Kevin Bond - */ -final class UnverifiedSignedUriException extends SignedUriException -{ - /** - * @internal - */ - public function __construct() - { - parent::__construct('The URI signature is invalid.'); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php deleted file mode 100644 index 79ab0fc..0000000 --- a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when the access on a file was denied. - * - * @author Bernhard Schussek - */ -class AccessDeniedException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(\sprintf('The file %s could not be accessed', $path)); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php deleted file mode 100644 index c49f53a..0000000 --- a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class CannotWriteFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php deleted file mode 100644 index ed83499..0000000 --- a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. - * - * @author Florent Mata - */ -class ExtensionFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/FileException.php b/vendor/symfony/http-foundation/File/Exception/FileException.php deleted file mode 100644 index fad5133..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred in the component File. - * - * @author Bernhard Schussek - */ -class FileException extends \RuntimeException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php deleted file mode 100644 index 3a5eb03..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when a file was not found. - * - * @author Bernhard Schussek - */ -class FileNotFoundException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(\sprintf('The file "%s" does not exist', $path)); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php deleted file mode 100644 index 8741be0..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class FormSizeFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php deleted file mode 100644 index c8fde61..0000000 --- a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class IniSizeFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/NoFileException.php b/vendor/symfony/http-foundation/File/Exception/NoFileException.php deleted file mode 100644 index 4b48cc7..0000000 --- a/vendor/symfony/http-foundation/File/Exception/NoFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php deleted file mode 100644 index bdead2d..0000000 --- a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoTmpDirFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php deleted file mode 100644 index 4641efb..0000000 --- a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. - * - * @author Florent Mata - */ -class PartialFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php deleted file mode 100644 index 09b1c7e..0000000 --- a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -class UnexpectedTypeException extends FileException -{ - public function __construct(mixed $value, string $expectedType) - { - parent::__construct(\sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value))); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/UploadException.php b/vendor/symfony/http-foundation/File/Exception/UploadException.php deleted file mode 100644 index 7074e76..0000000 --- a/vendor/symfony/http-foundation/File/Exception/UploadException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred during file upload. - * - * @author Bernhard Schussek - */ -class UploadException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/File.php b/vendor/symfony/http-foundation/File/File.php deleted file mode 100644 index 1200a8d..0000000 --- a/vendor/symfony/http-foundation/File/File.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file in the file system. - * - * @author Bernhard Schussek - */ -class File extends \SplFileInfo -{ - /** - * Constructs a new file from the given path. - * - * @param string $path The path to the file - * @param bool $checkPath Whether to check the path or not - * - * @throws FileNotFoundException If the given path is not a file - */ - public function __construct(string $path, bool $checkPath = true) - { - if ($checkPath && !is_file($path)) { - throw new FileNotFoundException($path); - } - - parent::__construct($path); - } - - /** - * Returns the extension based on the mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getMimeType() - * to guess the file extension. - * - * @see MimeTypes - * @see getMimeType() - */ - public function guessExtension(): ?string - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; - } - - /** - * Returns the mime type of the file. - * - * The mime type is guessed using a MimeTypeGuesserInterface instance, - * which uses finfo_file() then the "file" system binary, - * depending on which of those are available. - * - * @see MimeTypes - */ - public function getMimeType(): ?string - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->guessMimeType($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @throws FileException if the target file could not be created - */ - public function move(string $directory, ?string $name = null): self - { - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $renamed = rename($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$renamed) { - throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0o666 & ~umask()); - - return $target; - } - - public function getContent(): string - { - $content = file_get_contents($this->getPathname()); - - if (false === $content) { - throw new FileException(\sprintf('Could not get the content of the file "%s".', $this->getPathname())); - } - - return $content; - } - - protected function getTargetFile(string $directory, ?string $name = null): self - { - if (!is_dir($directory) && !@mkdir($directory, 0o777, true) && !is_dir($directory)) { - if (is_file($directory)) { - throw new FileException(\sprintf('Unable to create the "%s" directory: a similarly-named file exists.', $directory)); - } - throw new FileException(\sprintf('Unable to create the "%s" directory.', $directory)); - } elseif (!is_writable($directory)) { - throw new FileException(\sprintf('Unable to write in the "%s" directory.', $directory)); - } - - $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); - - return new self($target, false); - } - - /** - * Returns locale independent base name of the given path. - */ - protected function getName(string $name): string - { - $originalName = str_replace('\\', '/', $name); - $pos = strrpos($originalName, '/'); - - return false === $pos ? $originalName : substr($originalName, $pos + 1); - } -} diff --git a/vendor/symfony/http-foundation/File/Stream.php b/vendor/symfony/http-foundation/File/Stream.php deleted file mode 100644 index 2c156b2..0000000 --- a/vendor/symfony/http-foundation/File/Stream.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -/** - * A PHP stream of unknown size. - * - * @author Nicolas Grekas - */ -class Stream extends File -{ - public function getSize(): int|false - { - return false; - } -} diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php deleted file mode 100644 index 53dce7d..0000000 --- a/vendor/symfony/http-foundation/File/UploadedFile.php +++ /dev/null @@ -1,289 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; -use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; -use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file uploaded through a form. - * - * @author Bernhard Schussek - * @author Florian Eckerstorfer - * @author Fabien Potencier - */ -class UploadedFile extends File -{ - private string $originalName; - private string $mimeType; - private int $error; - private string $originalPath; - - /** - * Accepts the information of the uploaded file as provided by the PHP global $_FILES. - * - * The file object is only created when the uploaded file is valid (i.e. when the - * isValid() method returns true). Otherwise the only methods that could be called - * on an UploadedFile instance are: - * - * * getClientOriginalName, - * * getClientMimeType, - * * isValid, - * * getError. - * - * Calling any other method on an non-valid instance will cause an unpredictable result. - * - * @param string $path The full temporary path to the file - * @param string $originalName The original file name of the uploaded file - * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream - * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK - * @param bool $test Whether the test mode is active - * Local files are used in test mode hence the code should not enforce HTTP uploads - * - * @throws FileException If file_uploads is disabled - * @throws FileNotFoundException If the file does not exist - */ - public function __construct( - string $path, - string $originalName, - ?string $mimeType = null, - ?int $error = null, - private bool $test = false, - ) { - $this->originalName = $this->getName($originalName); - $this->originalPath = strtr($originalName, '\\', '/'); - $this->mimeType = $mimeType ?: 'application/octet-stream'; - $this->error = $error ?: \UPLOAD_ERR_OK; - - parent::__construct($path, \UPLOAD_ERR_OK === $this->error); - } - - /** - * Returns the original file name. - * - * It is extracted from the request from which the file has been uploaded. - * This should not be considered as a safe value to use for a file name on your servers. - */ - public function getClientOriginalName(): string - { - return $this->originalName; - } - - /** - * Returns the original file extension. - * - * It is extracted from the original file name that was uploaded. - * This should not be considered as a safe value to use for a file name on your servers. - */ - public function getClientOriginalExtension(): string - { - return pathinfo($this->originalName, \PATHINFO_EXTENSION); - } - - /** - * Returns the original file full path. - * - * It is extracted from the request from which the file has been uploaded. - * This should not be considered as a safe value to use for a file name/path on your servers. - * - * If this file was uploaded with the "webkitdirectory" upload directive, this will contain - * the path of the file relative to the uploaded root directory. Otherwise this will be identical - * to getClientOriginalName(). - */ - public function getClientOriginalPath(): string - { - return $this->originalPath; - } - - /** - * Returns the file mime type. - * - * The client mime type is extracted from the request from which the file - * was uploaded, so it should not be considered as a safe value. - * - * For a trusted mime type, use getMimeType() instead (which guesses the mime - * type based on the file content). - * - * @see getMimeType() - */ - public function getClientMimeType(): string - { - return $this->mimeType; - } - - /** - * Returns the extension based on the client mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getClientMimeType() - * to guess the file extension. As such, the extension returned - * by this method cannot be trusted. - * - * For a trusted extension, use guessExtension() instead (which guesses - * the extension based on the guessed mime type for the file). - * - * @see guessExtension() - * @see getClientMimeType() - */ - public function guessClientExtension(): ?string - { - if (!class_exists(MimeTypes::class)) { - throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; - } - - /** - * Returns the upload error. - * - * If the upload was successful, the constant UPLOAD_ERR_OK is returned. - * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. - */ - public function getError(): int - { - return $this->error; - } - - /** - * Returns whether the file has been uploaded with HTTP and no error occurred. - */ - public function isValid(): bool - { - $isOk = \UPLOAD_ERR_OK === $this->error; - - return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @throws FileException if, for any reason, the file could not have been moved - */ - public function move(string $directory, ?string $name = null): File - { - if ($this->isValid()) { - if ($this->test) { - return parent::move($directory, $name); - } - - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - try { - $moved = move_uploaded_file($this->getPathname(), $target); - } finally { - restore_error_handler(); - } - if (!$moved) { - throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0o666 & ~umask()); - - return $target; - } - - switch ($this->error) { - case \UPLOAD_ERR_INI_SIZE: - throw new IniSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_FORM_SIZE: - throw new FormSizeFileException($this->getErrorMessage()); - case \UPLOAD_ERR_PARTIAL: - throw new PartialFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_FILE: - throw new NoFileException($this->getErrorMessage()); - case \UPLOAD_ERR_CANT_WRITE: - throw new CannotWriteFileException($this->getErrorMessage()); - case \UPLOAD_ERR_NO_TMP_DIR: - throw new NoTmpDirFileException($this->getErrorMessage()); - case \UPLOAD_ERR_EXTENSION: - throw new ExtensionFileException($this->getErrorMessage()); - } - - throw new FileException($this->getErrorMessage()); - } - - /** - * Returns the maximum size of an uploaded file as configured in php.ini. - * - * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX) - */ - public static function getMaxFilesize(): int|float - { - $sizePostMax = self::parseFilesize(\ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize')); - - return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); - } - - private static function parseFilesize(string $size): int|float - { - if ('' === $size) { - return 0; - } - - $size = strtolower($size); - - $max = ltrim($size, '+'); - if (str_starts_with($max, '0x')) { - $max = \intval($max, 16); - } elseif (str_starts_with($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($size, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns an informative upload error message. - */ - public function getErrorMessage(): string - { - static $errors = [ - \UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', - \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', - \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', - \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', - \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', - \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', - \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', - ]; - - $errorCode = $this->error; - $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; - $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.'; - - return \sprintf($message, $this->getClientOriginalName(), $maxFilesize); - } -} diff --git a/vendor/symfony/http-foundation/FileBag.php b/vendor/symfony/http-foundation/FileBag.php deleted file mode 100644 index 561e7cd..0000000 --- a/vendor/symfony/http-foundation/FileBag.php +++ /dev/null @@ -1,127 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\UploadedFile; - -/** - * FileBag is a container for uploaded files. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - */ -class FileBag extends ParameterBag -{ - private const FILE_KEYS = ['error', 'full_path', 'name', 'size', 'tmp_name', 'type']; - - /** - * @param array|UploadedFile[] $parameters An array of HTTP files - */ - public function __construct(array $parameters = []) - { - $this->replace($parameters); - } - - public function replace(array $files = []): void - { - $this->parameters = []; - $this->add($files); - } - - public function set(string $key, mixed $value): void - { - if (!\is_array($value) && !$value instanceof UploadedFile) { - throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); - } - - parent::set($key, $this->convertFileInformation($value)); - } - - public function add(array $files = []): void - { - foreach ($files as $key => $file) { - $this->set($key, $file); - } - } - - /** - * Converts uploaded files to UploadedFile instances. - * - * @return UploadedFile[]|UploadedFile|null - */ - protected function convertFileInformation(array|UploadedFile $file): array|UploadedFile|null - { - if ($file instanceof UploadedFile) { - return $file; - } - - $file = $this->fixPhpFilesArray($file); - $keys = array_keys($file + ['full_path' => null]); - sort($keys); - - if (self::FILE_KEYS === $keys) { - if (\UPLOAD_ERR_NO_FILE === $file['error']) { - $file = null; - } else { - $file = new UploadedFile($file['tmp_name'], $file['full_path'] ?? $file['name'], $file['type'], $file['error'], false); - } - } else { - $file = array_map(fn ($v) => $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v, $file); - if (array_is_list($file)) { - $file = array_filter($file); - } - } - - return $file; - } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * It's safe to pass an already converted array, in which case this method - * just returns the original array unmodified. - */ - protected function fixPhpFilesArray(array $data): array - { - $keys = array_keys($data + ['full_path' => null]); - sort($keys); - - if (self::FILE_KEYS !== $keys || !isset($data['name']) || !\is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach (self::FILE_KEYS as $k) { - unset($files[$k]); - } - - foreach ($data['name'] as $key => $name) { - $files[$key] = $this->fixPhpFilesArray([ - 'error' => $data['error'][$key], - 'name' => $name, - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - ] + (isset($data['full_path'][$key]) ? [ - 'full_path' => $data['full_path'][$key], - ] : [])); - } - - return $files; - } -} diff --git a/vendor/symfony/http-foundation/HeaderBag.php b/vendor/symfony/http-foundation/HeaderBag.php deleted file mode 100644 index c2ede56..0000000 --- a/vendor/symfony/http-foundation/HeaderBag.php +++ /dev/null @@ -1,273 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HeaderBag is a container for HTTP headers. - * - * @author Fabien Potencier - * - * @implements \IteratorAggregate> - */ -class HeaderBag implements \IteratorAggregate, \Countable, \Stringable -{ - protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; - - /** - * @var array> - */ - protected array $headers = []; - protected array $cacheControl = []; - - public function __construct(array $headers = []) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the headers as a string. - */ - public function __toString(): string - { - if (!$headers = $this->all()) { - return ''; - } - - ksort($headers); - $max = max(array_map('strlen', array_keys($headers))) + 1; - $content = ''; - foreach ($headers as $name => $values) { - $name = ucwords($name, '-'); - foreach ($values as $value) { - $content .= \sprintf("%-{$max}s %s\r\n", $name.':', $value); - } - } - - return $content; - } - - /** - * Returns the headers. - * - * @param string|null $key The name of the headers to return or null to get them all - * - * @return ($key is null ? array> : list) - */ - public function all(?string $key = null): array - { - if (null !== $key) { - return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; - } - - return $this->headers; - } - - /** - * Returns the parameter keys. - * - * @return string[] - */ - public function keys(): array - { - return array_keys($this->all()); - } - - /** - * Replaces the current HTTP headers by a new set. - */ - public function replace(array $headers = []): void - { - $this->headers = []; - $this->add($headers); - } - - /** - * Adds new headers the current HTTP headers set. - */ - public function add(array $headers): void - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the first header by name or the default one. - */ - public function get(string $key, ?string $default = null): ?string - { - $headers = $this->all($key); - - if (!$headers) { - return $default; - } - - if (null === $headers[0]) { - return null; - } - - return $headers[0]; - } - - /** - * Sets a header by name. - * - * @param string|string[]|null $values The value or an array of values - * @param bool $replace Whether to replace the actual value or not (true by default) - */ - public function set(string $key, string|array|null $values, bool $replace = true): void - { - $key = strtr($key, self::UPPER, self::LOWER); - - if (\is_array($values)) { - $values = array_values($values); - - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = $values; - } else { - $this->headers[$key] = array_merge($this->headers[$key], $values); - } - } else { - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = [$values]; - } else { - $this->headers[$key][] = $values; - } - } - - if ('cache-control' === $key) { - $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); - } - } - - /** - * Returns true if the HTTP header is defined. - */ - public function has(string $key): bool - { - return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); - } - - /** - * Returns true if the given HTTP header contains the given value. - */ - public function contains(string $key, string $value): bool - { - return \in_array($value, $this->all($key), true); - } - - /** - * Removes a header. - */ - public function remove(string $key): void - { - $key = strtr($key, self::UPPER, self::LOWER); - - unset($this->headers[$key]); - - if ('cache-control' === $key) { - $this->cacheControl = []; - } - } - - /** - * Returns the HTTP header value converted to a date. - * - * @throws \RuntimeException When the HTTP header is not parseable - */ - public function getDate(string $key, ?\DateTimeInterface $default = null): ?\DateTimeImmutable - { - if (null === $value = $this->get($key)) { - return null !== $default ? \DateTimeImmutable::createFromInterface($default) : null; - } - - if (false === $date = \DateTimeImmutable::createFromFormat(\DATE_RFC2822, $value)) { - throw new \RuntimeException(\sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); - } - - return $date; - } - - /** - * Adds a custom Cache-Control directive. - */ - public function addCacheControlDirective(string $key, bool|string $value = true): void - { - $this->cacheControl[$key] = $value; - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns true if the Cache-Control directive is defined. - */ - public function hasCacheControlDirective(string $key): bool - { - return \array_key_exists($key, $this->cacheControl); - } - - /** - * Returns a Cache-Control directive value by name. - */ - public function getCacheControlDirective(string $key): bool|string|null - { - return $this->cacheControl[$key] ?? null; - } - - /** - * Removes a Cache-Control directive. - */ - public function removeCacheControlDirective(string $key): void - { - unset($this->cacheControl[$key]); - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns an iterator for headers. - * - * @return \ArrayIterator> - */ - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->headers); - } - - /** - * Returns the number of headers. - */ - public function count(): int - { - return \count($this->headers); - } - - protected function getCacheControlHeader(): string - { - ksort($this->cacheControl); - - return HeaderUtils::toString($this->cacheControl, ','); - } - - /** - * Parses a Cache-Control HTTP header. - */ - protected function parseCacheControl(string $header): array - { - $parts = HeaderUtils::split($header, ',='); - - return HeaderUtils::combine($parts); - } -} diff --git a/vendor/symfony/http-foundation/HeaderUtils.php b/vendor/symfony/http-foundation/HeaderUtils.php deleted file mode 100644 index 37953af..0000000 --- a/vendor/symfony/http-foundation/HeaderUtils.php +++ /dev/null @@ -1,298 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HTTP header utility functions. - * - * @author Christian Schmidt - */ -class HeaderUtils -{ - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Splits an HTTP header by one or more separators. - * - * Example: - * - * HeaderUtils::split('da, en-gb;q=0.8', ',;') - * # returns [['da'], ['en-gb', 'q=0.8']] - * - * @param string $separators List of characters to split on, ordered by - * precedence, e.g. ',', ';=', or ',;=' - * - * @return array Nested array with as many levels as there are characters in - * $separators - */ - public static function split(string $header, string $separators): array - { - if ('' === $separators) { - throw new \InvalidArgumentException('At least one separator must be specified.'); - } - - $quotedSeparators = preg_quote($separators, '/'); - - preg_match_all(' - / - (?!\s) - (?: - # quoted-string - "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) - | - # token - [^"'.$quotedSeparators.']+ - )+ - (?['.$quotedSeparators.']) - \s* - /x', trim($header), $matches, \PREG_SET_ORDER); - - return self::groupParts($matches, $separators); - } - - /** - * Combines an array of arrays into one associative array. - * - * Each of the nested arrays should have one or two elements. The first - * value will be used as the keys in the associative array, and the second - * will be used as the values, or true if the nested array only contains one - * element. Array keys are lowercased. - * - * Example: - * - * HeaderUtils::combine([['foo', 'abc'], ['bar']]) - * // => ['foo' => 'abc', 'bar' => true] - */ - public static function combine(array $parts): array - { - $assoc = []; - foreach ($parts as $part) { - $name = strtolower($part[0]); - $value = $part[1] ?? true; - $assoc[$name] = $value; - } - - return $assoc; - } - - /** - * Joins an associative array into a string for use in an HTTP header. - * - * The key and value of each entry are joined with '=', and all entries - * are joined with the specified separator and an additional space (for - * readability). Values are quoted if necessary. - * - * Example: - * - * HeaderUtils::toString(['foo' => 'abc', 'bar' => true, 'baz' => 'a b c'], ',') - * // => 'foo=abc, bar, baz="a b c"' - */ - public static function toString(array $assoc, string $separator): string - { - $parts = []; - foreach ($assoc as $name => $value) { - if (true === $value) { - $parts[] = $name; - } else { - $parts[] = $name.'='.self::quote($value); - } - } - - return implode($separator.' ', $parts); - } - - /** - * Encodes a string as a quoted string, if necessary. - * - * If a string contains characters not allowed by the "token" construct in - * the HTTP specification, it is backslash-escaped and enclosed in quotes - * to match the "quoted-string" construct. - */ - public static function quote(string $s): string - { - if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { - return $s; - } - - return '"'.addcslashes($s, '"\\"').'"'; - } - - /** - * Decodes a quoted string. - * - * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatim. - */ - public static function unquote(string $s): string - { - return preg_replace('/\\\\(.)|"/', '$1', $s); - } - - /** - * Generates an HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 - */ - public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string - { - if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE], true)) { - throw new \InvalidArgumentException(\sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - - if ('' === $filenameFallback) { - $filenameFallback = $filename; - } - - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - - // percent characters aren't safe in fallback. - if (str_contains($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - - // path separators aren't allowed in either. - if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - - $params = ['filename' => $filenameFallback]; - if ($filename !== $filenameFallback) { - $params['filename*'] = "utf-8''".rawurlencode($filename); - } - - return $disposition.'; '.self::toString($params, ';'); - } - - /** - * Like parse_str(), but preserves dots in variable names. - */ - public static function parseQuery(string $query, bool $ignoreBrackets = false, string $separator = '&'): array - { - $q = []; - - foreach (explode($separator, $query) as $v) { - if (false !== $i = strpos($v, "\0")) { - $v = substr($v, 0, $i); - } - - if (false === $i = strpos($v, '=')) { - $k = urldecode($v); - $v = ''; - } else { - $k = urldecode(substr($v, 0, $i)); - $v = substr($v, $i); - } - - if (false !== $i = strpos($k, "\0")) { - $k = substr($k, 0, $i); - } - - $k = ltrim($k, ' '); - - if ($ignoreBrackets) { - $q[$k][] = urldecode(substr($v, 1)); - - continue; - } - - if (false === $i = strpos($k, '[')) { - $q[] = bin2hex($k).$v; - } else { - $q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k, $i)).$v; - } - } - - if ($ignoreBrackets) { - return $q; - } - - parse_str(implode('&', $q), $q); - - $query = []; - - foreach ($q as $k => $v) { - if (false !== $i = strpos($k, '_')) { - $query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v; - } else { - $query[hex2bin($k)] = $v; - } - } - - return $query; - } - - private static function groupParts(array $matches, string $separators, bool $first = true): array - { - $separator = $separators[0]; - $separators = substr($separators, 1) ?: ''; - $i = 0; - - if ('' === $separators && !$first) { - $parts = ['']; - - foreach ($matches as $match) { - if (!$i && isset($match['separator'])) { - $i = 1; - $parts[1] = ''; - } else { - $parts[$i] .= self::unquote($match[0]); - } - } - - return $parts; - } - - $parts = []; - $partMatches = []; - - foreach ($matches as $match) { - if (($match['separator'] ?? null) === $separator) { - ++$i; - } else { - $partMatches[$i][] = $match; - } - } - - foreach ($partMatches as $matches) { - if ('' === $separators && '' !== $unquoted = self::unquote($matches[0][0])) { - $parts[] = $unquoted; - } elseif ($groupedParts = self::groupParts($matches, $separators, false)) { - $parts[] = $groupedParts; - } - } - - return $parts; - } -} diff --git a/vendor/symfony/http-foundation/InputBag.php b/vendor/symfony/http-foundation/InputBag.php deleted file mode 100644 index 8c153dc..0000000 --- a/vendor/symfony/http-foundation/InputBag.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; -use Symfony\Component\HttpFoundation\Exception\UnexpectedValueException; - -/** - * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE. - * - * @template TInput of string|int|float|bool|null - * - * @author Saif Eddin Gmati - */ -final class InputBag extends ParameterBag -{ - /** - * Returns a scalar input value by name. - * - * @template TDefault of string|int|float|bool|null - * - * @param TDefault $default The default value if the input key does not exist - * - * @return TDefault|TInput - * - * @throws BadRequestException if the input contains a non-scalar value - */ - public function get(string $key, mixed $default = null): string|int|float|bool|null - { - if (null !== $default && !\is_scalar($default) && !$default instanceof \Stringable) { - throw new \InvalidArgumentException(\sprintf('Expected a scalar value as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($default))); - } - - $value = parent::get($key, $this); - - if (null !== $value && $this !== $value && !\is_scalar($value) && !$value instanceof \Stringable) { - throw new BadRequestException(\sprintf('Input value "%s" contains a non-scalar value.', $key)); - } - - return $this === $value ? $default : $value; - } - - /** - * Replaces the current input values by a new set. - */ - public function replace(array $inputs = []): void - { - $this->parameters = []; - $this->add($inputs); - } - - /** - * Adds input values. - */ - public function add(array $inputs = []): void - { - foreach ($inputs as $input => $value) { - $this->set($input, $value); - } - } - - /** - * Sets an input by name. - * - * @param string|int|float|bool|array|null $value - */ - public function set(string $key, mixed $value): void - { - if (null !== $value && !\is_scalar($value) && !\is_array($value) && !$value instanceof \Stringable) { - throw new \InvalidArgumentException(\sprintf('Expected a scalar, or an array as a 2nd argument to "%s()", "%s" given.', __METHOD__, get_debug_type($value))); - } - - $this->parameters[$key] = $value; - } - - /** - * Returns the parameter value converted to an enum. - * - * @template T of \BackedEnum - * - * @param class-string $class - * @param ?T $default - * - * @return ?T - * - * @psalm-return ($default is null ? T|null : T) - * - * @throws BadRequestException if the input cannot be converted to an enum - */ - public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum - { - try { - return parent::getEnum($key, $class, $default); - } catch (UnexpectedValueException $e) { - throw new BadRequestException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * Returns the parameter value converted to string. - * - * @throws BadRequestException if the input contains a non-scalar value - */ - public function getString(string $key, string $default = ''): string - { - // Shortcuts the parent method because the validation on scalar is already done in get(). - return (string) $this->get($key, $default); - } - - /** - * @throws BadRequestException if the input value is an array and \FILTER_REQUIRE_ARRAY or \FILTER_FORCE_ARRAY is not set - * @throws BadRequestException if the input value is invalid and \FILTER_NULL_ON_FAILURE is not set - */ - public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed - { - $value = $this->has($key) ? $this->all()[$key] : $default; - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) { - throw new BadRequestException(\sprintf('Input value "%s" contains an array, but "FILTER_REQUIRE_ARRAY" or "FILTER_FORCE_ARRAY" flags were not set.', $key)); - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - throw new \InvalidArgumentException(\sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - $options['flags'] ??= 0; - $nullOnFailure = $options['flags'] & \FILTER_NULL_ON_FAILURE; - $options['flags'] |= \FILTER_NULL_ON_FAILURE; - - $value = filter_var($value, $filter, $options); - - if (null !== $value || $nullOnFailure) { - return $value; - } - - throw new BadRequestException(\sprintf('Input value "%s" is invalid and flag "FILTER_NULL_ON_FAILURE" was not set.', $key)); - } -} diff --git a/vendor/symfony/http-foundation/IpUtils.php b/vendor/symfony/http-foundation/IpUtils.php deleted file mode 100644 index b7a3467..0000000 --- a/vendor/symfony/http-foundation/IpUtils.php +++ /dev/null @@ -1,270 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Http utility functions. - * - * @author Fabien Potencier - */ -class IpUtils -{ - public const PRIVATE_SUBNETS = [ - '127.0.0.0/8', // RFC1700 (Loopback) - '10.0.0.0/8', // RFC1918 - '192.168.0.0/16', // RFC1918 - '172.16.0.0/12', // RFC1918 - '169.254.0.0/16', // RFC3927 - '0.0.0.0/8', // RFC5735 - '240.0.0.0/4', // RFC1112 - '::1/128', // Loopback - 'fc00::/7', // Unique Local Address - 'fe80::/10', // Link Local Address - '::ffff:0:0/96', // IPv4 translations - '::/128', // Unspecified address - ]; - - private static array $checkedIps = []; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. - * - * @param string|array $ips List of IPs or subnets (can be a string if only a single one) - */ - public static function checkIp(string $requestIp, string|array $ips): bool - { - if (!\is_array($ips)) { - $ips = [$ips]; - } - - $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; - - foreach ($ips as $ip) { - if (self::$method($requestIp, $ip)) { - return true; - } - } - - return false; - } - - /** - * Compares two IPv4 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @param string $ip IPv4 address or subnet in CIDR notation - * - * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet - */ - public static function checkIp4(string $requestIp, string $ip): bool - { - $cacheKey = $requestIp.'-'.$ip.'-v4'; - if (null !== $cacheValue = self::getCacheResult($cacheKey)) { - return $cacheValue; - } - - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { - return self::setCacheResult($cacheKey, false); - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if ('0' === $netmask) { - return self::setCacheResult($cacheKey, false !== filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)); - } - - if ($netmask < 0 || $netmask > 32) { - return self::setCacheResult($cacheKey, false); - } - } else { - $address = $ip; - $netmask = 32; - } - - if (false === ip2long($address)) { - return self::setCacheResult($cacheKey, false); - } - - return self::setCacheResult($cacheKey, 0 === substr_compare(\sprintf('%032b', ip2long($requestIp)), \sprintf('%032b', ip2long($address)), 0, $netmask)); - } - - /** - * Compares two IPv6 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @author David Soria Parra - * - * @see https://github.com/dsp/v6tools - * - * @param string $ip IPv6 address or subnet in CIDR notation - * - * @throws \RuntimeException When IPV6 support is not enabled - */ - public static function checkIp6(string $requestIp, string $ip): bool - { - $cacheKey = $requestIp.'-'.$ip.'-v6'; - if (null !== $cacheValue = self::getCacheResult($cacheKey)) { - return $cacheValue; - } - - if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { - throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); - } - - // Check to see if we were given a IP4 $requestIp or $ip by mistake - if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::setCacheResult($cacheKey, false); - } - - if (str_contains($ip, '/')) { - [$address, $netmask] = explode('/', $ip, 2); - - if (!filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::setCacheResult($cacheKey, false); - } - - if ('0' === $netmask) { - return (bool) unpack('n*', @inet_pton($address)); - } - - if ($netmask < 1 || $netmask > 128) { - return self::setCacheResult($cacheKey, false); - } - } else { - if (!filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { - return self::setCacheResult($cacheKey, false); - } - - $address = $ip; - $netmask = 128; - } - - $bytesAddr = unpack('n*', @inet_pton($address)); - $bytesTest = unpack('n*', @inet_pton($requestIp)); - - if (!$bytesAddr || !$bytesTest) { - return self::setCacheResult($cacheKey, false); - } - - for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { - $left = $netmask - 16 * ($i - 1); - $left = ($left <= 16) ? $left : 16; - $mask = ~(0xFFFF >> $left) & 0xFFFF; - if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return self::setCacheResult($cacheKey, false); - } - } - - return self::setCacheResult($cacheKey, true); - } - - /** - * Anonymizes an IP/IPv6. - * - * Removes the last bytes of IPv4 and IPv6 addresses (1 byte for IPv4 and 8 bytes for IPv6 by default). - * - * @param int<0, 4> $v4Bytes - * @param int<0, 16> $v6Bytes - */ - public static function anonymize(string $ip, int $v4Bytes = 1, int $v6Bytes = 8): string - { - if ($v4Bytes < 0 || $v6Bytes < 0) { - throw new \InvalidArgumentException('Cannot anonymize less than 0 bytes.'); - } - - if ($v4Bytes > 4 || $v6Bytes > 16) { - throw new \InvalidArgumentException('Cannot anonymize more than 4 bytes for IPv4 and 16 bytes for IPv6.'); - } - - /* - * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007 - * In that case, we only care about the part before the % symbol, as the following functions, can only work with - * the IP address itself. As the scope can leak information (containing interface name), we do not want to - * include it in our anonymized IP data. - */ - if (str_contains($ip, '%')) { - $ip = substr($ip, 0, strpos($ip, '%')); - } - - $wrappedIPv6 = false; - if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) { - $wrappedIPv6 = true; - $ip = substr($ip, 1, -1); - } - - $mappedIpV4MaskGenerator = function (string $mask, int $bytesToAnonymize) { - $mask .= str_repeat('ff', 4 - $bytesToAnonymize); - $mask .= str_repeat('00', $bytesToAnonymize); - - return '::'.implode(':', str_split($mask, 4)); - }; - - $packedAddress = inet_pton($ip); - if (4 === \strlen($packedAddress)) { - $mask = rtrim(str_repeat('255.', 4 - $v4Bytes).str_repeat('0.', $v4Bytes), '.'); - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { - $mask = $mappedIpV4MaskGenerator('ffff', $v4Bytes); - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { - $mask = $mappedIpV4MaskGenerator('', $v4Bytes); - } else { - $mask = str_repeat('ff', 16 - $v6Bytes).str_repeat('00', $v6Bytes); - $mask = implode(':', str_split($mask, 4)); - } - $ip = inet_ntop($packedAddress & inet_pton($mask)); - - if ($wrappedIPv6) { - $ip = '['.$ip.']'; - } - - return $ip; - } - - /** - * Checks if an IPv4 or IPv6 address is contained in the list of private IP subnets. - */ - public static function isPrivateIp(string $requestIp): bool - { - return self::checkIp($requestIp, self::PRIVATE_SUBNETS); - } - - private static function getCacheResult(string $cacheKey): ?bool - { - if (isset(self::$checkedIps[$cacheKey])) { - // Move the item last in cache (LRU) - $value = self::$checkedIps[$cacheKey]; - unset(self::$checkedIps[$cacheKey]); - self::$checkedIps[$cacheKey] = $value; - - return self::$checkedIps[$cacheKey]; - } - - return null; - } - - private static function setCacheResult(string $cacheKey, bool $result): bool - { - if (1000 < \count(self::$checkedIps)) { - // stop memory leak if there are many keys - self::$checkedIps = \array_slice(self::$checkedIps, 500, null, true); - } - - return self::$checkedIps[$cacheKey] = $result; - } -} diff --git a/vendor/symfony/http-foundation/JsonResponse.php b/vendor/symfony/http-foundation/JsonResponse.php deleted file mode 100644 index 187173b..0000000 --- a/vendor/symfony/http-foundation/JsonResponse.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Response represents an HTTP response in JSON format. - * - * Note that this class does not force the returned JSON content to be an - * object. It is however recommended that you do return an object as it - * protects yourself against XSSI and JSON-JavaScript Hijacking. - * - * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside - * - * @author Igor Wiedler - */ -class JsonResponse extends Response -{ - protected mixed $data; - protected ?string $callback = null; - - // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. - // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT - public const DEFAULT_ENCODING_OPTIONS = 15; - - protected int $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; - - /** - * @param bool $json If the data is already a JSON string - */ - public function __construct(mixed $data = null, int $status = 200, array $headers = [], bool $json = false) - { - parent::__construct('', $status, $headers); - - if ($json && !\is_string($data) && !is_numeric($data) && !$data instanceof \Stringable) { - throw new \TypeError(\sprintf('"%s": If $json is set to true, argument $data must be a string or object implementing __toString(), "%s" given.', __METHOD__, get_debug_type($data))); - } - - $data ??= new \ArrayObject(); - - $json ? $this->setJson($data) : $this->setData($data); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::fromJsonString('{"key": "value"}') - * ->setSharedMaxAge(300); - * - * @param string $data The JSON response string - * @param int $status The response status code (200 "OK" by default) - * @param array $headers An array of response headers - */ - public static function fromJsonString(string $data, int $status = 200, array $headers = []): static - { - return new static($data, $status, $headers, true); - } - - /** - * Sets the JSONP callback. - * - * @param string|null $callback The JSONP callback or null to use none - * - * @return $this - * - * @throws \InvalidArgumentException When the callback name is not valid - */ - public function setCallback(?string $callback): static - { - if (null !== $callback) { - // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ - // partially taken from https://github.com/willdurand/JsonpCallbackValidator - // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. - // (c) William Durand - $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; - $reserved = [ - 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', - 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', - 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', - ]; - $parts = explode('.', $callback); - foreach ($parts as $part) { - if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { - throw new \InvalidArgumentException('The callback name is not valid.'); - } - } - } - - $this->callback = $callback; - - return $this->update(); - } - - /** - * Sets a raw string containing a JSON document to be sent. - * - * @return $this - */ - public function setJson(string $json): static - { - $this->data = $json; - - return $this->update(); - } - - /** - * Sets the data to be sent as JSON. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setData(mixed $data = []): static - { - try { - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === $e::class && str_starts_with($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; - } - - if (\JSON_THROW_ON_ERROR & $this->encodingOptions) { - return $this->setJson($data); - } - - if (\JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException(json_last_error_msg()); - } - - return $this->setJson($data); - } - - /** - * Returns options used while encoding data to JSON. - */ - public function getEncodingOptions(): int - { - return $this->encodingOptions; - } - - /** - * Sets options used while encoding data to JSON. - * - * @return $this - */ - public function setEncodingOptions(int $encodingOptions): static - { - $this->encodingOptions = $encodingOptions; - - return $this->setData(json_decode($this->data)); - } - - /** - * Updates the content and headers according to the JSON data and callback. - * - * @return $this - */ - protected function update(): static - { - if (null !== $this->callback) { - // Not using application/javascript for compatibility reasons with older browsers. - $this->headers->set('Content-Type', 'text/javascript'); - - return $this->setContent(\sprintf('/**/%s(%s);', $this->callback, $this->data)); - } - - // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) - // in order to not overwrite a custom definition. - if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { - $this->headers->set('Content-Type', 'application/json'); - } - - return $this->setContent($this->data); - } -} diff --git a/vendor/symfony/http-foundation/LICENSE b/vendor/symfony/http-foundation/LICENSE deleted file mode 100644 index 0138f8f..0000000 --- a/vendor/symfony/http-foundation/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-present Fabien Potencier - -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/symfony/http-foundation/ParameterBag.php b/vendor/symfony/http-foundation/ParameterBag.php deleted file mode 100644 index 5e36cf2..0000000 --- a/vendor/symfony/http-foundation/ParameterBag.php +++ /dev/null @@ -1,271 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; -use Symfony\Component\HttpFoundation\Exception\UnexpectedValueException; - -/** - * ParameterBag is a container for key/value pairs. - * - * @author Fabien Potencier - * - * @implements \IteratorAggregate - */ -class ParameterBag implements \IteratorAggregate, \Countable -{ - /** - * @param array $parameters - */ - public function __construct( - protected array $parameters = [], - ) { - } - - /** - * Returns the parameters. - * - * @template TKey of string|null - * - * @param TKey $key The name of the parameter to return or null to get them all - * - * @return (TKey is null ? array : array) - * - * @throws BadRequestException if the value is not an array - */ - public function all(?string $key = null): array - { - if (null === $key) { - return $this->parameters; - } - - if (!\is_array($value = $this->parameters[$key] ?? [])) { - throw new BadRequestException(\sprintf('Unexpected value for parameter "%s": expecting "array", got "%s".', $key, get_debug_type($value))); - } - - return $value; - } - - /** - * Returns the parameter keys. - * - * @return list - */ - public function keys(): array - { - return array_keys($this->parameters); - } - - /** - * Replaces the current parameters by a new set. - * - * @param array $parameters - */ - public function replace(array $parameters = []): void - { - $this->parameters = $parameters; - } - - /** - * Adds parameters. - * - * @param array $parameters - */ - public function add(array $parameters = []): void - { - $this->parameters = array_replace($this->parameters, $parameters); - } - - public function get(string $key, mixed $default = null): mixed - { - return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; - } - - public function set(string $key, mixed $value): void - { - $this->parameters[$key] = $value; - } - - /** - * Returns true if the parameter is defined. - */ - public function has(string $key): bool - { - return \array_key_exists($key, $this->parameters); - } - - /** - * Removes a parameter. - */ - public function remove(string $key): void - { - unset($this->parameters[$key]); - } - - /** - * Returns the alphabetic characters of the parameter value. - * - * @throws UnexpectedValueException if the value cannot be converted to string - */ - public function getAlpha(string $key, string $default = ''): string - { - return preg_replace('/[^[:alpha:]]/', '', $this->getString($key, $default)); - } - - /** - * Returns the alphabetic characters and digits of the parameter value. - * - * @throws UnexpectedValueException if the value cannot be converted to string - */ - public function getAlnum(string $key, string $default = ''): string - { - return preg_replace('/[^[:alnum:]]/', '', $this->getString($key, $default)); - } - - /** - * Returns the digits of the parameter value. - * - * @throws UnexpectedValueException if the value cannot be converted to string - */ - public function getDigits(string $key, string $default = ''): string - { - return preg_replace('/[^[:digit:]]/', '', $this->getString($key, $default)); - } - - /** - * Returns the parameter as string. - * - * @throws UnexpectedValueException if the value cannot be converted to string - */ - public function getString(string $key, string $default = ''): string - { - $value = $this->get($key, $default); - if (!\is_scalar($value) && !$value instanceof \Stringable) { - throw new UnexpectedValueException(\sprintf('Parameter value "%s" cannot be converted to "string".', $key)); - } - - return (string) $value; - } - - /** - * Returns the parameter value converted to integer. - * - * @throws UnexpectedValueException if the value cannot be converted to integer - */ - public function getInt(string $key, int $default = 0): int - { - return $this->filter($key, $default, \FILTER_VALIDATE_INT, ['flags' => \FILTER_REQUIRE_SCALAR]); - } - - /** - * Returns the parameter value converted to boolean. - * - * @throws UnexpectedValueException if the value cannot be converted to a boolean - */ - public function getBoolean(string $key, bool $default = false): bool - { - return $this->filter($key, $default, \FILTER_VALIDATE_BOOL, ['flags' => \FILTER_REQUIRE_SCALAR]); - } - - /** - * Returns the parameter value converted to an enum. - * - * @template T of \BackedEnum - * - * @param class-string $class - * @param ?T $default - * - * @return ?T - * - * @psalm-return ($default is null ? T|null : T) - * - * @throws UnexpectedValueException if the parameter value cannot be converted to an enum - */ - public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum - { - $value = $this->get($key); - - if (null === $value) { - return $default; - } - - try { - return $class::from($value); - } catch (\ValueError|\TypeError $e) { - throw new UnexpectedValueException(\sprintf('Parameter "%s" cannot be converted to enum: ', $key).$e->getMessage().'.', $e->getCode(), $e); - } - } - - /** - * Filter key. - * - * @param int $filter FILTER_* constant - * @param int|array{flags?: int, options?: array} $options Flags from FILTER_* constants - * - * @see https://php.net/filter-var - * - * @throws UnexpectedValueException if the parameter value is a non-stringable object - * @throws UnexpectedValueException if the parameter value is invalid and \FILTER_NULL_ON_FAILURE is not set - */ - public function filter(string $key, mixed $default = null, int $filter = \FILTER_DEFAULT, mixed $options = []): mixed - { - $value = $this->get($key, $default); - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - // Add a convenience check for arrays. - if (\is_array($value) && !isset($options['flags'])) { - $options['flags'] = \FILTER_REQUIRE_ARRAY; - } - - if (\is_object($value) && !$value instanceof \Stringable) { - throw new UnexpectedValueException(\sprintf('Parameter value "%s" cannot be filtered.', $key)); - } - - if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { - throw new \InvalidArgumentException(\sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); - } - - $options['flags'] ??= 0; - $nullOnFailure = $options['flags'] & \FILTER_NULL_ON_FAILURE; - $options['flags'] |= \FILTER_NULL_ON_FAILURE; - - $value = filter_var($value, $filter, $options); - - if (null !== $value || $nullOnFailure) { - return $value; - } - - throw new \UnexpectedValueException(\sprintf('Parameter value "%s" is invalid and flag "FILTER_NULL_ON_FAILURE" was not set.', $key)); - } - - /** - * Returns an iterator for parameters. - * - * @return \ArrayIterator - */ - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->parameters); - } - - /** - * Returns the number of parameters. - */ - public function count(): int - { - return \count($this->parameters); - } -} diff --git a/vendor/symfony/http-foundation/README.md b/vendor/symfony/http-foundation/README.md deleted file mode 100644 index 5cf9007..0000000 --- a/vendor/symfony/http-foundation/README.md +++ /dev/null @@ -1,14 +0,0 @@ -HttpFoundation Component -======================== - -The HttpFoundation component defines an object-oriented layer for the HTTP -specification. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/http_foundation.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php deleted file mode 100644 index 550090f..0000000 --- a/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\LimiterInterface; -use Symfony\Component\RateLimiter\Policy\NoLimiter; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * An implementation of PeekableRequestRateLimiterInterface that - * fits most use-cases. - * - * @author Wouter de Jong - */ -abstract class AbstractRequestRateLimiter implements PeekableRequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit - { - return $this->doConsume($request, 1); - } - - public function peek(Request $request): RateLimit - { - return $this->doConsume($request, 0); - } - - private function doConsume(Request $request, int $tokens): RateLimit - { - $limiters = $this->getLimiters($request); - if (0 === \count($limiters)) { - $limiters = [new NoLimiter()]; - } - - $minimalRateLimit = null; - foreach ($limiters as $limiter) { - $rateLimit = $limiter->consume($tokens); - - $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit; - } - - return $minimalRateLimit; - } - - public function reset(Request $request): void - { - foreach ($this->getLimiters($request) as $limiter) { - $limiter->reset(); - } - } - - /** - * @return LimiterInterface[] a set of limiters using keys extracted from the request - */ - abstract protected function getLimiters(Request $request): array; - - private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit - { - if ($first->isAccepted() !== $second->isAccepted()) { - return $first->isAccepted() ? $second : $first; - } - - $firstRemainingTokens = $first->getRemainingTokens(); - $secondRemainingTokens = $second->getRemainingTokens(); - - if ($firstRemainingTokens === $secondRemainingTokens) { - return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first; - } - - return $firstRemainingTokens > $secondRemainingTokens ? $second : $first; - } -} diff --git a/vendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php b/vendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php deleted file mode 100644 index 63471af..0000000 --- a/vendor/symfony/http-foundation/RateLimiter/PeekableRequestRateLimiterInterface.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * A request limiter which allows peeking ahead. - * - * This is valuable to reduce the cache backend load in scenarios - * like a login when we only want to consume a token on login failure, - * and where the majority of requests will be successful and thus not - * need to consume a token. - * - * This way we can peek ahead before allowing the request through, and - * only consume if the request failed (1 backend op). This is compared - * to always consuming and then resetting the limit if the request - * is successful (2 backend ops). - * - * @author Jordi Boggiano - */ -interface PeekableRequestRateLimiterInterface extends RequestRateLimiterInterface -{ - public function peek(Request $request): RateLimit; -} diff --git a/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php b/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php deleted file mode 100644 index 4c87a40..0000000 --- a/vendor/symfony/http-foundation/RateLimiter/RequestRateLimiterInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RateLimiter; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\RateLimiter\RateLimit; - -/** - * A special type of limiter that deals with requests. - * - * This allows to limit on different types of information - * from the requests. - * - * @author Wouter de Jong - */ -interface RequestRateLimiterInterface -{ - public function consume(Request $request): RateLimit; - - public function reset(Request $request): void; -} diff --git a/vendor/symfony/http-foundation/RedirectResponse.php b/vendor/symfony/http-foundation/RedirectResponse.php deleted file mode 100644 index b1b1cf3..0000000 --- a/vendor/symfony/http-foundation/RedirectResponse.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RedirectResponse represents an HTTP response doing a redirect. - * - * @author Fabien Potencier - */ -class RedirectResponse extends Response -{ - protected string $targetUrl; - - /** - * Creates a redirect response so that it conforms to the rules defined for a redirect status code. - * - * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., - * but practically every browser redirects on paths only as well - * @param int $status The HTTP status code (302 "Found" by default) - * @param array $headers The headers (Location is always set to the given URL) - * - * @throws \InvalidArgumentException - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3 - */ - public function __construct(string $url, int $status = 302, array $headers = []) - { - parent::__construct('', $status, $headers); - - $this->setTargetUrl($url); - - if (!$this->isRedirect()) { - throw new \InvalidArgumentException(\sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); - } - - if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { - $this->headers->remove('cache-control'); - } - } - - /** - * Returns the target URL. - */ - public function getTargetUrl(): string - { - return $this->targetUrl; - } - - /** - * Sets the redirect target of this response. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setTargetUrl(string $url): static - { - if ('' === $url) { - throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); - } - - $this->targetUrl = $url; - - $this->setContent( - \sprintf(' - - - - - - Redirecting to %1$s - - - Redirecting to %1$s. - -', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); - - $this->headers->set('Location', $url); - $this->headers->set('Content-Type', 'text/html; charset=utf-8'); - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php deleted file mode 100644 index 9d74e2f..0000000 --- a/vendor/symfony/http-foundation/Request.php +++ /dev/null @@ -1,2214 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\BadRequestException; -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Exception\JsonException; -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AcceptHeader::class); -class_exists(FileBag::class); -class_exists(HeaderBag::class); -class_exists(HeaderUtils::class); -class_exists(InputBag::class); -class_exists(ParameterBag::class); -class_exists(ServerBag::class); - -/** - * Request represents an HTTP request. - * - * The methods dealing with URL accept / return a raw path (% encoded): - * * getBasePath - * * getBaseUrl - * * getPathInfo - * * getRequestUri - * * getUri - * * getUriForPath - * - * @author Fabien Potencier - */ -class Request -{ - public const HEADER_FORWARDED = 0b000001; // When using RFC 7239 - public const HEADER_X_FORWARDED_FOR = 0b000010; - public const HEADER_X_FORWARDED_HOST = 0b000100; - public const HEADER_X_FORWARDED_PROTO = 0b001000; - public const HEADER_X_FORWARDED_PORT = 0b010000; - public const HEADER_X_FORWARDED_PREFIX = 0b100000; - - public const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host - public const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy - - public const METHOD_HEAD = 'HEAD'; - public const METHOD_GET = 'GET'; - public const METHOD_POST = 'POST'; - public const METHOD_PUT = 'PUT'; - public const METHOD_PATCH = 'PATCH'; - public const METHOD_DELETE = 'DELETE'; - public const METHOD_PURGE = 'PURGE'; - public const METHOD_OPTIONS = 'OPTIONS'; - public const METHOD_TRACE = 'TRACE'; - public const METHOD_CONNECT = 'CONNECT'; - public const METHOD_QUERY = 'QUERY'; - - /** - * @var string[] - */ - protected static array $trustedProxies = []; - - /** - * @var string[] - */ - protected static array $trustedHostPatterns = []; - - /** - * @var string[] - */ - protected static array $trustedHosts = []; - - protected static bool $httpMethodParameterOverride = false; - - /** - * The HTTP methods that can be overridden. - * - * @var uppercase-string[]|null - */ - protected static ?array $allowedHttpMethodOverride = null; - - /** - * Custom parameters. - */ - public ParameterBag $attributes; - - /** - * Request body parameters ($_POST). - * - * @see getPayload() for portability between content types - */ - public InputBag $request; - - /** - * Query string parameters ($_GET). - * - * @var InputBag - */ - public InputBag $query; - - /** - * Server and execution environment parameters ($_SERVER). - */ - public ServerBag $server; - - /** - * Uploaded files ($_FILES). - */ - public FileBag $files; - - /** - * Cookies ($_COOKIE). - * - * @var InputBag - */ - public InputBag $cookies; - - /** - * Headers (taken from the $_SERVER). - */ - public HeaderBag $headers; - - /** - * @var string|resource|false|null - */ - protected $content; - - /** - * @var string[]|null - */ - protected ?array $languages = null; - - /** - * @var string[]|null - */ - protected ?array $charsets = null; - - /** - * @var string[]|null - */ - protected ?array $encodings = null; - - /** - * @var string[]|null - */ - protected ?array $acceptableContentTypes = null; - - protected ?string $pathInfo = null; - protected ?string $requestUri = null; - protected ?string $baseUrl = null; - protected ?string $basePath = null; - protected ?string $method = null; - protected ?string $format = null; - protected SessionInterface|\Closure|null $session = null; - protected ?string $locale = null; - protected string $defaultLocale = 'en'; - - /** - * @var array|null - */ - protected static ?array $formats = null; - - protected static ?\Closure $requestFactory = null; - - private ?string $preferredFormat = null; - - private bool $isHostValid = true; - private bool $isForwardedValid = true; - private bool $isSafeContentPreferred; - - private array $trustedValuesCache = []; - - private static int $trustedHeaderSet = -1; - - private const FORWARDED_PARAMS = [ - self::HEADER_X_FORWARDED_FOR => 'for', - self::HEADER_X_FORWARDED_HOST => 'host', - self::HEADER_X_FORWARDED_PROTO => 'proto', - self::HEADER_X_FORWARDED_PORT => 'host', - ]; - - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - */ - private const TRUSTED_HEADERS = [ - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', - self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', - self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', - self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX', - ]; - - /** - * This mapping is used when no exact MIME match is found in $formats. - * - * It enables mappings like application/soap+xml -> xml. - * - * @see https://datatracker.ietf.org/doc/html/rfc6839 - * @see https://datatracker.ietf.org/doc/html/rfc7303 - * @see https://www.iana.org/assignments/media-types/media-types.xhtml - */ - private const STRUCTURED_SUFFIX_FORMATS = [ - 'json' => 'json', - 'xml' => 'xml', - 'xhtml' => 'html', - 'cbor' => 'cbor', - 'zip' => 'zip', - 'ber' => 'asn1', - 'der' => 'asn1', - 'tlv' => 'tlv', - 'wbxml' => 'xml', - 'yaml' => 'yaml', - ]; - - private bool $isIisRewrite = false; - - /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Sets the parameters for this request. - * - * This method also re-initializes all properties. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void - { - $this->request = new InputBag($request); - $this->query = new InputBag($query); - $this->attributes = new ParameterBag($attributes); - $this->cookies = new InputBag($cookies); - $this->files = new FileBag($files); - $this->server = new ServerBag($server); - $this->headers = new HeaderBag($this->server->getHeaders()); - - $this->content = $content; - $this->languages = null; - $this->charsets = null; - $this->encodings = null; - $this->acceptableContentTypes = null; - $this->pathInfo = null; - $this->requestUri = null; - $this->baseUrl = null; - $this->basePath = null; - $this->method = null; - $this->format = null; - } - - /** - * Creates a new request with values from PHP's super globals. - */ - public static function createFromGlobals(): static - { - if (!\in_array($_SERVER['REQUEST_METHOD'] ?? null, ['PUT', 'DELETE', 'PATCH', 'QUERY'], true)) { - return self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); - } - - try { - [$post, $files] = request_parse_body(); - } catch (\RequestParseBodyException) { - $post = $_POST; - $files = $_FILES; - } - - return self::createRequestFromFactory($_GET, $post, [], $_COOKIE, $files, $_SERVER); - } - - /** - * Creates a Request based on a given URI and configuration. - * - * The information contained in the URI always take precedence - * over the other information (server and parameters). - * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource|null $content The raw body data - * - * @throws BadRequestException When the URI is invalid - */ - public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null): static - { - $server = array_replace([ - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => 80, - 'HTTP_HOST' => 'localhost', - 'HTTP_USER_AGENT' => 'Symfony', - 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', - 'REMOTE_ADDR' => '127.0.0.1', - 'SCRIPT_NAME' => '', - 'SCRIPT_FILENAME' => '', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'REQUEST_TIME' => time(), - 'REQUEST_TIME_FLOAT' => microtime(true), - ], $server); - - $server['PATH_INFO'] = ''; - $server['REQUEST_METHOD'] = strtoupper($method); - - if (($i = strcspn($uri, ':/?#')) && ':' === ($uri[$i] ?? null) && (strspn($uri, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-.') !== $i || strcspn($uri, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'))) { - throw new BadRequestException('Invalid URI: Scheme is malformed.'); - } - if (false === $components = parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri.'#')) { - throw new BadRequestException('Invalid URI.'); - } - - $part = ($components['user'] ?? '').':'.($components['pass'] ?? ''); - - if (':' !== $part && \strlen($part) !== strcspn($part, '[]')) { - throw new BadRequestException('Invalid URI: Userinfo is malformed.'); - } - if (($part = $components['host'] ?? '') && !self::isHostValid($part)) { - throw new BadRequestException('Invalid URI: Host is malformed.'); - } - if (false !== ($i = strpos($uri, '\\')) && $i < strcspn($uri, '?#')) { - throw new BadRequestException('Invalid URI: A URI cannot contain a backslash.'); - } - if (\strlen($uri) !== strcspn($uri, "\r\n\t")) { - throw new BadRequestException('Invalid URI: A URI cannot contain CR/LF/TAB characters.'); - } - if ('' !== $uri && (\ord($uri[0]) <= 32 || \ord($uri[-1]) <= 32)) { - throw new BadRequestException('Invalid URI: A URI must not start nor end with ASCII control characters or spaces.'); - } - - if (isset($components['host'])) { - $server['SERVER_NAME'] = $components['host']; - $server['HTTP_HOST'] = $components['host']; - } - - if (isset($components['scheme'])) { - if ('https' === $components['scheme']) { - $server['HTTPS'] = 'on'; - $server['SERVER_PORT'] = 443; - } else { - unset($server['HTTPS']); - $server['SERVER_PORT'] = 80; - } - } - - if (isset($components['port'])) { - $server['SERVER_PORT'] = $components['port']; - $server['HTTP_HOST'] .= ':'.$components['port']; - } - - if (isset($components['user'])) { - $server['PHP_AUTH_USER'] = $components['user']; - } - - if (isset($components['pass'])) { - $server['PHP_AUTH_PW'] = $components['pass']; - } - - if (!isset($components['path'])) { - $components['path'] = '/'; - } - - switch (strtoupper($method)) { - case 'POST': - case 'PUT': - case 'DELETE': - case 'QUERY': - if (!isset($server['CONTENT_TYPE'])) { - $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; - } - // no break - case 'PATCH': - $request = $parameters; - $query = []; - break; - default: - $request = []; - $query = $parameters; - break; - } - - $queryString = ''; - if (isset($components['query'])) { - parse_str(html_entity_decode($components['query']), $qs); - - if ($query) { - $query = array_replace($qs, $query); - $queryString = http_build_query($query, '', '&'); - } else { - $query = $qs; - $queryString = $components['query']; - } - } elseif ($query) { - $queryString = http_build_query($query, '', '&'); - } - - $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); - $server['QUERY_STRING'] = $queryString; - - return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); - } - - /** - * Sets a callable able to create a Request instance. - * - * This is mainly useful when you need to override the Request class - * to keep BC with an existing system. It should not be used for any - * other purpose. - */ - public static function setFactory(?callable $callable): void - { - self::$requestFactory = null === $callable ? null : $callable(...); - } - - /** - * Clones a request and overrides some of its parameters. - * - * @param array|null $query The GET parameters - * @param array|null $request The POST parameters - * @param array|null $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array|null $cookies The COOKIE parameters - * @param array|null $files The FILES parameters - * @param array|null $server The SERVER parameters - */ - public function duplicate(?array $query = null, ?array $request = null, ?array $attributes = null, ?array $cookies = null, ?array $files = null, ?array $server = null): static - { - $dup = clone $this; - if (null !== $query) { - $dup->query = new InputBag($query); - } - if (null !== $request) { - $dup->request = new InputBag($request); - } - if (null !== $attributes) { - $dup->attributes = new ParameterBag($attributes); - } - if (null !== $cookies) { - $dup->cookies = new InputBag($cookies); - } - if (null !== $files) { - $dup->files = new FileBag($files); - } - if (null !== $server) { - $dup->server = new ServerBag($server); - $dup->headers = new HeaderBag($dup->server->getHeaders()); - } - $dup->languages = null; - $dup->charsets = null; - $dup->encodings = null; - $dup->acceptableContentTypes = null; - $dup->pathInfo = null; - $dup->requestUri = null; - $dup->baseUrl = null; - $dup->basePath = null; - $dup->method = null; - $dup->format = null; - - if (!$dup->attributes->has('_format') && $this->attributes->has('_format')) { - $dup->attributes->set('_format', $this->attributes->get('_format')); - } - - if (!$dup->getRequestFormat(null)) { - $dup->setRequestFormat($this->getRequestFormat(null)); - } - - return $dup; - } - - /** - * Clones the current request. - * - * Note that the session is not cloned as duplicated requests - * are most of the time sub-requests of the main one. - */ - public function __clone() - { - $this->query = clone $this->query; - $this->request = clone $this->request; - $this->attributes = clone $this->attributes; - $this->cookies = clone $this->cookies; - $this->files = clone $this->files; - $this->server = clone $this->server; - $this->headers = clone $this->headers; - } - - public function __toString(): string - { - $content = $this->getContent(); - - $cookieHeader = ''; - $cookies = []; - - foreach ($this->cookies as $k => $v) { - $cookies[] = \is_array($v) ? http_build_query([$k => $v], '', '; ', \PHP_QUERY_RFC3986) : "$k=$v"; - } - - if ($cookies) { - $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; - } - - return - \sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". - $this->headers. - $cookieHeader."\r\n". - $content; - } - - /** - * Overrides the PHP global variables according to this request instance. - * - * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. - * $_FILES is never overridden, see rfc1867 - */ - public function overrideGlobals(): void - { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); - - $_GET = $this->query->all(); - $_POST = $this->request->all(); - $_SERVER = $this->server->all(); - $_COOKIE = $this->cookies->all(); - - foreach ($this->headers->all() as $key => $value) { - $key = strtoupper(str_replace('-', '_', $key)); - if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $_SERVER[$key] = implode(', ', $value); - } else { - $_SERVER['HTTP_'.$key] = implode(', ', $value); - } - } - - $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - - $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order'); - $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; - - $_REQUEST = [[]]; - - foreach (str_split($requestOrder) as $order) { - $_REQUEST[] = $request[$order]; - } - - $_REQUEST = array_merge(...$_REQUEST); - } - - /** - * Sets a list of trusted proxies. - * - * You should only list the reverse proxies that you manage directly. - * - * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] and 'PRIVATE_SUBNETS' by IpUtils::PRIVATE_SUBNETS - * @param int-mask-of $trustedHeaderSet A bit field to set which headers to trust from your proxies - */ - public static function setTrustedProxies(array $proxies, int $trustedHeaderSet): void - { - if (false !== $i = array_search('REMOTE_ADDR', $proxies, true)) { - if (isset($_SERVER['REMOTE_ADDR'])) { - $proxies[$i] = $_SERVER['REMOTE_ADDR']; - } else { - unset($proxies[$i]); - $proxies = array_values($proxies); - } - } - - if (false !== ($i = array_search('PRIVATE_SUBNETS', $proxies, true)) || false !== ($i = array_search('private_ranges', $proxies, true))) { - unset($proxies[$i]); - $proxies = array_merge($proxies, IpUtils::PRIVATE_SUBNETS); - } - - self::$trustedProxies = $proxies; - self::$trustedHeaderSet = $trustedHeaderSet; - } - - /** - * Gets the list of trusted proxies. - * - * @return string[] - */ - public static function getTrustedProxies(): array - { - return self::$trustedProxies; - } - - /** - * Gets the set of trusted headers from trusted proxies. - * - * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies - */ - public static function getTrustedHeaderSet(): int - { - return self::$trustedHeaderSet; - } - - /** - * Sets a list of trusted host patterns. - * - * You should only list the hosts you manage using regexs. - * - * @param array $hostPatterns A list of trusted host patterns - */ - public static function setTrustedHosts(array $hostPatterns): void - { - self::$trustedHostPatterns = array_map(fn ($hostPattern) => \sprintf('{%s}i', $hostPattern), $hostPatterns); - // we need to reset trusted hosts on trusted host patterns change - self::$trustedHosts = []; - } - - /** - * Gets the list of trusted host patterns. - * - * @return string[] - */ - public static function getTrustedHosts(): array - { - return self::$trustedHostPatterns; - } - - /** - * Normalizes a query string. - * - * It builds a normalized query string, where keys/value pairs are alphabetized, - * have consistent escaping and unneeded delimiters are removed. - */ - public static function normalizeQueryString(?string $qs): string - { - if ('' === ($qs ?? '')) { - return ''; - } - - $qs = HeaderUtils::parseQuery($qs); - ksort($qs); - - return http_build_query($qs, '', '&', \PHP_QUERY_RFC3986); - } - - /** - * Enables support for the _method request parameter to determine the intended HTTP method. - * - * Be warned that enabling this feature might lead to CSRF issues in your code. - * Check that you are using CSRF tokens when required. - * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered - * and used to send a "PUT" or "DELETE" request via the _method request parameter. - * If these methods are not protected against CSRF, this presents a possible vulnerability. - * - * The HTTP method can only be overridden when the real HTTP method is POST. - */ - public static function enableHttpMethodParameterOverride(): void - { - self::$httpMethodParameterOverride = true; - } - - /** - * Checks whether support for the _method request parameter is enabled. - */ - public static function getHttpMethodParameterOverride(): bool - { - return self::$httpMethodParameterOverride; - } - - /** - * Sets the list of HTTP methods that can be overridden. - * - * Set to null to allow all methods to be overridden (default). Set to an - * empty array to disallow overrides entirely. Otherwise, provide the list - * of uppercased method names that are allowed. - * - * @param uppercase-string[]|null $methods - */ - public static function setAllowedHttpMethodOverride(?array $methods): void - { - if (array_intersect($methods ?? [], ['GET', 'HEAD', 'CONNECT', 'TRACE'])) { - throw new \InvalidArgumentException('The HTTP methods "GET", "HEAD", "CONNECT", and "TRACE" cannot be overridden.'); - } - - self::$allowedHttpMethodOverride = $methods; - } - - /** - * Gets the list of HTTP methods that can be overridden. - * - * @return uppercase-string[]|null - */ - public static function getAllowedHttpMethodOverride(): ?array - { - return self::$allowedHttpMethodOverride; - } - - /** - * Gets the Session. - * - * @throws SessionNotFoundException When session is not set properly - */ - public function getSession(): SessionInterface - { - $session = $this->session; - if (!$session instanceof SessionInterface && null !== $session) { - $this->setSession($session = $session()); - } - - if (null === $session) { - throw new SessionNotFoundException('Session has not been set.'); - } - - return $session; - } - - /** - * Whether the request contains a Session which was started in one of the - * previous requests. - */ - public function hasPreviousSession(): bool - { - // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); - } - - /** - * Whether the request contains a Session object. - * - * This method does not give any information about the state of the session object, - * like whether the session is started or not. It is just a way to check if this Request - * is associated with a Session instance. - * - * @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory` - */ - public function hasSession(bool $skipIfUninitialized = false): bool - { - return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface); - } - - public function setSession(SessionInterface $session): void - { - $this->session = $session; - } - - /** - * @internal - * - * @param callable(): SessionInterface $factory - */ - public function setSessionFactory(callable $factory): void - { - $this->session = $factory(...); - } - - /** - * Returns the client IP addresses. - * - * In the returned array the most trusted IP address is first, and the - * least trusted one last. The "real" client IP address is the last one, - * but this is also the least trusted one. Trusted proxies are stripped. - * - * Use this method carefully; you should use getClientIp() instead. - * - * @see getClientIp() - */ - public function getClientIps(): array - { - $ip = $this->server->get('REMOTE_ADDR'); - - if (!$this->isFromTrustedProxy()) { - return [$ip]; - } - - return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; - } - - /** - * Returns the client IP address. - * - * This method can read the client IP address from the "X-Forwarded-For" header - * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" - * header value is a comma+space separated list of IP addresses, the left-most - * being the original client, and each successive proxy that passed the request - * adding the IP address where it received the request from. - * - * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * - * @see getClientIps() - * @see https://wikipedia.org/wiki/X-Forwarded-For - */ - public function getClientIp(): ?string - { - return $this->getClientIps()[0]; - } - - /** - * Returns current script name. - */ - public function getScriptName(): string - { - return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); - } - - /** - * Returns the path being requested relative to the executed script. - * - * The path info always starts with a /. - * - * Suppose this request is instantiated from /mysite on localhost: - * - * * http://localhost/mysite returns '/' - * * http://localhost/mysite/about returns '/about' - * * http://localhost/mysite/enco%20ded returns '/enco%20ded' - * * http://localhost/mysite/about?var=1 returns '/about' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getPathInfo(): string - { - return $this->pathInfo ??= $this->preparePathInfo(); - } - - /** - * Returns the root path from which this request is executed. - * - * Suppose that an index.php file instantiates this request object: - * - * * http://localhost/index.php returns an empty string - * * http://localhost/index.php/page returns an empty string - * * http://localhost/web/index.php returns '/web' - * * http://localhost/we%20b/index.php returns '/we%20b' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getBasePath(): string - { - return $this->basePath ??= $this->prepareBasePath(); - } - - /** - * Returns the root URL from which this request is executed. - * - * The base URL never ends with a /. - * - * This is similar to getBasePath(), except that it also includes the - * script filename (e.g. index.php) if one exists. - * - * @return string The raw URL (i.e. not urldecoded) - */ - public function getBaseUrl(): string - { - $trustedPrefix = ''; - - // the proxy prefix must be prepended to any prefix being needed at the webserver level - if ($this->isFromTrustedProxy() && $trustedPrefixValues = $this->getTrustedValues(self::HEADER_X_FORWARDED_PREFIX)) { - $trustedPrefix = rtrim($trustedPrefixValues[0], '/'); - } - - return $trustedPrefix.$this->getBaseUrlReal(); - } - - /** - * Returns the real base URL received by the webserver from which this request is executed. - * The URL does not include trusted reverse proxy prefix. - * - * @return string The raw URL (i.e. not urldecoded) - */ - private function getBaseUrlReal(): string - { - return $this->baseUrl ??= $this->prepareBaseUrl(); - } - - /** - * Gets the request's scheme. - */ - public function getScheme(): string - { - return $this->isSecure() ? 'https' : 'http'; - } - - /** - * Returns the port on which the request is made. - * - * This method can read the client port from the "X-Forwarded-Port" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Port" header must contain the client port. - * - * @return int|string|null Can be a string if fetched from the server bag - */ - public function getPort(): int|string|null - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { - $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - return $this->server->get('SERVER_PORT'); - } - - if ('[' === $host[0]) { - $pos = strpos($host, ':', strrpos($host, ']')); - } else { - $pos = strrpos($host, ':'); - } - - if (false !== $pos && $port = substr($host, $pos + 1)) { - return (int) $port; - } - - return 'https' === $this->getScheme() ? 443 : 80; - } - - /** - * Returns the user. - */ - public function getUser(): ?string - { - return $this->headers->get('PHP_AUTH_USER'); - } - - /** - * Returns the password. - */ - public function getPassword(): ?string - { - return $this->headers->get('PHP_AUTH_PW'); - } - - /** - * Gets the user info. - * - * @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server - */ - public function getUserInfo(): ?string - { - $userinfo = $this->getUser(); - - $pass = $this->getPassword(); - if ('' != $pass) { - $userinfo .= ":$pass"; - } - - return $userinfo; - } - - /** - * Returns the HTTP host being requested. - * - * The port name will be appended to the host if it's non-standard. - */ - public function getHttpHost(): string - { - $scheme = $this->getScheme(); - $port = $this->getPort(); - - if (('http' === $scheme && 80 == $port) || ('https' === $scheme && 443 == $port)) { - return $this->getHost(); - } - - return $this->getHost().':'.$port; - } - - /** - * Returns the requested URI (path and query string). - * - * @return string The raw URI (i.e. not URI decoded) - */ - public function getRequestUri(): string - { - return $this->requestUri ??= $this->prepareRequestUri(); - } - - /** - * Gets the scheme and HTTP host. - * - * If the URL was called with basic authentication, the user - * and the password are not added to the generated string. - */ - public function getSchemeAndHttpHost(): string - { - return $this->getScheme().'://'.$this->getHttpHost(); - } - - /** - * Generates a normalized URI (URL) for the Request. - * - * @see getQueryString() - */ - public function getUri(): string - { - if (null !== $qs = $this->getQueryString()) { - $qs = '?'.$qs; - } - - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; - } - - /** - * Generates a normalized URI for the given path. - * - * @param string $path A path to use instead of the current one - */ - public function getUriForPath(string $path): string - { - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; - } - - /** - * Returns the path as relative reference from the current Request path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - */ - public function getRelativeUriForPath(string $path): string - { - // be sure that we are dealing with an absolute path - if (!isset($path[0]) || '/' !== $path[0]) { - return $path; - } - - if ($path === $basePath = $this->getPathInfo()) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', substr($path, 1)); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see https://tools.ietf.org/html/rfc3986#section-4.2). - return !isset($path[0]) || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } - - /** - * Generates the normalized query string for the Request. - * - * It builds a normalized query string, where keys/value pairs are alphabetized - * and have consistent escaping. - */ - public function getQueryString(): ?string - { - $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); - - return '' === $qs ? null : $qs; - } - - /** - * Checks whether the request is secure or not. - * - * This method can read the client protocol from the "X-Forwarded-Proto" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". - */ - public function isSecure(): bool - { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { - return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); - } - - $https = $this->server->get('HTTPS'); - - return $https && (!\is_string($https) || 'off' !== strtolower($https)); - } - - /** - * Returns the host name. - * - * This method can read the client host name from the "X-Forwarded-Host" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Host" header must contain the client host name. - * - * @throws SuspiciousOperationException when the host name is invalid or not trusted - */ - public function getHost(): string - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } else { - $host = $this->headers->get('HOST') ?: $this->server->get('SERVER_NAME') ?: $this->server->get('SERVER_ADDR', ''); - } - - // trim and remove port number from host - // host is lowercase as per RFC 952/2181 - $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); - - // the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) - if ($host && !self::isHostValid($host)) { - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(\sprintf('Invalid Host "%s".', $host)); - } - - if (\count(self::$trustedHostPatterns) > 0) { - // to avoid host header injection attacks, you should provide a list of trusted host patterns - - if (\in_array($host, self::$trustedHosts, true)) { - return $host; - } - - foreach (self::$trustedHostPatterns as $pattern) { - if (preg_match($pattern, $host)) { - self::$trustedHosts[] = $host; - - return $host; - } - } - - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(\sprintf('Untrusted Host "%s".', $host)); - } - - return $host; - } - - /** - * Sets the request method. - */ - public function setMethod(string $method): void - { - $this->method = null; - $this->server->set('REQUEST_METHOD', $method); - } - - /** - * Gets the request "intended" method. - * - * If the X-HTTP-Method-Override header is set, and if the method is a POST, - * then it is used to determine the "real" intended HTTP method. - * - * The _method request parameter can also be used to determine the HTTP method, - * but only if enableHttpMethodParameterOverride() has been called. - * - * The method is always an uppercased string. - * - * @see getRealMethod() - */ - public function getMethod(): string - { - if (null !== $this->method) { - return $this->method; - } - - $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - - if ('POST' !== $this->method || !(self::$allowedHttpMethodOverride ?? true)) { - return $this->method; - } - - $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); - - if (!$method && self::$httpMethodParameterOverride) { - $method = $this->request->get('_method', $this->query->get('_method', 'POST')); - } - - if (!\is_string($method)) { - return $this->method; - } - - $method = strtoupper($method); - - if (\in_array($method, ['GET', 'HEAD', 'CONNECT', 'TRACE'], true)) { - return $this->method; - } - - if (self::$allowedHttpMethodOverride && !\in_array($method, self::$allowedHttpMethodOverride, true)) { - return $this->method; - } - - if (\strlen($method) !== strspn($method, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')) { - throw new SuspiciousOperationException('Invalid HTTP method override.'); - } - - return $this->method = $method; - } - - /** - * Gets the "real" request method. - * - * @see getMethod() - */ - public function getRealMethod(): string - { - return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - } - - /** - * Gets the mime type associated with the format. - */ - public function getMimeType(string $format): ?string - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; - } - - /** - * Gets the mime types associated with the format. - * - * @return string[] - */ - public static function getMimeTypes(string $format): array - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return static::$formats[$format] ?? []; - } - - /** - * Gets the format associated with the mime type. - * - * Resolution order: - * 1) Exact match on the full MIME type (e.g. "application/json"). - * 2) Match on the canonical MIME type (i.e. before the first ";" parameter). - * 3) If the type is "application/*+suffix", use the structured syntax suffix - * mapping (e.g. "application/foo+json" → "json"), when available. - * 4) If $subtypeFallback is true and no match was found: - * - return the MIME subtype (without "x-" prefix), provided it does not - * contain a "+" (e.g. "application/x-yaml" → "yaml", "text/csv" → "csv"). - * - * @param string|null $mimeType The mime type to check - * @param bool $subtypeFallback Whether to fall back to the subtype if no exact match is found - */ - public function getFormat(?string $mimeType, bool $subtypeFallback = false): ?string - { - $canonicalMimeType = null; - if ($mimeType && false !== $pos = strpos($mimeType, ';')) { - $canonicalMimeType = trim(substr($mimeType, 0, $pos)); - } - - if (null === static::$formats) { - static::initializeFormats(); - } - - $exactFormat = null; - $canonicalFormat = null; - - foreach (static::$formats as $format => $mimeTypes) { - if (\in_array($mimeType, $mimeTypes, true)) { - $exactFormat = $format; - } - if (null !== $canonicalMimeType && \in_array($canonicalMimeType, $mimeTypes, true)) { - $canonicalFormat = $format; - } - } - - if ($format = $exactFormat ?? $canonicalFormat) { - return $format; - } - - if (!$canonicalMimeType ??= $mimeType) { - return null; - } - - if (str_starts_with($canonicalMimeType, 'application/') && str_contains($canonicalMimeType, '+')) { - $suffix = substr(strrchr($canonicalMimeType, '+'), 1); - if (isset(self::STRUCTURED_SUFFIX_FORMATS[$suffix])) { - return self::STRUCTURED_SUFFIX_FORMATS[$suffix]; - } - } - - if ($subtypeFallback && str_contains($canonicalMimeType, '/')) { - [, $subtype] = explode('/', $canonicalMimeType, 2); - if (str_starts_with($subtype, 'x-')) { - $subtype = substr($subtype, 2); - } - if (!str_contains($subtype, '+')) { - return $subtype; - } - } - - return null; - } - - /** - * Associates a format with mime types. - * - * @param string|string[] $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) - */ - public function setFormat(string $format, string|array $mimeTypes): void - { - if (null === static::$formats) { - static::initializeFormats(); - } - - static::$formats[$format] = (array) $mimeTypes; - } - - /** - * Gets the request format. - * - * Here is the process to determine the format: - * - * * format defined by the user (with setRequestFormat()) - * * _format request attribute - * * $default - * - * @see getPreferredFormat - */ - public function getRequestFormat(?string $default = 'html'): ?string - { - $this->format ??= $this->attributes->get('_format'); - - return $this->format ?? $default; - } - - /** - * Sets the request format. - */ - public function setRequestFormat(?string $format): void - { - $this->format = $format; - } - - /** - * Gets the usual name of the format associated with the request's media type (provided in the Content-Type header). - * - * @see Request::$formats - */ - public function getContentTypeFormat(): ?string - { - return $this->getFormat($this->headers->get('CONTENT_TYPE', '')); - } - - /** - * Sets the default locale. - */ - public function setDefaultLocale(string $locale): void - { - $this->defaultLocale = $locale; - - if (null === $this->locale) { - $this->setPhpDefaultLocale($locale); - } - } - - /** - * Get the default locale. - */ - public function getDefaultLocale(): string - { - return $this->defaultLocale; - } - - /** - * Sets the locale. - */ - public function setLocale(string $locale): void - { - $this->setPhpDefaultLocale($this->locale = $locale); - } - - /** - * Get the locale. - */ - public function getLocale(): string - { - return $this->locale ?? $this->defaultLocale; - } - - /** - * Checks if the request method is of specified type. - * - * @param string $method Uppercase request method (GET, POST etc) - */ - public function isMethod(string $method): bool - { - return $this->getMethod() === strtoupper($method); - } - - /** - * Checks whether or not the method is safe. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 - */ - public function isMethodSafe(): bool - { - return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE', 'QUERY'], true); - } - - /** - * Checks whether or not the method is idempotent. - */ - public function isMethodIdempotent(): bool - { - return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE', 'QUERY'], true); - } - - /** - * Checks whether the method is cacheable or not. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 - */ - public function isMethodCacheable(): bool - { - return \in_array($this->getMethod(), ['GET', 'HEAD', 'QUERY'], true); - } - - /** - * Returns the protocol version. - * - * If the application is behind a proxy, the protocol version used in the - * requests between the client and the proxy and between the proxy and the - * server might be different. This returns the former (from the "Via" header) - * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns - * the latter (from the "SERVER_PROTOCOL" server parameter). - */ - public function getProtocolVersion(): ?string - { - if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9])\b~', $this->headers->get('Via') ?? '', $matches); - - if ($matches) { - return 'HTTP/'.$matches[2]; - } - } - - return $this->server->get('SERVER_PROTOCOL'); - } - - /** - * Returns the request body content. - * - * @param bool $asResource If true, a resource will be returned - * - * @return string|resource - * - * @psalm-return ($asResource is true ? resource : string) - */ - public function getContent(bool $asResource = false) - { - if ($asResource) { - if (\is_resource($this->content)) { - rewind($this->content); - - return $this->content; - } - - // Content passed in parameter (test) - if (\is_string($this->content)) { - $resource = fopen('php://temp', 'r+'); - fwrite($resource, $this->content); - rewind($resource); - - return $resource; - } - - $this->content = false; - - return fopen('php://input', 'r'); - } - - if (\is_resource($this->content)) { - rewind($this->content); - - return stream_get_contents($this->content); - } - - if (null === $this->content || false === $this->content) { - $this->content = file_get_contents('php://input'); - } - - return $this->content; - } - - /** - * Gets the decoded form or json request body. - * - * @throws JsonException When the body cannot be decoded to an array - */ - public function getPayload(): InputBag - { - if ($this->request->count()) { - return clone $this->request; - } - - if ('' === $content = $this->getContent()) { - return new InputBag([]); - } - - try { - $content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR); - } catch (\JsonException $e) { - throw new JsonException('Could not decode request body.', $e->getCode(), $e); - } - - if (!\is_array($content)) { - throw new JsonException(\sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content))); - } - - return new InputBag($content); - } - - /** - * Gets the request body decoded as array, typically from a JSON payload. - * - * @see getPayload() for portability between content types - * - * @throws JsonException When the body cannot be decoded to an array - */ - public function toArray(): array - { - if ('' === $content = $this->getContent()) { - throw new JsonException('Request body is empty.'); - } - - try { - $content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR); - } catch (\JsonException $e) { - throw new JsonException('Could not decode request body.', $e->getCode(), $e); - } - - if (!\is_array($content)) { - throw new JsonException(\sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content))); - } - - return $content; - } - - /** - * Gets the Etags. - */ - public function getETags(): array - { - return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY); - } - - public function isNoCache(): bool - { - return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); - } - - /** - * Gets the preferred format for the response by inspecting, in the following order: - * * the request format set using setRequestFormat; - * * the values of the Accept HTTP header. - * - * Note that if you use this method, you should send the "Vary: Accept" header - * in the response to prevent any issues with intermediary HTTP caches. - */ - public function getPreferredFormat(?string $default = 'html'): ?string - { - if (!isset($this->preferredFormat) && null !== $preferredFormat = $this->getRequestFormat(null)) { - $this->preferredFormat = $preferredFormat; - } - - if ($this->preferredFormat ?? null) { - return $this->preferredFormat; - } - - foreach ($this->getAcceptableContentTypes() as $mimeType) { - if ($this->preferredFormat = $this->getFormat($mimeType)) { - return $this->preferredFormat; - } - } - - return $default; - } - - /** - * Returns the preferred language. - * - * @param string[] $locales An array of ordered available locales - */ - public function getPreferredLanguage(?array $locales = null): ?string - { - $preferredLanguages = $this->getLanguages(); - - if (!$locales) { - return $preferredLanguages[0] ?? null; - } - - $locales = array_map($this->formatLocale(...), $locales); - if (!$preferredLanguages) { - return $locales[0]; - } - - $combinations = array_merge(...array_map($this->getLanguageCombinations(...), $preferredLanguages)); - foreach ($combinations as $combination) { - foreach ($locales as $locale) { - if (str_starts_with($locale, $combination)) { - return $locale; - } - } - } - - return $locales[0]; - } - - /** - * Gets a list of languages acceptable by the client browser ordered in the user browser preferences. - * - * @return string[] - */ - public function getLanguages(): array - { - if (null !== $this->languages) { - return $this->languages; - } - - $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); - $this->languages = []; - foreach ($languages as $acceptHeaderItem) { - $lang = $acceptHeaderItem->getValue(); - $this->languages[] = self::formatLocale($lang); - } - $this->languages = array_unique($this->languages); - - return $this->languages; - } - - /** - * Strips the locale to only keep the canonicalized language value. - * - * Depending on the $locale value, this method can return values like : - * - language_Script_REGION: "fr_Latn_FR", "zh_Hans_TW" - * - language_Script: "fr_Latn", "zh_Hans" - * - language_REGION: "fr_FR", "zh_TW" - * - language: "fr", "zh" - * - * Invalid locale values are returned as is. - * - * @see https://wikipedia.org/wiki/IETF_language_tag - * @see https://datatracker.ietf.org/doc/html/rfc5646 - */ - private static function formatLocale(string $locale): string - { - [$language, $script, $region] = self::getLanguageComponents($locale); - - return implode('_', array_filter([$language, $script, $region])); - } - - /** - * Returns an array of all possible combinations of the language components. - * - * For instance, if the locale is "fr_Latn_FR", this method will return: - * - "fr_Latn_FR" - * - "fr_Latn" - * - "fr_FR" - * - "fr" - * - * @return string[] - */ - private static function getLanguageCombinations(string $locale): array - { - [$language, $script, $region] = self::getLanguageComponents($locale); - - return array_unique([ - implode('_', array_filter([$language, $script, $region])), - implode('_', array_filter([$language, $script])), - implode('_', array_filter([$language, $region])), - $language, - ]); - } - - /** - * Returns an array with the language components of the locale. - * - * For example: - * - If the locale is "fr_Latn_FR", this method will return "fr", "Latn", "FR" - * - If the locale is "fr_FR", this method will return "fr", null, "FR" - * - If the locale is "zh_Hans", this method will return "zh", "Hans", null - * - * @see https://wikipedia.org/wiki/IETF_language_tag - * @see https://datatracker.ietf.org/doc/html/rfc5646 - * - * @return array{string, string|null, string|null} - */ - private static function getLanguageComponents(string $locale): array - { - $locale = str_replace('_', '-', strtolower($locale)); - $pattern = '/^([a-zA-Z]{2,3}|i-[a-zA-Z]{5,})(?:-([a-zA-Z]{4}))?(?:-([a-zA-Z]{2}))?(?:-(.+))?$/'; - if (!preg_match($pattern, $locale, $matches)) { - return [$locale, null, null]; - } - if (str_starts_with($matches[1], 'i-')) { - // Language not listed in ISO 639 that are not variants - // of any listed language, which can be registered with the - // i-prefix, such as i-cherokee - $matches[1] = substr($matches[1], 2); - } - - return [ - $matches[1], - isset($matches[2]) ? ucfirst(strtolower($matches[2])) : null, - isset($matches[3]) ? strtoupper($matches[3]) : null, - ]; - } - - /** - * Gets a list of charsets acceptable by the client browser in preferable order. - * - * @return string[] - */ - public function getCharsets(): array - { - return $this->charsets ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all())); - } - - /** - * Gets a list of encodings acceptable by the client browser in preferable order. - * - * @return string[] - */ - public function getEncodings(): array - { - return $this->encodings ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all())); - } - - /** - * Gets a list of content types acceptable by the client browser in preferable order. - * - * @return string[] - */ - public function getAcceptableContentTypes(): array - { - return $this->acceptableContentTypes ??= array_map('strval', array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all())); - } - - /** - * Returns true if the request is an XMLHttpRequest. - * - * It works if your JavaScript library sets an X-Requested-With HTTP header. - * It is known to work with common JavaScript frameworks: - * - * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript - */ - public function isXmlHttpRequest(): bool - { - return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); - } - - /** - * Checks whether the client browser prefers safe content or not according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function preferSafeContent(): bool - { - if (isset($this->isSafeContentPreferred)) { - return $this->isSafeContentPreferred; - } - - if (!$this->isSecure()) { - // see https://tools.ietf.org/html/rfc8674#section-3 - return $this->isSafeContentPreferred = false; - } - - return $this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe'); - } - - /* - * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) - * - * Code subject to the new BSD license (https://framework.zend.com/license). - * - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) - */ - - protected function prepareRequestUri(): string - { - $requestUri = ''; - - if ($this->isIisRewrite() && '' != $this->server->get('UNENCODED_URL')) { - // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) - $requestUri = $this->server->get('UNENCODED_URL'); - $this->server->remove('UNENCODED_URL'); - } elseif ($this->server->has('REQUEST_URI')) { - $requestUri = $this->server->get('REQUEST_URI'); - - if ('' !== $requestUri && '/' === $requestUri[0]) { - // To only use path and query remove the fragment. - if (false !== $pos = strpos($requestUri, '#')) { - $requestUri = substr($requestUri, 0, $pos); - } - } else { - // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, - // only use URL path. - $uriComponents = parse_url($requestUri); - - if (isset($uriComponents['path'])) { - $requestUri = $uriComponents['path']; - } - - if (isset($uriComponents['query'])) { - $requestUri .= '?'.$uriComponents['query']; - } - } - } elseif ($this->server->has('ORIG_PATH_INFO')) { - // IIS 5.0, PHP as CGI - $requestUri = $this->server->get('ORIG_PATH_INFO'); - if ('' != $this->server->get('QUERY_STRING')) { - $requestUri .= '?'.$this->server->get('QUERY_STRING'); - } - $this->server->remove('ORIG_PATH_INFO'); - } - - // normalize the request URI to ease creating sub-requests from this request - $this->server->set('REQUEST_URI', $requestUri); - - return $requestUri; - } - - /** - * Prepares the base URL. - */ - protected function prepareBaseUrl(): string - { - $filename = basename($this->server->get('SCRIPT_FILENAME', '')); - - if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('SCRIPT_NAME'); - } elseif (basename($this->server->get('PHP_SELF', '')) === $filename) { - $baseUrl = $this->server->get('PHP_SELF'); - } elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) { - $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility - } else { - // Backtrack up the script_filename to find the portion matching - // php_self - $path = $this->server->get('PHP_SELF', ''); - $file = $this->server->get('SCRIPT_FILENAME', ''); - $segs = explode('/', trim($file, '/')); - $segs = array_reverse($segs); - $index = 0; - $last = \count($segs); - $baseUrl = ''; - do { - $seg = $segs[$index]; - $baseUrl = '/'.$seg.$baseUrl; - ++$index; - } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); - } - - // Does the baseUrl have anything in common with the request_uri? - $requestUri = $this->getRequestUri(); - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { - // full $baseUrl matches - return $prefix; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { - // directory portion of $baseUrl matches - return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); - } - - $truncatedRequestUri = $requestUri; - if (false !== $pos = strpos($requestUri, '?')) { - $truncatedRequestUri = substr($requestUri, 0, $pos); - } - - $basename = basename($baseUrl ?? ''); - if (!$basename || !strpos(rawurldecode($truncatedRequestUri), $basename)) { - // no match whatsoever; set it blank - return ''; - } - - // If using mod_rewrite or ISAPI_Rewrite strip the script filename - // out of baseUrl. $pos !== 0 makes sure it is not matching a value - // from PATH_INFO or QUERY_STRING - if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { - $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); - } - - return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); - } - - /** - * Prepares the base path. - */ - protected function prepareBasePath(): string - { - $baseUrl = $this->getBaseUrl(); - if (!$baseUrl) { - return ''; - } - - $filename = basename($this->server->get('SCRIPT_FILENAME')); - if (basename($baseUrl) === $filename) { - $basePath = \dirname($baseUrl); - } else { - $basePath = $baseUrl; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $basePath = str_replace('\\', '/', $basePath); - } - - return rtrim($basePath, '/'); - } - - /** - * Prepares the path info. - */ - protected function preparePathInfo(): string - { - if (null === ($requestUri = $this->getRequestUri())) { - return '/'; - } - - // Remove the query string from REQUEST_URI - if (false !== $pos = strpos($requestUri, '?')) { - $requestUri = substr($requestUri, 0, $pos); - } - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if (null === ($baseUrl = $this->getBaseUrlReal())) { - return $requestUri; - } - - $pathInfo = substr($requestUri, \strlen($baseUrl)); - if ('' === $pathInfo || '/' !== $pathInfo[0]) { - return '/'.$pathInfo; - } - - return $pathInfo; - } - - /** - * Initializes HTTP request formats. - */ - protected static function initializeFormats(): void - { - static::$formats = [ - 'html' => ['text/html', 'application/xhtml+xml'], - 'txt' => ['text/plain'], - 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'css' => ['text/css'], - 'json' => ['application/json', 'application/x-json'], - 'jsonld' => ['application/ld+json'], - 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], - 'rdf' => ['application/rdf+xml'], - 'atom' => ['application/atom+xml'], - 'rss' => ['application/rss+xml'], - 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'], - 'soap' => ['application/soap+xml'], - 'problem' => ['application/problem+json'], - 'hal' => ['application/hal+json', 'application/hal+xml'], - 'jsonapi' => ['application/vnd.api+json'], - 'yaml' => ['text/yaml', 'application/x-yaml'], - 'wbxml' => ['application/vnd.wap.wbxml'], - 'pdf' => ['application/pdf'], - 'csv' => ['text/csv'], - ]; - } - - private function setPhpDefaultLocale(string $locale): void - { - // if either the class Locale doesn't exist, or an exception is thrown when - // setting the default locale, the intl module is not installed, and - // the call can be ignored: - try { - if (class_exists(\Locale::class, false)) { - \Locale::setDefault($locale); - } - } catch (\Exception) { - } - } - - /** - * Returns the prefix as encoded in the string when the string starts with - * the given prefix, null otherwise. - */ - private function getUrlencodedPrefix(string $string, string $prefix): ?string - { - if ($this->isIisRewrite()) { - // ISS with UrlRewriteModule might report SCRIPT_NAME/PHP_SELF with wrong case - // see https://github.com/php/php-src/issues/11981 - if (0 !== stripos(rawurldecode($string), $prefix)) { - return null; - } - } elseif (!str_starts_with(rawurldecode($string), $prefix)) { - return null; - } - - $len = \strlen($prefix); - - if (preg_match(\sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { - return $match[0]; - } - - return null; - } - - private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): static - { - if (self::$requestFactory) { - $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); - - if (!$request instanceof self) { - throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); - } - - return $request; - } - - return new static($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Indicates whether this request originated from a trusted proxy. - * - * This can be useful to determine whether or not to trust the - * contents of a proxy-specific header. - */ - public function isFromTrustedProxy(): bool - { - return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies); - } - - /** - * This method is rather heavy because it splits and merges headers, and it's called by many other methods such as - * getPort(), isSecure(), getHost(), getClientIps(), getBaseUrl() etc. Thus, we try to cache the results for - * best performance. - */ - private function getTrustedValues(int $type, ?string $ip = null): array - { - $cacheKey = $type."\0".((self::$trustedHeaderSet & $type) ? $this->headers->get(self::TRUSTED_HEADERS[$type]) : ''); - $cacheKey .= "\0".$ip."\0".$this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); - - if (isset($this->trustedValuesCache[$cacheKey])) { - return $this->trustedValuesCache[$cacheKey]; - } - - $clientValues = []; - $forwardedValues = []; - - if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::TRUSTED_HEADERS[$type])) { - foreach (explode(',', $this->headers->get(self::TRUSTED_HEADERS[$type])) as $v) { - $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); - } - } - - if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && (isset(self::FORWARDED_PARAMS[$type])) && $this->headers->has(self::TRUSTED_HEADERS[self::HEADER_FORWARDED])) { - $forwarded = $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); - $parts = HeaderUtils::split($forwarded, ',;='); - $param = self::FORWARDED_PARAMS[$type]; - foreach ($parts as $subParts) { - if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { - continue; - } - if (self::HEADER_X_FORWARDED_PORT === $type) { - if (str_ends_with($v, ']') || false === $v = strrchr($v, ':')) { - $v = $this->isSecure() ? ':443' : ':80'; - } - $v = '0.0.0.0'.$v; - } - $forwardedValues[] = $v; - } - } - - if (null !== $ip) { - $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); - $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); - } - - if ($forwardedValues === $clientValues || !$clientValues) { - return $this->trustedValuesCache[$cacheKey] = $forwardedValues; - } - - if (!$forwardedValues) { - return $this->trustedValuesCache[$cacheKey] = $clientValues; - } - - if (!$this->isForwardedValid) { - return $this->trustedValuesCache[$cacheKey] = null !== $ip ? ['0.0.0.0', $ip] : []; - } - $this->isForwardedValid = false; - - throw new ConflictingHeadersException(\sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::TRUSTED_HEADERS[self::HEADER_FORWARDED], self::TRUSTED_HEADERS[$type])); - } - - private function normalizeAndFilterClientIps(array $clientIps, string $ip): array - { - if (!$clientIps) { - return []; - } - $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from - $firstTrustedIp = null; - - foreach ($clientIps as $key => $clientIp) { - if (strpos($clientIp, '.')) { - // Strip :port from IPv4 addresses. This is allowed in Forwarded - // and may occur in X-Forwarded-For. - $i = strpos($clientIp, ':'); - if ($i) { - $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); - } - } elseif (str_starts_with($clientIp, '[')) { - // Strip brackets and :port from IPv6 addresses. - $i = strpos($clientIp, ']', 1); - $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); - } - - if (!filter_var($clientIp, \FILTER_VALIDATE_IP)) { - unset($clientIps[$key]); - - continue; - } - - if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { - unset($clientIps[$key]); - - // Fallback to this when the client IP falls into the range of trusted proxies - $firstTrustedIp ??= $clientIp; - } - } - - // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; - } - - /** - * Is this IIS with UrlRewriteModule? - * - * This method consumes, caches and removed the IIS_WasUrlRewritten env var, - * so we don't inherit it to sub-requests. - */ - private function isIisRewrite(): bool - { - if (1 === $this->server->getInt('IIS_WasUrlRewritten')) { - $this->isIisRewrite = true; - $this->server->remove('IIS_WasUrlRewritten'); - } - - return $this->isIisRewrite; - } - - /** - * See https://url.spec.whatwg.org/. - */ - private static function isHostValid(string $host): bool - { - if ('[' === $host[0]) { - return ']' === $host[-1] && filter_var(substr($host, 1, -1), \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6); - } - - if (preg_match('/\.[0-9]++\.?$/D', $host)) { - return null !== filter_var($host, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4 | \FILTER_NULL_ON_FAILURE); - } - - // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names - return '' === preg_replace('/[-a-zA-Z0-9_]++\.?/', '', $host); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php deleted file mode 100644 index 09d6f49..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/AttributesRequestMatcher.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the Request attributes matches all regular expressions. - * - * @author Fabien Potencier - */ -class AttributesRequestMatcher implements RequestMatcherInterface -{ - /** - * @param array $regexps - */ - public function __construct(private array $regexps) - { - } - - public function matches(Request $request): bool - { - foreach ($this->regexps as $key => $regexp) { - $attribute = $request->attributes->get($key); - if (!\is_string($attribute)) { - return false; - } - if (!preg_match('{'.$regexp.'}', $attribute)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php deleted file mode 100644 index 935853f..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/ExpressionRequestMatcher.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * ExpressionRequestMatcher uses an expression to match a Request. - * - * @author Fabien Potencier - */ -class ExpressionRequestMatcher implements RequestMatcherInterface -{ - public function __construct( - private ExpressionLanguage $language, - private Expression|string $expression, - ) { - } - - public function matches(Request $request): bool - { - return $this->language->evaluate($this->expression, [ - 'request' => $request, - 'method' => $request->getMethod(), - 'path' => rawurldecode($request->getPathInfo()), - 'host' => $request->getHost(), - 'ip' => $request->getClientIp(), - 'attributes' => $request->attributes->all(), - ]); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/HeaderRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/HeaderRequestMatcher.php deleted file mode 100644 index 8617a8a..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/HeaderRequestMatcher.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the presence of HTTP headers in a Request. - * - * @author Alexandre Daubois - */ -class HeaderRequestMatcher implements RequestMatcherInterface -{ - /** - * @var string[] - */ - private array $headers; - - /** - * @param string[]|string $headers A header or a list of headers - * Strings can contain a comma-delimited list of headers - */ - public function __construct(array|string $headers) - { - $this->headers = array_reduce((array) $headers, static fn (array $headers, string $header) => array_merge($headers, preg_split('/\s*,\s*/', $header)), []); - } - - public function matches(Request $request): bool - { - if (!$this->headers) { - return true; - } - - foreach ($this->headers as $header) { - if (!$request->headers->has($header)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php deleted file mode 100644 index 2836759..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/HostRequestMatcher.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the Request URL host name matches a regular expression. - * - * @author Fabien Potencier - */ -class HostRequestMatcher implements RequestMatcherInterface -{ - public function __construct(private string $regexp) - { - } - - public function matches(Request $request): bool - { - return preg_match('{'.$this->regexp.'}i', $request->getHost()); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php deleted file mode 100644 index 333612e..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/IpsRequestMatcher.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\IpUtils; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the client IP of a Request. - * - * @author Fabien Potencier - */ -class IpsRequestMatcher implements RequestMatcherInterface -{ - private array $ips; - - /** - * @param string[]|string $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - * Strings can contain a comma-delimited list of IPs/ranges - */ - public function __construct(array|string $ips) - { - $this->ips = array_reduce((array) $ips, static fn (array $ips, string $ip) => array_merge($ips, preg_split('/\s*,\s*/', $ip)), []); - } - - public function matches(Request $request): bool - { - if (!$this->ips) { - return true; - } - - return IpUtils::checkIp($request->getClientIp() ?? '', $this->ips); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php deleted file mode 100644 index 875f992..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/IsJsonRequestMatcher.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the Request content is valid JSON. - * - * @author Fabien Potencier - */ -class IsJsonRequestMatcher implements RequestMatcherInterface -{ - public function matches(Request $request): bool - { - return json_validate($request->getContent()); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php deleted file mode 100644 index b37f6e3..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/MethodRequestMatcher.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the HTTP method of a Request. - * - * @author Fabien Potencier - */ -class MethodRequestMatcher implements RequestMatcherInterface -{ - /** - * @var string[] - */ - private array $methods = []; - - /** - * @param string[]|string $methods An HTTP method or an array of HTTP methods - * Strings can contain a comma-delimited list of methods - */ - public function __construct(array|string $methods) - { - $this->methods = array_reduce(array_map('strtoupper', (array) $methods), static fn (array $methods, string $method) => array_merge($methods, preg_split('/\s*,\s*/', $method)), []); - } - - public function matches(Request $request): bool - { - if (!$this->methods) { - return true; - } - - return \in_array($request->getMethod(), $this->methods, true); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php deleted file mode 100644 index c7c7a02..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/PathRequestMatcher.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the Request URL path info matches a regular expression. - * - * @author Fabien Potencier - */ -class PathRequestMatcher implements RequestMatcherInterface -{ - public function __construct(private string $regexp) - { - } - - public function matches(Request $request): bool - { - return preg_match('{'.$this->regexp.'}', rawurldecode($request->getPathInfo())); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php deleted file mode 100644 index 5a01ce9..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/PortRequestMatcher.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the HTTP port of a Request. - * - * @author Fabien Potencier - */ -class PortRequestMatcher implements RequestMatcherInterface -{ - public function __construct(private int $port) - { - } - - public function matches(Request $request): bool - { - return $request->getPort() === $this->port; - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/QueryParameterRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/QueryParameterRequestMatcher.php deleted file mode 100644 index 86161e7..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/QueryParameterRequestMatcher.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the presence of HTTP query parameters of a Request. - * - * @author Alexandre Daubois - */ -class QueryParameterRequestMatcher implements RequestMatcherInterface -{ - /** - * @var string[] - */ - private array $parameters; - - /** - * @param string[]|string $parameters A parameter or a list of parameters - * Strings can contain a comma-delimited list of query parameters - */ - public function __construct(array|string $parameters) - { - $this->parameters = array_reduce(array_map(strtolower(...), (array) $parameters), static fn (array $parameters, string $parameter) => array_merge($parameters, preg_split('/\s*,\s*/', $parameter)), []); - } - - public function matches(Request $request): bool - { - if (!$this->parameters) { - return true; - } - - return 0 === \count(array_diff_assoc($this->parameters, $request->query->keys())); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php deleted file mode 100644 index 9c9cd58..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher/SchemeRequestMatcher.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\RequestMatcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; - -/** - * Checks the HTTP scheme of a Request. - * - * @author Fabien Potencier - */ -class SchemeRequestMatcher implements RequestMatcherInterface -{ - /** - * @var string[] - */ - private array $schemes; - - /** - * @param string[]|string $schemes A scheme or a list of schemes - * Strings can contain a comma-delimited list of schemes - */ - public function __construct(array|string $schemes) - { - $this->schemes = array_reduce(array_map('strtolower', (array) $schemes), static fn (array $schemes, string $scheme) => array_merge($schemes, preg_split('/\s*,\s*/', $scheme)), []); - } - - public function matches(Request $request): bool - { - if (!$this->schemes) { - return true; - } - - return \in_array($request->getScheme(), $this->schemes, true); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcherInterface.php b/vendor/symfony/http-foundation/RequestMatcherInterface.php deleted file mode 100644 index 6dcc3e0..0000000 --- a/vendor/symfony/http-foundation/RequestMatcherInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcherInterface is an interface for strategies to match a Request. - * - * @author Fabien Potencier - */ -interface RequestMatcherInterface -{ - /** - * Decides whether the rule(s) implemented by the strategy matches the supplied request. - */ - public function matches(Request $request): bool; -} diff --git a/vendor/symfony/http-foundation/RequestStack.php b/vendor/symfony/http-foundation/RequestStack.php deleted file mode 100644 index 153bd9a..0000000 --- a/vendor/symfony/http-foundation/RequestStack.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Request stack that controls the lifecycle of requests. - * - * @author Benjamin Eberlei - */ -class RequestStack -{ - /** - * @var Request[] - */ - private array $requests = []; - - /** - * @param Request[] $requests - */ - public function __construct(array $requests = []) - { - foreach ($requests as $request) { - $this->push($request); - } - } - - /** - * Pushes a Request on the stack. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - */ - public function push(Request $request): void - { - $this->requests[] = $request; - } - - /** - * Pops the current request from the stack. - * - * This operation lets the current request go out of scope. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - */ - public function pop(): ?Request - { - if (!$this->requests) { - return null; - } - - return array_pop($this->requests); - } - - public function getCurrentRequest(): ?Request - { - return end($this->requests) ?: null; - } - - /** - * Gets the main request. - * - * Be warned that making your code aware of the main request - * might make it un-compatible with other features of your framework - * like ESI support. - */ - public function getMainRequest(): ?Request - { - if (!$this->requests) { - return null; - } - - return $this->requests[0]; - } - - /** - * Returns the parent request of the current. - * - * Be warned that making your code aware of the parent request - * might make it un-compatible with other features of your framework - * like ESI support. - * - * If current Request is the main request, it returns null. - */ - public function getParentRequest(): ?Request - { - $pos = \count($this->requests) - 2; - - return $this->requests[$pos] ?? null; - } - - /** - * Gets the current session. - * - * @throws SessionNotFoundException - */ - public function getSession(): SessionInterface - { - if ((null !== $request = end($this->requests) ?: null) && $request->hasSession()) { - return $request->getSession(); - } - - throw new SessionNotFoundException(); - } - - public function resetRequestFormats(): void - { - static $resetRequestFormats; - $resetRequestFormats ??= \Closure::bind(static fn () => self::$formats = null, null, Request::class); - $resetRequestFormats(); - } -} diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php deleted file mode 100644 index 7cd3b87..0000000 --- a/vendor/symfony/http-foundation/Response.php +++ /dev/null @@ -1,1322 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -// Help opcache.preload discover always-needed symbols -class_exists(ResponseHeaderBag::class); - -/** - * Response represents an HTTP response. - * - * @author Fabien Potencier - */ -class Response -{ - public const HTTP_CONTINUE = 100; - public const HTTP_SWITCHING_PROTOCOLS = 101; - public const HTTP_PROCESSING = 102; // RFC2518 - public const HTTP_EARLY_HINTS = 103; // RFC8297 - public const HTTP_OK = 200; - public const HTTP_CREATED = 201; - public const HTTP_ACCEPTED = 202; - public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; - public const HTTP_NO_CONTENT = 204; - public const HTTP_RESET_CONTENT = 205; - public const HTTP_PARTIAL_CONTENT = 206; - public const HTTP_MULTI_STATUS = 207; // RFC4918 - public const HTTP_ALREADY_REPORTED = 208; // RFC5842 - public const HTTP_IM_USED = 226; // RFC3229 - public const HTTP_MULTIPLE_CHOICES = 300; - public const HTTP_MOVED_PERMANENTLY = 301; - public const HTTP_FOUND = 302; - public const HTTP_SEE_OTHER = 303; - public const HTTP_NOT_MODIFIED = 304; - public const HTTP_USE_PROXY = 305; - public const HTTP_RESERVED = 306; - public const HTTP_TEMPORARY_REDIRECT = 307; - public const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 - public const HTTP_BAD_REQUEST = 400; - public const HTTP_UNAUTHORIZED = 401; - public const HTTP_PAYMENT_REQUIRED = 402; - public const HTTP_FORBIDDEN = 403; - public const HTTP_NOT_FOUND = 404; - public const HTTP_METHOD_NOT_ALLOWED = 405; - public const HTTP_NOT_ACCEPTABLE = 406; - public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - public const HTTP_REQUEST_TIMEOUT = 408; - public const HTTP_CONFLICT = 409; - public const HTTP_GONE = 410; - public const HTTP_LENGTH_REQUIRED = 411; - public const HTTP_PRECONDITION_FAILED = 412; - public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; - public const HTTP_REQUEST_URI_TOO_LONG = 414; - public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - public const HTTP_EXPECTATION_FAILED = 417; - public const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 - public const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 - public const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 - public const HTTP_LOCKED = 423; // RFC4918 - public const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 - public const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 - public const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 - public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 - public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 - public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725 - public const HTTP_INTERNAL_SERVER_ERROR = 500; - public const HTTP_NOT_IMPLEMENTED = 501; - public const HTTP_BAD_GATEWAY = 502; - public const HTTP_SERVICE_UNAVAILABLE = 503; - public const HTTP_GATEWAY_TIMEOUT = 504; - public const HTTP_VERSION_NOT_SUPPORTED = 505; - public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 - public const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 - public const HTTP_LOOP_DETECTED = 508; // RFC5842 - public const HTTP_NOT_EXTENDED = 510; // RFC2774 - public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control - */ - private const HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES = [ - 'must_revalidate' => false, - 'no_cache' => false, - 'no_store' => false, - 'no_transform' => false, - 'public' => false, - 'private' => false, - 'proxy_revalidate' => false, - 'max_age' => true, - 's_maxage' => true, - 'stale_if_error' => true, // RFC5861 - 'stale_while_revalidate' => true, // RFC5861 - 'immutable' => false, - 'last_modified' => true, - 'etag' => true, - ]; - - public ResponseHeaderBag $headers; - - protected string $content; - protected string $version; - protected int $statusCode; - protected string $statusText; - protected ?string $charset = null; - - /** - * Status codes translation table. - * - * The list of codes is complete according to the - * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} - * (last updated 2021-10-01). - * - * Unless otherwise noted, the status code is defined in RFC2616. - * - * @var array - */ - public static array $statusTexts = [ - 100 => 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', // RFC2518 - 103 => 'Early Hints', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-Status', // RFC4918 - 208 => 'Already Reported', // RFC5842 - 226 => 'IM Used', // RFC3229 - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', // RFC7238 - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Content Too Large', // RFC-ietf-httpbis-semantics - 414 => 'URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Range Not Satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', // RFC2324 - 421 => 'Misdirected Request', // RFC7540 - 422 => 'Unprocessable Content', // RFC-ietf-httpbis-semantics - 423 => 'Locked', // RFC4918 - 424 => 'Failed Dependency', // RFC4918 - 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 - 426 => 'Upgrade Required', // RFC2817 - 428 => 'Precondition Required', // RFC6585 - 429 => 'Too Many Requests', // RFC6585 - 431 => 'Request Header Fields Too Large', // RFC6585 - 451 => 'Unavailable For Legal Reasons', // RFC7725 - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 506 => 'Variant Also Negotiates', // RFC2295 - 507 => 'Insufficient Storage', // RFC4918 - 508 => 'Loop Detected', // RFC5842 - 510 => 'Not Extended', // RFC2774 - 511 => 'Network Authentication Required', // RFC6585 - ]; - - /** - * Tracks headers already sent in informational responses. - */ - private array $sentHeaders; - - /** - * @param int $status The HTTP status code (200 "OK" by default) - * - * @throws \InvalidArgumentException When the HTTP status code is not valid - */ - public function __construct(?string $content = '', int $status = 200, array $headers = []) - { - $this->headers = new ResponseHeaderBag($headers); - $this->setContent($content); - $this->setStatusCode($status); - $this->setProtocolVersion('1.0'); - } - - /** - * Returns the Response as an HTTP string. - * - * The string representation of the Response is the same as the - * one that will be sent to the client only if the prepare() method - * has been called before. - * - * @see prepare() - */ - public function __toString(): string - { - return - \sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". - $this->headers."\r\n". - $this->getContent(); - } - - /** - * Clones the current Response instance. - */ - public function __clone() - { - $this->headers = clone $this->headers; - } - - /** - * Prepares the Response before it is sent to the client. - * - * This method tweaks the Response to ensure that it is - * compliant with RFC 2616. Most of the changes are based on - * the Request that is "associated" with this Response. - * - * @return $this - */ - public function prepare(Request $request): static - { - $headers = $this->headers; - - if ($this->isInformational() || $this->isEmpty()) { - $this->setContent(null); - $headers->remove('Content-Type'); - $headers->remove('Content-Length'); - // prevent PHP from sending the Content-Type header based on default_mimetype - ini_set('default_mimetype', ''); - } else { - // Content-type based on the Request - if (!$headers->has('Content-Type')) { - $format = $request->getRequestFormat(null); - if (null !== $format && $mimeType = $request->getMimeType($format)) { - $headers->set('Content-Type', $mimeType); - } - } - - // Fix Content-Type - $charset = $this->charset ?: 'utf-8'; - if (!$headers->has('Content-Type')) { - $headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif (0 === stripos($headers->get('Content-Type') ?? '', 'text/') && false === stripos($headers->get('Content-Type') ?? '', 'charset')) { - // add the charset - $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); - } - - // Fix Content-Length - if ($headers->has('Transfer-Encoding')) { - $headers->remove('Content-Length'); - } - - if ($request->isMethod('HEAD')) { - // cf. RFC2616 14.13 - $length = $headers->get('Content-Length'); - $this->setContent(null); - if ($length) { - $headers->set('Content-Length', $length); - } - } - } - - // Fix protocol - if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { - $this->setProtocolVersion('1.1'); - } - - // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && str_contains($headers->get('Cache-Control', ''), 'no-cache')) { - $headers->set('pragma', 'no-cache'); - $headers->set('expires', -1); - } - - $this->ensureIEOverSSLCompatibility($request); - - if ($request->isSecure()) { - foreach ($headers->getCookies() as $cookie) { - $cookie->setSecureDefault(true); - } - } - - return $this; - } - - /** - * Sends HTTP headers. - * - * @param positive-int|null $statusCode The status code to use, override the statusCode property if set and not null - * - * @return $this - */ - public function sendHeaders(?int $statusCode = null): static - { - // headers have already been sent by the developer - if (headers_sent()) { - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { - $statusCode ??= $this->statusCode; - header(\sprintf('HTTP/%s %s %s', $this->version, $statusCode, $this->statusText), true, $statusCode); - } - - return $this; - } - - $informationalResponse = $statusCode >= 100 && $statusCode < 200; - if ($informationalResponse && !\function_exists('headers_send')) { - // skip informational responses if not supported by the SAPI - return $this; - } - - // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { - // As recommended by RFC 8297, PHP automatically copies headers from previous 103 responses, we need to deal with that if headers changed - $previousValues = $this->sentHeaders[$name] ?? null; - if ($previousValues === $values) { - // Header already sent in a previous response, it will be automatically copied in this response by PHP - continue; - } - - $replace = 0 === strcasecmp($name, 'Content-Type'); - - if (null !== $previousValues && array_diff($previousValues, $values)) { - header_remove($name); - $previousValues = null; - } - - $newValues = null === $previousValues ? $values : array_diff($values, $previousValues); - - foreach ($newValues as $value) { - header($name.': '.$value, $replace, $this->statusCode); - } - - if ($informationalResponse) { - $this->sentHeaders[$name] = $values; - } - } - - // cookies - foreach ($this->headers->getCookies() as $cookie) { - header('Set-Cookie: '.$cookie, false, $this->statusCode); - } - - if ($informationalResponse) { - headers_send($statusCode); - - return $this; - } - - $statusCode ??= $this->statusCode; - - // status - header(\sprintf('HTTP/%s %s %s', $this->version, $statusCode, $this->statusText), true, $statusCode); - - return $this; - } - - /** - * Sends content for the current web response. - * - * @return $this - */ - public function sendContent(): static - { - echo $this->content; - - return $this; - } - - /** - * Sends HTTP headers and content. - * - * @param bool $flush Whether output buffers should be flushed - * - * @return $this - */ - public function send(bool $flush = true): static - { - $this->sendHeaders(); - $this->sendContent(); - - if (!$flush) { - return $this; - } - - if (\function_exists('fastcgi_finish_request')) { - fastcgi_finish_request(); - } elseif (\function_exists('litespeed_finish_request')) { - litespeed_finish_request(); - } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { - static::closeOutputBuffers(0, true); - flush(); - } - - return $this; - } - - /** - * Sets the response content. - * - * @return $this - */ - public function setContent(?string $content): static - { - $this->content = $content ?? ''; - - return $this; - } - - /** - * Gets the current response content. - */ - public function getContent(): string|false - { - return $this->content; - } - - /** - * Sets the HTTP protocol version (1.0 or 1.1). - * - * @return $this - * - * @final - */ - public function setProtocolVersion(string $version): static - { - $this->version = $version; - - return $this; - } - - /** - * Gets the HTTP protocol version. - * - * @final - */ - public function getProtocolVersion(): string - { - return $this->version; - } - - /** - * Sets the response status code. - * - * If the status text is null it will be automatically populated for the known - * status codes and left empty otherwise. - * - * @return $this - * - * @throws \InvalidArgumentException When the HTTP status code is not valid - * - * @final - */ - public function setStatusCode(int $code, ?string $text = null): static - { - $this->statusCode = $code; - if ($this->isInvalid()) { - throw new \InvalidArgumentException(\sprintf('The HTTP status code "%s" is not valid.', $code)); - } - - if (null === $text) { - $this->statusText = self::$statusTexts[$code] ?? 'unknown status'; - - return $this; - } - - $this->statusText = $text; - - return $this; - } - - /** - * Retrieves the status code for the current web response. - * - * @final - */ - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * Sets the response charset. - * - * @return $this - * - * @final - */ - public function setCharset(string $charset): static - { - $this->charset = $charset; - - return $this; - } - - /** - * Retrieves the response charset. - * - * @final - */ - public function getCharset(): ?string - { - return $this->charset; - } - - /** - * Returns true if the response may safely be kept in a shared (surrogate) cache. - * - * Responses marked "private" with an explicit Cache-Control directive are - * considered uncacheable. - * - * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable because there is - * no way to tell when or how to remove them from the cache. - * - * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, - * for example "status codes that are defined as cacheable by default [...] - * can be reused by a cache with heuristic expiration unless otherwise indicated" - * (https://tools.ietf.org/html/rfc7231#section-6.1) - * - * @final - */ - public function isCacheable(): bool - { - if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410], true)) { - return false; - } - - if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { - return false; - } - - return $this->isValidateable() || $this->isFresh(); - } - - /** - * Returns true if the response is "fresh". - * - * Fresh responses may be served from cache without any interaction with the - * origin. A response is considered fresh when it includes a Cache-Control/max-age - * indicator or Expires header and the calculated age is less than the freshness lifetime. - * - * @final - */ - public function isFresh(): bool - { - return $this->getTtl() > 0; - } - - /** - * Returns true if the response includes headers that can be used to validate - * the response with the origin server using a conditional GET request. - * - * @final - */ - public function isValidateable(): bool - { - return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); - } - - /** - * Marks the response as "private". - * - * It makes the response ineligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPrivate(): static - { - $this->headers->removeCacheControlDirective('public'); - $this->headers->addCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "public". - * - * It makes the response eligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPublic(): static - { - $this->headers->addCacheControlDirective('public'); - $this->headers->removeCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "immutable". - * - * @return $this - * - * @final - */ - public function setImmutable(bool $immutable = true): static - { - if ($immutable) { - $this->headers->addCacheControlDirective('immutable'); - } else { - $this->headers->removeCacheControlDirective('immutable'); - } - - return $this; - } - - /** - * Returns true if the response is marked as "immutable". - * - * @final - */ - public function isImmutable(): bool - { - return $this->headers->hasCacheControlDirective('immutable'); - } - - /** - * Returns true if the response must be revalidated by shared caches once it has become stale. - * - * This method indicates that the response must not be served stale by a - * cache in any circumstance without first revalidating with the origin. - * When present, the TTL of the response should not be overridden to be - * greater than the value provided by the origin. - * - * @final - */ - public function mustRevalidate(): bool - { - return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); - } - - /** - * Returns the Date header as a DateTime instance. - * - * @throws \RuntimeException When the header is not parseable - * - * @final - */ - public function getDate(): ?\DateTimeImmutable - { - return $this->headers->getDate('Date'); - } - - /** - * Sets the Date header. - * - * @return $this - * - * @final - */ - public function setDate(\DateTimeInterface $date): static - { - $date = \DateTimeImmutable::createFromInterface($date); - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the age of the response in seconds. - * - * @final - */ - public function getAge(): int - { - if (null !== $age = $this->headers->get('Age')) { - return (int) $age; - } - - return max(time() - (int) $this->getDate()->format('U'), 0); - } - - /** - * Marks the response stale by setting the Age header to be equal to the maximum age of the response. - * - * @return $this - */ - public function expire(): static - { - if ($this->isFresh()) { - $this->headers->set('Age', $this->getMaxAge()); - $this->headers->remove('Expires'); - } - - return $this; - } - - /** - * Returns the value of the Expires header as a DateTime instance. - * - * @final - */ - public function getExpires(): ?\DateTimeImmutable - { - try { - return $this->headers->getDate('Expires'); - } catch (\RuntimeException) { - // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past - return \DateTimeImmutable::createFromFormat('U', time() - 172800); - } - } - - /** - * Sets the Expires HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setExpires(?\DateTimeInterface $date): static - { - if (null === $date) { - $this->headers->remove('Expires'); - - return $this; - } - - $date = \DateTimeImmutable::createFromInterface($date); - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the number of seconds after the time specified in the response's Date - * header when the response should no longer be considered fresh. - * - * First, it checks for a s-maxage directive, then a max-age directive, and then it falls - * back on an expires header. It returns null when no maximum age can be established. - * - * @final - */ - public function getMaxAge(): ?int - { - if ($this->headers->hasCacheControlDirective('s-maxage')) { - return (int) $this->headers->getCacheControlDirective('s-maxage'); - } - - if ($this->headers->hasCacheControlDirective('max-age')) { - return (int) $this->headers->getCacheControlDirective('max-age'); - } - - if (null !== $expires = $this->getExpires()) { - $maxAge = (int) $expires->format('U') - (int) $this->getDate()->format('U'); - - return max($maxAge, 0); - } - - return null; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh. - * - * This method sets the Cache-Control max-age directive. - * - * @return $this - * - * @final - */ - public function setMaxAge(int $value): static - { - $this->headers->addCacheControlDirective('max-age', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer be returned by shared caches when backend is down. - * - * This method sets the Cache-Control stale-if-error directive. - * - * @return $this - * - * @final - */ - public function setStaleIfError(int $value): static - { - $this->headers->addCacheControlDirective('stale-if-error', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer return stale content by shared caches. - * - * This method sets the Cache-Control stale-while-revalidate directive. - * - * @return $this - * - * @final - */ - public function setStaleWhileRevalidate(int $value): static - { - $this->headers->addCacheControlDirective('stale-while-revalidate', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. - * - * This method sets the Cache-Control s-maxage directive. - * - * @return $this - * - * @final - */ - public function setSharedMaxAge(int $value): static - { - $this->setPublic(); - $this->headers->addCacheControlDirective('s-maxage', $value); - - return $this; - } - - /** - * Returns the response's time-to-live in seconds. - * - * It returns null when no freshness information is present in the response. - * - * When the response's TTL is 0, the response may not be served from cache without first - * revalidating with the origin. - * - * @final - */ - public function getTtl(): ?int - { - $maxAge = $this->getMaxAge(); - - return null !== $maxAge ? max($maxAge - $this->getAge(), 0) : null; - } - - /** - * Sets the response's time-to-live for shared caches in seconds. - * - * This method adjusts the Cache-Control/s-maxage directive. - * - * @return $this - * - * @final - */ - public function setTtl(int $seconds): static - { - $this->setSharedMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Sets the response's time-to-live for private/client caches in seconds. - * - * This method adjusts the Cache-Control/max-age directive. - * - * @return $this - * - * @final - */ - public function setClientTtl(int $seconds): static - { - $this->setMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Returns the Last-Modified HTTP header as a DateTime instance. - * - * @throws \RuntimeException When the HTTP header is not parseable - * - * @final - */ - public function getLastModified(): ?\DateTimeImmutable - { - return $this->headers->getDate('Last-Modified'); - } - - /** - * Sets the Last-Modified HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setLastModified(?\DateTimeInterface $date): static - { - if (null === $date) { - $this->headers->remove('Last-Modified'); - - return $this; - } - - $date = \DateTimeImmutable::createFromInterface($date); - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the literal value of the ETag HTTP header. - * - * @final - */ - public function getEtag(): ?string - { - return $this->headers->get('ETag'); - } - - /** - * Sets the ETag value. - * - * @param string|null $etag The ETag unique identifier or null to remove the header - * @param bool $weak Whether you want a weak ETag or not - * - * @return $this - * - * @final - */ - public function setEtag(?string $etag, bool $weak = false): static - { - if (null === $etag) { - $this->headers->remove('Etag'); - } else { - if (!str_starts_with($etag, '"')) { - $etag = '"'.$etag.'"'; - } - - $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); - } - - return $this; - } - - /** - * Sets the response's cache headers (validation and/or expiration). - * - * Available options are: must_revalidate, no_cache, no_store, no_transform, public, private, proxy_revalidate, max_age, s_maxage, immutable, last_modified and etag. - * - * @return $this - * - * @throws \InvalidArgumentException - * - * @final - */ - public function setCache(array $options): static - { - if ($diff = array_diff(array_keys($options), array_keys(self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES))) { - throw new \InvalidArgumentException(\sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); - } - - if (isset($options['etag'])) { - $this->setEtag($options['etag']); - } - - if (isset($options['last_modified'])) { - $this->setLastModified($options['last_modified']); - } - - if (isset($options['max_age'])) { - $this->setMaxAge($options['max_age']); - } - - if (isset($options['s_maxage'])) { - $this->setSharedMaxAge($options['s_maxage']); - } - - if (isset($options['stale_while_revalidate'])) { - $this->setStaleWhileRevalidate($options['stale_while_revalidate']); - } - - if (isset($options['stale_if_error'])) { - $this->setStaleIfError($options['stale_if_error']); - } - - foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) { - if (!$hasValue && isset($options[$directive])) { - if ($options[$directive]) { - $this->headers->addCacheControlDirective(str_replace('_', '-', $directive)); - } else { - $this->headers->removeCacheControlDirective(str_replace('_', '-', $directive)); - } - } - } - - if (isset($options['public'])) { - if ($options['public']) { - $this->setPublic(); - } else { - $this->setPrivate(); - } - } - - if (isset($options['private'])) { - if ($options['private']) { - $this->setPrivate(); - } else { - $this->setPublic(); - } - } - - return $this; - } - - /** - * Modifies the response so that it conforms to the rules defined for a 304 status code. - * - * This sets the status, removes the body, and discards any headers - * that MUST NOT be included in 304 responses. - * - * @return $this - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 - * - * @final - */ - public function setNotModified(): static - { - $this->setStatusCode(304); - $this->setContent(null); - - // remove headers that MUST NOT be included with 304 Not Modified responses - foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { - $this->headers->remove($header); - } - - return $this; - } - - /** - * Returns true if the response includes a Vary header. - * - * @final - */ - public function hasVary(): bool - { - return null !== $this->headers->get('Vary'); - } - - /** - * Returns an array of header names given in the Vary header. - * - * @final - */ - public function getVary(): array - { - if (!$vary = $this->headers->all('Vary')) { - return []; - } - - $ret = []; - foreach ($vary as $item) { - $ret[] = preg_split('/[\s,]+/', $item); - } - - return array_merge([], ...$ret); - } - - /** - * Sets the Vary header. - * - * @param bool $replace Whether to replace the actual value or not (true by default) - * - * @return $this - * - * @final - */ - public function setVary(string|array $headers, bool $replace = true): static - { - $this->headers->set('Vary', $headers, $replace); - - return $this; - } - - /** - * Determines if the Response validators (ETag, Last-Modified) match - * a conditional value specified in the Request. - * - * If the Response is not modified, it sets the status code to 304 and - * removes the actual content by calling the setNotModified() method. - * - * @final - */ - public function isNotModified(Request $request): bool - { - if (!$request->isMethodCacheable()) { - return false; - } - - $notModified = false; - $lastModified = $this->headers->get('Last-Modified'); - $modifiedSince = $request->headers->get('If-Modified-Since'); - - if (($ifNoneMatchEtags = $request->getETags()) && (null !== $etag = $this->getEtag())) { - if (0 == strncmp($etag, 'W/', 2)) { - $etag = substr($etag, 2); - } - - // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2. - foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) { - if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) { - $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2); - } - - if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) { - $notModified = true; - break; - } - } - } - // Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3. - elseif ($modifiedSince && $lastModified) { - $notModified = strtotime($modifiedSince) >= strtotime($lastModified); - } - - if ($notModified) { - $this->setNotModified(); - } - - return $notModified; - } - - /** - * Is response invalid? - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - * - * @final - */ - public function isInvalid(): bool - { - return $this->statusCode < 100 || $this->statusCode >= 600; - } - - /** - * Is response informative? - * - * @final - */ - public function isInformational(): bool - { - return $this->statusCode >= 100 && $this->statusCode < 200; - } - - /** - * Is response successful? - * - * @final - */ - public function isSuccessful(): bool - { - return $this->statusCode >= 200 && $this->statusCode < 300; - } - - /** - * Is the response a redirect? - * - * @final - */ - public function isRedirection(): bool - { - return $this->statusCode >= 300 && $this->statusCode < 400; - } - - /** - * Is there a client error? - * - * @final - */ - public function isClientError(): bool - { - return $this->statusCode >= 400 && $this->statusCode < 500; - } - - /** - * Was there a server side error? - * - * @final - */ - public function isServerError(): bool - { - return $this->statusCode >= 500 && $this->statusCode < 600; - } - - /** - * Is the response OK? - * - * @final - */ - public function isOk(): bool - { - return 200 === $this->statusCode; - } - - /** - * Is the response forbidden? - * - * @final - */ - public function isForbidden(): bool - { - return 403 === $this->statusCode; - } - - /** - * Is the response a not found error? - * - * @final - */ - public function isNotFound(): bool - { - return 404 === $this->statusCode; - } - - /** - * Is the response a redirect of some form? - * - * @final - */ - public function isRedirect(?string $location = null): bool - { - return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308], true) && (null === $location ?: $location == $this->headers->get('Location')); - } - - /** - * Is the response empty? - * - * @final - */ - public function isEmpty(): bool - { - return \in_array($this->statusCode, [204, 304], true); - } - - /** - * Cleans or flushes output buffers up to target level. - * - * Resulting level can be greater than target level if a non-removable buffer has been encountered. - * - * @final - */ - public static function closeOutputBuffers(int $targetLevel, bool $flush): void - { - $status = ob_get_status(true); - $level = \count($status); - $flags = \PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? \PHP_OUTPUT_HANDLER_FLUSHABLE : \PHP_OUTPUT_HANDLER_CLEANABLE); - - while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { - if ($flush) { - ob_end_flush(); - } else { - ob_end_clean(); - } - } - } - - /** - * Marks a response as safe according to RFC8674. - * - * @see https://tools.ietf.org/html/rfc8674 - */ - public function setContentSafe(bool $safe = true): void - { - if ($safe) { - $this->headers->set('Preference-Applied', 'safe'); - } elseif ('safe' === $this->headers->get('Preference-Applied')) { - $this->headers->remove('Preference-Applied'); - } - - $this->setVary('Prefer', false); - } - - /** - * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. - * - * @see http://support.microsoft.com/kb/323308 - * - * @final - */ - protected function ensureIEOverSSLCompatibility(Request $request): void - { - if (false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && true === $request->isSecure()) { - if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { - $this->headers->remove('Cache-Control'); - } - } - } -} diff --git a/vendor/symfony/http-foundation/ResponseHeaderBag.php b/vendor/symfony/http-foundation/ResponseHeaderBag.php deleted file mode 100644 index 5f11ffd..0000000 --- a/vendor/symfony/http-foundation/ResponseHeaderBag.php +++ /dev/null @@ -1,267 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ResponseHeaderBag is a container for Response HTTP headers. - * - * @author Fabien Potencier - */ -class ResponseHeaderBag extends HeaderBag -{ - public const COOKIES_FLAT = 'flat'; - public const COOKIES_ARRAY = 'array'; - - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - protected array $computedCacheControl = []; - protected array $cookies = []; - protected array $headerNames = []; - - public function __construct(array $headers = []) - { - parent::__construct($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * Returns the headers, with original capitalizations. - */ - public function allPreserveCase(): array - { - $headers = []; - foreach ($this->all() as $name => $value) { - $headers[$this->headerNames[$name] ?? $name] = $value; - } - - return $headers; - } - - public function allPreserveCaseWithoutCookies(): array - { - $headers = $this->allPreserveCase(); - if (isset($this->headerNames['set-cookie'])) { - unset($headers[$this->headerNames['set-cookie']]); - } - - return $headers; - } - - public function replace(array $headers = []): void - { - $this->headerNames = []; - - parent::replace($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - public function all(?string $key = null): array - { - $headers = parent::all(); - - if (null !== $key) { - $key = strtr($key, self::UPPER, self::LOWER); - - return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); - } - - foreach ($this->getCookies() as $cookie) { - $headers['set-cookie'][] = (string) $cookie; - } - - return $headers; - } - - public function set(string $key, string|array|null $values, bool $replace = true): void - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - - if ('set-cookie' === $uniqueKey) { - if ($replace) { - $this->cookies = []; - } - foreach ((array) $values as $cookie) { - $this->setCookie(Cookie::fromString($cookie)); - } - $this->headerNames[$uniqueKey] = $key; - - return; - } - - $this->headerNames[$uniqueKey] = $key; - - parent::set($key, $values, $replace); - - // ensure the cache-control header has sensible defaults - if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { - $this->headers['cache-control'] = [$computed]; - $this->headerNames['cache-control'] = 'Cache-Control'; - $this->computedCacheControl = $this->parseCacheControl($computed); - } - } - - public function remove(string $key): void - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - unset($this->headerNames[$uniqueKey]); - - if ('set-cookie' === $uniqueKey) { - $this->cookies = []; - - return; - } - - parent::remove($key); - - if ('cache-control' === $uniqueKey) { - $this->computedCacheControl = []; - } - - if ('date' === $uniqueKey) { - $this->initDate(); - } - } - - public function hasCacheControlDirective(string $key): bool - { - return \array_key_exists($key, $this->computedCacheControl); - } - - public function getCacheControlDirective(string $key): bool|string|null - { - return $this->computedCacheControl[$key] ?? null; - } - - public function setCookie(Cookie $cookie): void - { - $this->cookies[$cookie->getDomain() ?? ''][$cookie->getPath()][$cookie->getName()] = $cookie; - $this->headerNames['set-cookie'] = 'Set-Cookie'; - } - - /** - * Removes a cookie from the array, but does not unset it in the browser. - */ - public function removeCookie(string $name, ?string $path = '/', ?string $domain = null): void - { - $path ??= '/'; - - unset($this->cookies[$domain ?? ''][$path][$name]); - - if (empty($this->cookies[$domain ?? ''][$path])) { - unset($this->cookies[$domain ?? ''][$path]); - - if (empty($this->cookies[$domain ?? ''])) { - unset($this->cookies[$domain ?? '']); - } - } - - if (!$this->cookies) { - unset($this->headerNames['set-cookie']); - } - } - - /** - * Returns an array with all cookies. - * - * @return Cookie[] - * - * @throws \InvalidArgumentException When the $format is invalid - */ - public function getCookies(string $format = self::COOKIES_FLAT): array - { - if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY], true)) { - throw new \InvalidArgumentException(\sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); - } - - if (self::COOKIES_ARRAY === $format) { - return $this->cookies; - } - - $flattenedCookies = []; - foreach ($this->cookies as $path) { - foreach ($path as $cookies) { - foreach ($cookies as $cookie) { - $flattenedCookies[] = $cookie; - } - } - } - - return $flattenedCookies; - } - - /** - * Clears a cookie in the browser. - */ - public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null, bool $partitioned = false): void - { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite, $partitioned)); - } - - /** - * @see HeaderUtils::makeDisposition() - */ - public function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string - { - return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); - } - - /** - * Returns the calculated value of the cache-control header. - * - * This considers several other headers and calculates or modifies the - * cache-control header to a sensible, conservative value. - */ - protected function computeCacheControlValue(): string - { - if (!$this->cacheControl) { - if ($this->has('Last-Modified') || $this->has('Expires')) { - return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" - } - - // conservative by default - return 'no-cache, private'; - } - - $header = $this->getCacheControlHeader(); - if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { - return $header; - } - - // public if s-maxage is defined, private otherwise - if (!isset($this->cacheControl['s-maxage'])) { - return $header.', private'; - } - - return $header; - } - - private function initDate(): void - { - $this->set('Date', gmdate('D, d M Y H:i:s').' GMT'); - } -} diff --git a/vendor/symfony/http-foundation/ServerBag.php b/vendor/symfony/http-foundation/ServerBag.php deleted file mode 100644 index 09fc386..0000000 --- a/vendor/symfony/http-foundation/ServerBag.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ServerBag is a container for HTTP headers from the $_SERVER variable. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Robert Kiss - */ -class ServerBag extends ParameterBag -{ - /** - * Gets the HTTP headers. - */ - public function getHeaders(): array - { - $headers = []; - foreach ($this->parameters as $key => $value) { - if (str_starts_with($key, 'HTTP_')) { - $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true) && '' !== $value) { - $headers[$key] = $value; - } - } - - if (isset($this->parameters['PHP_AUTH_USER'])) { - $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; - $headers['PHP_AUTH_PW'] = $this->parameters['PHP_AUTH_PW'] ?? ''; - } else { - /* - * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default - * For this workaround to work, add these lines to your .htaccess file: - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * - * A sample .htaccess file: - * RewriteEngine On - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * RewriteCond %{REQUEST_FILENAME} !-f - * RewriteRule ^(.*)$ index.php [QSA,L] - */ - - $authorizationHeader = null; - if (isset($this->parameters['HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; - } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; - } - - if (null !== $authorizationHeader) { - if (0 === stripos($authorizationHeader, 'basic ')) { - // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (2 == \count($exploded)) { - [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded; - } - } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { - // In some circumstances PHP_AUTH_DIGEST needs to be set - $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; - $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; - } elseif (0 === stripos($authorizationHeader, 'bearer ')) { - /* - * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, - * I'll just set $headers['AUTHORIZATION'] here. - * https://php.net/reserved.variables.server - */ - $headers['AUTHORIZATION'] = $authorizationHeader; - } - } - } - - if (isset($headers['AUTHORIZATION'])) { - return $headers; - } - - // PHP_AUTH_USER/PHP_AUTH_PW - if (isset($headers['PHP_AUTH_USER'])) { - $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.($headers['PHP_AUTH_PW'] ?? '')); - } elseif (isset($headers['PHP_AUTH_DIGEST'])) { - $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; - } - - return $headers; - } -} diff --git a/vendor/symfony/http-foundation/ServerEvent.php b/vendor/symfony/http-foundation/ServerEvent.php deleted file mode 100644 index 7597058..0000000 --- a/vendor/symfony/http-foundation/ServerEvent.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * An event generated on the server intended for streaming to the client - * as part of the SSE streaming technique. - * - * @implements \IteratorAggregate - * - * @author Yonel Ceruto - */ -class ServerEvent implements \IteratorAggregate -{ - /** - * @param string|iterable $data The event data field for the message - * @param string|null $type The event type - * @param int|null $retry The number of milliseconds the client should wait - * before reconnecting in case of network failure - * @param string|null $id The event ID to set the EventSource object's last event ID value - * @param string|null $comment The event comment - */ - public function __construct( - private string|iterable $data, - private ?string $type = null, - private ?int $retry = null, - private ?string $id = null, - private ?string $comment = null, - ) { - } - - public function getData(): iterable|string - { - return $this->data; - } - - /** - * @return $this - */ - public function setData(iterable|string $data): static - { - $this->data = $data; - - return $this; - } - - public function getType(): ?string - { - return $this->type; - } - - /** - * @return $this - */ - public function setType(string $type): static - { - $this->type = $type; - - return $this; - } - - public function getRetry(): ?int - { - return $this->retry; - } - - /** - * @return $this - */ - public function setRetry(?int $retry): static - { - $this->retry = $retry; - - return $this; - } - - public function getId(): ?string - { - return $this->id; - } - - /** - * @return $this - */ - public function setId(string $id): static - { - $this->id = $id; - - return $this; - } - - public function getComment(): ?string - { - return $this->comment; - } - - public function setComment(string $comment): static - { - $this->comment = $comment; - - return $this; - } - - /** - * @return \Traversable - */ - public function getIterator(): \Traversable - { - static $lastRetry = null; - - $head = ''; - if ($this->comment) { - $head .= \sprintf(': %s', $this->comment)."\n"; - } - if ($this->id) { - $head .= \sprintf('id: %s', $this->id)."\n"; - } - if ($this->retry > 0 && $this->retry !== $lastRetry) { - $head .= \sprintf('retry: %s', $lastRetry = $this->retry)."\n"; - } - if ($this->type) { - $head .= \sprintf('event: %s', $this->type)."\n"; - } - yield $head; - - if (is_iterable($this->data)) { - foreach ($this->data as $data) { - yield \sprintf('data: %s', $data)."\n"; - } - } elseif ('' !== $this->data) { - yield \sprintf('data: %s', $this->data)."\n"; - } - - yield "\n"; - } -} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php deleted file mode 100644 index e34a497..0000000 --- a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -/** - * This class relates to session attribute storage. - * - * @implements \IteratorAggregate - */ -class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable -{ - protected array $attributes = []; - - private string $name = 'attributes'; - - /** - * @param string $storageKey The key used to store attributes in the session - */ - public function __construct( - private string $storageKey = '_sf2_attributes', - ) { - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function initialize(array &$attributes): void - { - $this->attributes = &$attributes; - } - - public function getStorageKey(): string - { - return $this->storageKey; - } - - public function has(string $name): bool - { - return \array_key_exists($name, $this->attributes); - } - - public function get(string $name, mixed $default = null): mixed - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - public function set(string $name, mixed $value): void - { - $this->attributes[$name] = $value; - } - - public function all(): array - { - return $this->attributes; - } - - public function replace(array $attributes): void - { - $this->attributes = []; - foreach ($attributes as $key => $value) { - $this->set($key, $value); - } - } - - public function remove(string $name): mixed - { - $retval = null; - if (\array_key_exists($name, $this->attributes)) { - $retval = $this->attributes[$name]; - unset($this->attributes[$name]); - } - - return $retval; - } - - public function clear(): mixed - { - $return = $this->attributes; - $this->attributes = []; - - return $return; - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator - */ - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->attributes); - } - - /** - * Returns the number of attributes. - */ - public function count(): int - { - return \count($this->attributes); - } -} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php deleted file mode 100644 index 39ec9d7..0000000 --- a/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Attributes store. - * - * @author Drak - */ -interface AttributeBagInterface extends SessionBagInterface -{ - /** - * Checks if an attribute is defined. - */ - public function has(string $name): bool; - - /** - * Returns an attribute. - */ - public function get(string $name, mixed $default = null): mixed; - - /** - * Sets an attribute. - */ - public function set(string $name, mixed $value): void; - - /** - * Returns attributes. - * - * @return array - */ - public function all(): array; - - public function replace(array $attributes): void; - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name): mixed; -} diff --git a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php deleted file mode 100644 index bfb856d..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * AutoExpireFlashBag flash message container. - * - * @author Drak - */ -class AutoExpireFlashBag implements FlashBagInterface -{ - private string $name = 'flashes'; - private array $flashes = ['display' => [], 'new' => []]; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct( - private string $storageKey = '_symfony_flashes', - ) { - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function initialize(array &$flashes): void - { - $this->flashes = &$flashes; - - // The logic: messages from the last request will be stored in new, so we move them to previous - // This request we will show what is in 'display'. What is placed into 'new' this time round will - // be moved to display next time round. - $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; - $this->flashes['new'] = []; - } - - public function add(string $type, mixed $message): void - { - $this->flashes['new'][$type][] = $message; - } - - public function peek(string $type, array $default = []): array - { - return $this->has($type) ? $this->flashes['display'][$type] : $default; - } - - public function peekAll(): array - { - return \array_key_exists('display', $this->flashes) ? $this->flashes['display'] : []; - } - - public function get(string $type, array $default = []): array - { - $return = $default; - - if (!$this->has($type)) { - return $return; - } - - if (isset($this->flashes['display'][$type])) { - $return = $this->flashes['display'][$type]; - unset($this->flashes['display'][$type]); - } - - return $return; - } - - public function all(): array - { - $return = $this->flashes['display']; - $this->flashes['display'] = []; - - return $return; - } - - public function setAll(array $messages): void - { - $this->flashes['new'] = $messages; - } - - public function set(string $type, string|array $messages): void - { - $this->flashes['new'][$type] = (array) $messages; - } - - public function has(string $type): bool - { - return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; - } - - public function keys(): array - { - return array_keys($this->flashes['display']); - } - - public function getStorageKey(): string - { - return $this->storageKey; - } - - public function clear(): mixed - { - return $this->all(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php deleted file mode 100644 index 72753a6..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * FlashBag flash message container. - * - * @author Drak - */ -class FlashBag implements FlashBagInterface -{ - private string $name = 'flashes'; - private array $flashes = []; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct( - private string $storageKey = '_symfony_flashes', - ) { - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function initialize(array &$flashes): void - { - $this->flashes = &$flashes; - } - - public function add(string $type, mixed $message): void - { - $this->flashes[$type][] = $message; - } - - public function peek(string $type, array $default = []): array - { - return $this->has($type) ? $this->flashes[$type] : $default; - } - - public function peekAll(): array - { - return $this->flashes; - } - - public function get(string $type, array $default = []): array - { - if (!$this->has($type)) { - return $default; - } - - $return = $this->flashes[$type]; - - unset($this->flashes[$type]); - - return $return; - } - - public function all(): array - { - $return = $this->peekAll(); - $this->flashes = []; - - return $return; - } - - public function set(string $type, string|array $messages): void - { - $this->flashes[$type] = (array) $messages; - } - - public function setAll(array $messages): void - { - $this->flashes = $messages; - } - - public function has(string $type): bool - { - return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; - } - - public function keys(): array - { - return array_keys($this->flashes); - } - - public function getStorageKey(): string - { - return $this->storageKey; - } - - public function clear(): mixed - { - return $this->all(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php deleted file mode 100644 index 79e98f5..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * FlashBagInterface. - * - * @author Drak - */ -interface FlashBagInterface extends SessionBagInterface -{ - /** - * Adds a flash message for the given type. - */ - public function add(string $type, mixed $message): void; - - /** - * Registers one or more messages for a given type. - */ - public function set(string $type, string|array $messages): void; - - /** - * Gets flash messages for a given type. - * - * @param string $type Message category type - * @param array $default Default value if $type does not exist - */ - public function peek(string $type, array $default = []): array; - - /** - * Gets all flash messages. - */ - public function peekAll(): array; - - /** - * Gets and clears flash from the stack. - * - * @param array $default Default value if $type does not exist - */ - public function get(string $type, array $default = []): array; - - /** - * Gets and clears flashes from the stack. - */ - public function all(): array; - - /** - * Sets all flash messages. - */ - public function setAll(array $messages): void; - - /** - * Has flash messages for a given type? - */ - public function has(string $type): bool; - - /** - * Returns a list of all defined types. - */ - public function keys(): array; -} diff --git a/vendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php b/vendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php deleted file mode 100644 index 90151d3..0000000 --- a/vendor/symfony/http-foundation/Session/FlashBagAwareSessionInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; - -/** - * Interface for session with a flashbag. - */ -interface FlashBagAwareSessionInterface extends SessionInterface -{ - public function getFlashBag(): FlashBagInterface; -} diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php deleted file mode 100644 index 972021f..0000000 --- a/vendor/symfony/http-foundation/Session/Session.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(AttributeBag::class); -class_exists(FlashBag::class); -class_exists(SessionBagProxy::class); - -/** - * @author Fabien Potencier - * @author Drak - * - * @implements \IteratorAggregate - */ -class Session implements FlashBagAwareSessionInterface, \IteratorAggregate, \Countable -{ - protected SessionStorageInterface $storage; - - private string $flashName; - private string $attributeName; - private array $data = []; - private int $usageIndex = 0; - private ?\Closure $usageReporter; - - public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null) - { - $this->storage = $storage ?? new NativeSessionStorage(); - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); - - $attributes ??= new AttributeBag(); - $this->attributeName = $attributes->getName(); - $this->registerBag($attributes); - - $flashes ??= new FlashBag(); - $this->flashName = $flashes->getName(); - $this->registerBag($flashes); - } - - public function start(): bool - { - return $this->storage->start(); - } - - public function has(string $name): bool - { - return $this->getAttributeBag()->has($name); - } - - public function get(string $name, mixed $default = null): mixed - { - return $this->getAttributeBag()->get($name, $default); - } - - public function set(string $name, mixed $value): void - { - $this->getAttributeBag()->set($name, $value); - } - - public function all(): array - { - return $this->getAttributeBag()->all(); - } - - public function replace(array $attributes): void - { - $this->getAttributeBag()->replace($attributes); - } - - public function remove(string $name): mixed - { - return $this->getAttributeBag()->remove($name); - } - - public function clear(): void - { - $this->getAttributeBag()->clear(); - } - - public function isStarted(): bool - { - return $this->storage->isStarted(); - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator - */ - public function getIterator(): \ArrayIterator - { - return new \ArrayIterator($this->getAttributeBag()->all()); - } - - /** - * Returns the number of attributes. - */ - public function count(): int - { - return \count($this->getAttributeBag()->all()); - } - - public function &getUsageIndex(): int - { - return $this->usageIndex; - } - - /** - * @internal - */ - public function isEmpty(): bool - { - if ($this->isStarted()) { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - } - foreach ($this->data as &$data) { - if ($data) { - return false; - } - } - - return true; - } - - public function invalidate(?int $lifetime = null): bool - { - $this->storage->clear(); - - return $this->migrate(true, $lifetime); - } - - public function migrate(bool $destroy = false, ?int $lifetime = null): bool - { - return $this->storage->regenerate($destroy, $lifetime); - } - - public function save(): void - { - $this->storage->save(); - } - - public function getId(): string - { - return $this->storage->getId(); - } - - public function setId(string $id): void - { - if ($this->storage->getId() !== $id) { - $this->storage->setId($id); - } - } - - public function getName(): string - { - return $this->storage->getName(); - } - - public function setName(string $name): void - { - $this->storage->setName($name); - } - - public function getMetadataBag(): MetadataBag - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->storage->getMetadataBag(); - } - - public function registerBag(SessionBagInterface $bag): void - { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter)); - } - - public function getBag(string $name): SessionBagInterface - { - $bag = $this->storage->getBag($name); - - return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; - } - - /** - * Gets the flashbag interface. - */ - public function getFlashBag(): FlashBagInterface - { - return $this->getBag($this->flashName); - } - - /** - * Gets the attributebag interface. - * - * Note that this method was added to help with IDE autocompletion. - */ - private function getAttributeBag(): AttributeBagInterface - { - return $this->getBag($this->attributeName); - } -} diff --git a/vendor/symfony/http-foundation/Session/SessionBagInterface.php b/vendor/symfony/http-foundation/Session/SessionBagInterface.php deleted file mode 100644 index 6a224cf..0000000 --- a/vendor/symfony/http-foundation/Session/SessionBagInterface.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session Bag store. - * - * @author Drak - */ -interface SessionBagInterface -{ - /** - * Gets this bag's name. - */ - public function getName(): string; - - /** - * Initializes the Bag. - */ - public function initialize(array &$array): void; - - /** - * Gets the storage key for this bag. - */ - public function getStorageKey(): string; - - /** - * Clears out data from bag. - * - * @return mixed Whatever data was contained - */ - public function clear(): mixed; -} diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php deleted file mode 100644 index a389bd8..0000000 --- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Nicolas Grekas - * - * @internal - */ -final class SessionBagProxy implements SessionBagInterface -{ - private array $data; - private ?int $usageIndex; - private ?\Closure $usageReporter; - - public function __construct( - private SessionBagInterface $bag, - array &$data, - ?int &$usageIndex, - ?callable $usageReporter, - ) { - $this->bag = $bag; - $this->data = &$data; - $this->usageIndex = &$usageIndex; - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); - } - - public function getBag(): SessionBagInterface - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return $this->bag; - } - - public function isEmpty(): bool - { - if (!isset($this->data[$this->bag->getStorageKey()])) { - return true; - } - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - return empty($this->data[$this->bag->getStorageKey()]); - } - - public function getName(): string - { - return $this->bag->getName(); - } - - public function initialize(array &$array): void - { - ++$this->usageIndex; - if ($this->usageReporter && 0 <= $this->usageIndex) { - ($this->usageReporter)(); - } - - $this->data[$this->bag->getStorageKey()] = &$array; - - $this->bag->initialize($array); - } - - public function getStorageKey(): string - { - return $this->bag->getStorageKey(); - } - - public function clear(): mixed - { - return $this->bag->clear(); - } -} diff --git a/vendor/symfony/http-foundation/Session/SessionFactory.php b/vendor/symfony/http-foundation/Session/SessionFactory.php deleted file mode 100644 index b875a23..0000000 --- a/vendor/symfony/http-foundation/Session/SessionFactory.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface; - -// Help opcache.preload discover always-needed symbols -class_exists(Session::class); - -/** - * @author Jérémy Derussé - */ -class SessionFactory implements SessionFactoryInterface -{ - private ?\Closure $usageReporter; - - public function __construct( - private RequestStack $requestStack, - private SessionStorageFactoryInterface $storageFactory, - ?callable $usageReporter = null, - ) { - $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); - } - - public function createSession(): SessionInterface - { - return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter); - } -} diff --git a/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php b/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php deleted file mode 100644 index b24fdc4..0000000 --- a/vendor/symfony/http-foundation/Session/SessionFactoryInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Kevin Bond - */ -interface SessionFactoryInterface -{ - public function createSession(): SessionInterface; -} diff --git a/vendor/symfony/http-foundation/Session/SessionInterface.php b/vendor/symfony/http-foundation/Session/SessionInterface.php deleted file mode 100644 index 3e29ba4..0000000 --- a/vendor/symfony/http-foundation/Session/SessionInterface.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; - -/** - * Interface for the session. - * - * @author Drak - */ -interface SessionInterface -{ - /** - * Starts the session storage. - * - * @throws \RuntimeException if session fails to start - */ - public function start(): bool; - - /** - * Returns the session ID. - */ - public function getId(): string; - - /** - * Sets the session ID. - */ - public function setId(string $id): void; - - /** - * Returns the session name. - */ - public function getName(): string; - - /** - * Sets the session name. - */ - public function setName(string $name): void; - - /** - * Invalidates the current session. - * - * Clears all session attributes and flashes and regenerates the - * session and deletes the old session from persistence. - * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function invalidate(?int $lifetime = null): bool; - - /** - * Migrates the current session to a new session id while maintaining all - * session attributes. - * - * @param bool $destroy Whether to delete the old session or leave it to garbage collection - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function migrate(bool $destroy = false, ?int $lifetime = null): bool; - - /** - * Force the session to be saved and closed. - * - * This method is generally not required for real sessions as - * the session will be automatically saved at the end of - * code execution. - */ - public function save(): void; - - /** - * Checks if an attribute is defined. - */ - public function has(string $name): bool; - - /** - * Returns an attribute. - */ - public function get(string $name, mixed $default = null): mixed; - - /** - * Sets an attribute. - */ - public function set(string $name, mixed $value): void; - - /** - * Returns attributes. - */ - public function all(): array; - - /** - * Sets attributes. - */ - public function replace(array $attributes): void; - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name): mixed; - - /** - * Clears all attributes. - */ - public function clear(): void; - - /** - * Checks if the session was started. - */ - public function isStarted(): bool; - - /** - * Registers a SessionBagInterface with the session. - */ - public function registerBag(SessionBagInterface $bag): void; - - /** - * Gets a bag instance by name. - */ - public function getBag(string $name): SessionBagInterface; - - /** - * Gets session meta. - */ - public function getMetadataBag(): MetadataBag; -} diff --git a/vendor/symfony/http-foundation/Session/SessionUtils.php b/vendor/symfony/http-foundation/Session/SessionUtils.php deleted file mode 100644 index 57aa565..0000000 --- a/vendor/symfony/http-foundation/Session/SessionUtils.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session utility functions. - * - * @author Nicolas Grekas - * @author Rémon van de Kamp - * - * @internal - */ -final class SessionUtils -{ - /** - * Finds the session header amongst the headers that are to be sent, removes it, and returns - * it so the caller can process it further. - */ - public static function popSessionCookie(string $sessionName, #[\SensitiveParameter] string $sessionId): ?string - { - $sessionCookie = null; - $sessionCookiePrefix = \sprintf(' %s=', urlencode($sessionName)); - $sessionCookieWithId = \sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); - $otherCookies = []; - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookiePrefix, 11)) { - $sessionCookie = $h; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } - } else { - $otherCookies[] = $h; - } - } - if (null === $sessionCookie) { - return null; - } - - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); - } - - return $sessionCookie; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php deleted file mode 100644 index fd85623..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\HttpFoundation\Session\SessionUtils; - -/** - * This abstract session handler provides a generic implementation - * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, - * enabling strict and lazy session handling. - * - * @author Nicolas Grekas - */ -abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private string $sessionName; - private string $prefetchId; - private string $prefetchData; - private ?string $newSessionId = null; - private string $igbinaryEmptyData; - - public function open(string $savePath, string $sessionName): bool - { - $this->sessionName = $sessionName; - if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) { - header(\sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire'))); - } - - return true; - } - - abstract protected function doRead(#[\SensitiveParameter] string $sessionId): string; - - abstract protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool; - - abstract protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool; - - public function validateId(#[\SensitiveParameter] string $sessionId): bool - { - $this->prefetchData = $this->read($sessionId); - $this->prefetchId = $sessionId; - - return '' !== $this->prefetchData; - } - - public function read(#[\SensitiveParameter] string $sessionId): string - { - if (isset($this->prefetchId)) { - $prefetchId = $this->prefetchId; - $prefetchData = $this->prefetchData; - unset($this->prefetchId, $this->prefetchData); - - if ($prefetchId === $sessionId || '' === $prefetchData) { - $this->newSessionId = '' === $prefetchData ? $sessionId : null; - - return $prefetchData; - } - } - - $data = $this->doRead($sessionId); - $this->newSessionId = '' === $data ? $sessionId : null; - - return $data; - } - - public function write(#[\SensitiveParameter] string $sessionId, string $data): bool - { - // see https://github.com/igbinary/igbinary/issues/146 - $this->igbinaryEmptyData ??= \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; - if ('' === $data || $this->igbinaryEmptyData === $data) { - return $this->destroy($sessionId); - } - $this->newSessionId = null; - - return $this->doWrite($sessionId, $data); - } - - public function destroy(#[\SensitiveParameter] string $sessionId): bool - { - if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOL)) { - if (!isset($this->sessionName)) { - throw new \LogicException(\sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); - } - $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); - - /* - * We send an invalidation Set-Cookie header (zero lifetime) - * when either the session was started or a cookie with - * the session name was sent by the client (in which case - * we know it's invalid as a valid session cookie would've - * started the session). - */ - if (null === $cookie || isset($_COOKIE[$this->sessionName])) { - $params = session_get_cookie_params(); - unset($params['lifetime']); - setcookie($this->sessionName, '', $params); - } - } - - return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php b/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php deleted file mode 100644 index 70ac762..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/IdentityMarshaller.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE - */ -class IdentityMarshaller implements MarshallerInterface -{ - public function marshall(array $values, ?array &$failed): array - { - foreach ($values as $key => $value) { - if (!\is_string($value)) { - throw new \LogicException(\sprintf('%s accepts only string as data.', __METHOD__)); - } - } - - return $values; - } - - public function unmarshall(string $value): string - { - return $value; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php deleted file mode 100644 index 8e82f18..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Ahmed TAILOULOUTE - */ -class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - public function __construct( - private AbstractSessionHandler $handler, - private MarshallerInterface $marshaller, - ) { - } - - public function open(string $savePath, string $name): bool - { - return $this->handler->open($savePath, $name); - } - - public function close(): bool - { - return $this->handler->close(); - } - - public function destroy(#[\SensitiveParameter] string $sessionId): bool - { - return $this->handler->destroy($sessionId); - } - - public function gc(int $maxlifetime): int|false - { - return $this->handler->gc($maxlifetime); - } - - public function read(#[\SensitiveParameter] string $sessionId): string - { - return $this->marshaller->unmarshall($this->handler->read($sessionId)); - } - - public function write(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $failed = []; - $marshalledData = $this->marshaller->marshall(['data' => $data], $failed); - - if (isset($failed['data'])) { - return false; - } - - return $this->handler->write($sessionId, $marshalledData['data']); - } - - public function validateId(#[\SensitiveParameter] string $sessionId): bool - { - return $this->handler->validateId($sessionId); - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->handler->updateTimestamp($sessionId, $data); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php deleted file mode 100644 index 4b95d88..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Memcached based session storage handler based on the Memcached class - * provided by the PHP memcached extension. - * - * @see https://php.net/memcached - * - * @author Drak - */ -class MemcachedSessionHandler extends AbstractSessionHandler -{ - /** - * Time to live in seconds. - */ - private int|\Closure|null $ttl; - - /** - * Key prefix for shared environments. - */ - private string $prefix; - - /** - * Constructor. - * - * List of available options: - * * prefix: The prefix to use for the memcached keys in order to avoid collision - * * ttl: The time to live in seconds. - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct( - private \Memcached $memcached, - array $options = [], - ) { - if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime', 'ttl'])) { - throw new \InvalidArgumentException(\sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->ttl = $options['expiretime'] ?? $options['ttl'] ?? null; - $this->prefix = $options['prefix'] ?? 'sf2s'; - } - - public function close(): bool - { - return $this->memcached->quit(); - } - - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - return $this->memcached->get($this->prefix.$sessionId) ?: ''; - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $this->memcached->touch($this->prefix.$sessionId, $this->getCompatibleTtl()); - - return true; - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->memcached->set($this->prefix.$sessionId, $data, $this->getCompatibleTtl()); - } - - private function getCompatibleTtl(): int - { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - - // If the relative TTL that is used exceeds 30 days, memcached will treat the value as Unix time. - // We have to convert it to an absolute Unix time at this point, to make sure the TTL is correct. - if ($ttl > 60 * 60 * 24 * 30) { - $ttl += time(); - } - - return $ttl; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - $result = $this->memcached->delete($this->prefix.$sessionId); - - return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); - } - - public function gc(int $maxlifetime): int|false - { - // not required here because memcached will auto expire the records anyhow. - return 0; - } - - /** - * Return a Memcached instance. - */ - protected function getMemcached(): \Memcached - { - return $this->memcached; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php deleted file mode 100644 index 8ed6a7b..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Migrating session handler for migrating from one handler to another. It reads - * from the current handler and writes both the current and new ones. - * - * It ignores errors from the new handler. - * - * @author Ross Motley - * @author Oliver Radwell - */ -class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $currentHandler; - private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $writeOnlyHandler; - - public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) - { - if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $currentHandler = new StrictSessionHandler($currentHandler); - } - if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); - } - - $this->currentHandler = $currentHandler; - $this->writeOnlyHandler = $writeOnlyHandler; - } - - public function close(): bool - { - $result = $this->currentHandler->close(); - $this->writeOnlyHandler->close(); - - return $result; - } - - public function destroy(#[\SensitiveParameter] string $sessionId): bool - { - $result = $this->currentHandler->destroy($sessionId); - $this->writeOnlyHandler->destroy($sessionId); - - return $result; - } - - public function gc(int $maxlifetime): int|false - { - $result = $this->currentHandler->gc($maxlifetime); - $this->writeOnlyHandler->gc($maxlifetime); - - return $result; - } - - public function open(string $savePath, string $sessionName): bool - { - $result = $this->currentHandler->open($savePath, $sessionName); - $this->writeOnlyHandler->open($savePath, $sessionName); - - return $result; - } - - public function read(#[\SensitiveParameter] string $sessionId): string - { - // No reading from new handler until switch-over - return $this->currentHandler->read($sessionId); - } - - public function write(#[\SensitiveParameter] string $sessionId, string $sessionData): bool - { - $result = $this->currentHandler->write($sessionId, $sessionData); - $this->writeOnlyHandler->write($sessionId, $sessionData); - - return $result; - } - - public function validateId(#[\SensitiveParameter] string $sessionId): bool - { - // No reading from new handler until switch-over - return $this->currentHandler->validateId($sessionId); - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $sessionData): bool - { - $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); - $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); - - return $result; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php deleted file mode 100644 index d558603..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ /dev/null @@ -1,186 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use MongoDB\BSON\Binary; -use MongoDB\BSON\UTCDateTime; -use MongoDB\Client; -use MongoDB\Driver\BulkWrite; -use MongoDB\Driver\Manager; -use MongoDB\Driver\Query; - -/** - * Session handler using the MongoDB driver extension. - * - * @author Markus Bachmann - * @author Jérôme Tamarelle - * - * @see https://php.net/mongodb - */ -class MongoDbSessionHandler extends AbstractSessionHandler -{ - private Manager $manager; - private string $namespace; - private array $options; - private int|\Closure|null $ttl; - - /** - * Constructor. - * - * List of available options: - * * database: The name of the database [required] - * * collection: The name of the collection [required] - * * id_field: The field name for storing the session id [default: _id] - * * data_field: The field name for storing the session data [default: data] - * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at] - * * ttl: The time to live in seconds. - * - * It is strongly recommended to put an index on the `expiry_field` for - * garbage-collection. Alternatively it's possible to automatically expire - * the sessions in the database as described below: - * - * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions - * automatically. Such an index can for example look like this: - * - * db..createIndex( - * { "": 1 }, - * { "expireAfterSeconds": 0 } - * ) - * - * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ - * - * If you use such an index, you can drop `gc_probability` to 0 since - * no garbage-collection is required. - * - * @throws \InvalidArgumentException When "database" or "collection" not provided - */ - public function __construct(Client|Manager $mongo, array $options) - { - if (!isset($options['database']) || !isset($options['collection'])) { - throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.'); - } - - if ($mongo instanceof Client) { - $mongo = $mongo->getManager(); - } - - $this->manager = $mongo; - $this->namespace = $options['database'].'.'.$options['collection']; - - $this->options = array_merge([ - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'expiry_field' => 'expires_at', - ], $options); - $this->ttl = $this->options['ttl'] ?? null; - } - - public function close(): bool - { - return true; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - $write = new BulkWrite(); - $write->delete( - [$this->options['id_field'] => $sessionId], - ['limit' => 1] - ); - - $this->manager->executeBulkWrite($this->namespace, $write); - - return true; - } - - public function gc(int $maxlifetime): int|false - { - $write = new BulkWrite(); - $write->delete( - [$this->options['expiry_field'] => ['$lt' => $this->getUTCDateTime()]], - ); - $result = $this->manager->executeBulkWrite($this->namespace, $write); - - return $result->getDeletedCount() ?? false; - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $expiry = $this->getUTCDateTime($ttl); - - $fields = [ - $this->options['time_field'] => $this->getUTCDateTime(), - $this->options['expiry_field'] => $expiry, - $this->options['data_field'] => new Binary($data, Binary::TYPE_GENERIC), - ]; - - $write = new BulkWrite(); - $write->update( - [$this->options['id_field'] => $sessionId], - ['$set' => $fields], - ['upsert' => true] - ); - - $this->manager->executeBulkWrite($this->namespace, $write); - - return true; - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $expiry = $this->getUTCDateTime($ttl); - - $write = new BulkWrite(); - $write->update( - [$this->options['id_field'] => $sessionId], - ['$set' => [ - $this->options['time_field'] => $this->getUTCDateTime(), - $this->options['expiry_field'] => $expiry, - ]], - ['multi' => false], - ); - - $this->manager->executeBulkWrite($this->namespace, $write); - - return true; - } - - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - $cursor = $this->manager->executeQuery($this->namespace, new Query([ - $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => ['$gte' => $this->getUTCDateTime()], - ], [ - 'projection' => [ - '_id' => false, - $this->options['data_field'] => true, - ], - 'limit' => 1, - ])); - - foreach ($cursor as $document) { - return (string) $document->{$this->options['data_field']} ?? ''; - } - - // Not found - return ''; - } - - private function getUTCDateTime(int $additionalSeconds = 0): UTCDateTime - { - return new UTCDateTime((time() + $additionalSeconds) * 1000); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php deleted file mode 100644 index 81e97be..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Native session handler using PHP's built in file storage. - * - * @author Drak - */ -class NativeFileSessionHandler extends \SessionHandler -{ - /** - * @param string|null $savePath Path of directory to save session files - * Default null will leave setting as defined by PHP. - * '/path', 'N;/path', or 'N;octal-mode;/path - * - * @see https://php.net/session.configuration#ini.session.save-path for further details. - * - * @throws \InvalidArgumentException On invalid $savePath - * @throws \RuntimeException When failing to create the save directory - */ - public function __construct(?string $savePath = null) - { - $baseDir = $savePath ??= \ini_get('session.save_path'); - - if ($count = substr_count($savePath, ';')) { - if ($count > 2) { - throw new \InvalidArgumentException(\sprintf('Invalid argument $savePath \'%s\'.', $savePath)); - } - - // characters after last ';' are the path - $baseDir = ltrim(strrchr($savePath, ';'), ';'); - } - - if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0o777, true) && !is_dir($baseDir)) { - throw new \RuntimeException(\sprintf('Session Storage was not able to create directory "%s".', $baseDir)); - } - - if ($savePath !== \ini_get('session.save_path')) { - ini_set('session.save_path', $savePath); - } - if ('files' !== \ini_get('session.save_handler')) { - ini_set('session.save_handler', 'files'); - } - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php deleted file mode 100644 index a77185e..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Can be used in unit testing or in a situations where persisted sessions are not desired. - * - * @author Drak - */ -class NullSessionHandler extends AbstractSessionHandler -{ - public function close(): bool - { - return true; - } - - public function validateId(#[\SensitiveParameter] string $sessionId): bool - { - return true; - } - - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - return ''; - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return true; - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return true; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - return true; - } - - public function gc(int $maxlifetime): int|false - { - return 0; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php deleted file mode 100644 index 2fef5cc..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ /dev/null @@ -1,919 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Doctrine\DBAL\Schema\Name\Identifier; -use Doctrine\DBAL\Schema\Name\UnqualifiedName; -use Doctrine\DBAL\Schema\PrimaryKeyConstraint; -use Doctrine\DBAL\Schema\Schema; -use Doctrine\DBAL\Types\Types; - -/** - * Session handler using a PDO connection to read and write data. - * - * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements - * different locking strategies to handle concurrent access to the same session. - * Locking is necessary to prevent loss of data due to race conditions and to keep - * the session data consistent between read() and write(). With locking, requests - * for the same session will wait until the other one finished writing. For this - * reason it's best practice to close a session as early as possible to improve - * concurrency. PHPs internal files session handler also implements locking. - * - * Attention: Since SQLite does not support row level locks but locks the whole database, - * it means only one session can be accessed at a time. Even different sessions would wait - * for another to finish. So saving session in SQLite should only be considered for - * development or prototypes. - * - * Session data is a binary string that can contain non-printable characters like the null byte. - * For this reason it must be saved in a binary column in the database like BLOB in MySQL. - * Saving it in a character column could corrupt the data. You can use createTable() - * to initialize a correctly defined table. - * - * @see https://php.net/sessionhandlerinterface - * - * @author Fabien Potencier - * @author Michael Williams - * @author Tobias Schultze - */ -class PdoSessionHandler extends AbstractSessionHandler -{ - /** - * No locking is done. This means sessions are prone to loss of data due to - * race conditions of concurrent requests to the same session. The last session - * write will win in this case. It might be useful when you implement your own - * logic to deal with this like an optimistic approach. - */ - public const LOCK_NONE = 0; - - /** - * Creates an application-level lock on a session. The disadvantage is that the - * lock is not enforced by the database and thus other, unaware parts of the - * application could still concurrently modify the session. The advantage is it - * does not require a transaction. - * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. - */ - public const LOCK_ADVISORY = 1; - - /** - * Issues a real row lock. Since it uses a transaction between opening and - * closing a session, you have to be careful when you use same database connection - * that you also use for your application logic. This mode is the default because - * it's the only reliable solution across DBMSs. - */ - public const LOCK_TRANSACTIONAL = 2; - - private \PDO $pdo; - - /** - * DSN string or null for session.save_path or false when lazy connection disabled. - */ - private string|false|null $dsn = false; - - private string $driver; - private string $table = 'sessions'; - private string $idCol = 'sess_id'; - private string $dataCol = 'sess_data'; - private string $lifetimeCol = 'sess_lifetime'; - private string $timeCol = 'sess_time'; - - /** - * Time to live in seconds. - */ - private int|\Closure|null $ttl; - - /** - * Username when lazy-connect. - */ - private ?string $username = null; - - /** - * Password when lazy-connect. - */ - private ?string $password = null; - - /** - * Connection options when lazy-connect. - */ - private array $connectionOptions = []; - - /** - * The strategy for locking, see constants. - */ - private int $lockMode = self::LOCK_TRANSACTIONAL; - - /** - * It's an array to support multiple reads before closing which is manual, non-standard usage. - * - * @var \PDOStatement[] An array of statements to release advisory locks - */ - private array $unlockStatements = []; - - /** - * True when the current session exists but expired according to session.gc_maxlifetime. - */ - private bool $sessionExpired = false; - - /** - * Whether a transaction is active. - */ - private bool $inTransaction = false; - - /** - * Whether gc() has been called. - */ - private bool $gcCalled = false; - - /** - * You can either pass an existing database connection as PDO instance or - * pass a DSN string that will be used to lazy-connect to the database - * when the session is actually used. Furthermore it's possible to pass null - * which will then use the session.save_path ini setting as PDO DSN parameter. - * - * List of available options: - * * db_table: The name of the table [default: sessions] - * * db_id_col: The column where to store the session id [default: sess_id] - * * db_data_col: The column where to store the session data [default: sess_data] - * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] - * * db_time_col: The column where to store the timestamp [default: sess_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] - * * ttl: The time to live in seconds. - * - * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null - * - * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - */ - public function __construct(#[\SensitiveParameter] \PDO|string|null $pdoOrDsn = null, #[\SensitiveParameter] array $options = []) - { - if ($pdoOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new \InvalidArgumentException(\sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); - } - - $this->pdo = $pdoOrDsn; - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } elseif (\is_string($pdoOrDsn) && str_contains($pdoOrDsn, '://')) { - $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); - } else { - $this->dsn = $pdoOrDsn; - } - - $this->table = $options['db_table'] ?? $this->table; - $this->idCol = $options['db_id_col'] ?? $this->idCol; - $this->dataCol = $options['db_data_col'] ?? $this->dataCol; - $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; - $this->timeCol = $options['db_time_col'] ?? $this->timeCol; - $this->username = $options['db_username'] ?? $this->username; - $this->password = $options['db_password'] ?? $this->password; - $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; - $this->lockMode = $options['lock_mode'] ?? $this->lockMode; - $this->ttl = $options['ttl'] ?? null; - } - - /** - * Adds the Table to the Schema if it doesn't exist. - */ - public function configureSchema(Schema $schema, ?\Closure $isSameDatabase = null): void - { - if ($schema->hasTable($this->table) || ($isSameDatabase && !$isSameDatabase($this->getConnection()->exec(...)))) { - return; - } - - $table = $schema->createTable($this->table); - switch ($this->driver) { - case 'mysql': - $table->addColumn($this->idCol, Types::BINARY)->setLength(128)->setNotnull(true); - $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(true); - $table->addColumn($this->lifetimeCol, Types::INTEGER)->setUnsigned(true)->setNotnull(true); - $table->addColumn($this->timeCol, Types::INTEGER)->setUnsigned(true)->setNotnull(true); - $table->addOption('collate', 'utf8mb4_bin'); - $table->addOption('engine', 'InnoDB'); - break; - case 'sqlite': - $table->addColumn($this->idCol, Types::TEXT)->setNotnull(true); - $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(true); - $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(true); - $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(true); - break; - case 'pgsql': - $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(true); - $table->addColumn($this->dataCol, Types::BINARY)->setNotnull(true); - $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(true); - $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(true); - break; - case 'oci': - $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(true); - $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(true); - $table->addColumn($this->lifetimeCol, Types::INTEGER)->setNotnull(true); - $table->addColumn($this->timeCol, Types::INTEGER)->setNotnull(true); - break; - case 'sqlsrv': - $table->addColumn($this->idCol, Types::STRING)->setLength(128)->setNotnull(true); - $table->addColumn($this->dataCol, Types::BLOB)->setNotnull(true); - $table->addColumn($this->lifetimeCol, Types::INTEGER)->setUnsigned(true)->setNotnull(true); - $table->addColumn($this->timeCol, Types::INTEGER)->setUnsigned(true)->setNotnull(true); - break; - default: - throw new \DomainException(\sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - $table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, [new UnqualifiedName(Identifier::unquoted($this->idCol))], true)); - $table->addIndex([$this->lifetimeCol], $this->lifetimeCol.'_idx'); - } - - /** - * Creates the table to store sessions which can be called once for setup. - * - * Session ID is saved in a column of maximum length 128 because that is enough even - * for a 512 bit configured session.hash_function like Whirlpool. Session data is - * saved in a BLOB. One could also use a shorter inlined varbinary column - * if one was sure the data fits into it. - * - * @throws \PDOException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable(): void - { - // connect if we are not yet - $this->getConnection(); - - $sql = match ($this->driver) { - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - 'mysql' => "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB", - 'sqlite' => "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'pgsql' => "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'oci' => "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - 'sqlsrv' => "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)", - default => throw new \DomainException(\sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)), - }; - - try { - $this->pdo->exec($sql); - $this->pdo->exec("CREATE INDEX {$this->lifetimeCol}_idx ON $this->table ($this->lifetimeCol)"); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * Returns true when the current session exists but expired according to session.gc_maxlifetime. - * - * Can be used to distinguish between a new session and one that expired due to inactivity. - */ - public function isSessionExpired(): bool - { - return $this->sessionExpired; - } - - public function open(string $savePath, string $sessionName): bool - { - $this->sessionExpired = false; - - if (!isset($this->pdo)) { - $this->connect($this->dsn ?: $savePath); - } - - return parent::open($savePath, $sessionName); - } - - public function read(#[\SensitiveParameter] string $sessionId): string - { - try { - return parent::read($sessionId); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - public function gc(int $maxlifetime): int|false - { - // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. - // This way, pruning expired sessions does not block them from being started while the current session is used. - $this->gcCalled = true; - - return 0; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - // delete the record associated with this id - $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $maxlifetime = (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime')); - - try { - // We use a single MERGE SQL query when supported by the database. - $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); - if (null !== $mergeStmt) { - $mergeStmt->execute(); - - return true; - } - - $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); - $updateStmt->execute(); - - // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in - // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). - // We can just catch such an error and re-execute the update. This is similar to a serializable - // transaction with retry logic on serialization failures but without the overhead and without possible - // false positives due to longer gap locking. - if (!$updateStmt->rowCount()) { - try { - $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys - if (str_starts_with($e->getCode(), '23')) { - $updateStmt->execute(); - } else { - throw $e; - } - } - } - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $expiry = time() + (int) (($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime')); - - try { - $updateStmt = $this->pdo->prepare( - "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindValue(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindValue(':expiry', $expiry, \PDO::PARAM_INT); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $updateStmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - public function close(): bool - { - $this->commit(); - - while ($unlockStmt = array_shift($this->unlockStatements)) { - $unlockStmt->execute(); - } - - if ($this->gcCalled) { - $this->gcCalled = false; - - // delete the session records that have expired - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time"; - $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->execute(); - } - - if (false !== $this->dsn) { - unset($this->pdo, $this->driver); // only close lazy-connection - } - - return true; - } - - /** - * Lazy-connects to the database. - */ - private function connect(#[\SensitiveParameter] string $dsn): void - { - $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); - $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } - - /** - * Builds a PDO DSN from a URL-like connection string. - * - * @todo implement missing support for oci DSN (which look totally different from other PDO ones) - */ - private function buildDsnFromUrl(#[\SensitiveParameter] string $dsnOrUrl): string - { - // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid - $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); - - $params = parse_url($url); - - if (false === $params) { - return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. - } - - $params = array_map('rawurldecode', $params); - - // Override the default username and password. Values passed through options will still win over these in the constructor. - if (isset($params['user'])) { - $this->username = $params['user']; - } - - if (isset($params['pass'])) { - $this->password = $params['pass']; - } - - if (!isset($params['scheme'])) { - throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.'); - } - - $driverAliasMap = [ - 'mssql' => 'sqlsrv', - 'mysql2' => 'mysql', // Amazon RDS, for some weird reason - 'postgres' => 'pgsql', - 'postgresql' => 'pgsql', - 'sqlite3' => 'sqlite', - ]; - - $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme']; - - // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. - if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) { - $driver = substr($driver, 4); - } - - $dsn = null; - switch ($driver) { - case 'mysql': - $dsn = 'mysql:'; - if ('' !== ($params['query'] ?? '')) { - $queryParams = []; - parse_str($params['query'], $queryParams); - if ('' !== ($queryParams['charset'] ?? '')) { - $dsn .= 'charset='.$queryParams['charset'].';'; - } - - if ('' !== ($queryParams['unix_socket'] ?? '')) { - $dsn .= 'unix_socket='.$queryParams['unix_socket'].';'; - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - } - } - // If "unix_socket" is not in the query, we continue with the same process as pgsql - // no break - case 'pgsql': - $dsn ??= 'pgsql:'; - - if (isset($params['host']) && '' !== $params['host']) { - $dsn .= 'host='.$params['host'].';'; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= 'port='.$params['port'].';'; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - - case 'sqlite': - return 'sqlite:'.substr($params['path'], 1); - - case 'sqlsrv': - $dsn = 'sqlsrv:server='; - - if (isset($params['host'])) { - $dsn .= $params['host']; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= ','.$params['port']; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= ';Database='.$dbName; - } - - return $dsn; - - default: - throw new \InvalidArgumentException(\sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); - } - } - - /** - * Helper method to begin a transaction. - * - * Since SQLite does not support row level locks, we have to acquire a reserved lock - * on the database immediately. Because of https://bugs.php.net/42766 we have to create - * such a transaction manually which also means we cannot use PDO::commit or - * PDO::rollback or PDO::inTransaction for SQLite. - * - * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions - * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . - * So we change it to READ COMMITTED. - */ - private function beginTransaction(): void - { - if (!$this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); - } else { - if ('mysql' === $this->driver) { - $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); - } - $this->pdo->beginTransaction(); - } - $this->inTransaction = true; - } - } - - /** - * Helper method to commit a transaction. - */ - private function commit(): void - { - if ($this->inTransaction) { - try { - // commit read-write transaction which also releases the lock - if ('sqlite' === $this->driver) { - $this->pdo->exec('COMMIT'); - } else { - $this->pdo->commit(); - } - $this->inTransaction = false; - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - } - - /** - * Helper method to rollback a transaction. - */ - private function rollback(): void - { - // We only need to rollback if we are in a transaction. Otherwise the resulting - // error would hide the real problem why rollback was called. We might not be - // in a transaction when not using the transactional locking behavior or when - // two callbacks (e.g. destroy and write) are invoked that both fail. - if ($this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('ROLLBACK'); - } else { - $this->pdo->rollBack(); - } - $this->inTransaction = false; - } - } - - /** - * Reads the session data in respect to the different locking strategies. - * - * We need to make sure we do not return session data that is already considered garbage according - * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. - */ - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - if (self::LOCK_ADVISORY === $this->lockMode) { - $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); - } - - $selectSql = $this->getSelectSql(); - $selectStmt = $this->pdo->prepare($selectSql); - $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt = null; - - while (true) { - $selectStmt->execute(); - $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); - - if ($sessionRows) { - $expiry = (int) $sessionRows[0][1]; - - if ($expiry < time()) { - $this->sessionExpired = true; - - return ''; - } - - return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; - } - - if (null !== $insertStmt) { - $this->rollback(); - throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); - } - - if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOL) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { - // In strict mode, session fixation is not possible: new sessions always start with a unique - // random id, so that concurrency is not possible and this code path can be skipped. - // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block - // until other connections to the session are committed. - try { - $insertStmt = $this->getInsertStatement($sessionId, '', 0); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Catch duplicate key error because other connection created the session already. - // It would only not be the case when the other connection destroyed the session. - if (str_starts_with($e->getCode(), '23')) { - // Retrieve finished session data written by concurrent connection by restarting the loop. - // We have to start a new transaction as a failed query will mark the current transaction as - // aborted in PostgreSQL and disallow further queries within it. - $this->rollback(); - $this->beginTransaction(); - continue; - } - - throw $e; - } - } - - return ''; - } - } - - /** - * Executes an application-level lock on the database. - * - * @return \PDOStatement The statement that needs to be executed later to release the lock - * - * @throws \DomainException When an unsupported PDO driver is used - * - * @todo implement missing advisory locks - * - for oci using DBMS_LOCK.REQUEST - * - for sqlsrv using sp_getapplock with LockOwner = Session - */ - private function doAdvisoryLock(#[\SensitiveParameter] string $sessionId): \PDOStatement - { - switch ($this->driver) { - case 'mysql': - // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. - $lockId = substr($sessionId, 0, 64); - // should we handle the return value? 0 on timeout, null on error - // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout - $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - - return $releaseStmt; - case 'pgsql': - // Obtaining an exclusive session level advisory lock requires an integer key. - // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. - // So we cannot just use hexdec(). - if (4 === \PHP_INT_SIZE) { - $sessionInt1 = $this->convertStringToInt($sessionId); - $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); - $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); - $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - } else { - $sessionBigInt = $this->convertStringToInt($sessionId); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); - $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); - $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - } - - return $releaseStmt; - case 'sqlite': - throw new \DomainException('SQLite does not support advisory locks.'); - default: - throw new \DomainException(\sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - /** - * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. - * - * Keep in mind, PHP integers are signed. - */ - private function convertStringToInt(string $string): int - { - if (4 === \PHP_INT_SIZE) { - return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - } - - $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); - $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - - return $int2 + ($int1 << 32); - } - - /** - * Return a locking or nonlocking SQL query to read session information. - * - * @throws \DomainException When an unsupported PDO driver is used - */ - private function getSelectSql(): string - { - if (self::LOCK_TRANSACTIONAL === $this->lockMode) { - $this->beginTransaction(); - - switch ($this->driver) { - case 'mysql': - case 'oci': - case 'pgsql': - return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; - case 'sqlsrv': - return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; - case 'sqlite': - // we already locked when starting transaction - break; - default: - throw new \DomainException(\sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - return "SELECT $this->dataCol, $this->lifetimeCol FROM $this->table WHERE $this->idCol = :id"; - } - - /** - * Returns an insert statement supported by the database for writing session data. - */ - private function getInsertStatement(#[\SensitiveParameter] string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; - break; - case 'sqlsrv': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - default: - $data = $sessionData; - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns an update statement supported by the database for writing session data. - */ - private function getUpdateStatement(#[\SensitiveParameter] string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; - break; - case 'sqlsrv': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - default: - $data = $sessionData; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. - */ - private function getMergeStatement(#[\SensitiveParameter] string $sessionId, string $data, int $maxlifetime): ?\PDOStatement - { - switch (true) { - case 'mysql' === $this->driver: - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ - $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $this->driver: - $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html - return null; - } - - $mergeStmt = $this->pdo->prepare($mergeSql); - - if ('sqlsrv' === $this->driver) { - $dataStream = fopen('php://memory', 'r+'); - fwrite($dataStream, $data); - rewind($dataStream); - - $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(3, $dataStream, \PDO::PARAM_LOB); - $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); - $mergeStmt->bindParam(6, $dataStream, \PDO::PARAM_LOB); - $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); - } else { - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - } - - return $mergeStmt; - } - - /** - * Return a PDO instance. - */ - protected function getConnection(): \PDO - { - if (!isset($this->pdo)) { - $this->connect($this->dsn ?: \ini_get('session.save_path')); - } - - return $this->pdo; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php deleted file mode 100644 index 78cd4e7..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Predis\Response\ErrorInterface; -use Relay\Relay; - -/** - * Redis based session storage handler based on the Redis class - * provided by the PHP redis extension. - * - * @author Dalibor Karlović - */ -class RedisSessionHandler extends AbstractSessionHandler -{ - /** - * Key prefix for shared environments. - */ - private string $prefix; - - /** - * Time to live in seconds. - */ - private int|\Closure|null $ttl; - - /** - * List of available options: - * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server - * * ttl: The time to live in seconds. - * - * @throws \InvalidArgumentException When unsupported client or options are passed - */ - public function __construct( - private \Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, - array $options = [], - ) { - if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { - throw new \InvalidArgumentException(\sprintf('The following options are not supported "%s".', implode(', ', $diff))); - } - - $this->prefix = $options['prefix'] ?? 'sf_s'; - $this->ttl = $options['ttl'] ?? null; - } - - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - return $this->redis->get($this->prefix.$sessionId) ?: ''; - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - $result = $this->redis->setEx($this->prefix.$sessionId, (int) $ttl, $data); - - return $result && !$result instanceof ErrorInterface; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - static $unlink = true; - - if ($unlink) { - try { - $unlink = false !== $this->redis->unlink($this->prefix.$sessionId); - } catch (\Throwable) { - $unlink = false; - } - } - - if (!$unlink) { - $this->redis->del($this->prefix.$sessionId); - } - - return true; - } - - #[\ReturnTypeWillChange] - public function close(): bool - { - return true; - } - - public function gc(int $maxlifetime): int|false - { - return 0; - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - $ttl = ($this->ttl instanceof \Closure ? ($this->ttl)() : $this->ttl) ?? \ini_get('session.gc_maxlifetime'); - - return $this->redis->expire($this->prefix.$sessionId, (int) $ttl); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php deleted file mode 100644 index cb0b6f8..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Doctrine\DBAL\Configuration; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory; -use Doctrine\DBAL\Tools\DsnParser; -use Relay\Relay; -use Symfony\Component\Cache\Adapter\AbstractAdapter; - -/** - * @author Nicolas Grekas - */ -class SessionHandlerFactory -{ - public static function createHandler(object|string $connection, array $options = []): AbstractSessionHandler - { - if ($query = \is_string($connection) ? parse_url($connection) : false) { - parse_str($query['query'] ?? '', $query); - - if (($options['ttl'] ?? null) instanceof \Closure) { - $query['ttl'] = $options['ttl']; - } - } - $options = ($query ?: []) + $options; - - switch (true) { - case $connection instanceof \Redis: - case $connection instanceof Relay: - case $connection instanceof \RedisArray: - case $connection instanceof \RedisCluster: - case $connection instanceof \Predis\ClientInterface: - return new RedisSessionHandler($connection); - - case $connection instanceof \Memcached: - return new MemcachedSessionHandler($connection); - - case $connection instanceof \PDO: - return new PdoSessionHandler($connection); - - case !\is_string($connection): - throw new \InvalidArgumentException(\sprintf('Unsupported Connection: "%s".', get_debug_type($connection))); - case str_starts_with($connection, 'file://'): - $savePath = substr($connection, 7); - - return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath)); - - case str_starts_with($connection, 'redis:'): - case str_starts_with($connection, 'rediss:'): - case str_starts_with($connection, 'valkey:'): - case str_starts_with($connection, 'valkeys:'): - case str_starts_with($connection, 'memcached:'): - if (!class_exists(AbstractAdapter::class)) { - throw new \InvalidArgumentException('Unsupported Redis or Memcached DSN. Try running "composer require symfony/cache".'); - } - $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; - $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); - - return new $handlerClass($connection, array_intersect_key($options, ['prefix' => 1, 'ttl' => 1])); - - case str_starts_with($connection, 'pdo_oci://'): - if (!class_exists(DriverManager::class)) { - throw new \InvalidArgumentException('Unsupported PDO OCI DSN. Try running "composer require doctrine/dbal".'); - } - $connection[3] = '-'; - $params = (new DsnParser())->parse($connection); - $config = new Configuration(); - $config->setSchemaManagerFactory(new DefaultSchemaManagerFactory()); - - $connection = DriverManager::getConnection($params, $config)->getNativeConnection(); - // no break; - - case str_starts_with($connection, 'mssql://'): - case str_starts_with($connection, 'mysql://'): - case str_starts_with($connection, 'mysql2://'): - case str_starts_with($connection, 'pgsql://'): - case str_starts_with($connection, 'postgres://'): - case str_starts_with($connection, 'postgresql://'): - case str_starts_with($connection, 'sqlsrv://'): - case str_starts_with($connection, 'sqlite://'): - case str_starts_with($connection, 'sqlite3://'): - return new PdoSessionHandler($connection, $options); - } - - throw new \InvalidArgumentException(\sprintf('Unsupported Connection: "%s".', $connection)); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php deleted file mode 100644 index 0d84eac..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. - * - * @author Nicolas Grekas - */ -class StrictSessionHandler extends AbstractSessionHandler -{ - private bool $doDestroy; - - public function __construct( - private \SessionHandlerInterface $handler, - ) { - if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { - throw new \LogicException(\sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_debug_type($handler), self::class)); - } - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @internal - */ - public function isWrapper(): bool - { - return $this->handler instanceof \SessionHandler; - } - - public function open(string $savePath, string $sessionName): bool - { - parent::open($savePath, $sessionName); - - return $this->handler->open($savePath, $sessionName); - } - - protected function doRead(#[\SensitiveParameter] string $sessionId): string - { - return $this->handler->read($sessionId); - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->write($sessionId, $data); - } - - protected function doWrite(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->handler->write($sessionId, $data); - } - - public function destroy(#[\SensitiveParameter] string $sessionId): bool - { - $this->doDestroy = true; - $destroyed = parent::destroy($sessionId); - - return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; - } - - protected function doDestroy(#[\SensitiveParameter] string $sessionId): bool - { - $this->doDestroy = false; - - return $this->handler->destroy($sessionId); - } - - public function close(): bool - { - return $this->handler->close(); - } - - public function gc(int $maxlifetime): int|false - { - return $this->handler->gc($maxlifetime); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php deleted file mode 100644 index c9e0bdd..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Metadata container. - * - * Adds metadata to the session. - * - * @author Drak - */ -class MetadataBag implements SessionBagInterface -{ - public const CREATED = 'c'; - public const UPDATED = 'u'; - public const LIFETIME = 'l'; - - protected array $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; - - private string $name = '__metadata'; - private int $lastUsed; - - /** - * @param string $storageKey The key used to store bag in the session - * @param int $updateThreshold The time to wait between two UPDATED updates - */ - public function __construct( - private string $storageKey = '_sf2_meta', - private int $updateThreshold = 0, - ) { - } - - public function initialize(array &$array): void - { - $this->meta = &$array; - - if (isset($array[self::CREATED])) { - $this->lastUsed = $this->meta[self::UPDATED]; - - $timeStamp = time(); - if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { - $this->meta[self::UPDATED] = $timeStamp; - } - } else { - $this->stampCreated(); - } - } - - /** - * Gets the lifetime that the session cookie was set with. - */ - public function getLifetime(): int - { - return $this->meta[self::LIFETIME]; - } - - /** - * Stamps a new session's metadata. - * - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function stampNew(?int $lifetime = null): void - { - $this->stampCreated($lifetime); - } - - public function getStorageKey(): string - { - return $this->storageKey; - } - - /** - * Gets the created timestamp metadata. - * - * @return int Unix timestamp - */ - public function getCreated(): int - { - return $this->meta[self::CREATED]; - } - - /** - * Gets the last used metadata. - * - * @return int Unix timestamp - */ - public function getLastUsed(): int - { - return $this->lastUsed; - } - - public function clear(): mixed - { - // nothing to do - return null; - } - - public function getName(): string - { - return $this->name; - } - - /** - * Sets name. - */ - public function setName(string $name): void - { - $this->name = $name; - } - - private function stampCreated(?int $lifetime = null): void - { - $timeStamp = time(); - $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php deleted file mode 100644 index a32a43d..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * MockArraySessionStorage mocks the session for unit tests. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle. - * - * When doing functional testing, you should use MockFileSessionStorage instead. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Drak - */ -class MockArraySessionStorage implements SessionStorageInterface -{ - protected string $id = ''; - protected bool $started = false; - protected bool $closed = false; - protected array $data = []; - protected MetadataBag $metadataBag; - - /** - * @var SessionBagInterface[] - */ - protected array $bags = []; - - public function __construct( - protected string $name = 'MOCKSESSID', - ?MetadataBag $metaBag = null, - ) { - $this->setMetadataBag($metaBag); - } - - public function setSessionData(array $array): void - { - $this->data = $array; - } - - public function start(): bool - { - if ($this->started) { - return true; - } - - if (!$this->id) { - $this->id = $this->generateId(); - } - - $this->loadSession(); - - return true; - } - - public function regenerate(bool $destroy = false, ?int $lifetime = null): bool - { - if (!$this->started) { - $this->start(); - } - - $this->metadataBag->stampNew($lifetime); - $this->id = $this->generateId(); - - return true; - } - - public function getId(): string - { - return $this->id; - } - - public function setId(string $id): void - { - if ($this->started) { - throw new \LogicException('Cannot set session ID after the session has started.'); - } - - $this->id = $id; - } - - public function getName(): string - { - return $this->name; - } - - public function setName(string $name): void - { - $this->name = $name; - } - - public function save(): void - { - if (!$this->started || $this->closed) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - // nothing to do since we don't persist the session data - $this->closed = false; - $this->started = false; - } - - public function clear(): void - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $this->data = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - public function registerBag(SessionBagInterface $bag): void - { - $this->bags[$bag->getName()] = $bag; - } - - public function getBag(string $name): SessionBagInterface - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(\sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - public function isStarted(): bool - { - return $this->started; - } - - public function setMetadataBag(?MetadataBag $bag): void - { - $this->metadataBag = $bag ?? new MetadataBag(); - } - - /** - * Gets the MetadataBag. - */ - public function getMetadataBag(): MetadataBag - { - return $this->metadataBag; - } - - /** - * Generates a session ID. - * - * This doesn't need to be particularly cryptographically secure since this is just - * a mock. - */ - protected function generateId(): string - { - return bin2hex(random_bytes(16)); - } - - protected function loadSession(): void - { - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $this->data[$key] ??= []; - $bag->initialize($this->data[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php deleted file mode 100644 index d7a9793..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -/** - * MockFileSessionStorage is used to mock sessions for - * functional testing where you may need to persist session data - * across separate PHP processes. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle and this class does - * not pollute any session related globals, including session_*() functions - * or session.* PHP ini directives. - * - * @author Drak - */ -class MockFileSessionStorage extends MockArraySessionStorage -{ - private string $savePath; - - /** - * @param string|null $savePath Path of directory to save session files - */ - public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) - { - $savePath ??= sys_get_temp_dir(); - - if (!is_dir($savePath) && !@mkdir($savePath, 0o777, true) && !is_dir($savePath)) { - throw new \RuntimeException(\sprintf('Session Storage was not able to create directory "%s".', $savePath)); - } - - $this->savePath = $savePath; - - parent::__construct($name, $metaBag); - } - - public function start(): bool - { - if ($this->started) { - return true; - } - - if (!$this->id) { - $this->id = $this->generateId(); - } - - $this->read(); - - $this->started = true; - - return true; - } - - public function regenerate(bool $destroy = false, ?int $lifetime = null): bool - { - if (!$this->started) { - $this->start(); - } - - if ($destroy) { - $this->destroy(); - } - - return parent::regenerate($destroy, $lifetime); - } - - public function save(): void - { - if (!$this->started) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); - } - - $data = $this->data; - - foreach ($this->bags as $bag) { - if (empty($data[$key = $bag->getStorageKey()])) { - unset($data[$key]); - } - } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { - unset($data[$key]); - } - - try { - if ($data) { - $path = $this->getFilePath(); - $tmp = $path.bin2hex(random_bytes(6)); - file_put_contents($tmp, serialize($data)); - rename($tmp, $path); - } else { - $this->destroy(); - } - } finally { - $this->data = $data; - } - - // this is needed when the session object is reused across multiple requests - // in functional tests. - $this->started = false; - } - - /** - * Deletes a session from persistent storage. - * Deliberately leaves session data in memory intact. - */ - private function destroy(): void - { - set_error_handler(static function () {}); - try { - unlink($this->getFilePath()); - } finally { - restore_error_handler(); - } - } - - /** - * Calculate path to file. - */ - private function getFilePath(): string - { - return $this->savePath.'/'.$this->id.'.mocksess'; - } - - /** - * Reads session from storage and loads session. - */ - private function read(): void - { - set_error_handler(static function () {}); - try { - $data = file_get_contents($this->getFilePath()); - } finally { - restore_error_handler(); - } - - $this->data = $data ? unserialize($data) : []; - - $this->loadSession(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php deleted file mode 100644 index 77ee7b6..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -// Help opcache.preload discover always-needed symbols -class_exists(MockFileSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class MockFileSessionStorageFactory implements SessionStorageFactoryInterface -{ - /** - * @see MockFileSessionStorage constructor. - */ - public function __construct( - private ?string $savePath = null, - private string $name = 'MOCKSESSID', - private ?MetadataBag $metaBag = null, - ) { - } - - public function createStorage(?Request $request): SessionStorageInterface - { - return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php deleted file mode 100644 index 4077160..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ /dev/null @@ -1,389 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -// Help opcache.preload discover always-needed symbols -class_exists(MetadataBag::class); -class_exists(StrictSessionHandler::class); -class_exists(SessionHandlerProxy::class); - -/** - * This provides a base class for session attribute storage. - * - * @author Drak - */ -class NativeSessionStorage implements SessionStorageInterface -{ - /** - * @var SessionBagInterface[] - */ - protected array $bags = []; - protected bool $started = false; - protected bool $closed = false; - protected AbstractProxy|\SessionHandlerInterface $saveHandler; - protected MetadataBag $metadataBag; - - /** - * Depending on how you want the storage driver to behave you probably - * want to override this constructor entirely. - * - * List of options for $options array with their defaults. - * - * @see https://php.net/session.configuration for options - * but we omit 'session.' from the beginning of the keys for convenience. - * - * ("auto_start", is not supported as it tells PHP to start a session before - * PHP starts to execute user-land code. Setting during runtime has no effect). - * - * cache_limiter, "" (use "0" to prevent headers from being sent entirely). - * cache_expire, "0" - * cookie_domain, "" - * cookie_httponly, "" - * cookie_lifetime, "0" - * cookie_path, "/" - * cookie_secure, "" - * cookie_samesite, null - * gc_divisor, "100" - * gc_maxlifetime, "1440" - * gc_probability, "1" - * lazy_write, "1" - * name, "PHPSESSID" - * serialize_handler, "php" - * use_strict_mode, "1" - * use_cookies, "1" - */ - public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $options += [ - 'cache_limiter' => '', - 'cache_expire' => 0, - 'use_cookies' => 1, - 'lazy_write' => 1, - 'use_strict_mode' => 1, - ]; - - session_register_shutdown(); - - $this->setMetadataBag($metaBag); - $this->setOptions($options); - $this->setSaveHandler($handler); - } - - /** - * Gets the save handler instance. - */ - public function getSaveHandler(): AbstractProxy|\SessionHandlerInterface - { - return $this->saveHandler; - } - - public function start(): bool - { - if ($this->started) { - return true; - } - - if (\PHP_SESSION_ACTIVE === session_status()) { - throw new \RuntimeException('Failed to start the session: already started by PHP.'); - } - - if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOL) && headers_sent($file, $line)) { - throw new \RuntimeException(\sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); - } - - $sessionId = $_COOKIE[session_name()] ?? null; - /* - * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`. - * - * ---------- Part 1 - * - * The part `[a-zA-Z0-9,-]` corresponds to the character range when PHP's `session.sid_bits_per_character` is set to 6. - * See https://php.net/session.configuration#ini.session.sid-bits-per-character - * - * ---------- Part 2 - * - * The part `{22,250}` defines the acceptable length range for session IDs. - * See https://php.net/session.configuration#ini.session.sid-length - * Allowed values are integers between 22 and 256, but we use 250 for the max. - * - * Where does the 250 come from? - * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255. - * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250. - * - * ---------- Conclusion - * - * The parts 1 and 2 prevent the warning below: - * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.` - * - * The part 2 prevents the warning below: - * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).` - */ - if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) { - // the session ID in the header is invalid, create a new one - session_id(session_create_id()); - } - - // ok to try and start the session - if (!session_start()) { - throw new \RuntimeException('Failed to start the session.'); - } - - $this->loadSession(); - - return true; - } - - public function getId(): string - { - return $this->saveHandler->getId(); - } - - public function setId(string $id): void - { - $this->saveHandler->setId($id); - } - - public function getName(): string - { - return $this->saveHandler->getName(); - } - - public function setName(string $name): void - { - $this->saveHandler->setName($name); - } - - public function regenerate(bool $destroy = false, ?int $lifetime = null): bool - { - // Cannot regenerate the session ID for non-active sessions. - if (\PHP_SESSION_ACTIVE !== session_status()) { - return false; - } - - if (headers_sent()) { - return false; - } - - if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) { - $this->save(); - ini_set('session.cookie_lifetime', $lifetime); - $this->start(); - } - - if ($destroy) { - $this->metadataBag->stampNew(); - } - - return session_regenerate_id($destroy); - } - - public function save(): void - { - // Store a copy so we can restore the bags in case the session was not left empty - $session = $_SESSION; - - foreach ($this->bags as $bag) { - if (empty($_SESSION[$key = $bag->getStorageKey()])) { - unset($_SESSION[$key]); - } - } - if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { - unset($_SESSION[$key]); - } - - // Register error handler to add information about the current save handler - $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { - if (\E_WARNING === $type && str_starts_with($msg, 'session_write_close():')) { - $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; - $msg = \sprintf('session_write_close(): Failed to write session data with "%s" handler', $handler::class); - } - - return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; - }); - - try { - session_write_close(); - } finally { - restore_error_handler(); - - // Restore only if not empty - if ($_SESSION) { - $_SESSION = $session; - } - } - - $this->closed = true; - $this->started = false; - } - - public function clear(): void - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $_SESSION = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - public function registerBag(SessionBagInterface $bag): void - { - if ($this->started) { - throw new \LogicException('Cannot register a bag when the session is already started.'); - } - - $this->bags[$bag->getName()] = $bag; - } - - public function getBag(string $name): SessionBagInterface - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(\sprintf('The SessionBagInterface "%s" is not registered.', $name)); - } - - if (!$this->started && $this->saveHandler->isActive()) { - $this->loadSession(); - } elseif (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - public function setMetadataBag(?MetadataBag $metaBag): void - { - $this->metadataBag = $metaBag ?? new MetadataBag(); - } - - /** - * Gets the MetadataBag. - */ - public function getMetadataBag(): MetadataBag - { - return $this->metadataBag; - } - - public function isStarted(): bool - { - return $this->started; - } - - /** - * Sets session.* ini variables. - * - * For convenience we omit 'session.' from the beginning of the keys. - * Explicitly ignores other ini keys. - * - * @param array $options Session ini directives [key => value] - * - * @see https://php.net/session.configuration - */ - public function setOptions(array $options): void - { - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - $validOptions = array_flip([ - 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', - 'gc_divisor', 'gc_maxlifetime', 'gc_probability', - 'lazy_write', 'name', - 'serialize_handler', 'use_strict_mode', 'use_cookies', - ]); - - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - if ('cookie_secure' === $key && 'auto' === $value) { - continue; - } - ini_set('session.'.$key, $value); - } - } - } - - /** - * Registers session save handler as a PHP session handler. - * - * To use internal PHP session save handlers, override this method using ini_set with - * session.save_handler and session.save_path e.g. - * - * ini_set('session.save_handler', 'files'); - * ini_set('session.save_path', '/tmp'); - * - * or pass in a \SessionHandler instance which configures session.save_handler in the - * constructor, for a template see NativeFileSessionHandler. - * - * @see https://php.net/session-set-save-handler - * @see https://php.net/sessionhandlerinterface - * @see https://php.net/sessionhandler - * - * @throws \InvalidArgumentException - */ - public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler): void - { - // Wrap $saveHandler in proxy and prevent double wrapping of proxy - if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { - $saveHandler = new SessionHandlerProxy($saveHandler); - } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); - } - $this->saveHandler = $saveHandler; - - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - if ($this->saveHandler instanceof SessionHandlerProxy) { - session_set_save_handler($this->saveHandler, false); - } - } - - /** - * Load the session with attributes. - * - * After starting the session, PHP retrieves the session from whatever handlers - * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). - * PHP takes the return value from the read() handler, unserializes it - * and populates $_SESSION with the result automatically. - */ - protected function loadSession(?array &$session = null): void - { - if (null === $session) { - $session = &$_SESSION; - } - - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; - $bag->initialize($session[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php deleted file mode 100644 index cb8c535..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -// Help opcache.preload discover always-needed symbols -class_exists(NativeSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class NativeSessionStorageFactory implements SessionStorageFactoryInterface -{ - /** - * @see NativeSessionStorage constructor. - */ - public function __construct( - private array $options = [], - private AbstractProxy|\SessionHandlerInterface|null $handler = null, - private ?MetadataBag $metaBag = null, - private bool $secure = false, - ) { - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag); - if ($this->secure && $request?->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php deleted file mode 100644 index 8a8c50c..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -/** - * Allows session to be started by PHP and managed by Symfony. - * - * @author Drak - */ -class PhpBridgeSessionStorage extends NativeSessionStorage -{ - public function __construct(AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $this->setMetadataBag($metaBag); - $this->setSaveHandler($handler); - } - - public function start(): bool - { - if ($this->started) { - return true; - } - - $this->loadSession(); - - return true; - } - - public function clear(): void - { - // clear out the bags and nothing else that may be set - // since the purpose of this driver is to share a handler - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // reconnect the bags to the session - $this->loadSession(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php deleted file mode 100644 index 357e5c7..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -// Help opcache.preload discover always-needed symbols -class_exists(PhpBridgeSessionStorage::class); - -/** - * @author Jérémy Derussé - */ -class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface -{ - public function __construct( - private AbstractProxy|\SessionHandlerInterface|null $handler = null, - private ?MetadataBag $metaBag = null, - private bool $secure = false, - ) { - } - - public function createStorage(?Request $request): SessionStorageInterface - { - $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag); - if ($this->secure && $request?->isSecure()) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $storage; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php deleted file mode 100644 index c3a0278..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -/** - * @author Drak - */ -abstract class AbstractProxy -{ - protected bool $wrapper = false; - - protected ?string $saveHandlerName = null; - - /** - * Gets the session.save_handler name. - */ - public function getSaveHandlerName(): ?string - { - return $this->saveHandlerName; - } - - /** - * Is this proxy handler and instance of \SessionHandlerInterface. - */ - public function isSessionHandlerInterface(): bool - { - return $this instanceof \SessionHandlerInterface; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - */ - public function isWrapper(): bool - { - return $this->wrapper; - } - - /** - * Has a session started? - */ - public function isActive(): bool - { - return \PHP_SESSION_ACTIVE === session_status(); - } - - /** - * Gets the session ID. - */ - public function getId(): string - { - return session_id(); - } - - /** - * Sets the session ID. - * - * @throws \LogicException - */ - public function setId(string $id): void - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session.'); - } - - session_id($id); - } - - /** - * Gets the session name. - */ - public function getName(): string - { - return session_name(); - } - - /** - * Sets the session name. - * - * @throws \LogicException - */ - public function setName(string $name): void - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session.'); - } - - session_name($name); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php deleted file mode 100644 index 0316362..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; - -/** - * @author Drak - */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - public function __construct( - protected \SessionHandlerInterface $handler, - ) { - $this->wrapper = $handler instanceof \SessionHandler; - $this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user'; - } - - public function getHandler(): \SessionHandlerInterface - { - return $this->handler; - } - - // \SessionHandlerInterface - - public function open(string $savePath, string $sessionName): bool - { - return $this->handler->open($savePath, $sessionName); - } - - public function close(): bool - { - return $this->handler->close(); - } - - public function read(#[\SensitiveParameter] string $sessionId): string|false - { - return $this->handler->read($sessionId); - } - - public function write(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->handler->write($sessionId, $data); - } - - public function destroy(#[\SensitiveParameter] string $sessionId): bool - { - return $this->handler->destroy($sessionId); - } - - public function gc(int $maxlifetime): int|false - { - return $this->handler->gc($maxlifetime); - } - - public function validateId(#[\SensitiveParameter] string $sessionId): bool - { - return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); - } - - public function updateTimestamp(#[\SensitiveParameter] string $sessionId, string $data): bool - { - return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php deleted file mode 100644 index d03f0da..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/SessionStorageFactoryInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Request; - -/** - * @author Jérémy Derussé - */ -interface SessionStorageFactoryInterface -{ - /** - * Creates a new instance of SessionStorageInterface. - */ - public function createStorage(?Request $request): SessionStorageInterface; -} diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php deleted file mode 100644 index c51850d..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * StorageInterface. - * - * @author Fabien Potencier - * @author Drak - */ -interface SessionStorageInterface -{ - /** - * Starts the session. - * - * @throws \RuntimeException if something goes wrong starting the session - */ - public function start(): bool; - - /** - * Checks if the session is started. - */ - public function isStarted(): bool; - - /** - * Returns the session ID. - */ - public function getId(): string; - - /** - * Sets the session ID. - */ - public function setId(string $id): void; - - /** - * Returns the session name. - */ - public function getName(): string; - - /** - * Sets the session name. - */ - public function setName(string $name): void; - - /** - * Regenerates id that represents this storage. - * - * This method must invoke session_regenerate_id($destroy) unless - * this interface is used for a storage object designed for unit - * or functional testing where a real PHP session would interfere - * with testing. - * - * Note regenerate+destroy should not clear the session data in memory - * only delete the session data from persistent storage. - * - * Care: When regenerating the session ID no locking is involved in PHP's - * session design. See https://bugs.php.net/61470 for a discussion. - * So you must make sure the regenerated session is saved BEFORE sending the - * headers with the new ID. Symfony's HttpKernel offers a listener for this. - * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. - * Otherwise session data could get lost again for concurrent requests with the - * new ID. One result could be that you get logged out after just logging in. - * - * @param bool $destroy Destroy session when regenerating? - * @param int|null $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @throws \RuntimeException If an error occurs while regenerating this storage - */ - public function regenerate(bool $destroy = false, ?int $lifetime = null): bool; - - /** - * Force the session to be saved and closed. - * - * This method must invoke session_write_close() unless this interface is - * used for a storage object design for unit or functional testing where - * a real PHP session would interfere with testing, in which case - * it should actually persist the session data if required. - * - * @throws \RuntimeException if the session is saved without being started, or if the session - * is already closed - */ - public function save(): void; - - /** - * Clear all session data in memory. - */ - public function clear(): void; - - /** - * Gets a SessionBagInterface by name. - * - * @throws \InvalidArgumentException If the bag does not exist - */ - public function getBag(string $name): SessionBagInterface; - - /** - * Registers a SessionBagInterface for use. - */ - public function registerBag(SessionBagInterface $bag): void; - - public function getMetadataBag(): MetadataBag; -} diff --git a/vendor/symfony/http-foundation/StreamedJsonResponse.php b/vendor/symfony/http-foundation/StreamedJsonResponse.php deleted file mode 100644 index 5b20ce9..0000000 --- a/vendor/symfony/http-foundation/StreamedJsonResponse.php +++ /dev/null @@ -1,162 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * StreamedJsonResponse represents a streamed HTTP response for JSON. - * - * A StreamedJsonResponse uses a structure and generics to create an - * efficient resource-saving JSON response. - * - * It is recommended to use flush() function after a specific number of items to directly stream the data. - * - * @see flush() - * - * @author Alexander Schranz - * - * Example usage: - * - * function loadArticles(): \Generator - * // some streamed loading - * yield ['title' => 'Article 1']; - * yield ['title' => 'Article 2']; - * yield ['title' => 'Article 3']; - * // recommended to use flush() after every specific number of items - * }), - * - * $response = new StreamedJsonResponse( - * // json structure with generators in which will be streamed - * [ - * '_embedded' => [ - * 'articles' => loadArticles(), // any generator which you want to stream as list of data - * ], - * ], - * ); - */ -class StreamedJsonResponse extends StreamedResponse -{ - private const PLACEHOLDER = '__symfony_json__'; - - /** - * @param mixed[] $data JSON Data containing PHP generators which will be streamed as list of data or a Generator - * @param int $status The HTTP status code (200 "OK" by default) - * @param array $headers An array of HTTP headers - * @param int $encodingOptions Flags for the json_encode() function - */ - public function __construct( - private readonly iterable $data, - int $status = 200, - array $headers = [], - private int $encodingOptions = JsonResponse::DEFAULT_ENCODING_OPTIONS, - ) { - parent::__construct($this->stream(...), $status, $headers); - - if (!$this->headers->get('Content-Type')) { - $this->headers->set('Content-Type', 'application/json'); - } - } - - private function stream(): void - { - $jsonEncodingOptions = \JSON_THROW_ON_ERROR | $this->encodingOptions; - $keyEncodingOptions = $jsonEncodingOptions & ~\JSON_NUMERIC_CHECK; - - $this->streamData($this->data, $jsonEncodingOptions, $keyEncodingOptions); - } - - private function streamData(mixed $data, int $jsonEncodingOptions, int $keyEncodingOptions): void - { - if (\is_array($data)) { - $this->streamArray($data, $jsonEncodingOptions, $keyEncodingOptions); - - return; - } - - if (is_iterable($data) && !$data instanceof \JsonSerializable) { - $this->streamIterable($data, $jsonEncodingOptions, $keyEncodingOptions); - - return; - } - - echo json_encode($data, $jsonEncodingOptions); - } - - private function streamArray(array $data, int $jsonEncodingOptions, int $keyEncodingOptions): void - { - $generators = []; - - array_walk_recursive($data, function (&$item, $key) use (&$generators) { - if (self::PLACEHOLDER === $key) { - // if the placeholder is already in the structure it should be replaced with a new one that explode - // works like expected for the structure - $generators[] = $key; - } - - // generators should be used but for better DX all kind of Traversable and objects are supported - if (\is_object($item)) { - $generators[] = $item; - $item = self::PLACEHOLDER; - } elseif (self::PLACEHOLDER === $item) { - // if the placeholder is already in the structure it should be replaced with a new one that explode - // works like expected for the structure - $generators[] = $item; - } - }); - - $jsonParts = explode('"'.self::PLACEHOLDER.'"', json_encode($data, $jsonEncodingOptions)); - - foreach ($generators as $index => $generator) { - // send first and between parts of the structure - echo $jsonParts[$index]; - - $this->streamData($generator, $jsonEncodingOptions, $keyEncodingOptions); - } - - // send last part of the structure - echo $jsonParts[array_key_last($jsonParts)]; - } - - private function streamIterable(iterable $iterable, int $jsonEncodingOptions, int $keyEncodingOptions): void - { - $isFirstItem = true; - $startTag = '['; - - foreach ($iterable as $key => $item) { - if ($isFirstItem) { - $isFirstItem = false; - // depending on the first elements key the generator is detected as a list or map - // we can not check for a whole list or map because that would hurt the performance - // of the streamed response which is the main goal of this response class - if (0 !== $key) { - $startTag = '{'; - } - - echo $startTag; - } else { - // if not first element of the generic, a separator is required between the elements - echo ','; - } - - if ('{' === $startTag) { - echo json_encode((string) $key, $keyEncodingOptions).':'; - } - - $this->streamData($item, $jsonEncodingOptions, $keyEncodingOptions); - } - - if ($isFirstItem) { // indicates that the generator was empty - echo '['; - } - - echo '[' === $startTag ? ']' : '}'; - } -} diff --git a/vendor/symfony/http-foundation/StreamedResponse.php b/vendor/symfony/http-foundation/StreamedResponse.php deleted file mode 100644 index 4e755a7..0000000 --- a/vendor/symfony/http-foundation/StreamedResponse.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * StreamedResponse represents a streamed HTTP response. - * - * A StreamedResponse uses a callback or an iterable of strings for its content. - * - * The callback should use the standard PHP functions like echo - * to stream the response back to the client. The flush() function - * can also be used if needed. - * - * @see flush() - * - * @author Fabien Potencier - */ -class StreamedResponse extends Response -{ - protected ?\Closure $callback = null; - protected bool $streamed = false; - - private bool $headersSent = false; - - /** - * @param callable|iterable|null $callbackOrChunks - * @param int $status The HTTP status code (200 "OK" by default) - */ - public function __construct(callable|iterable|null $callbackOrChunks = null, int $status = 200, array $headers = []) - { - parent::__construct(null, $status, $headers); - - if (\is_callable($callbackOrChunks)) { - $this->setCallback($callbackOrChunks); - } elseif ($callbackOrChunks) { - $this->setChunks($callbackOrChunks); - } - $this->streamed = false; - $this->headersSent = false; - } - - /** - * @param iterable $chunks - */ - public function setChunks(iterable $chunks): static - { - $this->callback = static function () use ($chunks): void { - foreach ($chunks as $chunk) { - echo $chunk; - @ob_flush(); - flush(); - } - }; - - return $this; - } - - /** - * Sets the PHP callback associated with this Response. - * - * @return $this - */ - public function setCallback(callable $callback): static - { - $this->callback = $callback(...); - - return $this; - } - - public function getCallback(): ?\Closure - { - if (!isset($this->callback)) { - return null; - } - - return ($this->callback)(...); - } - - /** - * This method only sends the headers once. - * - * @param positive-int|null $statusCode The status code to use, override the statusCode property if set and not null - * - * @return $this - */ - public function sendHeaders(?int $statusCode = null): static - { - if ($this->headersSent) { - return $this; - } - - if ($statusCode < 100 || $statusCode >= 200) { - $this->headersSent = true; - } - - return parent::sendHeaders($statusCode); - } - - /** - * This method only sends the content once. - * - * @return $this - */ - public function sendContent(): static - { - if ($this->streamed) { - return $this; - } - - $this->streamed = true; - - if (!isset($this->callback)) { - throw new \LogicException('The Response callback must be set.'); - } - - ($this->callback)(); - - return $this; - } - - /** - * @return $this - * - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content): static - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); - } - - $this->streamed = true; - - return $this; - } - - public function getContent(): string|false - { - return false; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php deleted file mode 100644 index c570848..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; - -final class RequestAttributeValueSame extends Constraint -{ - public function __construct( - private string $name, - private string $value, - ) { - } - - public function toString(): string - { - return \sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); - } - - /** - * @param Request $request - */ - protected function matches($request): bool - { - return $this->value === $request->attributes->get($this->name); - } - - /** - * @param Request $request - */ - protected function failureDescription($request): string - { - return 'the Request '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php deleted file mode 100644 index dbf9add..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseCookieValueSame extends Constraint -{ - public function __construct( - private string $name, - private string $value, - private string $path = '/', - private ?string $domain = null, - ) { - } - - public function toString(): string - { - $str = \sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= \sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= \sprintf(' for domain "%s"', $this->domain); - } - - return $str.\sprintf(' with value "%s"', $this->value); - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - $cookie = $this->getCookie($response); - if (!$cookie) { - return false; - } - - return $this->value === (string) $cookie->getValue(); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - protected function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, fn (Cookie $cookie) => $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain); - - return reset($filteredCookies) ?: null; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php deleted file mode 100644 index cc3655a..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseFormatSame.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Asserts that the response is in the given format. - * - * @author Kévin Dunglas - */ -final class ResponseFormatSame extends Constraint -{ - public function __construct( - private Request $request, - private ?string $format, - private readonly bool $verbose = true, - ) { - } - - public function toString(): string - { - return 'format is '.($this->format ?? 'null'); - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $this->format === $this->request->getFormat($response->headers->get('Content-Type')); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - */ - protected function additionalFailureDescription($response): string - { - return $this->verbose ? (string) $response : explode("\r\n\r\n", (string) $response)[0]; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php deleted file mode 100644 index 0bc5803..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasCookie extends Constraint -{ - public function __construct( - private string $name, - private string $path = '/', - private ?string $domain = null, - ) { - } - - public function toString(): string - { - $str = \sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= \sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= \sprintf(' for domain "%s"', $this->domain); - } - - return $str; - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return null !== $this->getCookie($response); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - private function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, fn (Cookie $cookie) => $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain); - - return reset($filteredCookies) ?: null; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php deleted file mode 100644 index 52fd3c1..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasHeader extends Constraint -{ - public function __construct( - private string $headerName, - ) { - } - - public function toString(): string - { - return \sprintf('has header "%s"', $this->headerName); - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $response->headers->has($this->headerName); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php deleted file mode 100644 index 833ffd9..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderLocationSame.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHeaderLocationSame extends Constraint -{ - public function __construct(private Request $request, private string $expectedValue) - { - } - - public function toString(): string - { - return \sprintf('has header "Location" matching "%s"', $this->expectedValue); - } - - protected function matches($other): bool - { - if (!$other instanceof Response) { - return false; - } - - $location = $other->headers->get('Location'); - - if (null === $location) { - return false; - } - - return $this->toFullUrl($this->expectedValue) === $this->toFullUrl($location); - } - - protected function failureDescription($other): string - { - return 'the Response '.$this->toString(); - } - - private function toFullUrl(string $url): string - { - if (null === parse_url($url, \PHP_URL_PATH)) { - $url .= '/'; - } - - if (str_starts_with($url, '//')) { - return \sprintf('%s:%s', $this->request->getScheme(), $url); - } - - if (str_starts_with($url, '/')) { - return $this->request->getSchemeAndHttpHost().$url; - } - - return $url; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php deleted file mode 100644 index f2ae27f..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHeaderSame extends Constraint -{ - public function __construct( - private string $headerName, - private string $expectedValue, - ) { - } - - public function toString(): string - { - return \sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $this->expectedValue === $response->headers->get($this->headerName, null); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php deleted file mode 100644 index b7ae15e..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsRedirected extends Constraint -{ - /** - * @param bool $verbose If true, the entire response is printed on failure. If false, the response body is omitted. - */ - public function __construct(private readonly bool $verbose = true) - { - } - - public function toString(): string - { - return 'is redirected'; - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $response->isRedirect(); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - */ - protected function additionalFailureDescription($response): string - { - return $this->verbose ? (string) $response : explode("\r\n\r\n", (string) $response)[0]; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php deleted file mode 100644 index 94a65ed..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsSuccessful extends Constraint -{ - /** - * @param bool $verbose If true, the entire response is printed on failure. If false, the response body is omitted. - */ - public function __construct(private readonly bool $verbose = true) - { - } - - public function toString(): string - { - return 'is successful'; - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $response->isSuccessful(); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - */ - protected function additionalFailureDescription($response): string - { - return $this->verbose ? (string) $response : explode("\r\n\r\n", (string) $response)[0]; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php deleted file mode 100644 index 799d558..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsUnprocessable.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsUnprocessable extends Constraint -{ - /** - * @param bool $verbose If true, the entire response is printed on failure. If false, the response body is omitted. - */ - public function __construct(private readonly bool $verbose = true) - { - } - - public function toString(): string - { - return 'is unprocessable'; - } - - /** - * @param Response $other - */ - protected function matches($other): bool - { - return Response::HTTP_UNPROCESSABLE_ENTITY === $other->getStatusCode(); - } - - /** - * @param Response $other - */ - protected function failureDescription($other): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - */ - protected function additionalFailureDescription($response): string - { - return $this->verbose ? (string) $response : explode("\r\n\r\n", (string) $response)[0]; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php deleted file mode 100644 index 1223608..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseStatusCodeSame extends Constraint -{ - public function __construct( - private int $statusCode, - private readonly bool $verbose = true, - ) { - } - - public function toString(): string - { - return 'status code is '.$this->statusCode; - } - - /** - * @param Response $response - */ - protected function matches($response): bool - { - return $this->statusCode === $response->getStatusCode(); - } - - /** - * @param Response $response - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - */ - protected function additionalFailureDescription($response): string - { - return $this->verbose ? (string) $response : explode("\r\n\r\n", (string) $response)[0]; - } -} diff --git a/vendor/symfony/http-foundation/UriSigner.php b/vendor/symfony/http-foundation/UriSigner.php deleted file mode 100644 index d441e47..0000000 --- a/vendor/symfony/http-foundation/UriSigner.php +++ /dev/null @@ -1,206 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Psr\Clock\ClockInterface; -use Symfony\Component\HttpFoundation\Exception\ExpiredSignedUriException; -use Symfony\Component\HttpFoundation\Exception\LogicException; -use Symfony\Component\HttpFoundation\Exception\SignedUriException; -use Symfony\Component\HttpFoundation\Exception\UnsignedUriException; -use Symfony\Component\HttpFoundation\Exception\UnverifiedSignedUriException; - -/** - * @author Fabien Potencier - */ -class UriSigner -{ - private const STATUS_VALID = 1; - private const STATUS_INVALID = 2; - private const STATUS_MISSING = 3; - private const STATUS_EXPIRED = 4; - - /** - * @param string $hashParameter Query string parameter to use - * @param string $expirationParameter Query string parameter to use for expiration - */ - public function __construct( - #[\SensitiveParameter] private string $secret, - private string $hashParameter = '_hash', - private string $expirationParameter = '_expiration', - private ?ClockInterface $clock = null, - ) { - if (!$secret) { - throw new \InvalidArgumentException('A non-empty secret is required.'); - } - } - - /** - * Signs a URI. - * - * The given URI is signed by adding the query string parameter - * which value depends on the URI and the secret. - * - * @param \DateTimeInterface|\DateInterval|int|null $expiration The expiration for the given URI. - * If $expiration is a \DateTimeInterface, it's expected to be the exact date + time. - * If $expiration is a \DateInterval, the interval is added to "now" to get the date + time. - * If $expiration is an int, it's expected to be a timestamp in seconds of the exact date + time. - * If $expiration is null, no expiration. - * - * The expiration is added as a query string parameter. - */ - public function sign(string $uri, \DateTimeInterface|\DateInterval|int|null $expiration = null): string - { - $url = parse_url($uri); - $params = []; - - if (isset($url['query'])) { - parse_str($url['query'], $params); - } - - if (isset($params[$this->hashParameter])) { - throw new LogicException(\sprintf('URI query parameter conflict: parameter name "%s" is reserved.', $this->hashParameter)); - } - - if (isset($params[$this->expirationParameter])) { - throw new LogicException(\sprintf('URI query parameter conflict: parameter name "%s" is reserved.', $this->expirationParameter)); - } - - if (null !== $expiration) { - $params[$this->expirationParameter] = $this->getExpirationTime($expiration); - } - - $uri = $this->buildUrl($url, $params); - $params[$this->hashParameter] = $this->computeHash($uri); - - return $this->buildUrl($url, $params); - } - - /** - * Checks that a URI contains the correct hash. - * Also checks if the URI has not expired (If you used expiration during signing). - */ - public function check(string $uri): bool - { - return self::STATUS_VALID === $this->doVerify($uri); - } - - public function checkRequest(Request $request): bool - { - return self::STATUS_VALID === $this->doVerify(self::normalize($request)); - } - - /** - * Verify a Request or string URI. - * - * @throws UnsignedUriException If the URI is not signed - * @throws UnverifiedSignedUriException If the signature is invalid - * @throws ExpiredSignedUriException If the URI has expired - * @throws SignedUriException - */ - public function verify(Request|string $uri): void - { - $uri = self::normalize($uri); - $status = $this->doVerify($uri); - - match ($status) { - self::STATUS_VALID => null, - self::STATUS_INVALID => throw new UnverifiedSignedUriException(), - self::STATUS_EXPIRED => throw new ExpiredSignedUriException(), - default => throw new UnsignedUriException(), - }; - } - - private function computeHash(string $uri): string - { - return strtr(rtrim(base64_encode(hash_hmac('sha256', $uri, $this->secret, true)), '='), ['/' => '_', '+' => '-']); - } - - private function buildUrl(array $url, array $params = []): string - { - ksort($params, \SORT_STRING); - $url['query'] = http_build_query($params, '', '&'); - - $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; - $host = $url['host'] ?? ''; - $port = isset($url['port']) ? ':'.$url['port'] : ''; - $user = $url['user'] ?? ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; - $pass = ($user || $pass) ? "$pass@" : ''; - $path = $url['path'] ?? ''; - $query = $url['query'] ? '?'.$url['query'] : ''; - $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; - - return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; - } - - private function getExpirationTime(\DateTimeInterface|\DateInterval|int $expiration): string - { - if ($expiration instanceof \DateTimeInterface) { - return $expiration->format('U'); - } - - if ($expiration instanceof \DateInterval) { - return $this->now()->add($expiration)->format('U'); - } - - return (string) $expiration; - } - - private function now(): \DateTimeImmutable - { - return $this->clock?->now() ?? \DateTimeImmutable::createFromFormat('U', time()); - } - - /** - * @return self::STATUS_* - */ - private function doVerify(string $uri): int - { - $url = parse_url($uri); - $params = []; - - if (isset($url['query'])) { - parse_str($url['query'], $params); - } - - if (empty($params[$this->hashParameter])) { - return self::STATUS_MISSING; - } - - $hash = $params[$this->hashParameter]; - unset($params[$this->hashParameter]); - - if (!hash_equals($this->computeHash($this->buildUrl($url, $params)), strtr(rtrim($hash, '='), ['/' => '_', '+' => '-']))) { - return self::STATUS_INVALID; - } - - if (!$expiration = $params[$this->expirationParameter] ?? false) { - return self::STATUS_VALID; - } - - if ($this->now()->getTimestamp() < $expiration) { - return self::STATUS_VALID; - } - - return self::STATUS_EXPIRED; - } - - private static function normalize(Request|string $uri): string - { - if ($uri instanceof Request) { - $qs = ($qs = $uri->server->get('QUERY_STRING')) ? '?'.$qs : ''; - $uri = $uri->getSchemeAndHttpHost().$uri->getBaseUrl().$uri->getPathInfo().$qs; - } - - return $uri; - } -} diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php deleted file mode 100644 index f971cf6..0000000 --- a/vendor/symfony/http-foundation/UrlHelper.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * A helper service for manipulating URLs within and outside the request scope. - * - * @author Valentin Udaltsov - */ -final class UrlHelper -{ - public function __construct( - private RequestStack $requestStack, - private RequestContextAwareInterface|RequestContext|null $requestContext = null, - ) { - } - - public function getAbsoluteUrl(string $path): string - { - if (str_contains($path, '://') || str_starts_with($path, '//')) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $this->getAbsoluteUrlFromContext($path); - } - - if ('#' === $path[0]) { - $path = $request->getRequestUri().$path; - } elseif ('?' === $path[0]) { - $path = $request->getPathInfo().$path; - } - - if (!$path || '/' !== $path[0]) { - $prefix = $request->getPathInfo(); - $last = \strlen($prefix) - 1; - if ($last !== $pos = strrpos($prefix, '/')) { - $prefix = substr($prefix, 0, $pos).'/'; - } - - return $request->getUriForPath($prefix.$path); - } - - return $request->getSchemeAndHttpHost().$path; - } - - public function getRelativePath(string $path): string - { - if (str_contains($path, '://') || str_starts_with($path, '//')) { - return $path; - } - - if (null === $request = $this->requestStack->getMainRequest()) { - return $path; - } - - return $request->getRelativeUriForPath($path); - } - - private function getAbsoluteUrlFromContext(string $path): string - { - if (null === $context = $this->requestContext) { - return $path; - } - - if ($context instanceof RequestContextAwareInterface) { - $context = $context->getContext(); - } - - if ('' === $host = $context->getHost()) { - return $path; - } - - $scheme = $context->getScheme(); - $port = ''; - - if ('http' === $scheme && 80 !== $context->getHttpPort()) { - $port = ':'.$context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $context->getHttpsPort()) { - $port = ':'.$context->getHttpsPort(); - } - - if ('#' === $path[0]) { - $queryString = $context->getQueryString(); - $path = $context->getPathInfo().($queryString ? '?'.$queryString : '').$path; - } elseif ('?' === $path[0]) { - $path = $context->getPathInfo().$path; - } - - if ('/' !== $path[0]) { - $path = rtrim($context->getBaseUrl(), '/').'/'.$path; - } - - return $scheme.'://'.$host.$port.$path; - } -} diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json deleted file mode 100644 index 6c54d43..0000000 --- a/vendor/symfony/http-foundation/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "symfony/http-foundation", - "type": "library", - "description": "Defines an object-oriented layer for the HTTP specification", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=8.4", - "symfony/polyfill-mbstring": "^1.1" - }, - "require-dev": { - "doctrine/dbal": "^4.3", - "predis/predis": "^1.1|^2.0", - "symfony/cache": "^7.4|^8.0", - "symfony/clock": "^7.4|^8.0", - "symfony/dependency-injection": "^7.4|^8.0", - "symfony/expression-language": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/mime": "^7.4|^8.0", - "symfony/rate-limiter": "^7.4|^8.0" - }, - "conflict": { - "doctrine/dbal": "<4.3" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev" -} diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE deleted file mode 100644 index 6e3afce..0000000 --- a/vendor/symfony/polyfill-mbstring/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-present Fabien Potencier - -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/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php deleted file mode 100644 index 3d45c9d..0000000 --- a/vendor/symfony/polyfill-mbstring/Mbstring.php +++ /dev/null @@ -1,1045 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Mbstring; - -/** - * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. - * - * Implemented: - * - mb_chr - Returns a specific character from its Unicode code point - * - mb_convert_encoding - Convert character encoding - * - mb_convert_variables - Convert character code in variable(s) - * - mb_decode_mimeheader - Decode string in MIME header field - * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED - * - mb_decode_numericentity - Decode HTML numeric string reference to character - * - mb_encode_numericentity - Encode character to HTML numeric string reference - * - mb_convert_case - Perform case folding on a string - * - mb_detect_encoding - Detect character encoding - * - mb_get_info - Get internal settings of mbstring - * - mb_http_input - Detect HTTP input character encoding - * - mb_http_output - Set/Get HTTP output character encoding - * - mb_internal_encoding - Set/Get internal character encoding - * - mb_list_encodings - Returns an array of all supported encodings - * - mb_ord - Returns the Unicode code point of a character - * - mb_output_handler - Callback function converts character encoding in output buffer - * - mb_scrub - Replaces ill-formed byte sequences with substitute characters - * - mb_strlen - Get string length - * - mb_strpos - Find position of first occurrence of string in a string - * - mb_strrpos - Find position of last occurrence of a string in a string - * - mb_str_split - Convert a string to an array - * - mb_strtolower - Make a string lowercase - * - mb_strtoupper - Make a string uppercase - * - mb_substitute_character - Set/Get substitution character - * - mb_substr - Get part of string - * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive - * - mb_stristr - Finds first occurrence of a string within another, case insensitive - * - mb_strrchr - Finds the last occurrence of a character in a string within another - * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive - * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive - * - mb_strstr - Finds first occurrence of a string within another - * - mb_strwidth - Return width of string - * - mb_substr_count - Count the number of substring occurrences - * - mb_ucfirst - Make a string's first character uppercase - * - mb_lcfirst - Make a string's first character lowercase - * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string - * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string - * - mb_rtrim - Strip whitespace (or other characters) from the end of a string - * - * Not implemented: - * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) - * - mb_ereg_* - Regular expression with multibyte support - * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable - * - mb_preferred_mime_name - Get MIME charset string - * - mb_regex_encoding - Returns current encoding for multibyte regex as string - * - mb_regex_set_options - Set/Get the default options for mbregex functions - * - mb_send_mail - Send encoded mail - * - mb_split - Split multibyte string using regular expression - * - mb_strcut - Get part of string - * - mb_strimwidth - Get truncated string with specified width - * - * @author Nicolas Grekas - * - * @internal - */ -final class Mbstring -{ - public const MB_CASE_FOLD = \PHP_INT_MAX; - - private const SIMPLE_CASE_FOLD = [ - ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], - ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], - ]; - - private static $encodingList = ['ASCII', 'UTF-8']; - private static $language = 'neutral'; - private static $internalEncoding = 'UTF-8'; - - public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) - { - if (\is_array($s)) { - $r = []; - foreach ($s as $str) { - $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding); - } - - return $r; - } - - if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) { - $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); - } else { - $fromEncoding = self::getEncoding($fromEncoding); - } - - $toEncoding = self::getEncoding($toEncoding); - - if ('BASE64' === $fromEncoding) { - $s = base64_decode($s); - $fromEncoding = $toEncoding; - } - - if ('BASE64' === $toEncoding) { - return base64_encode($s); - } - - if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { - if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { - $fromEncoding = 'Windows-1252'; - } - if ('UTF-8' !== $fromEncoding) { - $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); - } - - return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); - } - - if ('HTML-ENTITIES' === $fromEncoding) { - $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); - $fromEncoding = 'UTF-8'; - } - - return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); - } - - public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) - { - $ok = true; - array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { - if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { - $ok = false; - } - }); - - return $ok ? $fromEncoding : false; - } - - public static function mb_decode_mimeheader($s) - { - return iconv_mime_decode($s, 2, self::$internalEncoding); - } - - public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) - { - trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); - } - - public static function mb_decode_numericentity($s, $convmap, $encoding = null) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return ''; // Instead of null (cf. mb_encode_numericentity). - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $cnt = floor(\count($convmap) / 4) * 4; - - for ($i = 0; $i < $cnt; $i += 4) { - // collector_decode_htmlnumericentity ignores $convmap[$i + 3] - $convmap[$i] += $convmap[$i + 2]; - $convmap[$i + 1] += $convmap[$i + 2]; - } - - $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { - $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; - for ($i = 0; $i < $cnt; $i += 4) { - if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { - return self::mb_chr($c - $convmap[$i + 2]); - } - } - - return $m[0]; - }, $s); - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); - - return null; // Instead of '' (cf. mb_decode_numericentity). - } - - if (null !== $is_hex && !\is_scalar($is_hex)) { - trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); - - return null; - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; - - $cnt = floor(\count($convmap) / 4) * 4; - $i = 0; - $len = \strlen($s); - $result = ''; - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - $c = self::mb_ord($uchr); - - for ($j = 0; $j < $cnt; $j += 4) { - if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { - $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; - $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; - continue 2; - } - } - $result .= $uchr; - } - - if (null === $encoding) { - return $result; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $result); - } - - public static function mb_convert_case($s, $mode, $encoding = null) - { - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - if (\MB_CASE_TITLE == $mode) { - static $titleRegexp = null; - if (null === $titleRegexp) { - $titleRegexp = self::getData('titleCaseRegexp'); - } - $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); - } else { - if (\MB_CASE_UPPER == $mode) { - static $upper = null; - if (null === $upper) { - $upper = self::getData('upperCase'); - } - $map = $upper; - } else { - if (self::MB_CASE_FOLD === $mode) { - static $caseFolding = null; - if (null === $caseFolding) { - $caseFolding = self::getData('caseFolding'); - } - $s = strtr($s, $caseFolding); - } - - static $lower = null; - if (null === $lower) { - $lower = self::getData('lowerCase'); - } - $map = $lower; - } - - static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; - - $i = 0; - $len = \strlen($s); - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - - if (isset($map[$uchr])) { - $uchr = $map[$uchr]; - $nlen = \strlen($uchr); - - if ($nlen == $ulen) { - $nlen = $i; - do { - $s[--$nlen] = $uchr[--$ulen]; - } while ($ulen); - } else { - $s = substr_replace($s, $uchr, $i - $ulen, $ulen); - $len += $nlen - $ulen; - $i += $nlen - $ulen; - } - } - } - } - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_internal_encoding($encoding = null) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - $normalizedEncoding = self::getEncoding($encoding); - - if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) { - self::$internalEncoding = $normalizedEncoding; - - return true; - } - - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); - } - - public static function mb_language($lang = null) - { - if (null === $lang) { - return self::$language; - } - - switch ($normalizedLang = strtolower($lang)) { - case 'uni': - case 'neutral': - self::$language = $normalizedLang; - - return true; - } - - if (80000 > \PHP_VERSION_ID) { - return false; - } - - throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); - } - - public static function mb_list_encodings() - { - return ['UTF-8']; - } - - public static function mb_encoding_aliases($encoding) - { - switch (strtoupper($encoding)) { - case 'UTF8': - case 'UTF-8': - return ['utf8']; - } - - return false; - } - - public static function mb_check_encoding($var = null, $encoding = null) - { - if (null === $encoding) { - if (null === $var) { - return false; - } - $encoding = self::$internalEncoding; - } - - if (!\is_array($var)) { - return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var); - } - - foreach ($var as $key => $value) { - if (!self::mb_check_encoding($key, $encoding)) { - return false; - } - if (!self::mb_check_encoding($value, $encoding)) { - return false; - } - } - - return true; - } - - public static function mb_detect_encoding($str, $encodingList = null, $strict = false) - { - if (null === $encodingList) { - $encodingList = self::$encodingList; - } else { - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - } - - foreach ($encodingList as $enc) { - switch ($enc) { - case 'ASCII': - if (!preg_match('/[\x80-\xFF]/', $str)) { - return $enc; - } - break; - - case 'UTF8': - case 'UTF-8': - if (preg_match('//u', $str)) { - return 'UTF-8'; - } - break; - - default: - if (0 === strncmp($enc, 'ISO-8859-', 9)) { - return $enc; - } - } - } - - return false; - } - - public static function mb_detect_order($encodingList = null) - { - if (null === $encodingList) { - return self::$encodingList; - } - - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - - foreach ($encodingList as $enc) { - switch ($enc) { - default: - if (strncmp($enc, 'ISO-8859-', 9)) { - return false; - } - // no break - case 'ASCII': - case 'UTF8': - case 'UTF-8': - } - } - - self::$encodingList = $encodingList; - - return true; - } - - public static function mb_strlen($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return \strlen($s); - } - - return @iconv_strlen($s, $encoding); - } - - public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strpos($haystack, $needle, $offset); - } - - $needle = (string) $needle; - if ('' === $needle) { - if (80000 > \PHP_VERSION_ID) { - trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); - - return false; - } - - return 0; - } - - return iconv_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strrpos($haystack, $needle, $offset); - } - - if ($offset != (int) $offset) { - $offset = 0; - } elseif ($offset = (int) $offset) { - if ($offset < 0) { - if (0 > $offset += self::mb_strlen($needle)) { - $haystack = self::mb_substr($haystack, 0, $offset, $encoding); - } - $offset = 0; - } else { - $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); - } - } - - $pos = '' !== $needle || 80000 > \PHP_VERSION_ID - ? iconv_strrpos($haystack, $needle, $encoding) - : self::mb_strlen($haystack, $encoding); - - return false !== $pos ? $offset + $pos : false; - } - - public static function mb_str_split($string, $split_length = 1, $encoding = null) - { - if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { - trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); - - return null; - } - - if (1 > $split_length = (int) $split_length) { - if (80000 > \PHP_VERSION_ID) { - trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); - - return false; - } - - throw new \ValueError('Argument #2 ($length) must be greater than 0'); - } - - if (null === $encoding) { - $encoding = mb_internal_encoding(); - } - - if ('UTF-8' === $encoding = self::getEncoding($encoding)) { - $rx = '/('; - while (65535 < $split_length) { - $rx .= '.{65535}'; - $split_length -= 65535; - } - $rx .= '.{'.$split_length.'})/us'; - - return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); - } - - $result = []; - $length = mb_strlen($string, $encoding); - - for ($i = 0; $i < $length; $i += $split_length) { - $result[] = mb_substr($string, $i, $split_length, $encoding); - } - - return $result; - } - - public static function mb_strtolower($s, $encoding = null) - { - return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); - } - - public static function mb_strtoupper($s, $encoding = null) - { - return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); - } - - public static function mb_substitute_character($c = null) - { - if (null === $c) { - return 'none'; - } - if (0 === strcasecmp($c, 'none')) { - return true; - } - if (80000 > \PHP_VERSION_ID) { - return false; - } - if (\is_int($c) || 'long' === $c || 'entity' === $c) { - return false; - } - - throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); - } - - public static function mb_substr($s, $start, $length = null, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return (string) substr($s, $start, null === $length ? 2147483647 : $length); - } - - if ($start < 0) { - $start = iconv_strlen($s, $encoding) + $start; - if ($start < 0) { - $start = 0; - } - } - - if (null === $length) { - $length = 2147483647; - } elseif ($length < 0) { - $length = iconv_strlen($s, $encoding) + $length - $start; - if ($length < 0) { - return ''; - } - } - - return (string) iconv_substr($s, $start, $length, $encoding); - } - - public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) - { - [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [ - self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), - self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding), - ]); - - return self::mb_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) - { - $pos = self::mb_stripos($haystack, $needle, 0, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - $pos = strrpos($haystack, $needle); - } else { - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); - } - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) - { - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = self::mb_strripos($haystack, $needle, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) - { - $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding); - $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding); - - $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack); - $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle); - - return self::mb_strrpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) - { - $pos = strpos($haystack, $needle); - if (false === $pos) { - return false; - } - if ($part) { - return substr($haystack, 0, $pos); - } - - return substr($haystack, $pos); - } - - public static function mb_get_info($type = 'all') - { - $info = [ - 'internal_encoding' => self::$internalEncoding, - 'http_output' => 'pass', - 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', - 'func_overload' => 0, - 'func_overload_list' => 'no overload', - 'mail_charset' => 'UTF-8', - 'mail_header_encoding' => 'BASE64', - 'mail_body_encoding' => 'BASE64', - 'illegal_chars' => 0, - 'encoding_translation' => 'Off', - 'language' => self::$language, - 'detect_order' => self::$encodingList, - 'substitute_character' => 'none', - 'strict_detection' => 'Off', - ]; - - if ('all' === $type) { - return $info; - } - if (isset($info[$type])) { - return $info[$type]; - } - - return false; - } - - public static function mb_http_input($type = '') - { - return false; - } - - public static function mb_http_output($encoding = null) - { - return null !== $encoding ? 'pass' === $encoding : 'pass'; - } - - public static function mb_strwidth($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - - if ('UTF-8' !== $encoding) { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); - - return ($wide << 1) + iconv_strlen($s, 'UTF-8'); - } - - public static function mb_substr_count($haystack, $needle, $encoding = null) - { - return substr_count($haystack, $needle); - } - - public static function mb_output_handler($contents, $status) - { - return $contents; - } - - public static function mb_chr($code, $encoding = null) - { - if (0x80 > $code %= 0x200000) { - $s = \chr($code); - } elseif (0x800 > $code) { - $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, $encoding, 'UTF-8'); - } - - return $s; - } - - public static function mb_ord($s, $encoding = null) - { - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, 'UTF-8', $encoding); - } - - if (1 === \strlen($s)) { - return \ord($s); - } - - $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; - if (0xF0 <= $code) { - return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; - } - if (0xE0 <= $code) { - return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; - } - if (0xC0 <= $code) { - return (($code - 0xC0) << 6) + $s[2] - 0x80; - } - - return $code; - } - - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string - { - if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { - throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); - } - - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); - } - - if (self::mb_strlen($pad_string, $encoding) <= 0) { - throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); - } - - $paddingRequired = $length - self::mb_strlen($string, $encoding); - - if ($paddingRequired < 1) { - return $string; - } - - switch ($pad_type) { - case \STR_PAD_LEFT: - return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string; - case \STR_PAD_RIGHT: - return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding); - default: - $leftPaddingLength = floor($paddingRequired / 2); - $rightPaddingLength = $paddingRequired - $leftPaddingLength; - - return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding); - } - } - - public static function mb_ucfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - public static function mb_lcfirst(string $string, ?string $encoding = null): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); - } - - $firstChar = mb_substr($string, 0, 1, $encoding); - $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding); - - return $firstChar.mb_substr($string, 1, null, $encoding); - } - - private static function getSubpart($pos, $part, $haystack, $encoding) - { - if (false === $pos) { - return false; - } - if ($part) { - return self::mb_substr($haystack, 0, $pos, $encoding); - } - - return self::mb_substr($haystack, $pos, null, $encoding); - } - - private static function html_encoding_callback(array $m) - { - $i = 1; - $entities = ''; - $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); - - while (isset($m[$i])) { - if (0x80 > $m[$i]) { - $entities .= \chr($m[$i++]); - continue; - } - if (0xF0 <= $m[$i]) { - $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } elseif (0xE0 <= $m[$i]) { - $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } else { - $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; - } - - $entities .= '&#'.$c.';'; - } - - return $entities; - } - - private static function title_case(array $s) - { - return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); - } - - private static function getData($file) - { - if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { - return require $file; - } - - return false; - } - - private static function getEncoding($encoding) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - if ('UTF-8' === $encoding) { - return 'UTF-8'; - } - - $encoding = strtoupper($encoding); - - if ('8BIT' === $encoding || 'BINARY' === $encoding) { - return 'CP850'; - } - - if ('UTF8' === $encoding) { - return 'UTF-8'; - } - - return $encoding; - } - - public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__); - } - - public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string - { - return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__); - } - - private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string - { - if (null === $encoding) { - $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given'); - } - - if ('' === $characters) { - return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding); - } - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $string)) { - $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string); - } - if (null !== $characters && !preg_match('//u', $characters)) { - $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters); - } - } else { - $string = iconv($encoding, 'UTF-8//IGNORE', $string); - - if (null !== $characters) { - $characters = iconv($encoding, 'UTF-8//IGNORE', $characters); - } - } - - if (null === $characters) { - $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}"; - } else { - $characters = preg_quote($characters); - } - - $string = preg_replace(sprintf($regex, $characters), '', $string); - - if (null === $encoding) { - return $string; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $string); - } - - private static function assertEncoding(string $encoding, string $errorFormat): void - { - try { - $validEncoding = @self::mb_check_encoding('', $encoding); - } catch (\ValueError $e) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - - // BC for PHP 7.3 and lower - if (!$validEncoding) { - throw new \ValueError(sprintf($errorFormat, $encoding)); - } - } -} diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md deleted file mode 100644 index 478b40d..0000000 --- a/vendor/symfony/polyfill-mbstring/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Symfony Polyfill / Mbstring -=========================== - -This component provides a partial, native PHP implementation for the -[Mbstring](https://php.net/mbstring) extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php deleted file mode 100644 index 512bba0..0000000 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php +++ /dev/null @@ -1,119 +0,0 @@ - 'i̇', - 'µ' => 'μ', - 'ſ' => 's', - 'ͅ' => 'ι', - 'ς' => 'σ', - 'ϐ' => 'β', - 'ϑ' => 'θ', - 'ϕ' => 'φ', - 'ϖ' => 'π', - 'ϰ' => 'κ', - 'ϱ' => 'ρ', - 'ϵ' => 'ε', - 'ẛ' => 'ṡ', - 'ι' => 'ι', - 'ß' => 'ss', - 'ʼn' => 'ʼn', - 'ǰ' => 'ǰ', - 'ΐ' => 'ΐ', - 'ΰ' => 'ΰ', - 'և' => 'եւ', - 'ẖ' => 'ẖ', - 'ẗ' => 'ẗ', - 'ẘ' => 'ẘ', - 'ẙ' => 'ẙ', - 'ẚ' => 'aʾ', - 'ẞ' => 'ss', - 'ὐ' => 'ὐ', - 'ὒ' => 'ὒ', - 'ὔ' => 'ὔ', - 'ὖ' => 'ὖ', - 'ᾀ' => 'ἀι', - 'ᾁ' => 'ἁι', - 'ᾂ' => 'ἂι', - 'ᾃ' => 'ἃι', - 'ᾄ' => 'ἄι', - 'ᾅ' => 'ἅι', - 'ᾆ' => 'ἆι', - 'ᾇ' => 'ἇι', - 'ᾈ' => 'ἀι', - 'ᾉ' => 'ἁι', - 'ᾊ' => 'ἂι', - 'ᾋ' => 'ἃι', - 'ᾌ' => 'ἄι', - 'ᾍ' => 'ἅι', - 'ᾎ' => 'ἆι', - 'ᾏ' => 'ἇι', - 'ᾐ' => 'ἠι', - 'ᾑ' => 'ἡι', - 'ᾒ' => 'ἢι', - 'ᾓ' => 'ἣι', - 'ᾔ' => 'ἤι', - 'ᾕ' => 'ἥι', - 'ᾖ' => 'ἦι', - 'ᾗ' => 'ἧι', - 'ᾘ' => 'ἠι', - 'ᾙ' => 'ἡι', - 'ᾚ' => 'ἢι', - 'ᾛ' => 'ἣι', - 'ᾜ' => 'ἤι', - 'ᾝ' => 'ἥι', - 'ᾞ' => 'ἦι', - 'ᾟ' => 'ἧι', - 'ᾠ' => 'ὠι', - 'ᾡ' => 'ὡι', - 'ᾢ' => 'ὢι', - 'ᾣ' => 'ὣι', - 'ᾤ' => 'ὤι', - 'ᾥ' => 'ὥι', - 'ᾦ' => 'ὦι', - 'ᾧ' => 'ὧι', - 'ᾨ' => 'ὠι', - 'ᾩ' => 'ὡι', - 'ᾪ' => 'ὢι', - 'ᾫ' => 'ὣι', - 'ᾬ' => 'ὤι', - 'ᾭ' => 'ὥι', - 'ᾮ' => 'ὦι', - 'ᾯ' => 'ὧι', - 'ᾲ' => 'ὰι', - 'ᾳ' => 'αι', - 'ᾴ' => 'άι', - 'ᾶ' => 'ᾶ', - 'ᾷ' => 'ᾶι', - 'ᾼ' => 'αι', - 'ῂ' => 'ὴι', - 'ῃ' => 'ηι', - 'ῄ' => 'ήι', - 'ῆ' => 'ῆ', - 'ῇ' => 'ῆι', - 'ῌ' => 'ηι', - 'ῒ' => 'ῒ', - 'ῖ' => 'ῖ', - 'ῗ' => 'ῗ', - 'ῢ' => 'ῢ', - 'ῤ' => 'ῤ', - 'ῦ' => 'ῦ', - 'ῧ' => 'ῧ', - 'ῲ' => 'ὼι', - 'ῳ' => 'ωι', - 'ῴ' => 'ώι', - 'ῶ' => 'ῶ', - 'ῷ' => 'ῶι', - 'ῼ' => 'ωι', - 'ff' => 'ff', - 'fi' => 'fi', - 'fl' => 'fl', - 'ffi' => 'ffi', - 'ffl' => 'ffl', - 'ſt' => 'st', - 'st' => 'st', - 'ﬓ' => 'մն', - 'ﬔ' => 'մե', - 'ﬕ' => 'մի', - 'ﬖ' => 'վն', - 'ﬗ' => 'մխ', -]; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php deleted file mode 100644 index fac60b0..0000000 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ /dev/null @@ -1,1397 +0,0 @@ - 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - 'À' => 'à', - 'Á' => 'á', - 'Â' => 'â', - 'Ã' => 'ã', - 'Ä' => 'ä', - 'Å' => 'å', - 'Æ' => 'æ', - 'Ç' => 'ç', - 'È' => 'è', - 'É' => 'é', - 'Ê' => 'ê', - 'Ë' => 'ë', - 'Ì' => 'ì', - 'Í' => 'í', - 'Î' => 'î', - 'Ï' => 'ï', - 'Ð' => 'ð', - 'Ñ' => 'ñ', - 'Ò' => 'ò', - 'Ó' => 'ó', - 'Ô' => 'ô', - 'Õ' => 'õ', - 'Ö' => 'ö', - 'Ø' => 'ø', - 'Ù' => 'ù', - 'Ú' => 'ú', - 'Û' => 'û', - 'Ü' => 'ü', - 'Ý' => 'ý', - 'Þ' => 'þ', - 'Ā' => 'ā', - 'Ă' => 'ă', - 'Ą' => 'ą', - 'Ć' => 'ć', - 'Ĉ' => 'ĉ', - 'Ċ' => 'ċ', - 'Č' => 'č', - 'Ď' => 'ď', - 'Đ' => 'đ', - 'Ē' => 'ē', - 'Ĕ' => 'ĕ', - 'Ė' => 'ė', - 'Ę' => 'ę', - 'Ě' => 'ě', - 'Ĝ' => 'ĝ', - 'Ğ' => 'ğ', - 'Ġ' => 'ġ', - 'Ģ' => 'ģ', - 'Ĥ' => 'ĥ', - 'Ħ' => 'ħ', - 'Ĩ' => 'ĩ', - 'Ī' => 'ī', - 'Ĭ' => 'ĭ', - 'Į' => 'į', - 'İ' => 'i̇', - 'IJ' => 'ij', - 'Ĵ' => 'ĵ', - 'Ķ' => 'ķ', - 'Ĺ' => 'ĺ', - 'Ļ' => 'ļ', - 'Ľ' => 'ľ', - 'Ŀ' => 'ŀ', - 'Ł' => 'ł', - 'Ń' => 'ń', - 'Ņ' => 'ņ', - 'Ň' => 'ň', - 'Ŋ' => 'ŋ', - 'Ō' => 'ō', - 'Ŏ' => 'ŏ', - 'Ő' => 'ő', - 'Œ' => 'œ', - 'Ŕ' => 'ŕ', - 'Ŗ' => 'ŗ', - 'Ř' => 'ř', - 'Ś' => 'ś', - 'Ŝ' => 'ŝ', - 'Ş' => 'ş', - 'Š' => 'š', - 'Ţ' => 'ţ', - 'Ť' => 'ť', - 'Ŧ' => 'ŧ', - 'Ũ' => 'ũ', - 'Ū' => 'ū', - 'Ŭ' => 'ŭ', - 'Ů' => 'ů', - 'Ű' => 'ű', - 'Ų' => 'ų', - 'Ŵ' => 'ŵ', - 'Ŷ' => 'ŷ', - 'Ÿ' => 'ÿ', - 'Ź' => 'ź', - 'Ż' => 'ż', - 'Ž' => 'ž', - 'Ɓ' => 'ɓ', - 'Ƃ' => 'ƃ', - 'Ƅ' => 'ƅ', - 'Ɔ' => 'ɔ', - 'Ƈ' => 'ƈ', - 'Ɖ' => 'ɖ', - 'Ɗ' => 'ɗ', - 'Ƌ' => 'ƌ', - 'Ǝ' => 'ǝ', - 'Ə' => 'ə', - 'Ɛ' => 'ɛ', - 'Ƒ' => 'ƒ', - 'Ɠ' => 'ɠ', - 'Ɣ' => 'ɣ', - 'Ɩ' => 'ɩ', - 'Ɨ' => 'ɨ', - 'Ƙ' => 'ƙ', - 'Ɯ' => 'ɯ', - 'Ɲ' => 'ɲ', - 'Ɵ' => 'ɵ', - 'Ơ' => 'ơ', - 'Ƣ' => 'ƣ', - 'Ƥ' => 'ƥ', - 'Ʀ' => 'ʀ', - 'Ƨ' => 'ƨ', - 'Ʃ' => 'ʃ', - 'Ƭ' => 'ƭ', - 'Ʈ' => 'ʈ', - 'Ư' => 'ư', - 'Ʊ' => 'ʊ', - 'Ʋ' => 'ʋ', - 'Ƴ' => 'ƴ', - 'Ƶ' => 'ƶ', - 'Ʒ' => 'ʒ', - 'Ƹ' => 'ƹ', - 'Ƽ' => 'ƽ', - 'DŽ' => 'dž', - 'Dž' => 'dž', - 'LJ' => 'lj', - 'Lj' => 'lj', - 'NJ' => 'nj', - 'Nj' => 'nj', - 'Ǎ' => 'ǎ', - 'Ǐ' => 'ǐ', - 'Ǒ' => 'ǒ', - 'Ǔ' => 'ǔ', - 'Ǖ' => 'ǖ', - 'Ǘ' => 'ǘ', - 'Ǚ' => 'ǚ', - 'Ǜ' => 'ǜ', - 'Ǟ' => 'ǟ', - 'Ǡ' => 'ǡ', - 'Ǣ' => 'ǣ', - 'Ǥ' => 'ǥ', - 'Ǧ' => 'ǧ', - 'Ǩ' => 'ǩ', - 'Ǫ' => 'ǫ', - 'Ǭ' => 'ǭ', - 'Ǯ' => 'ǯ', - 'DZ' => 'dz', - 'Dz' => 'dz', - 'Ǵ' => 'ǵ', - 'Ƕ' => 'ƕ', - 'Ƿ' => 'ƿ', - 'Ǹ' => 'ǹ', - 'Ǻ' => 'ǻ', - 'Ǽ' => 'ǽ', - 'Ǿ' => 'ǿ', - 'Ȁ' => 'ȁ', - 'Ȃ' => 'ȃ', - 'Ȅ' => 'ȅ', - 'Ȇ' => 'ȇ', - 'Ȉ' => 'ȉ', - 'Ȋ' => 'ȋ', - 'Ȍ' => 'ȍ', - 'Ȏ' => 'ȏ', - 'Ȑ' => 'ȑ', - 'Ȓ' => 'ȓ', - 'Ȕ' => 'ȕ', - 'Ȗ' => 'ȗ', - 'Ș' => 'ș', - 'Ț' => 'ț', - 'Ȝ' => 'ȝ', - 'Ȟ' => 'ȟ', - 'Ƞ' => 'ƞ', - 'Ȣ' => 'ȣ', - 'Ȥ' => 'ȥ', - 'Ȧ' => 'ȧ', - 'Ȩ' => 'ȩ', - 'Ȫ' => 'ȫ', - 'Ȭ' => 'ȭ', - 'Ȯ' => 'ȯ', - 'Ȱ' => 'ȱ', - 'Ȳ' => 'ȳ', - 'Ⱥ' => 'ⱥ', - 'Ȼ' => 'ȼ', - 'Ƚ' => 'ƚ', - 'Ⱦ' => 'ⱦ', - 'Ɂ' => 'ɂ', - 'Ƀ' => 'ƀ', - 'Ʉ' => 'ʉ', - 'Ʌ' => 'ʌ', - 'Ɇ' => 'ɇ', - 'Ɉ' => 'ɉ', - 'Ɋ' => 'ɋ', - 'Ɍ' => 'ɍ', - 'Ɏ' => 'ɏ', - 'Ͱ' => 'ͱ', - 'Ͳ' => 'ͳ', - 'Ͷ' => 'ͷ', - 'Ϳ' => 'ϳ', - 'Ά' => 'ά', - 'Έ' => 'έ', - 'Ή' => 'ή', - 'Ί' => 'ί', - 'Ό' => 'ό', - 'Ύ' => 'ύ', - 'Ώ' => 'ώ', - 'Α' => 'α', - 'Β' => 'β', - 'Γ' => 'γ', - 'Δ' => 'δ', - 'Ε' => 'ε', - 'Ζ' => 'ζ', - 'Η' => 'η', - 'Θ' => 'θ', - 'Ι' => 'ι', - 'Κ' => 'κ', - 'Λ' => 'λ', - 'Μ' => 'μ', - 'Ν' => 'ν', - 'Ξ' => 'ξ', - 'Ο' => 'ο', - 'Π' => 'π', - 'Ρ' => 'ρ', - 'Σ' => 'σ', - 'Τ' => 'τ', - 'Υ' => 'υ', - 'Φ' => 'φ', - 'Χ' => 'χ', - 'Ψ' => 'ψ', - 'Ω' => 'ω', - 'Ϊ' => 'ϊ', - 'Ϋ' => 'ϋ', - 'Ϗ' => 'ϗ', - 'Ϙ' => 'ϙ', - 'Ϛ' => 'ϛ', - 'Ϝ' => 'ϝ', - 'Ϟ' => 'ϟ', - 'Ϡ' => 'ϡ', - 'Ϣ' => 'ϣ', - 'Ϥ' => 'ϥ', - 'Ϧ' => 'ϧ', - 'Ϩ' => 'ϩ', - 'Ϫ' => 'ϫ', - 'Ϭ' => 'ϭ', - 'Ϯ' => 'ϯ', - 'ϴ' => 'θ', - 'Ϸ' => 'ϸ', - 'Ϲ' => 'ϲ', - 'Ϻ' => 'ϻ', - 'Ͻ' => 'ͻ', - 'Ͼ' => 'ͼ', - 'Ͽ' => 'ͽ', - 'Ѐ' => 'ѐ', - 'Ё' => 'ё', - 'Ђ' => 'ђ', - 'Ѓ' => 'ѓ', - 'Є' => 'є', - 'Ѕ' => 'ѕ', - 'І' => 'і', - 'Ї' => 'ї', - 'Ј' => 'ј', - 'Љ' => 'љ', - 'Њ' => 'њ', - 'Ћ' => 'ћ', - 'Ќ' => 'ќ', - 'Ѝ' => 'ѝ', - 'Ў' => 'ў', - 'Џ' => 'џ', - 'А' => 'а', - 'Б' => 'б', - 'В' => 'в', - 'Г' => 'г', - 'Д' => 'д', - 'Е' => 'е', - 'Ж' => 'ж', - 'З' => 'з', - 'И' => 'и', - 'Й' => 'й', - 'К' => 'к', - 'Л' => 'л', - 'М' => 'м', - 'Н' => 'н', - 'О' => 'о', - 'П' => 'п', - 'Р' => 'р', - 'С' => 'с', - 'Т' => 'т', - 'У' => 'у', - 'Ф' => 'ф', - 'Х' => 'х', - 'Ц' => 'ц', - 'Ч' => 'ч', - 'Ш' => 'ш', - 'Щ' => 'щ', - 'Ъ' => 'ъ', - 'Ы' => 'ы', - 'Ь' => 'ь', - 'Э' => 'э', - 'Ю' => 'ю', - 'Я' => 'я', - 'Ѡ' => 'ѡ', - 'Ѣ' => 'ѣ', - 'Ѥ' => 'ѥ', - 'Ѧ' => 'ѧ', - 'Ѩ' => 'ѩ', - 'Ѫ' => 'ѫ', - 'Ѭ' => 'ѭ', - 'Ѯ' => 'ѯ', - 'Ѱ' => 'ѱ', - 'Ѳ' => 'ѳ', - 'Ѵ' => 'ѵ', - 'Ѷ' => 'ѷ', - 'Ѹ' => 'ѹ', - 'Ѻ' => 'ѻ', - 'Ѽ' => 'ѽ', - 'Ѿ' => 'ѿ', - 'Ҁ' => 'ҁ', - 'Ҋ' => 'ҋ', - 'Ҍ' => 'ҍ', - 'Ҏ' => 'ҏ', - 'Ґ' => 'ґ', - 'Ғ' => 'ғ', - 'Ҕ' => 'ҕ', - 'Җ' => 'җ', - 'Ҙ' => 'ҙ', - 'Қ' => 'қ', - 'Ҝ' => 'ҝ', - 'Ҟ' => 'ҟ', - 'Ҡ' => 'ҡ', - 'Ң' => 'ң', - 'Ҥ' => 'ҥ', - 'Ҧ' => 'ҧ', - 'Ҩ' => 'ҩ', - 'Ҫ' => 'ҫ', - 'Ҭ' => 'ҭ', - 'Ү' => 'ү', - 'Ұ' => 'ұ', - 'Ҳ' => 'ҳ', - 'Ҵ' => 'ҵ', - 'Ҷ' => 'ҷ', - 'Ҹ' => 'ҹ', - 'Һ' => 'һ', - 'Ҽ' => 'ҽ', - 'Ҿ' => 'ҿ', - 'Ӏ' => 'ӏ', - 'Ӂ' => 'ӂ', - 'Ӄ' => 'ӄ', - 'Ӆ' => 'ӆ', - 'Ӈ' => 'ӈ', - 'Ӊ' => 'ӊ', - 'Ӌ' => 'ӌ', - 'Ӎ' => 'ӎ', - 'Ӑ' => 'ӑ', - 'Ӓ' => 'ӓ', - 'Ӕ' => 'ӕ', - 'Ӗ' => 'ӗ', - 'Ә' => 'ә', - 'Ӛ' => 'ӛ', - 'Ӝ' => 'ӝ', - 'Ӟ' => 'ӟ', - 'Ӡ' => 'ӡ', - 'Ӣ' => 'ӣ', - 'Ӥ' => 'ӥ', - 'Ӧ' => 'ӧ', - 'Ө' => 'ө', - 'Ӫ' => 'ӫ', - 'Ӭ' => 'ӭ', - 'Ӯ' => 'ӯ', - 'Ӱ' => 'ӱ', - 'Ӳ' => 'ӳ', - 'Ӵ' => 'ӵ', - 'Ӷ' => 'ӷ', - 'Ӹ' => 'ӹ', - 'Ӻ' => 'ӻ', - 'Ӽ' => 'ӽ', - 'Ӿ' => 'ӿ', - 'Ԁ' => 'ԁ', - 'Ԃ' => 'ԃ', - 'Ԅ' => 'ԅ', - 'Ԇ' => 'ԇ', - 'Ԉ' => 'ԉ', - 'Ԋ' => 'ԋ', - 'Ԍ' => 'ԍ', - 'Ԏ' => 'ԏ', - 'Ԑ' => 'ԑ', - 'Ԓ' => 'ԓ', - 'Ԕ' => 'ԕ', - 'Ԗ' => 'ԗ', - 'Ԙ' => 'ԙ', - 'Ԛ' => 'ԛ', - 'Ԝ' => 'ԝ', - 'Ԟ' => 'ԟ', - 'Ԡ' => 'ԡ', - 'Ԣ' => 'ԣ', - 'Ԥ' => 'ԥ', - 'Ԧ' => 'ԧ', - 'Ԩ' => 'ԩ', - 'Ԫ' => 'ԫ', - 'Ԭ' => 'ԭ', - 'Ԯ' => 'ԯ', - 'Ա' => 'ա', - 'Բ' => 'բ', - 'Գ' => 'գ', - 'Դ' => 'դ', - 'Ե' => 'ե', - 'Զ' => 'զ', - 'Է' => 'է', - 'Ը' => 'ը', - 'Թ' => 'թ', - 'Ժ' => 'ժ', - 'Ի' => 'ի', - 'Լ' => 'լ', - 'Խ' => 'խ', - 'Ծ' => 'ծ', - 'Կ' => 'կ', - 'Հ' => 'հ', - 'Ձ' => 'ձ', - 'Ղ' => 'ղ', - 'Ճ' => 'ճ', - 'Մ' => 'մ', - 'Յ' => 'յ', - 'Ն' => 'ն', - 'Շ' => 'շ', - 'Ո' => 'ո', - 'Չ' => 'չ', - 'Պ' => 'պ', - 'Ջ' => 'ջ', - 'Ռ' => 'ռ', - 'Ս' => 'ս', - 'Վ' => 'վ', - 'Տ' => 'տ', - 'Ր' => 'ր', - 'Ց' => 'ց', - 'Ւ' => 'ւ', - 'Փ' => 'փ', - 'Ք' => 'ք', - 'Օ' => 'օ', - 'Ֆ' => 'ֆ', - 'Ⴀ' => 'ⴀ', - 'Ⴁ' => 'ⴁ', - 'Ⴂ' => 'ⴂ', - 'Ⴃ' => 'ⴃ', - 'Ⴄ' => 'ⴄ', - 'Ⴅ' => 'ⴅ', - 'Ⴆ' => 'ⴆ', - 'Ⴇ' => 'ⴇ', - 'Ⴈ' => 'ⴈ', - 'Ⴉ' => 'ⴉ', - 'Ⴊ' => 'ⴊ', - 'Ⴋ' => 'ⴋ', - 'Ⴌ' => 'ⴌ', - 'Ⴍ' => 'ⴍ', - 'Ⴎ' => 'ⴎ', - 'Ⴏ' => 'ⴏ', - 'Ⴐ' => 'ⴐ', - 'Ⴑ' => 'ⴑ', - 'Ⴒ' => 'ⴒ', - 'Ⴓ' => 'ⴓ', - 'Ⴔ' => 'ⴔ', - 'Ⴕ' => 'ⴕ', - 'Ⴖ' => 'ⴖ', - 'Ⴗ' => 'ⴗ', - 'Ⴘ' => 'ⴘ', - 'Ⴙ' => 'ⴙ', - 'Ⴚ' => 'ⴚ', - 'Ⴛ' => 'ⴛ', - 'Ⴜ' => 'ⴜ', - 'Ⴝ' => 'ⴝ', - 'Ⴞ' => 'ⴞ', - 'Ⴟ' => 'ⴟ', - 'Ⴠ' => 'ⴠ', - 'Ⴡ' => 'ⴡ', - 'Ⴢ' => 'ⴢ', - 'Ⴣ' => 'ⴣ', - 'Ⴤ' => 'ⴤ', - 'Ⴥ' => 'ⴥ', - 'Ⴧ' => 'ⴧ', - 'Ⴭ' => 'ⴭ', - 'Ꭰ' => 'ꭰ', - 'Ꭱ' => 'ꭱ', - 'Ꭲ' => 'ꭲ', - 'Ꭳ' => 'ꭳ', - 'Ꭴ' => 'ꭴ', - 'Ꭵ' => 'ꭵ', - 'Ꭶ' => 'ꭶ', - 'Ꭷ' => 'ꭷ', - 'Ꭸ' => 'ꭸ', - 'Ꭹ' => 'ꭹ', - 'Ꭺ' => 'ꭺ', - 'Ꭻ' => 'ꭻ', - 'Ꭼ' => 'ꭼ', - 'Ꭽ' => 'ꭽ', - 'Ꭾ' => 'ꭾ', - 'Ꭿ' => 'ꭿ', - 'Ꮀ' => 'ꮀ', - 'Ꮁ' => 'ꮁ', - 'Ꮂ' => 'ꮂ', - 'Ꮃ' => 'ꮃ', - 'Ꮄ' => 'ꮄ', - 'Ꮅ' => 'ꮅ', - 'Ꮆ' => 'ꮆ', - 'Ꮇ' => 'ꮇ', - 'Ꮈ' => 'ꮈ', - 'Ꮉ' => 'ꮉ', - 'Ꮊ' => 'ꮊ', - 'Ꮋ' => 'ꮋ', - 'Ꮌ' => 'ꮌ', - 'Ꮍ' => 'ꮍ', - 'Ꮎ' => 'ꮎ', - 'Ꮏ' => 'ꮏ', - 'Ꮐ' => 'ꮐ', - 'Ꮑ' => 'ꮑ', - 'Ꮒ' => 'ꮒ', - 'Ꮓ' => 'ꮓ', - 'Ꮔ' => 'ꮔ', - 'Ꮕ' => 'ꮕ', - 'Ꮖ' => 'ꮖ', - 'Ꮗ' => 'ꮗ', - 'Ꮘ' => 'ꮘ', - 'Ꮙ' => 'ꮙ', - 'Ꮚ' => 'ꮚ', - 'Ꮛ' => 'ꮛ', - 'Ꮜ' => 'ꮜ', - 'Ꮝ' => 'ꮝ', - 'Ꮞ' => 'ꮞ', - 'Ꮟ' => 'ꮟ', - 'Ꮠ' => 'ꮠ', - 'Ꮡ' => 'ꮡ', - 'Ꮢ' => 'ꮢ', - 'Ꮣ' => 'ꮣ', - 'Ꮤ' => 'ꮤ', - 'Ꮥ' => 'ꮥ', - 'Ꮦ' => 'ꮦ', - 'Ꮧ' => 'ꮧ', - 'Ꮨ' => 'ꮨ', - 'Ꮩ' => 'ꮩ', - 'Ꮪ' => 'ꮪ', - 'Ꮫ' => 'ꮫ', - 'Ꮬ' => 'ꮬ', - 'Ꮭ' => 'ꮭ', - 'Ꮮ' => 'ꮮ', - 'Ꮯ' => 'ꮯ', - 'Ꮰ' => 'ꮰ', - 'Ꮱ' => 'ꮱ', - 'Ꮲ' => 'ꮲ', - 'Ꮳ' => 'ꮳ', - 'Ꮴ' => 'ꮴ', - 'Ꮵ' => 'ꮵ', - 'Ꮶ' => 'ꮶ', - 'Ꮷ' => 'ꮷ', - 'Ꮸ' => 'ꮸ', - 'Ꮹ' => 'ꮹ', - 'Ꮺ' => 'ꮺ', - 'Ꮻ' => 'ꮻ', - 'Ꮼ' => 'ꮼ', - 'Ꮽ' => 'ꮽ', - 'Ꮾ' => 'ꮾ', - 'Ꮿ' => 'ꮿ', - 'Ᏸ' => 'ᏸ', - 'Ᏹ' => 'ᏹ', - 'Ᏺ' => 'ᏺ', - 'Ᏻ' => 'ᏻ', - 'Ᏼ' => 'ᏼ', - 'Ᏽ' => 'ᏽ', - 'Ა' => 'ა', - 'Ბ' => 'ბ', - 'Გ' => 'გ', - 'Დ' => 'დ', - 'Ე' => 'ე', - 'Ვ' => 'ვ', - 'Ზ' => 'ზ', - 'Თ' => 'თ', - 'Ი' => 'ი', - 'Კ' => 'კ', - 'Ლ' => 'ლ', - 'Მ' => 'მ', - 'Ნ' => 'ნ', - 'Ო' => 'ო', - 'Პ' => 'პ', - 'Ჟ' => 'ჟ', - 'Რ' => 'რ', - 'Ს' => 'ს', - 'Ტ' => 'ტ', - 'Უ' => 'უ', - 'Ფ' => 'ფ', - 'Ქ' => 'ქ', - 'Ღ' => 'ღ', - 'Ყ' => 'ყ', - 'Შ' => 'შ', - 'Ჩ' => 'ჩ', - 'Ც' => 'ც', - 'Ძ' => 'ძ', - 'Წ' => 'წ', - 'Ჭ' => 'ჭ', - 'Ხ' => 'ხ', - 'Ჯ' => 'ჯ', - 'Ჰ' => 'ჰ', - 'Ჱ' => 'ჱ', - 'Ჲ' => 'ჲ', - 'Ჳ' => 'ჳ', - 'Ჴ' => 'ჴ', - 'Ჵ' => 'ჵ', - 'Ჶ' => 'ჶ', - 'Ჷ' => 'ჷ', - 'Ჸ' => 'ჸ', - 'Ჹ' => 'ჹ', - 'Ჺ' => 'ჺ', - 'Ჽ' => 'ჽ', - 'Ჾ' => 'ჾ', - 'Ჿ' => 'ჿ', - 'Ḁ' => 'ḁ', - 'Ḃ' => 'ḃ', - 'Ḅ' => 'ḅ', - 'Ḇ' => 'ḇ', - 'Ḉ' => 'ḉ', - 'Ḋ' => 'ḋ', - 'Ḍ' => 'ḍ', - 'Ḏ' => 'ḏ', - 'Ḑ' => 'ḑ', - 'Ḓ' => 'ḓ', - 'Ḕ' => 'ḕ', - 'Ḗ' => 'ḗ', - 'Ḙ' => 'ḙ', - 'Ḛ' => 'ḛ', - 'Ḝ' => 'ḝ', - 'Ḟ' => 'ḟ', - 'Ḡ' => 'ḡ', - 'Ḣ' => 'ḣ', - 'Ḥ' => 'ḥ', - 'Ḧ' => 'ḧ', - 'Ḩ' => 'ḩ', - 'Ḫ' => 'ḫ', - 'Ḭ' => 'ḭ', - 'Ḯ' => 'ḯ', - 'Ḱ' => 'ḱ', - 'Ḳ' => 'ḳ', - 'Ḵ' => 'ḵ', - 'Ḷ' => 'ḷ', - 'Ḹ' => 'ḹ', - 'Ḻ' => 'ḻ', - 'Ḽ' => 'ḽ', - 'Ḿ' => 'ḿ', - 'Ṁ' => 'ṁ', - 'Ṃ' => 'ṃ', - 'Ṅ' => 'ṅ', - 'Ṇ' => 'ṇ', - 'Ṉ' => 'ṉ', - 'Ṋ' => 'ṋ', - 'Ṍ' => 'ṍ', - 'Ṏ' => 'ṏ', - 'Ṑ' => 'ṑ', - 'Ṓ' => 'ṓ', - 'Ṕ' => 'ṕ', - 'Ṗ' => 'ṗ', - 'Ṙ' => 'ṙ', - 'Ṛ' => 'ṛ', - 'Ṝ' => 'ṝ', - 'Ṟ' => 'ṟ', - 'Ṡ' => 'ṡ', - 'Ṣ' => 'ṣ', - 'Ṥ' => 'ṥ', - 'Ṧ' => 'ṧ', - 'Ṩ' => 'ṩ', - 'Ṫ' => 'ṫ', - 'Ṭ' => 'ṭ', - 'Ṯ' => 'ṯ', - 'Ṱ' => 'ṱ', - 'Ṳ' => 'ṳ', - 'Ṵ' => 'ṵ', - 'Ṷ' => 'ṷ', - 'Ṹ' => 'ṹ', - 'Ṻ' => 'ṻ', - 'Ṽ' => 'ṽ', - 'Ṿ' => 'ṿ', - 'Ẁ' => 'ẁ', - 'Ẃ' => 'ẃ', - 'Ẅ' => 'ẅ', - 'Ẇ' => 'ẇ', - 'Ẉ' => 'ẉ', - 'Ẋ' => 'ẋ', - 'Ẍ' => 'ẍ', - 'Ẏ' => 'ẏ', - 'Ẑ' => 'ẑ', - 'Ẓ' => 'ẓ', - 'Ẕ' => 'ẕ', - 'ẞ' => 'ß', - 'Ạ' => 'ạ', - 'Ả' => 'ả', - 'Ấ' => 'ấ', - 'Ầ' => 'ầ', - 'Ẩ' => 'ẩ', - 'Ẫ' => 'ẫ', - 'Ậ' => 'ậ', - 'Ắ' => 'ắ', - 'Ằ' => 'ằ', - 'Ẳ' => 'ẳ', - 'Ẵ' => 'ẵ', - 'Ặ' => 'ặ', - 'Ẹ' => 'ẹ', - 'Ẻ' => 'ẻ', - 'Ẽ' => 'ẽ', - 'Ế' => 'ế', - 'Ề' => 'ề', - 'Ể' => 'ể', - 'Ễ' => 'ễ', - 'Ệ' => 'ệ', - 'Ỉ' => 'ỉ', - 'Ị' => 'ị', - 'Ọ' => 'ọ', - 'Ỏ' => 'ỏ', - 'Ố' => 'ố', - 'Ồ' => 'ồ', - 'Ổ' => 'ổ', - 'Ỗ' => 'ỗ', - 'Ộ' => 'ộ', - 'Ớ' => 'ớ', - 'Ờ' => 'ờ', - 'Ở' => 'ở', - 'Ỡ' => 'ỡ', - 'Ợ' => 'ợ', - 'Ụ' => 'ụ', - 'Ủ' => 'ủ', - 'Ứ' => 'ứ', - 'Ừ' => 'ừ', - 'Ử' => 'ử', - 'Ữ' => 'ữ', - 'Ự' => 'ự', - 'Ỳ' => 'ỳ', - 'Ỵ' => 'ỵ', - 'Ỷ' => 'ỷ', - 'Ỹ' => 'ỹ', - 'Ỻ' => 'ỻ', - 'Ỽ' => 'ỽ', - 'Ỿ' => 'ỿ', - 'Ἀ' => 'ἀ', - 'Ἁ' => 'ἁ', - 'Ἂ' => 'ἂ', - 'Ἃ' => 'ἃ', - 'Ἄ' => 'ἄ', - 'Ἅ' => 'ἅ', - 'Ἆ' => 'ἆ', - 'Ἇ' => 'ἇ', - 'Ἐ' => 'ἐ', - 'Ἑ' => 'ἑ', - 'Ἒ' => 'ἒ', - 'Ἓ' => 'ἓ', - 'Ἔ' => 'ἔ', - 'Ἕ' => 'ἕ', - 'Ἠ' => 'ἠ', - 'Ἡ' => 'ἡ', - 'Ἢ' => 'ἢ', - 'Ἣ' => 'ἣ', - 'Ἤ' => 'ἤ', - 'Ἥ' => 'ἥ', - 'Ἦ' => 'ἦ', - 'Ἧ' => 'ἧ', - 'Ἰ' => 'ἰ', - 'Ἱ' => 'ἱ', - 'Ἲ' => 'ἲ', - 'Ἳ' => 'ἳ', - 'Ἴ' => 'ἴ', - 'Ἵ' => 'ἵ', - 'Ἶ' => 'ἶ', - 'Ἷ' => 'ἷ', - 'Ὀ' => 'ὀ', - 'Ὁ' => 'ὁ', - 'Ὂ' => 'ὂ', - 'Ὃ' => 'ὃ', - 'Ὄ' => 'ὄ', - 'Ὅ' => 'ὅ', - 'Ὑ' => 'ὑ', - 'Ὓ' => 'ὓ', - 'Ὕ' => 'ὕ', - 'Ὗ' => 'ὗ', - 'Ὠ' => 'ὠ', - 'Ὡ' => 'ὡ', - 'Ὢ' => 'ὢ', - 'Ὣ' => 'ὣ', - 'Ὤ' => 'ὤ', - 'Ὥ' => 'ὥ', - 'Ὦ' => 'ὦ', - 'Ὧ' => 'ὧ', - 'ᾈ' => 'ᾀ', - 'ᾉ' => 'ᾁ', - 'ᾊ' => 'ᾂ', - 'ᾋ' => 'ᾃ', - 'ᾌ' => 'ᾄ', - 'ᾍ' => 'ᾅ', - 'ᾎ' => 'ᾆ', - 'ᾏ' => 'ᾇ', - 'ᾘ' => 'ᾐ', - 'ᾙ' => 'ᾑ', - 'ᾚ' => 'ᾒ', - 'ᾛ' => 'ᾓ', - 'ᾜ' => 'ᾔ', - 'ᾝ' => 'ᾕ', - 'ᾞ' => 'ᾖ', - 'ᾟ' => 'ᾗ', - 'ᾨ' => 'ᾠ', - 'ᾩ' => 'ᾡ', - 'ᾪ' => 'ᾢ', - 'ᾫ' => 'ᾣ', - 'ᾬ' => 'ᾤ', - 'ᾭ' => 'ᾥ', - 'ᾮ' => 'ᾦ', - 'ᾯ' => 'ᾧ', - 'Ᾰ' => 'ᾰ', - 'Ᾱ' => 'ᾱ', - 'Ὰ' => 'ὰ', - 'Ά' => 'ά', - 'ᾼ' => 'ᾳ', - 'Ὲ' => 'ὲ', - 'Έ' => 'έ', - 'Ὴ' => 'ὴ', - 'Ή' => 'ή', - 'ῌ' => 'ῃ', - 'Ῐ' => 'ῐ', - 'Ῑ' => 'ῑ', - 'Ὶ' => 'ὶ', - 'Ί' => 'ί', - 'Ῠ' => 'ῠ', - 'Ῡ' => 'ῡ', - 'Ὺ' => 'ὺ', - 'Ύ' => 'ύ', - 'Ῥ' => 'ῥ', - 'Ὸ' => 'ὸ', - 'Ό' => 'ό', - 'Ὼ' => 'ὼ', - 'Ώ' => 'ώ', - 'ῼ' => 'ῳ', - 'Ω' => 'ω', - 'K' => 'k', - 'Å' => 'å', - 'Ⅎ' => 'ⅎ', - 'Ⅰ' => 'ⅰ', - 'Ⅱ' => 'ⅱ', - 'Ⅲ' => 'ⅲ', - 'Ⅳ' => 'ⅳ', - 'Ⅴ' => 'ⅴ', - 'Ⅵ' => 'ⅵ', - 'Ⅶ' => 'ⅶ', - 'Ⅷ' => 'ⅷ', - 'Ⅸ' => 'ⅸ', - 'Ⅹ' => 'ⅹ', - 'Ⅺ' => 'ⅺ', - 'Ⅻ' => 'ⅻ', - 'Ⅼ' => 'ⅼ', - 'Ⅽ' => 'ⅽ', - 'Ⅾ' => 'ⅾ', - 'Ⅿ' => 'ⅿ', - 'Ↄ' => 'ↄ', - 'Ⓐ' => 'ⓐ', - 'Ⓑ' => 'ⓑ', - 'Ⓒ' => 'ⓒ', - 'Ⓓ' => 'ⓓ', - 'Ⓔ' => 'ⓔ', - 'Ⓕ' => 'ⓕ', - 'Ⓖ' => 'ⓖ', - 'Ⓗ' => 'ⓗ', - 'Ⓘ' => 'ⓘ', - 'Ⓙ' => 'ⓙ', - 'Ⓚ' => 'ⓚ', - 'Ⓛ' => 'ⓛ', - 'Ⓜ' => 'ⓜ', - 'Ⓝ' => 'ⓝ', - 'Ⓞ' => 'ⓞ', - 'Ⓟ' => 'ⓟ', - 'Ⓠ' => 'ⓠ', - 'Ⓡ' => 'ⓡ', - 'Ⓢ' => 'ⓢ', - 'Ⓣ' => 'ⓣ', - 'Ⓤ' => 'ⓤ', - 'Ⓥ' => 'ⓥ', - 'Ⓦ' => 'ⓦ', - 'Ⓧ' => 'ⓧ', - 'Ⓨ' => 'ⓨ', - 'Ⓩ' => 'ⓩ', - 'Ⰰ' => 'ⰰ', - 'Ⰱ' => 'ⰱ', - 'Ⰲ' => 'ⰲ', - 'Ⰳ' => 'ⰳ', - 'Ⰴ' => 'ⰴ', - 'Ⰵ' => 'ⰵ', - 'Ⰶ' => 'ⰶ', - 'Ⰷ' => 'ⰷ', - 'Ⰸ' => 'ⰸ', - 'Ⰹ' => 'ⰹ', - 'Ⰺ' => 'ⰺ', - 'Ⰻ' => 'ⰻ', - 'Ⰼ' => 'ⰼ', - 'Ⰽ' => 'ⰽ', - 'Ⰾ' => 'ⰾ', - 'Ⰿ' => 'ⰿ', - 'Ⱀ' => 'ⱀ', - 'Ⱁ' => 'ⱁ', - 'Ⱂ' => 'ⱂ', - 'Ⱃ' => 'ⱃ', - 'Ⱄ' => 'ⱄ', - 'Ⱅ' => 'ⱅ', - 'Ⱆ' => 'ⱆ', - 'Ⱇ' => 'ⱇ', - 'Ⱈ' => 'ⱈ', - 'Ⱉ' => 'ⱉ', - 'Ⱊ' => 'ⱊ', - 'Ⱋ' => 'ⱋ', - 'Ⱌ' => 'ⱌ', - 'Ⱍ' => 'ⱍ', - 'Ⱎ' => 'ⱎ', - 'Ⱏ' => 'ⱏ', - 'Ⱐ' => 'ⱐ', - 'Ⱑ' => 'ⱑ', - 'Ⱒ' => 'ⱒ', - 'Ⱓ' => 'ⱓ', - 'Ⱔ' => 'ⱔ', - 'Ⱕ' => 'ⱕ', - 'Ⱖ' => 'ⱖ', - 'Ⱗ' => 'ⱗ', - 'Ⱘ' => 'ⱘ', - 'Ⱙ' => 'ⱙ', - 'Ⱚ' => 'ⱚ', - 'Ⱛ' => 'ⱛ', - 'Ⱜ' => 'ⱜ', - 'Ⱝ' => 'ⱝ', - 'Ⱞ' => 'ⱞ', - 'Ⱡ' => 'ⱡ', - 'Ɫ' => 'ɫ', - 'Ᵽ' => 'ᵽ', - 'Ɽ' => 'ɽ', - 'Ⱨ' => 'ⱨ', - 'Ⱪ' => 'ⱪ', - 'Ⱬ' => 'ⱬ', - 'Ɑ' => 'ɑ', - 'Ɱ' => 'ɱ', - 'Ɐ' => 'ɐ', - 'Ɒ' => 'ɒ', - 'Ⱳ' => 'ⱳ', - 'Ⱶ' => 'ⱶ', - 'Ȿ' => 'ȿ', - 'Ɀ' => 'ɀ', - 'Ⲁ' => 'ⲁ', - 'Ⲃ' => 'ⲃ', - 'Ⲅ' => 'ⲅ', - 'Ⲇ' => 'ⲇ', - 'Ⲉ' => 'ⲉ', - 'Ⲋ' => 'ⲋ', - 'Ⲍ' => 'ⲍ', - 'Ⲏ' => 'ⲏ', - 'Ⲑ' => 'ⲑ', - 'Ⲓ' => 'ⲓ', - 'Ⲕ' => 'ⲕ', - 'Ⲗ' => 'ⲗ', - 'Ⲙ' => 'ⲙ', - 'Ⲛ' => 'ⲛ', - 'Ⲝ' => 'ⲝ', - 'Ⲟ' => 'ⲟ', - 'Ⲡ' => 'ⲡ', - 'Ⲣ' => 'ⲣ', - 'Ⲥ' => 'ⲥ', - 'Ⲧ' => 'ⲧ', - 'Ⲩ' => 'ⲩ', - 'Ⲫ' => 'ⲫ', - 'Ⲭ' => 'ⲭ', - 'Ⲯ' => 'ⲯ', - 'Ⲱ' => 'ⲱ', - 'Ⲳ' => 'ⲳ', - 'Ⲵ' => 'ⲵ', - 'Ⲷ' => 'ⲷ', - 'Ⲹ' => 'ⲹ', - 'Ⲻ' => 'ⲻ', - 'Ⲽ' => 'ⲽ', - 'Ⲿ' => 'ⲿ', - 'Ⳁ' => 'ⳁ', - 'Ⳃ' => 'ⳃ', - 'Ⳅ' => 'ⳅ', - 'Ⳇ' => 'ⳇ', - 'Ⳉ' => 'ⳉ', - 'Ⳋ' => 'ⳋ', - 'Ⳍ' => 'ⳍ', - 'Ⳏ' => 'ⳏ', - 'Ⳑ' => 'ⳑ', - 'Ⳓ' => 'ⳓ', - 'Ⳕ' => 'ⳕ', - 'Ⳗ' => 'ⳗ', - 'Ⳙ' => 'ⳙ', - 'Ⳛ' => 'ⳛ', - 'Ⳝ' => 'ⳝ', - 'Ⳟ' => 'ⳟ', - 'Ⳡ' => 'ⳡ', - 'Ⳣ' => 'ⳣ', - 'Ⳬ' => 'ⳬ', - 'Ⳮ' => 'ⳮ', - 'Ⳳ' => 'ⳳ', - 'Ꙁ' => 'ꙁ', - 'Ꙃ' => 'ꙃ', - 'Ꙅ' => 'ꙅ', - 'Ꙇ' => 'ꙇ', - 'Ꙉ' => 'ꙉ', - 'Ꙋ' => 'ꙋ', - 'Ꙍ' => 'ꙍ', - 'Ꙏ' => 'ꙏ', - 'Ꙑ' => 'ꙑ', - 'Ꙓ' => 'ꙓ', - 'Ꙕ' => 'ꙕ', - 'Ꙗ' => 'ꙗ', - 'Ꙙ' => 'ꙙ', - 'Ꙛ' => 'ꙛ', - 'Ꙝ' => 'ꙝ', - 'Ꙟ' => 'ꙟ', - 'Ꙡ' => 'ꙡ', - 'Ꙣ' => 'ꙣ', - 'Ꙥ' => 'ꙥ', - 'Ꙧ' => 'ꙧ', - 'Ꙩ' => 'ꙩ', - 'Ꙫ' => 'ꙫ', - 'Ꙭ' => 'ꙭ', - 'Ꚁ' => 'ꚁ', - 'Ꚃ' => 'ꚃ', - 'Ꚅ' => 'ꚅ', - 'Ꚇ' => 'ꚇ', - 'Ꚉ' => 'ꚉ', - 'Ꚋ' => 'ꚋ', - 'Ꚍ' => 'ꚍ', - 'Ꚏ' => 'ꚏ', - 'Ꚑ' => 'ꚑ', - 'Ꚓ' => 'ꚓ', - 'Ꚕ' => 'ꚕ', - 'Ꚗ' => 'ꚗ', - 'Ꚙ' => 'ꚙ', - 'Ꚛ' => 'ꚛ', - 'Ꜣ' => 'ꜣ', - 'Ꜥ' => 'ꜥ', - 'Ꜧ' => 'ꜧ', - 'Ꜩ' => 'ꜩ', - 'Ꜫ' => 'ꜫ', - 'Ꜭ' => 'ꜭ', - 'Ꜯ' => 'ꜯ', - 'Ꜳ' => 'ꜳ', - 'Ꜵ' => 'ꜵ', - 'Ꜷ' => 'ꜷ', - 'Ꜹ' => 'ꜹ', - 'Ꜻ' => 'ꜻ', - 'Ꜽ' => 'ꜽ', - 'Ꜿ' => 'ꜿ', - 'Ꝁ' => 'ꝁ', - 'Ꝃ' => 'ꝃ', - 'Ꝅ' => 'ꝅ', - 'Ꝇ' => 'ꝇ', - 'Ꝉ' => 'ꝉ', - 'Ꝋ' => 'ꝋ', - 'Ꝍ' => 'ꝍ', - 'Ꝏ' => 'ꝏ', - 'Ꝑ' => 'ꝑ', - 'Ꝓ' => 'ꝓ', - 'Ꝕ' => 'ꝕ', - 'Ꝗ' => 'ꝗ', - 'Ꝙ' => 'ꝙ', - 'Ꝛ' => 'ꝛ', - 'Ꝝ' => 'ꝝ', - 'Ꝟ' => 'ꝟ', - 'Ꝡ' => 'ꝡ', - 'Ꝣ' => 'ꝣ', - 'Ꝥ' => 'ꝥ', - 'Ꝧ' => 'ꝧ', - 'Ꝩ' => 'ꝩ', - 'Ꝫ' => 'ꝫ', - 'Ꝭ' => 'ꝭ', - 'Ꝯ' => 'ꝯ', - 'Ꝺ' => 'ꝺ', - 'Ꝼ' => 'ꝼ', - 'Ᵹ' => 'ᵹ', - 'Ꝿ' => 'ꝿ', - 'Ꞁ' => 'ꞁ', - 'Ꞃ' => 'ꞃ', - 'Ꞅ' => 'ꞅ', - 'Ꞇ' => 'ꞇ', - 'Ꞌ' => 'ꞌ', - 'Ɥ' => 'ɥ', - 'Ꞑ' => 'ꞑ', - 'Ꞓ' => 'ꞓ', - 'Ꞗ' => 'ꞗ', - 'Ꞙ' => 'ꞙ', - 'Ꞛ' => 'ꞛ', - 'Ꞝ' => 'ꞝ', - 'Ꞟ' => 'ꞟ', - 'Ꞡ' => 'ꞡ', - 'Ꞣ' => 'ꞣ', - 'Ꞥ' => 'ꞥ', - 'Ꞧ' => 'ꞧ', - 'Ꞩ' => 'ꞩ', - 'Ɦ' => 'ɦ', - 'Ɜ' => 'ɜ', - 'Ɡ' => 'ɡ', - 'Ɬ' => 'ɬ', - 'Ɪ' => 'ɪ', - 'Ʞ' => 'ʞ', - 'Ʇ' => 'ʇ', - 'Ʝ' => 'ʝ', - 'Ꭓ' => 'ꭓ', - 'Ꞵ' => 'ꞵ', - 'Ꞷ' => 'ꞷ', - 'Ꞹ' => 'ꞹ', - 'Ꞻ' => 'ꞻ', - 'Ꞽ' => 'ꞽ', - 'Ꞿ' => 'ꞿ', - 'Ꟃ' => 'ꟃ', - 'Ꞔ' => 'ꞔ', - 'Ʂ' => 'ʂ', - 'Ᶎ' => 'ᶎ', - 'Ꟈ' => 'ꟈ', - 'Ꟊ' => 'ꟊ', - 'Ꟶ' => 'ꟶ', - 'A' => 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - '𐐀' => '𐐨', - '𐐁' => '𐐩', - '𐐂' => '𐐪', - '𐐃' => '𐐫', - '𐐄' => '𐐬', - '𐐅' => '𐐭', - '𐐆' => '𐐮', - '𐐇' => '𐐯', - '𐐈' => '𐐰', - '𐐉' => '𐐱', - '𐐊' => '𐐲', - '𐐋' => '𐐳', - '𐐌' => '𐐴', - '𐐍' => '𐐵', - '𐐎' => '𐐶', - '𐐏' => '𐐷', - '𐐐' => '𐐸', - '𐐑' => '𐐹', - '𐐒' => '𐐺', - '𐐓' => '𐐻', - '𐐔' => '𐐼', - '𐐕' => '𐐽', - '𐐖' => '𐐾', - '𐐗' => '𐐿', - '𐐘' => '𐑀', - '𐐙' => '𐑁', - '𐐚' => '𐑂', - '𐐛' => '𐑃', - '𐐜' => '𐑄', - '𐐝' => '𐑅', - '𐐞' => '𐑆', - '𐐟' => '𐑇', - '𐐠' => '𐑈', - '𐐡' => '𐑉', - '𐐢' => '𐑊', - '𐐣' => '𐑋', - '𐐤' => '𐑌', - '𐐥' => '𐑍', - '𐐦' => '𐑎', - '𐐧' => '𐑏', - '𐒰' => '𐓘', - '𐒱' => '𐓙', - '𐒲' => '𐓚', - '𐒳' => '𐓛', - '𐒴' => '𐓜', - '𐒵' => '𐓝', - '𐒶' => '𐓞', - '𐒷' => '𐓟', - '𐒸' => '𐓠', - '𐒹' => '𐓡', - '𐒺' => '𐓢', - '𐒻' => '𐓣', - '𐒼' => '𐓤', - '𐒽' => '𐓥', - '𐒾' => '𐓦', - '𐒿' => '𐓧', - '𐓀' => '𐓨', - '𐓁' => '𐓩', - '𐓂' => '𐓪', - '𐓃' => '𐓫', - '𐓄' => '𐓬', - '𐓅' => '𐓭', - '𐓆' => '𐓮', - '𐓇' => '𐓯', - '𐓈' => '𐓰', - '𐓉' => '𐓱', - '𐓊' => '𐓲', - '𐓋' => '𐓳', - '𐓌' => '𐓴', - '𐓍' => '𐓵', - '𐓎' => '𐓶', - '𐓏' => '𐓷', - '𐓐' => '𐓸', - '𐓑' => '𐓹', - '𐓒' => '𐓺', - '𐓓' => '𐓻', - '𐲀' => '𐳀', - '𐲁' => '𐳁', - '𐲂' => '𐳂', - '𐲃' => '𐳃', - '𐲄' => '𐳄', - '𐲅' => '𐳅', - '𐲆' => '𐳆', - '𐲇' => '𐳇', - '𐲈' => '𐳈', - '𐲉' => '𐳉', - '𐲊' => '𐳊', - '𐲋' => '𐳋', - '𐲌' => '𐳌', - '𐲍' => '𐳍', - '𐲎' => '𐳎', - '𐲏' => '𐳏', - '𐲐' => '𐳐', - '𐲑' => '𐳑', - '𐲒' => '𐳒', - '𐲓' => '𐳓', - '𐲔' => '𐳔', - '𐲕' => '𐳕', - '𐲖' => '𐳖', - '𐲗' => '𐳗', - '𐲘' => '𐳘', - '𐲙' => '𐳙', - '𐲚' => '𐳚', - '𐲛' => '𐳛', - '𐲜' => '𐳜', - '𐲝' => '𐳝', - '𐲞' => '𐳞', - '𐲟' => '𐳟', - '𐲠' => '𐳠', - '𐲡' => '𐳡', - '𐲢' => '𐳢', - '𐲣' => '𐳣', - '𐲤' => '𐳤', - '𐲥' => '𐳥', - '𐲦' => '𐳦', - '𐲧' => '𐳧', - '𐲨' => '𐳨', - '𐲩' => '𐳩', - '𐲪' => '𐳪', - '𐲫' => '𐳫', - '𐲬' => '𐳬', - '𐲭' => '𐳭', - '𐲮' => '𐳮', - '𐲯' => '𐳯', - '𐲰' => '𐳰', - '𐲱' => '𐳱', - '𐲲' => '𐳲', - '𑢠' => '𑣀', - '𑢡' => '𑣁', - '𑢢' => '𑣂', - '𑢣' => '𑣃', - '𑢤' => '𑣄', - '𑢥' => '𑣅', - '𑢦' => '𑣆', - '𑢧' => '𑣇', - '𑢨' => '𑣈', - '𑢩' => '𑣉', - '𑢪' => '𑣊', - '𑢫' => '𑣋', - '𑢬' => '𑣌', - '𑢭' => '𑣍', - '𑢮' => '𑣎', - '𑢯' => '𑣏', - '𑢰' => '𑣐', - '𑢱' => '𑣑', - '𑢲' => '𑣒', - '𑢳' => '𑣓', - '𑢴' => '𑣔', - '𑢵' => '𑣕', - '𑢶' => '𑣖', - '𑢷' => '𑣗', - '𑢸' => '𑣘', - '𑢹' => '𑣙', - '𑢺' => '𑣚', - '𑢻' => '𑣛', - '𑢼' => '𑣜', - '𑢽' => '𑣝', - '𑢾' => '𑣞', - '𑢿' => '𑣟', - '𖹀' => '𖹠', - '𖹁' => '𖹡', - '𖹂' => '𖹢', - '𖹃' => '𖹣', - '𖹄' => '𖹤', - '𖹅' => '𖹥', - '𖹆' => '𖹦', - '𖹇' => '𖹧', - '𖹈' => '𖹨', - '𖹉' => '𖹩', - '𖹊' => '𖹪', - '𖹋' => '𖹫', - '𖹌' => '𖹬', - '𖹍' => '𖹭', - '𖹎' => '𖹮', - '𖹏' => '𖹯', - '𖹐' => '𖹰', - '𖹑' => '𖹱', - '𖹒' => '𖹲', - '𖹓' => '𖹳', - '𖹔' => '𖹴', - '𖹕' => '𖹵', - '𖹖' => '𖹶', - '𖹗' => '𖹷', - '𖹘' => '𖹸', - '𖹙' => '𖹹', - '𖹚' => '𖹺', - '𖹛' => '𖹻', - '𖹜' => '𖹼', - '𖹝' => '𖹽', - '𖹞' => '𖹾', - '𖹟' => '𖹿', - '𞤀' => '𞤢', - '𞤁' => '𞤣', - '𞤂' => '𞤤', - '𞤃' => '𞤥', - '𞤄' => '𞤦', - '𞤅' => '𞤧', - '𞤆' => '𞤨', - '𞤇' => '𞤩', - '𞤈' => '𞤪', - '𞤉' => '𞤫', - '𞤊' => '𞤬', - '𞤋' => '𞤭', - '𞤌' => '𞤮', - '𞤍' => '𞤯', - '𞤎' => '𞤰', - '𞤏' => '𞤱', - '𞤐' => '𞤲', - '𞤑' => '𞤳', - '𞤒' => '𞤴', - '𞤓' => '𞤵', - '𞤔' => '𞤶', - '𞤕' => '𞤷', - '𞤖' => '𞤸', - '𞤗' => '𞤹', - '𞤘' => '𞤺', - '𞤙' => '𞤻', - '𞤚' => '𞤼', - '𞤛' => '𞤽', - '𞤜' => '𞤾', - '𞤝' => '𞤿', - '𞤞' => '𞥀', - '𞤟' => '𞥁', - '𞤠' => '𞥂', - '𞤡' => '𞥃', -); diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php deleted file mode 100644 index 2a8f6e7..0000000 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +++ /dev/null @@ -1,5 +0,0 @@ - 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - 'µ' => 'Μ', - 'à' => 'À', - 'á' => 'Á', - 'â' => 'Â', - 'ã' => 'Ã', - 'ä' => 'Ä', - 'å' => 'Å', - 'æ' => 'Æ', - 'ç' => 'Ç', - 'è' => 'È', - 'é' => 'É', - 'ê' => 'Ê', - 'ë' => 'Ë', - 'ì' => 'Ì', - 'í' => 'Í', - 'î' => 'Î', - 'ï' => 'Ï', - 'ð' => 'Ð', - 'ñ' => 'Ñ', - 'ò' => 'Ò', - 'ó' => 'Ó', - 'ô' => 'Ô', - 'õ' => 'Õ', - 'ö' => 'Ö', - 'ø' => 'Ø', - 'ù' => 'Ù', - 'ú' => 'Ú', - 'û' => 'Û', - 'ü' => 'Ü', - 'ý' => 'Ý', - 'þ' => 'Þ', - 'ÿ' => 'Ÿ', - 'ā' => 'Ā', - 'ă' => 'Ă', - 'ą' => 'Ą', - 'ć' => 'Ć', - 'ĉ' => 'Ĉ', - 'ċ' => 'Ċ', - 'č' => 'Č', - 'ď' => 'Ď', - 'đ' => 'Đ', - 'ē' => 'Ē', - 'ĕ' => 'Ĕ', - 'ė' => 'Ė', - 'ę' => 'Ę', - 'ě' => 'Ě', - 'ĝ' => 'Ĝ', - 'ğ' => 'Ğ', - 'ġ' => 'Ġ', - 'ģ' => 'Ģ', - 'ĥ' => 'Ĥ', - 'ħ' => 'Ħ', - 'ĩ' => 'Ĩ', - 'ī' => 'Ī', - 'ĭ' => 'Ĭ', - 'į' => 'Į', - 'ı' => 'I', - 'ij' => 'IJ', - 'ĵ' => 'Ĵ', - 'ķ' => 'Ķ', - 'ĺ' => 'Ĺ', - 'ļ' => 'Ļ', - 'ľ' => 'Ľ', - 'ŀ' => 'Ŀ', - 'ł' => 'Ł', - 'ń' => 'Ń', - 'ņ' => 'Ņ', - 'ň' => 'Ň', - 'ŋ' => 'Ŋ', - 'ō' => 'Ō', - 'ŏ' => 'Ŏ', - 'ő' => 'Ő', - 'œ' => 'Œ', - 'ŕ' => 'Ŕ', - 'ŗ' => 'Ŗ', - 'ř' => 'Ř', - 'ś' => 'Ś', - 'ŝ' => 'Ŝ', - 'ş' => 'Ş', - 'š' => 'Š', - 'ţ' => 'Ţ', - 'ť' => 'Ť', - 'ŧ' => 'Ŧ', - 'ũ' => 'Ũ', - 'ū' => 'Ū', - 'ŭ' => 'Ŭ', - 'ů' => 'Ů', - 'ű' => 'Ű', - 'ų' => 'Ų', - 'ŵ' => 'Ŵ', - 'ŷ' => 'Ŷ', - 'ź' => 'Ź', - 'ż' => 'Ż', - 'ž' => 'Ž', - 'ſ' => 'S', - 'ƀ' => 'Ƀ', - 'ƃ' => 'Ƃ', - 'ƅ' => 'Ƅ', - 'ƈ' => 'Ƈ', - 'ƌ' => 'Ƌ', - 'ƒ' => 'Ƒ', - 'ƕ' => 'Ƕ', - 'ƙ' => 'Ƙ', - 'ƚ' => 'Ƚ', - 'ƞ' => 'Ƞ', - 'ơ' => 'Ơ', - 'ƣ' => 'Ƣ', - 'ƥ' => 'Ƥ', - 'ƨ' => 'Ƨ', - 'ƭ' => 'Ƭ', - 'ư' => 'Ư', - 'ƴ' => 'Ƴ', - 'ƶ' => 'Ƶ', - 'ƹ' => 'Ƹ', - 'ƽ' => 'Ƽ', - 'ƿ' => 'Ƿ', - 'Dž' => 'DŽ', - 'dž' => 'DŽ', - 'Lj' => 'LJ', - 'lj' => 'LJ', - 'Nj' => 'NJ', - 'nj' => 'NJ', - 'ǎ' => 'Ǎ', - 'ǐ' => 'Ǐ', - 'ǒ' => 'Ǒ', - 'ǔ' => 'Ǔ', - 'ǖ' => 'Ǖ', - 'ǘ' => 'Ǘ', - 'ǚ' => 'Ǚ', - 'ǜ' => 'Ǜ', - 'ǝ' => 'Ǝ', - 'ǟ' => 'Ǟ', - 'ǡ' => 'Ǡ', - 'ǣ' => 'Ǣ', - 'ǥ' => 'Ǥ', - 'ǧ' => 'Ǧ', - 'ǩ' => 'Ǩ', - 'ǫ' => 'Ǫ', - 'ǭ' => 'Ǭ', - 'ǯ' => 'Ǯ', - 'Dz' => 'DZ', - 'dz' => 'DZ', - 'ǵ' => 'Ǵ', - 'ǹ' => 'Ǹ', - 'ǻ' => 'Ǻ', - 'ǽ' => 'Ǽ', - 'ǿ' => 'Ǿ', - 'ȁ' => 'Ȁ', - 'ȃ' => 'Ȃ', - 'ȅ' => 'Ȅ', - 'ȇ' => 'Ȇ', - 'ȉ' => 'Ȉ', - 'ȋ' => 'Ȋ', - 'ȍ' => 'Ȍ', - 'ȏ' => 'Ȏ', - 'ȑ' => 'Ȑ', - 'ȓ' => 'Ȓ', - 'ȕ' => 'Ȕ', - 'ȗ' => 'Ȗ', - 'ș' => 'Ș', - 'ț' => 'Ț', - 'ȝ' => 'Ȝ', - 'ȟ' => 'Ȟ', - 'ȣ' => 'Ȣ', - 'ȥ' => 'Ȥ', - 'ȧ' => 'Ȧ', - 'ȩ' => 'Ȩ', - 'ȫ' => 'Ȫ', - 'ȭ' => 'Ȭ', - 'ȯ' => 'Ȯ', - 'ȱ' => 'Ȱ', - 'ȳ' => 'Ȳ', - 'ȼ' => 'Ȼ', - 'ȿ' => 'Ȿ', - 'ɀ' => 'Ɀ', - 'ɂ' => 'Ɂ', - 'ɇ' => 'Ɇ', - 'ɉ' => 'Ɉ', - 'ɋ' => 'Ɋ', - 'ɍ' => 'Ɍ', - 'ɏ' => 'Ɏ', - 'ɐ' => 'Ɐ', - 'ɑ' => 'Ɑ', - 'ɒ' => 'Ɒ', - 'ɓ' => 'Ɓ', - 'ɔ' => 'Ɔ', - 'ɖ' => 'Ɖ', - 'ɗ' => 'Ɗ', - 'ə' => 'Ə', - 'ɛ' => 'Ɛ', - 'ɜ' => 'Ɜ', - 'ɠ' => 'Ɠ', - 'ɡ' => 'Ɡ', - 'ɣ' => 'Ɣ', - 'ɥ' => 'Ɥ', - 'ɦ' => 'Ɦ', - 'ɨ' => 'Ɨ', - 'ɩ' => 'Ɩ', - 'ɪ' => 'Ɪ', - 'ɫ' => 'Ɫ', - 'ɬ' => 'Ɬ', - 'ɯ' => 'Ɯ', - 'ɱ' => 'Ɱ', - 'ɲ' => 'Ɲ', - 'ɵ' => 'Ɵ', - 'ɽ' => 'Ɽ', - 'ʀ' => 'Ʀ', - 'ʂ' => 'Ʂ', - 'ʃ' => 'Ʃ', - 'ʇ' => 'Ʇ', - 'ʈ' => 'Ʈ', - 'ʉ' => 'Ʉ', - 'ʊ' => 'Ʊ', - 'ʋ' => 'Ʋ', - 'ʌ' => 'Ʌ', - 'ʒ' => 'Ʒ', - 'ʝ' => 'Ʝ', - 'ʞ' => 'Ʞ', - 'ͅ' => 'Ι', - 'ͱ' => 'Ͱ', - 'ͳ' => 'Ͳ', - 'ͷ' => 'Ͷ', - 'ͻ' => 'Ͻ', - 'ͼ' => 'Ͼ', - 'ͽ' => 'Ͽ', - 'ά' => 'Ά', - 'έ' => 'Έ', - 'ή' => 'Ή', - 'ί' => 'Ί', - 'α' => 'Α', - 'β' => 'Β', - 'γ' => 'Γ', - 'δ' => 'Δ', - 'ε' => 'Ε', - 'ζ' => 'Ζ', - 'η' => 'Η', - 'θ' => 'Θ', - 'ι' => 'Ι', - 'κ' => 'Κ', - 'λ' => 'Λ', - 'μ' => 'Μ', - 'ν' => 'Ν', - 'ξ' => 'Ξ', - 'ο' => 'Ο', - 'π' => 'Π', - 'ρ' => 'Ρ', - 'ς' => 'Σ', - 'σ' => 'Σ', - 'τ' => 'Τ', - 'υ' => 'Υ', - 'φ' => 'Φ', - 'χ' => 'Χ', - 'ψ' => 'Ψ', - 'ω' => 'Ω', - 'ϊ' => 'Ϊ', - 'ϋ' => 'Ϋ', - 'ό' => 'Ό', - 'ύ' => 'Ύ', - 'ώ' => 'Ώ', - 'ϐ' => 'Β', - 'ϑ' => 'Θ', - 'ϕ' => 'Φ', - 'ϖ' => 'Π', - 'ϗ' => 'Ϗ', - 'ϙ' => 'Ϙ', - 'ϛ' => 'Ϛ', - 'ϝ' => 'Ϝ', - 'ϟ' => 'Ϟ', - 'ϡ' => 'Ϡ', - 'ϣ' => 'Ϣ', - 'ϥ' => 'Ϥ', - 'ϧ' => 'Ϧ', - 'ϩ' => 'Ϩ', - 'ϫ' => 'Ϫ', - 'ϭ' => 'Ϭ', - 'ϯ' => 'Ϯ', - 'ϰ' => 'Κ', - 'ϱ' => 'Ρ', - 'ϲ' => 'Ϲ', - 'ϳ' => 'Ϳ', - 'ϵ' => 'Ε', - 'ϸ' => 'Ϸ', - 'ϻ' => 'Ϻ', - 'а' => 'А', - 'б' => 'Б', - 'в' => 'В', - 'г' => 'Г', - 'д' => 'Д', - 'е' => 'Е', - 'ж' => 'Ж', - 'з' => 'З', - 'и' => 'И', - 'й' => 'Й', - 'к' => 'К', - 'л' => 'Л', - 'м' => 'М', - 'н' => 'Н', - 'о' => 'О', - 'п' => 'П', - 'р' => 'Р', - 'с' => 'С', - 'т' => 'Т', - 'у' => 'У', - 'ф' => 'Ф', - 'х' => 'Х', - 'ц' => 'Ц', - 'ч' => 'Ч', - 'ш' => 'Ш', - 'щ' => 'Щ', - 'ъ' => 'Ъ', - 'ы' => 'Ы', - 'ь' => 'Ь', - 'э' => 'Э', - 'ю' => 'Ю', - 'я' => 'Я', - 'ѐ' => 'Ѐ', - 'ё' => 'Ё', - 'ђ' => 'Ђ', - 'ѓ' => 'Ѓ', - 'є' => 'Є', - 'ѕ' => 'Ѕ', - 'і' => 'І', - 'ї' => 'Ї', - 'ј' => 'Ј', - 'љ' => 'Љ', - 'њ' => 'Њ', - 'ћ' => 'Ћ', - 'ќ' => 'Ќ', - 'ѝ' => 'Ѝ', - 'ў' => 'Ў', - 'џ' => 'Џ', - 'ѡ' => 'Ѡ', - 'ѣ' => 'Ѣ', - 'ѥ' => 'Ѥ', - 'ѧ' => 'Ѧ', - 'ѩ' => 'Ѩ', - 'ѫ' => 'Ѫ', - 'ѭ' => 'Ѭ', - 'ѯ' => 'Ѯ', - 'ѱ' => 'Ѱ', - 'ѳ' => 'Ѳ', - 'ѵ' => 'Ѵ', - 'ѷ' => 'Ѷ', - 'ѹ' => 'Ѹ', - 'ѻ' => 'Ѻ', - 'ѽ' => 'Ѽ', - 'ѿ' => 'Ѿ', - 'ҁ' => 'Ҁ', - 'ҋ' => 'Ҋ', - 'ҍ' => 'Ҍ', - 'ҏ' => 'Ҏ', - 'ґ' => 'Ґ', - 'ғ' => 'Ғ', - 'ҕ' => 'Ҕ', - 'җ' => 'Җ', - 'ҙ' => 'Ҙ', - 'қ' => 'Қ', - 'ҝ' => 'Ҝ', - 'ҟ' => 'Ҟ', - 'ҡ' => 'Ҡ', - 'ң' => 'Ң', - 'ҥ' => 'Ҥ', - 'ҧ' => 'Ҧ', - 'ҩ' => 'Ҩ', - 'ҫ' => 'Ҫ', - 'ҭ' => 'Ҭ', - 'ү' => 'Ү', - 'ұ' => 'Ұ', - 'ҳ' => 'Ҳ', - 'ҵ' => 'Ҵ', - 'ҷ' => 'Ҷ', - 'ҹ' => 'Ҹ', - 'һ' => 'Һ', - 'ҽ' => 'Ҽ', - 'ҿ' => 'Ҿ', - 'ӂ' => 'Ӂ', - 'ӄ' => 'Ӄ', - 'ӆ' => 'Ӆ', - 'ӈ' => 'Ӈ', - 'ӊ' => 'Ӊ', - 'ӌ' => 'Ӌ', - 'ӎ' => 'Ӎ', - 'ӏ' => 'Ӏ', - 'ӑ' => 'Ӑ', - 'ӓ' => 'Ӓ', - 'ӕ' => 'Ӕ', - 'ӗ' => 'Ӗ', - 'ә' => 'Ә', - 'ӛ' => 'Ӛ', - 'ӝ' => 'Ӝ', - 'ӟ' => 'Ӟ', - 'ӡ' => 'Ӡ', - 'ӣ' => 'Ӣ', - 'ӥ' => 'Ӥ', - 'ӧ' => 'Ӧ', - 'ө' => 'Ө', - 'ӫ' => 'Ӫ', - 'ӭ' => 'Ӭ', - 'ӯ' => 'Ӯ', - 'ӱ' => 'Ӱ', - 'ӳ' => 'Ӳ', - 'ӵ' => 'Ӵ', - 'ӷ' => 'Ӷ', - 'ӹ' => 'Ӹ', - 'ӻ' => 'Ӻ', - 'ӽ' => 'Ӽ', - 'ӿ' => 'Ӿ', - 'ԁ' => 'Ԁ', - 'ԃ' => 'Ԃ', - 'ԅ' => 'Ԅ', - 'ԇ' => 'Ԇ', - 'ԉ' => 'Ԉ', - 'ԋ' => 'Ԋ', - 'ԍ' => 'Ԍ', - 'ԏ' => 'Ԏ', - 'ԑ' => 'Ԑ', - 'ԓ' => 'Ԓ', - 'ԕ' => 'Ԕ', - 'ԗ' => 'Ԗ', - 'ԙ' => 'Ԙ', - 'ԛ' => 'Ԛ', - 'ԝ' => 'Ԝ', - 'ԟ' => 'Ԟ', - 'ԡ' => 'Ԡ', - 'ԣ' => 'Ԣ', - 'ԥ' => 'Ԥ', - 'ԧ' => 'Ԧ', - 'ԩ' => 'Ԩ', - 'ԫ' => 'Ԫ', - 'ԭ' => 'Ԭ', - 'ԯ' => 'Ԯ', - 'ա' => 'Ա', - 'բ' => 'Բ', - 'գ' => 'Գ', - 'դ' => 'Դ', - 'ե' => 'Ե', - 'զ' => 'Զ', - 'է' => 'Է', - 'ը' => 'Ը', - 'թ' => 'Թ', - 'ժ' => 'Ժ', - 'ի' => 'Ի', - 'լ' => 'Լ', - 'խ' => 'Խ', - 'ծ' => 'Ծ', - 'կ' => 'Կ', - 'հ' => 'Հ', - 'ձ' => 'Ձ', - 'ղ' => 'Ղ', - 'ճ' => 'Ճ', - 'մ' => 'Մ', - 'յ' => 'Յ', - 'ն' => 'Ն', - 'շ' => 'Շ', - 'ո' => 'Ո', - 'չ' => 'Չ', - 'պ' => 'Պ', - 'ջ' => 'Ջ', - 'ռ' => 'Ռ', - 'ս' => 'Ս', - 'վ' => 'Վ', - 'տ' => 'Տ', - 'ր' => 'Ր', - 'ց' => 'Ց', - 'ւ' => 'Ւ', - 'փ' => 'Փ', - 'ք' => 'Ք', - 'օ' => 'Օ', - 'ֆ' => 'Ֆ', - 'ა' => 'Ა', - 'ბ' => 'Ბ', - 'გ' => 'Გ', - 'დ' => 'Დ', - 'ე' => 'Ე', - 'ვ' => 'Ვ', - 'ზ' => 'Ზ', - 'თ' => 'Თ', - 'ი' => 'Ი', - 'კ' => 'Კ', - 'ლ' => 'Ლ', - 'მ' => 'Მ', - 'ნ' => 'Ნ', - 'ო' => 'Ო', - 'პ' => 'Პ', - 'ჟ' => 'Ჟ', - 'რ' => 'Რ', - 'ს' => 'Ს', - 'ტ' => 'Ტ', - 'უ' => 'Უ', - 'ფ' => 'Ფ', - 'ქ' => 'Ქ', - 'ღ' => 'Ღ', - 'ყ' => 'Ყ', - 'შ' => 'Შ', - 'ჩ' => 'Ჩ', - 'ც' => 'Ც', - 'ძ' => 'Ძ', - 'წ' => 'Წ', - 'ჭ' => 'Ჭ', - 'ხ' => 'Ხ', - 'ჯ' => 'Ჯ', - 'ჰ' => 'Ჰ', - 'ჱ' => 'Ჱ', - 'ჲ' => 'Ჲ', - 'ჳ' => 'Ჳ', - 'ჴ' => 'Ჴ', - 'ჵ' => 'Ჵ', - 'ჶ' => 'Ჶ', - 'ჷ' => 'Ჷ', - 'ჸ' => 'Ჸ', - 'ჹ' => 'Ჹ', - 'ჺ' => 'Ჺ', - 'ჽ' => 'Ჽ', - 'ჾ' => 'Ჾ', - 'ჿ' => 'Ჿ', - 'ᏸ' => 'Ᏸ', - 'ᏹ' => 'Ᏹ', - 'ᏺ' => 'Ᏺ', - 'ᏻ' => 'Ᏻ', - 'ᏼ' => 'Ᏼ', - 'ᏽ' => 'Ᏽ', - 'ᲀ' => 'В', - 'ᲁ' => 'Д', - 'ᲂ' => 'О', - 'ᲃ' => 'С', - 'ᲄ' => 'Т', - 'ᲅ' => 'Т', - 'ᲆ' => 'Ъ', - 'ᲇ' => 'Ѣ', - 'ᲈ' => 'Ꙋ', - 'ᵹ' => 'Ᵹ', - 'ᵽ' => 'Ᵽ', - 'ᶎ' => 'Ᶎ', - 'ḁ' => 'Ḁ', - 'ḃ' => 'Ḃ', - 'ḅ' => 'Ḅ', - 'ḇ' => 'Ḇ', - 'ḉ' => 'Ḉ', - 'ḋ' => 'Ḋ', - 'ḍ' => 'Ḍ', - 'ḏ' => 'Ḏ', - 'ḑ' => 'Ḑ', - 'ḓ' => 'Ḓ', - 'ḕ' => 'Ḕ', - 'ḗ' => 'Ḗ', - 'ḙ' => 'Ḙ', - 'ḛ' => 'Ḛ', - 'ḝ' => 'Ḝ', - 'ḟ' => 'Ḟ', - 'ḡ' => 'Ḡ', - 'ḣ' => 'Ḣ', - 'ḥ' => 'Ḥ', - 'ḧ' => 'Ḧ', - 'ḩ' => 'Ḩ', - 'ḫ' => 'Ḫ', - 'ḭ' => 'Ḭ', - 'ḯ' => 'Ḯ', - 'ḱ' => 'Ḱ', - 'ḳ' => 'Ḳ', - 'ḵ' => 'Ḵ', - 'ḷ' => 'Ḷ', - 'ḹ' => 'Ḹ', - 'ḻ' => 'Ḻ', - 'ḽ' => 'Ḽ', - 'ḿ' => 'Ḿ', - 'ṁ' => 'Ṁ', - 'ṃ' => 'Ṃ', - 'ṅ' => 'Ṅ', - 'ṇ' => 'Ṇ', - 'ṉ' => 'Ṉ', - 'ṋ' => 'Ṋ', - 'ṍ' => 'Ṍ', - 'ṏ' => 'Ṏ', - 'ṑ' => 'Ṑ', - 'ṓ' => 'Ṓ', - 'ṕ' => 'Ṕ', - 'ṗ' => 'Ṗ', - 'ṙ' => 'Ṙ', - 'ṛ' => 'Ṛ', - 'ṝ' => 'Ṝ', - 'ṟ' => 'Ṟ', - 'ṡ' => 'Ṡ', - 'ṣ' => 'Ṣ', - 'ṥ' => 'Ṥ', - 'ṧ' => 'Ṧ', - 'ṩ' => 'Ṩ', - 'ṫ' => 'Ṫ', - 'ṭ' => 'Ṭ', - 'ṯ' => 'Ṯ', - 'ṱ' => 'Ṱ', - 'ṳ' => 'Ṳ', - 'ṵ' => 'Ṵ', - 'ṷ' => 'Ṷ', - 'ṹ' => 'Ṹ', - 'ṻ' => 'Ṻ', - 'ṽ' => 'Ṽ', - 'ṿ' => 'Ṿ', - 'ẁ' => 'Ẁ', - 'ẃ' => 'Ẃ', - 'ẅ' => 'Ẅ', - 'ẇ' => 'Ẇ', - 'ẉ' => 'Ẉ', - 'ẋ' => 'Ẋ', - 'ẍ' => 'Ẍ', - 'ẏ' => 'Ẏ', - 'ẑ' => 'Ẑ', - 'ẓ' => 'Ẓ', - 'ẕ' => 'Ẕ', - 'ẛ' => 'Ṡ', - 'ạ' => 'Ạ', - 'ả' => 'Ả', - 'ấ' => 'Ấ', - 'ầ' => 'Ầ', - 'ẩ' => 'Ẩ', - 'ẫ' => 'Ẫ', - 'ậ' => 'Ậ', - 'ắ' => 'Ắ', - 'ằ' => 'Ằ', - 'ẳ' => 'Ẳ', - 'ẵ' => 'Ẵ', - 'ặ' => 'Ặ', - 'ẹ' => 'Ẹ', - 'ẻ' => 'Ẻ', - 'ẽ' => 'Ẽ', - 'ế' => 'Ế', - 'ề' => 'Ề', - 'ể' => 'Ể', - 'ễ' => 'Ễ', - 'ệ' => 'Ệ', - 'ỉ' => 'Ỉ', - 'ị' => 'Ị', - 'ọ' => 'Ọ', - 'ỏ' => 'Ỏ', - 'ố' => 'Ố', - 'ồ' => 'Ồ', - 'ổ' => 'Ổ', - 'ỗ' => 'Ỗ', - 'ộ' => 'Ộ', - 'ớ' => 'Ớ', - 'ờ' => 'Ờ', - 'ở' => 'Ở', - 'ỡ' => 'Ỡ', - 'ợ' => 'Ợ', - 'ụ' => 'Ụ', - 'ủ' => 'Ủ', - 'ứ' => 'Ứ', - 'ừ' => 'Ừ', - 'ử' => 'Ử', - 'ữ' => 'Ữ', - 'ự' => 'Ự', - 'ỳ' => 'Ỳ', - 'ỵ' => 'Ỵ', - 'ỷ' => 'Ỷ', - 'ỹ' => 'Ỹ', - 'ỻ' => 'Ỻ', - 'ỽ' => 'Ỽ', - 'ỿ' => 'Ỿ', - 'ἀ' => 'Ἀ', - 'ἁ' => 'Ἁ', - 'ἂ' => 'Ἂ', - 'ἃ' => 'Ἃ', - 'ἄ' => 'Ἄ', - 'ἅ' => 'Ἅ', - 'ἆ' => 'Ἆ', - 'ἇ' => 'Ἇ', - 'ἐ' => 'Ἐ', - 'ἑ' => 'Ἑ', - 'ἒ' => 'Ἒ', - 'ἓ' => 'Ἓ', - 'ἔ' => 'Ἔ', - 'ἕ' => 'Ἕ', - 'ἠ' => 'Ἠ', - 'ἡ' => 'Ἡ', - 'ἢ' => 'Ἢ', - 'ἣ' => 'Ἣ', - 'ἤ' => 'Ἤ', - 'ἥ' => 'Ἥ', - 'ἦ' => 'Ἦ', - 'ἧ' => 'Ἧ', - 'ἰ' => 'Ἰ', - 'ἱ' => 'Ἱ', - 'ἲ' => 'Ἲ', - 'ἳ' => 'Ἳ', - 'ἴ' => 'Ἴ', - 'ἵ' => 'Ἵ', - 'ἶ' => 'Ἶ', - 'ἷ' => 'Ἷ', - 'ὀ' => 'Ὀ', - 'ὁ' => 'Ὁ', - 'ὂ' => 'Ὂ', - 'ὃ' => 'Ὃ', - 'ὄ' => 'Ὄ', - 'ὅ' => 'Ὅ', - 'ὑ' => 'Ὑ', - 'ὓ' => 'Ὓ', - 'ὕ' => 'Ὕ', - 'ὗ' => 'Ὗ', - 'ὠ' => 'Ὠ', - 'ὡ' => 'Ὡ', - 'ὢ' => 'Ὢ', - 'ὣ' => 'Ὣ', - 'ὤ' => 'Ὤ', - 'ὥ' => 'Ὥ', - 'ὦ' => 'Ὦ', - 'ὧ' => 'Ὧ', - 'ὰ' => 'Ὰ', - 'ά' => 'Ά', - 'ὲ' => 'Ὲ', - 'έ' => 'Έ', - 'ὴ' => 'Ὴ', - 'ή' => 'Ή', - 'ὶ' => 'Ὶ', - 'ί' => 'Ί', - 'ὸ' => 'Ὸ', - 'ό' => 'Ό', - 'ὺ' => 'Ὺ', - 'ύ' => 'Ύ', - 'ὼ' => 'Ὼ', - 'ώ' => 'Ώ', - 'ᾀ' => 'ἈΙ', - 'ᾁ' => 'ἉΙ', - 'ᾂ' => 'ἊΙ', - 'ᾃ' => 'ἋΙ', - 'ᾄ' => 'ἌΙ', - 'ᾅ' => 'ἍΙ', - 'ᾆ' => 'ἎΙ', - 'ᾇ' => 'ἏΙ', - 'ᾐ' => 'ἨΙ', - 'ᾑ' => 'ἩΙ', - 'ᾒ' => 'ἪΙ', - 'ᾓ' => 'ἫΙ', - 'ᾔ' => 'ἬΙ', - 'ᾕ' => 'ἭΙ', - 'ᾖ' => 'ἮΙ', - 'ᾗ' => 'ἯΙ', - 'ᾠ' => 'ὨΙ', - 'ᾡ' => 'ὩΙ', - 'ᾢ' => 'ὪΙ', - 'ᾣ' => 'ὫΙ', - 'ᾤ' => 'ὬΙ', - 'ᾥ' => 'ὭΙ', - 'ᾦ' => 'ὮΙ', - 'ᾧ' => 'ὯΙ', - 'ᾰ' => 'Ᾰ', - 'ᾱ' => 'Ᾱ', - 'ᾳ' => 'ΑΙ', - 'ι' => 'Ι', - 'ῃ' => 'ΗΙ', - 'ῐ' => 'Ῐ', - 'ῑ' => 'Ῑ', - 'ῠ' => 'Ῠ', - 'ῡ' => 'Ῡ', - 'ῥ' => 'Ῥ', - 'ῳ' => 'ΩΙ', - 'ⅎ' => 'Ⅎ', - 'ⅰ' => 'Ⅰ', - 'ⅱ' => 'Ⅱ', - 'ⅲ' => 'Ⅲ', - 'ⅳ' => 'Ⅳ', - 'ⅴ' => 'Ⅴ', - 'ⅵ' => 'Ⅵ', - 'ⅶ' => 'Ⅶ', - 'ⅷ' => 'Ⅷ', - 'ⅸ' => 'Ⅸ', - 'ⅹ' => 'Ⅹ', - 'ⅺ' => 'Ⅺ', - 'ⅻ' => 'Ⅻ', - 'ⅼ' => 'Ⅼ', - 'ⅽ' => 'Ⅽ', - 'ⅾ' => 'Ⅾ', - 'ⅿ' => 'Ⅿ', - 'ↄ' => 'Ↄ', - 'ⓐ' => 'Ⓐ', - 'ⓑ' => 'Ⓑ', - 'ⓒ' => 'Ⓒ', - 'ⓓ' => 'Ⓓ', - 'ⓔ' => 'Ⓔ', - 'ⓕ' => 'Ⓕ', - 'ⓖ' => 'Ⓖ', - 'ⓗ' => 'Ⓗ', - 'ⓘ' => 'Ⓘ', - 'ⓙ' => 'Ⓙ', - 'ⓚ' => 'Ⓚ', - 'ⓛ' => 'Ⓛ', - 'ⓜ' => 'Ⓜ', - 'ⓝ' => 'Ⓝ', - 'ⓞ' => 'Ⓞ', - 'ⓟ' => 'Ⓟ', - 'ⓠ' => 'Ⓠ', - 'ⓡ' => 'Ⓡ', - 'ⓢ' => 'Ⓢ', - 'ⓣ' => 'Ⓣ', - 'ⓤ' => 'Ⓤ', - 'ⓥ' => 'Ⓥ', - 'ⓦ' => 'Ⓦ', - 'ⓧ' => 'Ⓧ', - 'ⓨ' => 'Ⓨ', - 'ⓩ' => 'Ⓩ', - 'ⰰ' => 'Ⰰ', - 'ⰱ' => 'Ⰱ', - 'ⰲ' => 'Ⰲ', - 'ⰳ' => 'Ⰳ', - 'ⰴ' => 'Ⰴ', - 'ⰵ' => 'Ⰵ', - 'ⰶ' => 'Ⰶ', - 'ⰷ' => 'Ⰷ', - 'ⰸ' => 'Ⰸ', - 'ⰹ' => 'Ⰹ', - 'ⰺ' => 'Ⰺ', - 'ⰻ' => 'Ⰻ', - 'ⰼ' => 'Ⰼ', - 'ⰽ' => 'Ⰽ', - 'ⰾ' => 'Ⰾ', - 'ⰿ' => 'Ⰿ', - 'ⱀ' => 'Ⱀ', - 'ⱁ' => 'Ⱁ', - 'ⱂ' => 'Ⱂ', - 'ⱃ' => 'Ⱃ', - 'ⱄ' => 'Ⱄ', - 'ⱅ' => 'Ⱅ', - 'ⱆ' => 'Ⱆ', - 'ⱇ' => 'Ⱇ', - 'ⱈ' => 'Ⱈ', - 'ⱉ' => 'Ⱉ', - 'ⱊ' => 'Ⱊ', - 'ⱋ' => 'Ⱋ', - 'ⱌ' => 'Ⱌ', - 'ⱍ' => 'Ⱍ', - 'ⱎ' => 'Ⱎ', - 'ⱏ' => 'Ⱏ', - 'ⱐ' => 'Ⱐ', - 'ⱑ' => 'Ⱑ', - 'ⱒ' => 'Ⱒ', - 'ⱓ' => 'Ⱓ', - 'ⱔ' => 'Ⱔ', - 'ⱕ' => 'Ⱕ', - 'ⱖ' => 'Ⱖ', - 'ⱗ' => 'Ⱗ', - 'ⱘ' => 'Ⱘ', - 'ⱙ' => 'Ⱙ', - 'ⱚ' => 'Ⱚ', - 'ⱛ' => 'Ⱛ', - 'ⱜ' => 'Ⱜ', - 'ⱝ' => 'Ⱝ', - 'ⱞ' => 'Ⱞ', - 'ⱡ' => 'Ⱡ', - 'ⱥ' => 'Ⱥ', - 'ⱦ' => 'Ⱦ', - 'ⱨ' => 'Ⱨ', - 'ⱪ' => 'Ⱪ', - 'ⱬ' => 'Ⱬ', - 'ⱳ' => 'Ⱳ', - 'ⱶ' => 'Ⱶ', - 'ⲁ' => 'Ⲁ', - 'ⲃ' => 'Ⲃ', - 'ⲅ' => 'Ⲅ', - 'ⲇ' => 'Ⲇ', - 'ⲉ' => 'Ⲉ', - 'ⲋ' => 'Ⲋ', - 'ⲍ' => 'Ⲍ', - 'ⲏ' => 'Ⲏ', - 'ⲑ' => 'Ⲑ', - 'ⲓ' => 'Ⲓ', - 'ⲕ' => 'Ⲕ', - 'ⲗ' => 'Ⲗ', - 'ⲙ' => 'Ⲙ', - 'ⲛ' => 'Ⲛ', - 'ⲝ' => 'Ⲝ', - 'ⲟ' => 'Ⲟ', - 'ⲡ' => 'Ⲡ', - 'ⲣ' => 'Ⲣ', - 'ⲥ' => 'Ⲥ', - 'ⲧ' => 'Ⲧ', - 'ⲩ' => 'Ⲩ', - 'ⲫ' => 'Ⲫ', - 'ⲭ' => 'Ⲭ', - 'ⲯ' => 'Ⲯ', - 'ⲱ' => 'Ⲱ', - 'ⲳ' => 'Ⲳ', - 'ⲵ' => 'Ⲵ', - 'ⲷ' => 'Ⲷ', - 'ⲹ' => 'Ⲹ', - 'ⲻ' => 'Ⲻ', - 'ⲽ' => 'Ⲽ', - 'ⲿ' => 'Ⲿ', - 'ⳁ' => 'Ⳁ', - 'ⳃ' => 'Ⳃ', - 'ⳅ' => 'Ⳅ', - 'ⳇ' => 'Ⳇ', - 'ⳉ' => 'Ⳉ', - 'ⳋ' => 'Ⳋ', - 'ⳍ' => 'Ⳍ', - 'ⳏ' => 'Ⳏ', - 'ⳑ' => 'Ⳑ', - 'ⳓ' => 'Ⳓ', - 'ⳕ' => 'Ⳕ', - 'ⳗ' => 'Ⳗ', - 'ⳙ' => 'Ⳙ', - 'ⳛ' => 'Ⳛ', - 'ⳝ' => 'Ⳝ', - 'ⳟ' => 'Ⳟ', - 'ⳡ' => 'Ⳡ', - 'ⳣ' => 'Ⳣ', - 'ⳬ' => 'Ⳬ', - 'ⳮ' => 'Ⳮ', - 'ⳳ' => 'Ⳳ', - 'ⴀ' => 'Ⴀ', - 'ⴁ' => 'Ⴁ', - 'ⴂ' => 'Ⴂ', - 'ⴃ' => 'Ⴃ', - 'ⴄ' => 'Ⴄ', - 'ⴅ' => 'Ⴅ', - 'ⴆ' => 'Ⴆ', - 'ⴇ' => 'Ⴇ', - 'ⴈ' => 'Ⴈ', - 'ⴉ' => 'Ⴉ', - 'ⴊ' => 'Ⴊ', - 'ⴋ' => 'Ⴋ', - 'ⴌ' => 'Ⴌ', - 'ⴍ' => 'Ⴍ', - 'ⴎ' => 'Ⴎ', - 'ⴏ' => 'Ⴏ', - 'ⴐ' => 'Ⴐ', - 'ⴑ' => 'Ⴑ', - 'ⴒ' => 'Ⴒ', - 'ⴓ' => 'Ⴓ', - 'ⴔ' => 'Ⴔ', - 'ⴕ' => 'Ⴕ', - 'ⴖ' => 'Ⴖ', - 'ⴗ' => 'Ⴗ', - 'ⴘ' => 'Ⴘ', - 'ⴙ' => 'Ⴙ', - 'ⴚ' => 'Ⴚ', - 'ⴛ' => 'Ⴛ', - 'ⴜ' => 'Ⴜ', - 'ⴝ' => 'Ⴝ', - 'ⴞ' => 'Ⴞ', - 'ⴟ' => 'Ⴟ', - 'ⴠ' => 'Ⴠ', - 'ⴡ' => 'Ⴡ', - 'ⴢ' => 'Ⴢ', - 'ⴣ' => 'Ⴣ', - 'ⴤ' => 'Ⴤ', - 'ⴥ' => 'Ⴥ', - 'ⴧ' => 'Ⴧ', - 'ⴭ' => 'Ⴭ', - 'ꙁ' => 'Ꙁ', - 'ꙃ' => 'Ꙃ', - 'ꙅ' => 'Ꙅ', - 'ꙇ' => 'Ꙇ', - 'ꙉ' => 'Ꙉ', - 'ꙋ' => 'Ꙋ', - 'ꙍ' => 'Ꙍ', - 'ꙏ' => 'Ꙏ', - 'ꙑ' => 'Ꙑ', - 'ꙓ' => 'Ꙓ', - 'ꙕ' => 'Ꙕ', - 'ꙗ' => 'Ꙗ', - 'ꙙ' => 'Ꙙ', - 'ꙛ' => 'Ꙛ', - 'ꙝ' => 'Ꙝ', - 'ꙟ' => 'Ꙟ', - 'ꙡ' => 'Ꙡ', - 'ꙣ' => 'Ꙣ', - 'ꙥ' => 'Ꙥ', - 'ꙧ' => 'Ꙧ', - 'ꙩ' => 'Ꙩ', - 'ꙫ' => 'Ꙫ', - 'ꙭ' => 'Ꙭ', - 'ꚁ' => 'Ꚁ', - 'ꚃ' => 'Ꚃ', - 'ꚅ' => 'Ꚅ', - 'ꚇ' => 'Ꚇ', - 'ꚉ' => 'Ꚉ', - 'ꚋ' => 'Ꚋ', - 'ꚍ' => 'Ꚍ', - 'ꚏ' => 'Ꚏ', - 'ꚑ' => 'Ꚑ', - 'ꚓ' => 'Ꚓ', - 'ꚕ' => 'Ꚕ', - 'ꚗ' => 'Ꚗ', - 'ꚙ' => 'Ꚙ', - 'ꚛ' => 'Ꚛ', - 'ꜣ' => 'Ꜣ', - 'ꜥ' => 'Ꜥ', - 'ꜧ' => 'Ꜧ', - 'ꜩ' => 'Ꜩ', - 'ꜫ' => 'Ꜫ', - 'ꜭ' => 'Ꜭ', - 'ꜯ' => 'Ꜯ', - 'ꜳ' => 'Ꜳ', - 'ꜵ' => 'Ꜵ', - 'ꜷ' => 'Ꜷ', - 'ꜹ' => 'Ꜹ', - 'ꜻ' => 'Ꜻ', - 'ꜽ' => 'Ꜽ', - 'ꜿ' => 'Ꜿ', - 'ꝁ' => 'Ꝁ', - 'ꝃ' => 'Ꝃ', - 'ꝅ' => 'Ꝅ', - 'ꝇ' => 'Ꝇ', - 'ꝉ' => 'Ꝉ', - 'ꝋ' => 'Ꝋ', - 'ꝍ' => 'Ꝍ', - 'ꝏ' => 'Ꝏ', - 'ꝑ' => 'Ꝑ', - 'ꝓ' => 'Ꝓ', - 'ꝕ' => 'Ꝕ', - 'ꝗ' => 'Ꝗ', - 'ꝙ' => 'Ꝙ', - 'ꝛ' => 'Ꝛ', - 'ꝝ' => 'Ꝝ', - 'ꝟ' => 'Ꝟ', - 'ꝡ' => 'Ꝡ', - 'ꝣ' => 'Ꝣ', - 'ꝥ' => 'Ꝥ', - 'ꝧ' => 'Ꝧ', - 'ꝩ' => 'Ꝩ', - 'ꝫ' => 'Ꝫ', - 'ꝭ' => 'Ꝭ', - 'ꝯ' => 'Ꝯ', - 'ꝺ' => 'Ꝺ', - 'ꝼ' => 'Ꝼ', - 'ꝿ' => 'Ꝿ', - 'ꞁ' => 'Ꞁ', - 'ꞃ' => 'Ꞃ', - 'ꞅ' => 'Ꞅ', - 'ꞇ' => 'Ꞇ', - 'ꞌ' => 'Ꞌ', - 'ꞑ' => 'Ꞑ', - 'ꞓ' => 'Ꞓ', - 'ꞔ' => 'Ꞔ', - 'ꞗ' => 'Ꞗ', - 'ꞙ' => 'Ꞙ', - 'ꞛ' => 'Ꞛ', - 'ꞝ' => 'Ꞝ', - 'ꞟ' => 'Ꞟ', - 'ꞡ' => 'Ꞡ', - 'ꞣ' => 'Ꞣ', - 'ꞥ' => 'Ꞥ', - 'ꞧ' => 'Ꞧ', - 'ꞩ' => 'Ꞩ', - 'ꞵ' => 'Ꞵ', - 'ꞷ' => 'Ꞷ', - 'ꞹ' => 'Ꞹ', - 'ꞻ' => 'Ꞻ', - 'ꞽ' => 'Ꞽ', - 'ꞿ' => 'Ꞿ', - 'ꟃ' => 'Ꟃ', - 'ꟈ' => 'Ꟈ', - 'ꟊ' => 'Ꟊ', - 'ꟶ' => 'Ꟶ', - 'ꭓ' => 'Ꭓ', - 'ꭰ' => 'Ꭰ', - 'ꭱ' => 'Ꭱ', - 'ꭲ' => 'Ꭲ', - 'ꭳ' => 'Ꭳ', - 'ꭴ' => 'Ꭴ', - 'ꭵ' => 'Ꭵ', - 'ꭶ' => 'Ꭶ', - 'ꭷ' => 'Ꭷ', - 'ꭸ' => 'Ꭸ', - 'ꭹ' => 'Ꭹ', - 'ꭺ' => 'Ꭺ', - 'ꭻ' => 'Ꭻ', - 'ꭼ' => 'Ꭼ', - 'ꭽ' => 'Ꭽ', - 'ꭾ' => 'Ꭾ', - 'ꭿ' => 'Ꭿ', - 'ꮀ' => 'Ꮀ', - 'ꮁ' => 'Ꮁ', - 'ꮂ' => 'Ꮂ', - 'ꮃ' => 'Ꮃ', - 'ꮄ' => 'Ꮄ', - 'ꮅ' => 'Ꮅ', - 'ꮆ' => 'Ꮆ', - 'ꮇ' => 'Ꮇ', - 'ꮈ' => 'Ꮈ', - 'ꮉ' => 'Ꮉ', - 'ꮊ' => 'Ꮊ', - 'ꮋ' => 'Ꮋ', - 'ꮌ' => 'Ꮌ', - 'ꮍ' => 'Ꮍ', - 'ꮎ' => 'Ꮎ', - 'ꮏ' => 'Ꮏ', - 'ꮐ' => 'Ꮐ', - 'ꮑ' => 'Ꮑ', - 'ꮒ' => 'Ꮒ', - 'ꮓ' => 'Ꮓ', - 'ꮔ' => 'Ꮔ', - 'ꮕ' => 'Ꮕ', - 'ꮖ' => 'Ꮖ', - 'ꮗ' => 'Ꮗ', - 'ꮘ' => 'Ꮘ', - 'ꮙ' => 'Ꮙ', - 'ꮚ' => 'Ꮚ', - 'ꮛ' => 'Ꮛ', - 'ꮜ' => 'Ꮜ', - 'ꮝ' => 'Ꮝ', - 'ꮞ' => 'Ꮞ', - 'ꮟ' => 'Ꮟ', - 'ꮠ' => 'Ꮠ', - 'ꮡ' => 'Ꮡ', - 'ꮢ' => 'Ꮢ', - 'ꮣ' => 'Ꮣ', - 'ꮤ' => 'Ꮤ', - 'ꮥ' => 'Ꮥ', - 'ꮦ' => 'Ꮦ', - 'ꮧ' => 'Ꮧ', - 'ꮨ' => 'Ꮨ', - 'ꮩ' => 'Ꮩ', - 'ꮪ' => 'Ꮪ', - 'ꮫ' => 'Ꮫ', - 'ꮬ' => 'Ꮬ', - 'ꮭ' => 'Ꮭ', - 'ꮮ' => 'Ꮮ', - 'ꮯ' => 'Ꮯ', - 'ꮰ' => 'Ꮰ', - 'ꮱ' => 'Ꮱ', - 'ꮲ' => 'Ꮲ', - 'ꮳ' => 'Ꮳ', - 'ꮴ' => 'Ꮴ', - 'ꮵ' => 'Ꮵ', - 'ꮶ' => 'Ꮶ', - 'ꮷ' => 'Ꮷ', - 'ꮸ' => 'Ꮸ', - 'ꮹ' => 'Ꮹ', - 'ꮺ' => 'Ꮺ', - 'ꮻ' => 'Ꮻ', - 'ꮼ' => 'Ꮼ', - 'ꮽ' => 'Ꮽ', - 'ꮾ' => 'Ꮾ', - 'ꮿ' => 'Ꮿ', - 'a' => 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - '𐐨' => '𐐀', - '𐐩' => '𐐁', - '𐐪' => '𐐂', - '𐐫' => '𐐃', - '𐐬' => '𐐄', - '𐐭' => '𐐅', - '𐐮' => '𐐆', - '𐐯' => '𐐇', - '𐐰' => '𐐈', - '𐐱' => '𐐉', - '𐐲' => '𐐊', - '𐐳' => '𐐋', - '𐐴' => '𐐌', - '𐐵' => '𐐍', - '𐐶' => '𐐎', - '𐐷' => '𐐏', - '𐐸' => '𐐐', - '𐐹' => '𐐑', - '𐐺' => '𐐒', - '𐐻' => '𐐓', - '𐐼' => '𐐔', - '𐐽' => '𐐕', - '𐐾' => '𐐖', - '𐐿' => '𐐗', - '𐑀' => '𐐘', - '𐑁' => '𐐙', - '𐑂' => '𐐚', - '𐑃' => '𐐛', - '𐑄' => '𐐜', - '𐑅' => '𐐝', - '𐑆' => '𐐞', - '𐑇' => '𐐟', - '𐑈' => '𐐠', - '𐑉' => '𐐡', - '𐑊' => '𐐢', - '𐑋' => '𐐣', - '𐑌' => '𐐤', - '𐑍' => '𐐥', - '𐑎' => '𐐦', - '𐑏' => '𐐧', - '𐓘' => '𐒰', - '𐓙' => '𐒱', - '𐓚' => '𐒲', - '𐓛' => '𐒳', - '𐓜' => '𐒴', - '𐓝' => '𐒵', - '𐓞' => '𐒶', - '𐓟' => '𐒷', - '𐓠' => '𐒸', - '𐓡' => '𐒹', - '𐓢' => '𐒺', - '𐓣' => '𐒻', - '𐓤' => '𐒼', - '𐓥' => '𐒽', - '𐓦' => '𐒾', - '𐓧' => '𐒿', - '𐓨' => '𐓀', - '𐓩' => '𐓁', - '𐓪' => '𐓂', - '𐓫' => '𐓃', - '𐓬' => '𐓄', - '𐓭' => '𐓅', - '𐓮' => '𐓆', - '𐓯' => '𐓇', - '𐓰' => '𐓈', - '𐓱' => '𐓉', - '𐓲' => '𐓊', - '𐓳' => '𐓋', - '𐓴' => '𐓌', - '𐓵' => '𐓍', - '𐓶' => '𐓎', - '𐓷' => '𐓏', - '𐓸' => '𐓐', - '𐓹' => '𐓑', - '𐓺' => '𐓒', - '𐓻' => '𐓓', - '𐳀' => '𐲀', - '𐳁' => '𐲁', - '𐳂' => '𐲂', - '𐳃' => '𐲃', - '𐳄' => '𐲄', - '𐳅' => '𐲅', - '𐳆' => '𐲆', - '𐳇' => '𐲇', - '𐳈' => '𐲈', - '𐳉' => '𐲉', - '𐳊' => '𐲊', - '𐳋' => '𐲋', - '𐳌' => '𐲌', - '𐳍' => '𐲍', - '𐳎' => '𐲎', - '𐳏' => '𐲏', - '𐳐' => '𐲐', - '𐳑' => '𐲑', - '𐳒' => '𐲒', - '𐳓' => '𐲓', - '𐳔' => '𐲔', - '𐳕' => '𐲕', - '𐳖' => '𐲖', - '𐳗' => '𐲗', - '𐳘' => '𐲘', - '𐳙' => '𐲙', - '𐳚' => '𐲚', - '𐳛' => '𐲛', - '𐳜' => '𐲜', - '𐳝' => '𐲝', - '𐳞' => '𐲞', - '𐳟' => '𐲟', - '𐳠' => '𐲠', - '𐳡' => '𐲡', - '𐳢' => '𐲢', - '𐳣' => '𐲣', - '𐳤' => '𐲤', - '𐳥' => '𐲥', - '𐳦' => '𐲦', - '𐳧' => '𐲧', - '𐳨' => '𐲨', - '𐳩' => '𐲩', - '𐳪' => '𐲪', - '𐳫' => '𐲫', - '𐳬' => '𐲬', - '𐳭' => '𐲭', - '𐳮' => '𐲮', - '𐳯' => '𐲯', - '𐳰' => '𐲰', - '𐳱' => '𐲱', - '𐳲' => '𐲲', - '𑣀' => '𑢠', - '𑣁' => '𑢡', - '𑣂' => '𑢢', - '𑣃' => '𑢣', - '𑣄' => '𑢤', - '𑣅' => '𑢥', - '𑣆' => '𑢦', - '𑣇' => '𑢧', - '𑣈' => '𑢨', - '𑣉' => '𑢩', - '𑣊' => '𑢪', - '𑣋' => '𑢫', - '𑣌' => '𑢬', - '𑣍' => '𑢭', - '𑣎' => '𑢮', - '𑣏' => '𑢯', - '𑣐' => '𑢰', - '𑣑' => '𑢱', - '𑣒' => '𑢲', - '𑣓' => '𑢳', - '𑣔' => '𑢴', - '𑣕' => '𑢵', - '𑣖' => '𑢶', - '𑣗' => '𑢷', - '𑣘' => '𑢸', - '𑣙' => '𑢹', - '𑣚' => '𑢺', - '𑣛' => '𑢻', - '𑣜' => '𑢼', - '𑣝' => '𑢽', - '𑣞' => '𑢾', - '𑣟' => '𑢿', - '𖹠' => '𖹀', - '𖹡' => '𖹁', - '𖹢' => '𖹂', - '𖹣' => '𖹃', - '𖹤' => '𖹄', - '𖹥' => '𖹅', - '𖹦' => '𖹆', - '𖹧' => '𖹇', - '𖹨' => '𖹈', - '𖹩' => '𖹉', - '𖹪' => '𖹊', - '𖹫' => '𖹋', - '𖹬' => '𖹌', - '𖹭' => '𖹍', - '𖹮' => '𖹎', - '𖹯' => '𖹏', - '𖹰' => '𖹐', - '𖹱' => '𖹑', - '𖹲' => '𖹒', - '𖹳' => '𖹓', - '𖹴' => '𖹔', - '𖹵' => '𖹕', - '𖹶' => '𖹖', - '𖹷' => '𖹗', - '𖹸' => '𖹘', - '𖹹' => '𖹙', - '𖹺' => '𖹚', - '𖹻' => '𖹛', - '𖹼' => '𖹜', - '𖹽' => '𖹝', - '𖹾' => '𖹞', - '𖹿' => '𖹟', - '𞤢' => '𞤀', - '𞤣' => '𞤁', - '𞤤' => '𞤂', - '𞤥' => '𞤃', - '𞤦' => '𞤄', - '𞤧' => '𞤅', - '𞤨' => '𞤆', - '𞤩' => '𞤇', - '𞤪' => '𞤈', - '𞤫' => '𞤉', - '𞤬' => '𞤊', - '𞤭' => '𞤋', - '𞤮' => '𞤌', - '𞤯' => '𞤍', - '𞤰' => '𞤎', - '𞤱' => '𞤏', - '𞤲' => '𞤐', - '𞤳' => '𞤑', - '𞤴' => '𞤒', - '𞤵' => '𞤓', - '𞤶' => '𞤔', - '𞤷' => '𞤕', - '𞤸' => '𞤖', - '𞤹' => '𞤗', - '𞤺' => '𞤘', - '𞤻' => '𞤙', - '𞤼' => '𞤚', - '𞤽' => '𞤛', - '𞤾' => '𞤜', - '𞤿' => '𞤝', - '𞥀' => '𞤞', - '𞥁' => '𞤟', - '𞥂' => '𞤠', - '𞥃' => '𞤡', - 'ß' => 'SS', - 'ff' => 'FF', - 'fi' => 'FI', - 'fl' => 'FL', - 'ffi' => 'FFI', - 'ffl' => 'FFL', - 'ſt' => 'ST', - 'st' => 'ST', - 'և' => 'ԵՒ', - 'ﬓ' => 'ՄՆ', - 'ﬔ' => 'ՄԵ', - 'ﬕ' => 'ՄԻ', - 'ﬖ' => 'ՎՆ', - 'ﬗ' => 'ՄԽ', - 'ʼn' => 'ʼN', - 'ΐ' => 'Ϊ́', - 'ΰ' => 'Ϋ́', - 'ǰ' => 'J̌', - 'ẖ' => 'H̱', - 'ẗ' => 'T̈', - 'ẘ' => 'W̊', - 'ẙ' => 'Y̊', - 'ẚ' => 'Aʾ', - 'ὐ' => 'Υ̓', - 'ὒ' => 'Υ̓̀', - 'ὔ' => 'Υ̓́', - 'ὖ' => 'Υ̓͂', - 'ᾶ' => 'Α͂', - 'ῆ' => 'Η͂', - 'ῒ' => 'Ϊ̀', - 'ΐ' => 'Ϊ́', - 'ῖ' => 'Ι͂', - 'ῗ' => 'Ϊ͂', - 'ῢ' => 'Ϋ̀', - 'ΰ' => 'Ϋ́', - 'ῤ' => 'Ρ̓', - 'ῦ' => 'Υ͂', - 'ῧ' => 'Ϋ͂', - 'ῶ' => 'Ω͂', - 'ᾈ' => 'ἈΙ', - 'ᾉ' => 'ἉΙ', - 'ᾊ' => 'ἊΙ', - 'ᾋ' => 'ἋΙ', - 'ᾌ' => 'ἌΙ', - 'ᾍ' => 'ἍΙ', - 'ᾎ' => 'ἎΙ', - 'ᾏ' => 'ἏΙ', - 'ᾘ' => 'ἨΙ', - 'ᾙ' => 'ἩΙ', - 'ᾚ' => 'ἪΙ', - 'ᾛ' => 'ἫΙ', - 'ᾜ' => 'ἬΙ', - 'ᾝ' => 'ἭΙ', - 'ᾞ' => 'ἮΙ', - 'ᾟ' => 'ἯΙ', - 'ᾨ' => 'ὨΙ', - 'ᾩ' => 'ὩΙ', - 'ᾪ' => 'ὪΙ', - 'ᾫ' => 'ὫΙ', - 'ᾬ' => 'ὬΙ', - 'ᾭ' => 'ὭΙ', - 'ᾮ' => 'ὮΙ', - 'ᾯ' => 'ὯΙ', - 'ᾼ' => 'ΑΙ', - 'ῌ' => 'ΗΙ', - 'ῼ' => 'ΩΙ', - 'ᾲ' => 'ᾺΙ', - 'ᾴ' => 'ΆΙ', - 'ῂ' => 'ῊΙ', - 'ῄ' => 'ΉΙ', - 'ῲ' => 'ῺΙ', - 'ῴ' => 'ΏΙ', - 'ᾷ' => 'Α͂Ι', - 'ῇ' => 'Η͂Ι', - 'ῷ' => 'Ω͂Ι', -); diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php deleted file mode 100644 index ff51ae0..0000000 --- a/vendor/symfony/polyfill-mbstring/bootstrap.php +++ /dev/null @@ -1,172 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (\PHP_VERSION_ID >= 80000) { - return require __DIR__.'/bootstrap80.php'; -} - -if (!function_exists('mb_convert_encoding')) { - function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } -} -if (!function_exists('mb_decode_mimeheader')) { - function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } -} -if (!function_exists('mb_encode_mimeheader')) { - function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } -} -if (!function_exists('mb_decode_numericentity')) { - function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } -} -if (!function_exists('mb_encode_numericentity')) { - function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } -} -if (!function_exists('mb_convert_case')) { - function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } -} -if (!function_exists('mb_internal_encoding')) { - function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } -} -if (!function_exists('mb_language')) { - function mb_language($language = null) { return p\Mbstring::mb_language($language); } -} -if (!function_exists('mb_list_encodings')) { - function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } -} -if (!function_exists('mb_encoding_aliases')) { - function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } -} -if (!function_exists('mb_check_encoding')) { - function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } -} -if (!function_exists('mb_detect_encoding')) { - function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } -} -if (!function_exists('mb_detect_order')) { - function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } -} -if (!function_exists('mb_parse_str')) { - function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } -} -if (!function_exists('mb_strlen')) { - function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } -} -if (!function_exists('mb_strpos')) { - function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strtolower')) { - function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } -} -if (!function_exists('mb_strtoupper')) { - function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } -} -if (!function_exists('mb_substitute_character')) { - function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } -} -if (!function_exists('mb_substr')) { - function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } -} -if (!function_exists('mb_stripos')) { - function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_stristr')) { - function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strrchr')) { - function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strrichr')) { - function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_strripos')) { - function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strrpos')) { - function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } -} -if (!function_exists('mb_strstr')) { - function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } -} -if (!function_exists('mb_get_info')) { - function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } -} -if (!function_exists('mb_http_output')) { - function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } -} -if (!function_exists('mb_strwidth')) { - function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } -} -if (!function_exists('mb_substr_count')) { - function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } -} -if (!function_exists('mb_output_handler')) { - function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } -} -if (!function_exists('mb_http_input')) { - function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } -} - -if (!function_exists('mb_convert_variables')) { - function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } -} - -if (!function_exists('mb_ord')) { - function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } -} -if (!function_exists('mb_str_split')) { - function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } -} - -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - - -if (extension_loaded('mbstring')) { - return; -} - -if (!defined('MB_CASE_UPPER')) { - define('MB_CASE_UPPER', 0); -} -if (!defined('MB_CASE_LOWER')) { - define('MB_CASE_LOWER', 1); -} -if (!defined('MB_CASE_TITLE')) { - define('MB_CASE_TITLE', 2); -} diff --git a/vendor/symfony/polyfill-mbstring/bootstrap80.php b/vendor/symfony/polyfill-mbstring/bootstrap80.php deleted file mode 100644 index 5be7d20..0000000 --- a/vendor/symfony/polyfill-mbstring/bootstrap80.php +++ /dev/null @@ -1,167 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (!function_exists('mb_convert_encoding')) { - function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } -} -if (!function_exists('mb_decode_mimeheader')) { - function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } -} -if (!function_exists('mb_encode_mimeheader')) { - function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } -} -if (!function_exists('mb_decode_numericentity')) { - function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } -} -if (!function_exists('mb_encode_numericentity')) { - function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } -} -if (!function_exists('mb_convert_case')) { - function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } -} -if (!function_exists('mb_internal_encoding')) { - function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } -} -if (!function_exists('mb_language')) { - function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } -} -if (!function_exists('mb_list_encodings')) { - function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } -} -if (!function_exists('mb_encoding_aliases')) { - function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } -} -if (!function_exists('mb_check_encoding')) { - function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } -} -if (!function_exists('mb_detect_encoding')) { - function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } -} -if (!function_exists('mb_detect_order')) { - function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } -} -if (!function_exists('mb_parse_str')) { - function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } -} -if (!function_exists('mb_strlen')) { - function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } -} -if (!function_exists('mb_strpos')) { - function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strtolower')) { - function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } -} -if (!function_exists('mb_strtoupper')) { - function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } -} -if (!function_exists('mb_substitute_character')) { - function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } -} -if (!function_exists('mb_substr')) { - function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } -} -if (!function_exists('mb_stripos')) { - function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_stristr')) { - function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrchr')) { - function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strrichr')) { - function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_strripos')) { - function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strrpos')) { - function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } -} -if (!function_exists('mb_strstr')) { - function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } -} -if (!function_exists('mb_get_info')) { - function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); } -} -if (!function_exists('mb_http_output')) { - function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } -} -if (!function_exists('mb_strwidth')) { - function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } -} -if (!function_exists('mb_substr_count')) { - function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } -} -if (!function_exists('mb_output_handler')) { - function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } -} -if (!function_exists('mb_http_input')) { - function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } -} - -if (!function_exists('mb_convert_variables')) { - function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } -} - -if (!function_exists('mb_ord')) { - function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } -} -if (!function_exists('mb_chr')) { - function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } -} -if (!function_exists('mb_scrub')) { - function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } -} -if (!function_exists('mb_str_split')) { - function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } -} - -if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } -} - -if (!function_exists('mb_ucfirst')) { - function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } -} - -if (!function_exists('mb_lcfirst')) { - function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } -} - -if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } -} - -if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } -} - -if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } -} - -if (extension_loaded('mbstring')) { - return; -} - -if (!defined('MB_CASE_UPPER')) { - define('MB_CASE_UPPER', 0); -} -if (!defined('MB_CASE_LOWER')) { - define('MB_CASE_LOWER', 1); -} -if (!defined('MB_CASE_TITLE')) { - define('MB_CASE_TITLE', 2); -} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json deleted file mode 100644 index 4ed241a..0000000 --- a/vendor/symfony/polyfill-mbstring/composer.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "symfony/polyfill-mbstring", - "type": "library", - "description": "Symfony polyfill for the Mbstring extension", - "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - } -}