From 469dbafeb3b67548a54107534fd4172f69815124 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 01:34:30 +0000 Subject: [PATCH 1/6] Lock file maintenance Signed-off-by: Renovate Bot --- composer.lock | 100 ++++---------------------------------------------- 1 file changed, 8 insertions(+), 92 deletions(-) diff --git a/composer.lock b/composer.lock index cc1adac0..9c02ac6e 100644 --- a/composer.lock +++ b/composer.lock @@ -3783,89 +3783,6 @@ ], "time": "2022-11-03T14:55:06+00:00" }, - { - "name": "symfony/polyfill-php80", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.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" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, { "name": "symfony/service-contracts", "version": "v3.0.2", @@ -4085,16 +4002,16 @@ }, { "name": "vimeo/psalm", - "version": "5.4.0", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "62db5d4f6a7ae0a20f7cc5a4952d730272fc0863" + "reference": "e784128902dfe01d489c4123d69918a9f3c1eac5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/62db5d4f6a7ae0a20f7cc5a4952d730272fc0863", - "reference": "62db5d4f6a7ae0a20f7cc5a4952d730272fc0863", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/e784128902dfe01d489c4123d69918a9f3c1eac5", + "reference": "e784128902dfe01d489c4123d69918a9f3c1eac5", "shasum": "" }, "require": { @@ -4117,11 +4034,10 @@ "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", "nikic/php-parser": "^4.13", "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", - "sebastian/diff": "^4.0", + "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/polyfill-php80": "^1.25" + "symfony/filesystem": "^5.4 || ^6.0" }, "provide": { "psalm/psalm": "self.version" @@ -4184,9 +4100,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.4.0" + "source": "https://github.com/vimeo/psalm/tree/5.6.0" }, - "time": "2022-12-19T21:31:12+00:00" + "time": "2023-01-23T20:32:47+00:00" }, { "name": "webimpress/coding-standard", From 06ec8e9f7ba724fb7e840a898873edf0f48b6b72 Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 31 Jan 2023 10:22:47 +0000 Subject: [PATCH 2/6] `shmop_open` now returns an object https://www.php.net/manual/en/migration80.incompatible.php#migration80.incompatible.resource2object Signed-off-by: George Steel --- test/StreamTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/StreamTest.php b/test/StreamTest.php index 1b72fb31..d2737c47 100644 --- a/test/StreamTest.php +++ b/test/StreamTest.php @@ -11,6 +11,7 @@ use PHPUnit\Framework\TestCase; use ReflectionProperty; use RuntimeException; +use Shmop; use function curl_init; use function feof; @@ -636,7 +637,7 @@ public function testRaisesExceptionOnAttachForNonStreamResources(): void $stream->attach($resource); } - /** @return CurlHandle|GdImage|false|resource */ + /** @return CurlHandle|GdImage|Shmop|false */ public function getResourceFor67() { if (function_exists('curl_init')) { From 364fad52c04fdf44bdb377b86f959af2e4b64081 Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 31 Jan 2023 10:26:54 +0000 Subject: [PATCH 3/6] The stream resource is very possibly an object Signed-off-by: George Steel --- src/Stream.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Stream.php b/src/Stream.php index e3ef4717..96c0982e 100644 --- a/src/Stream.php +++ b/src/Stream.php @@ -44,11 +44,11 @@ class Stream implements StreamInterface, Stringable /** @var resource|null */ protected $resource; - /** @var string|resource */ + /** @var string|object|resource|null */ protected $stream; /** - * @param string|resource $stream + * @param string|object|resource $stream * @param string $mode Mode with which to open stream * @throws Exception\InvalidArgumentException */ @@ -103,7 +103,7 @@ public function detach() /** * Attach a new stream/resource to the instance. * - * @param string|resource $resource + * @param string|object|resource $resource * @throws Exception\InvalidArgumentException For stream identifier that cannot be cast to a resource. * @throws Exception\InvalidArgumentException For non-resource stream. */ @@ -313,7 +313,7 @@ public function getMetadata($key = null) /** * Set the internal stream resource. * - * @param string|resource $stream String stream target or stream resource. + * @param string|object|resource $stream String stream target or stream resource. * @param string $mode Resource mode for stream target. * @throws Exception\InvalidArgumentException For invalid streams or resources. */ From fe3012ef04f45d68757076c9c6be8edd7863b76d Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 31 Jan 2023 10:33:34 +0000 Subject: [PATCH 4/6] Assert the number of array elements returned by explode before de-referencing the array Signed-off-by: George Steel --- .../FilterUsingXForwardedHeaders.php | 6 +++++- src/ServerRequestFilter/IPRange.php | 10 ++++++++-- src/UriFactory.php | 6 +++++- src/functions/marshal_uri_from_sapi.php | 6 +++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php b/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php index 2327646d..fbd65090 100644 --- a/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php +++ b/src/ServerRequestFilter/FilterUsingXForwardedHeaders.php @@ -8,6 +8,8 @@ use Laminas\Diactoros\Exception\InvalidProxyAddressException; use Psr\Http\Message\ServerRequestInterface; +use function assert; +use function count; use function explode; use function filter_var; use function in_array; @@ -224,7 +226,9 @@ private static function validateProxyCIDR(mixed $cidr): bool $address = $cidr; $mask = null; if (str_contains($cidr, '/')) { - [$address, $mask] = explode('/', $cidr, 2); + $parts = explode('/', $cidr, 2); + assert(count($parts) >= 2); + [$address, $mask] = $parts; $mask = (int) $mask; } diff --git a/src/ServerRequestFilter/IPRange.php b/src/ServerRequestFilter/IPRange.php index cdf16d0b..fbdb65ee 100644 --- a/src/ServerRequestFilter/IPRange.php +++ b/src/ServerRequestFilter/IPRange.php @@ -4,6 +4,8 @@ namespace Laminas\Diactoros\ServerRequestFilter; +use function assert; +use function count; use function explode; use function inet_pton; use function intval; @@ -43,7 +45,9 @@ public static function matchesIPv4(string $ip, string $cidr): bool $subnet = $cidr; if (str_contains($cidr, '/')) { - [$subnet, $mask] = explode('/', $cidr, 2); + $parts = explode('/', $cidr, 2); + assert(count($parts) >= 2); + [$subnet, $mask] = $parts; $mask = (int) $mask; } @@ -73,7 +77,9 @@ public static function matchesIPv6(string $ip, string $cidr): bool $subnet = $cidr; if (str_contains($cidr, '/')) { - [$subnet, $mask] = explode('/', $cidr, 2); + $parts = explode('/', $cidr, 2); + assert(count($parts) >= 2); + [$subnet, $mask] = $parts; $mask = (int) $mask; } diff --git a/src/UriFactory.php b/src/UriFactory.php index d0ce13af..ba3bd78e 100644 --- a/src/UriFactory.php +++ b/src/UriFactory.php @@ -9,6 +9,8 @@ use function array_change_key_case; use function array_key_exists; +use function assert; +use function count; use function explode; use function gettype; use function implode; @@ -76,7 +78,9 @@ public static function createFromSapi(array $server, array $headers): Uri $fragment = ''; if (str_contains($path, '#')) { - [$path, $fragment] = explode('#', $path, 2); + $parts = explode('#', $path, 2); + assert(count($parts) >= 2); + [$path, $fragment] = $parts; } return $uri diff --git a/src/functions/marshal_uri_from_sapi.php b/src/functions/marshal_uri_from_sapi.php index 124cdff4..186d6d9a 100644 --- a/src/functions/marshal_uri_from_sapi.php +++ b/src/functions/marshal_uri_from_sapi.php @@ -6,6 +6,8 @@ use function array_change_key_case; use function array_key_exists; +use function assert; +use function count; use function explode; use function gettype; use function implode; @@ -219,7 +221,9 @@ function marshalUriFromSapi(array $server, array $headers): Uri // URI fragment $fragment = ''; if (str_contains($path, '#')) { - [$path, $fragment] = explode('#', $path, 2); + $parts = explode('#', $path, 2); + assert(count($parts) >= 2); + [$path, $fragment] = $parts; } return $uri From dfc930bad064cb3d4d8b1344ff8d21e7ed4a693b Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 31 Jan 2023 10:34:41 +0000 Subject: [PATCH 5/6] Refresh lock, bump dev deps, refresh baseline Signed-off-by: George Steel --- composer.json | 6 +- composer.lock | 50 ++++----- psalm-baseline.xml | 251 ++++++++++++++++++++++----------------------- 3 files changed, 149 insertions(+), 158 deletions(-) diff --git a/composer.json b/composer.json index 37210111..c64ee44d 100644 --- a/composer.json +++ b/composer.json @@ -44,11 +44,11 @@ "ext-gd": "*", "ext-libxml": "*", "http-interop/http-factory-tests": "^0.9.0", - "laminas/laminas-coding-standard": "^2.4.0", + "laminas/laminas-coding-standard": "^2.5", "php-http/psr7-integration-tests": "^1.2", - "phpunit/phpunit": "^9.5.27", + "phpunit/phpunit": "^9.5.28", "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.4" + "vimeo/psalm": "^5.6" }, "provide": { "psr/http-factory-implementation": "1.0", diff --git a/composer.lock b/composer.lock index 9c02ac6e..44ffef07 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1ed729b44928df771fa1af7a5f07bfd6", + "content-hash": "c25e73f49b971e1a04c8a20ddf532540", "packages": [ { "name": "psr/http-factory", @@ -1569,16 +1569,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.23", + "version": "9.2.24", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c" + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed", + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed", "shasum": "" }, "require": { @@ -1634,7 +1634,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24" }, "funding": [ { @@ -1642,7 +1642,7 @@ "type": "github" } ], - "time": "2022-12-28T12:41:10+00:00" + "time": "2023-01-26T08:26:55+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3297,16 +3297,16 @@ }, { "name": "symfony/console", - "version": "v6.0.17", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18" + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ab307342a7233b9a260edd5ef94087aaca57d18", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18", + "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", "shasum": "" }, "require": { @@ -3372,7 +3372,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.17" + "source": "https://github.com/symfony/console/tree/v6.0.19" }, "funding": [ { @@ -3388,20 +3388,20 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/filesystem", - "version": "v6.0.13", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79" + "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3adca49133bd055ebe6011ed1e012be3c908af79", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/3d49eec03fda1f0fc19b7349fbbe55ebc1004214", + "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214", "shasum": "" }, "require": { @@ -3435,7 +3435,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.0.13" + "source": "https://github.com/symfony/filesystem/tree/v6.0.19" }, "funding": [ { @@ -3451,7 +3451,7 @@ "type": "tidelift" } ], - "time": "2022-09-21T20:25:27+00:00" + "time": "2023-01-20T17:44:14+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3867,16 +3867,16 @@ }, { "name": "symfony/string", - "version": "v6.0.17", + "version": "v6.0.19", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9" + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/3f57003dd8a67ed76870cc03092f8501db7788d9", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9", + "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", + "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", "shasum": "" }, "require": { @@ -3932,7 +3932,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.17" + "source": "https://github.com/symfony/string/tree/v6.0.19" }, "funding": [ { @@ -3948,7 +3948,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "theseer/tokenizer", diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 1741a4f9..9f643aa0 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,85 +1,82 @@ - + - + null|callable - + $contents - + $previous->getCode() $previous->getCode() - + ! is_string($name) ! is_string($stream) && ! is_resource($stream) - + $new->headerNames[$normalized] $this->headerNames[strtolower($header)] $this->headerNames[strtolower($header)] $this->headerNames[strtolower($name)] - + $headerNames - + is_object($version) ? $version::class : gettype($version) - + $header $header $header $header - + $value - + $headers - + $header $header - + $new->headerNames $new->headers - + gettype($version) - + is_object($version) is_string($version) - + $maxLength - + $maxLength - + $this->resource - - PhpInputStream - - + $this->decoratedStream->getSize() - + $headers $method $protocolVersion @@ -87,7 +84,7 @@ $uri self::getValueFromKey($serializedRequest, 'body') - + $headers $method $protocolVersion @@ -96,56 +93,56 @@ - + $body $headers $method $requestTarget $version - + $request->getHeaders() - + is_string($method) - + $requestTarget - + $this->uri->getPort() $uri->getPort() - + ! is_numeric($code) gettype($code) is_float($code) is_string($reasonPhrase) - + static::MAX_STATUS_CODE_VALUE static::MIN_STATUS_CODE_VALUE - + (int) $code - + is_scalar($code) - + $headers $protocolVersion $reasonPhrase $statusCode self::getValueFromKey($serializedResponse, 'body') - + $headers $protocolVersion $reasonPhrase @@ -153,88 +150,88 @@ - + new static(204, $headers) - + is_string($html) - + $item - + $hasContentType - + json_encode - + gettype($uri) - + is_object($uri) - + $body $headers $reasonPhrase $status $version - + $response->getHeaders() - + (int) $status - + is_string($text) - + is_string($xml) - + ! is_array($data) && ! is_object($data) && null !== $data - + $attribute $attribute - - + + $headers['cookie'] - + $headers $server - + ServerRequest - + is_callable(self::$apacheRequestHeaders) - + getHeaderLine getServerParams getUri @@ -243,44 +240,41 @@ withScheme withUri - + $proxyCIDRList - + list<non-empty-string> - + $resource $this->resource $this->resource $this->resource - - $stream - - + $file - + ! is_string($targetPath) - + $this->file - + $size - + ! is_numeric($port) is_float($port) is_object($port) @@ -292,29 +286,29 @@ is_string($user) null !== $password && ! is_string($password) - + $key $key $matches[0] $value - + $this->port - + (int) $port - + gettype($port) - + func_get_args() - + $spec['error'] $spec['name'] ?? null $spec['tmp_name'] @@ -322,58 +316,58 @@ - + func_get_args() - + $headers[$name] $headers[$name] $value - + func_get_args() - + string - + $server['REQUEST_METHOD'] ?? 'GET' $server['REQUEST_METHOD'] ?? 'GET' - + func_get_args() - + $server['SERVER_PROTOCOL'] - + func_get_args() func_get_args() - + $default $host $https - + static function ($host) { static function (string $name, array $headers, $default = null) { - + $getHeaderFromArray('x-forwarded-proto', $headers, '') $host $host @@ -383,185 +377,182 @@ $requestUri $server['QUERY_STRING'] - + $headers[$header] $host - + $host $iisUrlRewritten $origPathInfo $unencodedUrl - + array string - + $server['SERVER_ADDR'] - + $defaults $origPathInfo $unencodedUrl - + strrpos($host, ':') - + func_get_args() func_get_args() - + $apacheRequestHeaders['Authorization'] $apacheRequestHeaders['authorization'] - + $apacheRequestHeaders $server['HTTP_AUTHORIZATION'] $server['HTTP_AUTHORIZATION'] - + func_get_args() - + $normalized - + UploadedFileInterface[] - + $normalized[$key] $value $value - - + + array - + - + func_get_args() - + $cookies - + array<non-empty-string, string> - + $ret $ret - + $stream->getSize() - + $value $version - + assertSame - + static function () use ($payload) { - + $payload[$i++] - + $i - + $i - + $headers - + $ianaCodesReasonPhrases - + $record $record - + $responseCode - + list<array{numeric-string, non-empty-string}> - + assertIsInt - + $value - + $normalizedFiles['fooFiles'] - + $parsedBody - + setMethods - - $resource - - + $path $streamOrFile - + $test - + $test - + $normalised['my-form']['details']['avatars'] $normalised['slide-shows'][0]['slides'] - + $normalised['my-form']['details']['avatar'] $normalised['my-form']['details']['avatars'] $normalised['my-form']['details']['avatars'] @@ -576,7 +567,7 @@ $normalised['slide-shows'][0]['slides'][0] $normalised['slide-shows'][0]['slides'][1] - + getClientFilename getClientFilename getClientFilename @@ -584,7 +575,7 @@ getClientFilename getClientFilename - + $normalised['my-form'] $normalised['my-form'] $normalised['my-form'] From 3329e919896dc1f87b6d819e87bc386fb09c1c6a Mon Sep 17 00:00:00 2001 From: George Steel Date: Tue, 31 Jan 2023 10:47:29 +0000 Subject: [PATCH 6/6] Baseline new psalm issues that cannot be easily fixed Signed-off-by: George Steel --- psalm-baseline.xml | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 9f643aa0..03cb33d2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -119,6 +119,8 @@ ! is_numeric($code) + ! is_numeric($code) + || is_float($code) gettype($code) is_float($code) is_string($reasonPhrase) @@ -215,7 +217,20 @@ - + + $requestFilter(new ServerRequest( + $server, + $files, + UriFactory::createFromSapi($server, $headers), + marshalMethodFromSapi($server), + 'php://input', + $headers, + $cookies ?: $_COOKIE, + $query ?: $_GET, + $body ?: $_POST, + marshalProtocolVersionFromSapi($server) + )) + $headers['cookie'] @@ -437,11 +452,34 @@ $value $value - + + $recursiveNormalize( + $tmpNameTree[$key], + $sizeTree[$key], + $errorTree[$key], + $nameTree[$key] ?? null, + $typeTree[$key] ?? null + ) + $recursiveNormalize( + $files['tmp_name'], + $files['size'], + $files['error'], + $files['name'] ?? null, + $files['type'] ?? null + ) + array - + + $recursiveNormalize( + $files['tmp_name'], + $files['size'], + $files['error'], + $files['name'] ?? null, + $files['type'] ?? null + ) +