From 41ce1aa07693a15fa43acd02099b1261a1b50560 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Tue, 19 Nov 2024 09:59:00 +0100 Subject: [PATCH] Update website --- vendor/composer/autoload_psr4.php | 2 +- vendor/composer/autoload_static.php | 4 +- vendor/composer/installed.json | 70 +++++++++---------- vendor/composer/installed.php | 34 ++++----- vendor/symfony/error-handler/ErrorHandler.php | 2 +- .../Exception/FlattenException.php | 2 +- vendor/symfony/http-client/HttpOptions.php | 2 + .../symfony/http-client/NativeHttpClient.php | 12 +++- .../NoPrivateNetworkHttpClient.php | 26 ++++++- .../http-client/Response/AmpResponse.php | 11 ++- .../http-client/Response/AsyncContext.php | 4 +- .../http-client/Response/AsyncResponse.php | 4 +- .../http-client/Response/CurlResponse.php | 11 ++- .../http-client/TraceableHttpClient.php | 4 +- .../string/Inflector/EnglishInflector.php | 10 +-- .../symfony/var-dumper/Caster/ClassStub.php | 2 +- .../var-dumper/Caster/ExceptionCaster.php | 2 +- vendor/twig/twig/CHANGELOG | 11 +++ vendor/twig/twig/src/Environment.php | 6 +- .../twig/twig/src/Extension/CoreExtension.php | 64 ++++++++++++++--- .../twig/src/Extension/SandboxExtension.php | 47 +++++++++++++ .../src/Node/Expression/GetAttrExpression.php | 33 +++++++-- .../src/NodeVisitor/SandboxNodeVisitor.php | 15 +++- 23 files changed, 284 insertions(+), 94 deletions(-) diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6c260d9..3585b00 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -25,7 +25,7 @@ return array( 'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'), 'Stevenmaguire\\OAuth2\\Client\\' => array($vendorDir . '/stevenmaguire/oauth2-bitbucket/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'), 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 7836183..fd09967 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -159,8 +159,8 @@ class ComposerStaticInitecf73f43d2b62bd3c0232fbab805eceb ), 'Psr\\Http\\Message\\' => array ( - 0 => __DIR__ . '/..' . '/psr/http-message/src', - 1 => __DIR__ . '/..' . '/psr/http-factory/src', + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', ), 'Psr\\Http\\Client\\' => array ( diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 7af1a74..012f9bd 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1536,17 +1536,17 @@ }, { "name": "symfony/error-handler", - "version": "v5.4.45", - "version_normalized": "5.4.45.0", + "version": "v5.4.46", + "version_normalized": "5.4.46.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "55ac2507a8bf97f2d04f8d1e7f104c984ddcaf31" + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/55ac2507a8bf97f2d04f8d1e7f104c984ddcaf31", - "reference": "55ac2507a8bf97f2d04f8d1e7f104c984ddcaf31", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d19ede7a2cafb386be9486c580649d0f9e3d0363", + "reference": "d19ede7a2cafb386be9486c580649d0f9e3d0363", "shasum": "" }, "require": { @@ -1559,7 +1559,7 @@ "symfony/http-kernel": "^4.4|^5.0|^6.0", "symfony/serializer": "^4.4|^5.0|^6.0" }, - "time": "2024-09-25T14:11:13+00:00", + "time": "2024-11-05T14:17:06+00:00", "bin": [ "Resources/bin/patch-type-declarations" ], @@ -1590,7 +1590,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.4.45" + "source": "https://github.com/symfony/error-handler/tree/v5.4.46" }, "funding": [ { @@ -1746,17 +1746,17 @@ }, { "name": "symfony/http-client", - "version": "v5.4.45", - "version_normalized": "5.4.45.0", + "version": "v5.4.47", + "version_normalized": "5.4.47.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "54118c6340dc6831a00f10b296ea6e80592ec89d" + "reference": "3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/54118c6340dc6831a00f10b296ea6e80592ec89d", - "reference": "54118c6340dc6831a00f10b296ea6e80592ec89d", + "url": "https://api.github.com/repos/symfony/http-client/zipball/3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde", + "reference": "3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde", "shasum": "" }, "require": { @@ -1789,7 +1789,7 @@ "symfony/process": "^4.4|^5.0|^6.0", "symfony/stopwatch": "^4.4|^5.0|^6.0" }, - "time": "2024-09-25T14:11:13+00:00", + "time": "2024-11-13T12:18:12+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1820,7 +1820,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v5.4.45" + "source": "https://github.com/symfony/http-client/tree/v5.4.47" }, "funding": [ { @@ -2578,17 +2578,17 @@ }, { "name": "symfony/string", - "version": "v5.4.45", - "version_normalized": "5.4.45.0", + "version": "v5.4.47", + "version_normalized": "5.4.47.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7f6807add88b1e2635f3c6de5e1ace631ed7cad2" + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7f6807add88b1e2635f3c6de5e1ace631ed7cad2", - "reference": "7f6807add88b1e2635f3c6de5e1ace631ed7cad2", + "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", "shasum": "" }, "require": { @@ -2608,7 +2608,7 @@ "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0|^6.0" }, - "time": "2024-09-25T14:11:13+00:00", + "time": "2024-11-10T20:33:58+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2647,7 +2647,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.45" + "source": "https://github.com/symfony/string/tree/v5.4.47" }, "funding": [ { @@ -2748,17 +2748,17 @@ }, { "name": "symfony/var-dumper", - "version": "v5.4.45", - "version_normalized": "5.4.45.0", + "version": "v5.4.47", + "version_normalized": "5.4.47.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c4a5a08fe8d836a1aeec59eeee9697457fd28723" + "reference": "e13e8dfa8eaab2b0536ef365beddc2af723a9ac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c4a5a08fe8d836a1aeec59eeee9697457fd28723", - "reference": "c4a5a08fe8d836a1aeec59eeee9697457fd28723", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e13e8dfa8eaab2b0536ef365beddc2af723a9ac0", + "reference": "e13e8dfa8eaab2b0536ef365beddc2af723a9ac0", "shasum": "" }, "require": { @@ -2782,7 +2782,7 @@ "ext-intl": "To show region name in time zone dump", "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, - "time": "2024-09-25T14:11:13+00:00", + "time": "2024-11-08T15:21:10+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -2820,7 +2820,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.45" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.47" }, "funding": [ { @@ -2893,17 +2893,17 @@ }, { "name": "twig/twig", - "version": "v3.11.1", - "version_normalized": "3.11.1.0", + "version": "v3.11.3", + "version_normalized": "3.11.3.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "ff063afc691e1cfda6714f1915ed766cb108d188" + "reference": "3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/ff063afc691e1cfda6714f1915ed766cb108d188", - "reference": "ff063afc691e1cfda6714f1915ed766cb108d188", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e", + "reference": "3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e", "shasum": "" }, "require": { @@ -2918,7 +2918,7 @@ "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, - "time": "2024-09-10T10:40:14+00:00", + "time": "2024-11-07T12:34:41+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2960,7 +2960,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.11.1" + "source": "https://github.com/twigphp/Twig/tree/v3.11.3" }, "funding": [ { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 0de16ee..5f3f720 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'lavaux/website', 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => 'daa513a17eb44c84c7a93675c67c268afc2a27c0', + 'reference' => 'a1314b0ad5d4b3202bc5f3e4c0fb9dd7ddbca62a', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -85,7 +85,7 @@ 'lavaux/website' => array( 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => 'daa513a17eb44c84c7a93675c67c268afc2a27c0', + 'reference' => 'a1314b0ad5d4b3202bc5f3e4c0fb9dd7ddbca62a', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -239,9 +239,9 @@ 'dev_requirement' => false, ), 'symfony/error-handler' => array( - 'pretty_version' => 'v5.4.45', - 'version' => '5.4.45.0', - 'reference' => '55ac2507a8bf97f2d04f8d1e7f104c984ddcaf31', + 'pretty_version' => 'v5.4.46', + 'version' => '5.4.46.0', + 'reference' => 'd19ede7a2cafb386be9486c580649d0f9e3d0363', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), @@ -266,9 +266,9 @@ 'dev_requirement' => false, ), 'symfony/http-client' => array( - 'pretty_version' => 'v5.4.45', - 'version' => '5.4.45.0', - 'reference' => '54118c6340dc6831a00f10b296ea6e80592ec89d', + 'pretty_version' => 'v5.4.47', + 'version' => '5.4.47.0', + 'reference' => '3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-client', 'aliases' => array(), @@ -362,9 +362,9 @@ 'dev_requirement' => false, ), 'symfony/string' => array( - 'pretty_version' => 'v5.4.45', - 'version' => '5.4.45.0', - 'reference' => '7f6807add88b1e2635f3c6de5e1ace631ed7cad2', + 'pretty_version' => 'v5.4.47', + 'version' => '5.4.47.0', + 'reference' => '136ca7d72f72b599f2631aca474a4f8e26719799', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), @@ -380,9 +380,9 @@ 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v5.4.45', - 'version' => '5.4.45.0', - 'reference' => 'c4a5a08fe8d836a1aeec59eeee9697457fd28723', + 'pretty_version' => 'v5.4.47', + 'version' => '5.4.47.0', + 'reference' => 'e13e8dfa8eaab2b0536ef365beddc2af723a9ac0', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), @@ -398,9 +398,9 @@ 'dev_requirement' => false, ), 'twig/twig' => array( - 'pretty_version' => 'v3.11.1', - 'version' => '3.11.1.0', - 'reference' => 'ff063afc691e1cfda6714f1915ed766cb108d188', + 'pretty_version' => 'v3.11.3', + 'version' => '3.11.3.0', + 'reference' => '3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), diff --git a/vendor/symfony/error-handler/ErrorHandler.php b/vendor/symfony/error-handler/ErrorHandler.php index 840353f..4107bae 100644 --- a/vendor/symfony/error-handler/ErrorHandler.php +++ b/vendor/symfony/error-handler/ErrorHandler.php @@ -806,7 +806,7 @@ class ErrorHandler */ private function parseAnonymousClass(string $message): string { - return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static function ($m) { + return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', static function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } diff --git a/vendor/symfony/error-handler/Exception/FlattenException.php b/vendor/symfony/error-handler/Exception/FlattenException.php index f73842a..2532b8c 100644 --- a/vendor/symfony/error-handler/Exception/FlattenException.php +++ b/vendor/symfony/error-handler/Exception/FlattenException.php @@ -226,7 +226,7 @@ class FlattenException public function setMessage(string $message): self { if (false !== strpos($message, "@anonymous\0")) { - $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } diff --git a/vendor/symfony/http-client/HttpOptions.php b/vendor/symfony/http-client/HttpOptions.php index da55f99..5a178dd 100644 --- a/vendor/symfony/http-client/HttpOptions.php +++ b/vendor/symfony/http-client/HttpOptions.php @@ -148,6 +148,8 @@ class HttpOptions } /** + * @param callable(int, int, array, \Closure|null=):void $callback + * * @return $this */ public function setOnProgress(callable $callback) diff --git a/vendor/symfony/http-client/NativeHttpClient.php b/vendor/symfony/http-client/NativeHttpClient.php index e5bc61c..8819848 100644 --- a/vendor/symfony/http-client/NativeHttpClient.php +++ b/vendor/symfony/http-client/NativeHttpClient.php @@ -138,7 +138,15 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac // Memoize the last progress to ease calling the callback periodically when no network transfer happens $lastProgress = [0, 0]; $maxDuration = 0 < $options['max_duration'] ? $options['max_duration'] : \INF; - $onProgress = static function (...$progress) use ($onProgress, &$lastProgress, &$info, $maxDuration) { + $multi = $this->multi; + $resolve = static function (string $host, ?string $ip = null) use ($multi): ?string { + if (null !== $ip) { + $multi->dnsCache[$host] = $ip; + } + + return $multi->dnsCache[$host] ?? null; + }; + $onProgress = static function (...$progress) use ($onProgress, &$lastProgress, &$info, $maxDuration, $resolve) { if ($info['total_time'] >= $maxDuration) { throw new TransportException(sprintf('Max duration was reached for "%s".', implode('', $info['url']))); } @@ -154,7 +162,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $lastProgress = $progress ?: $lastProgress; } - $onProgress($lastProgress[0], $lastProgress[1], $progressInfo); + $onProgress($lastProgress[0], $lastProgress[1], $progressInfo, $resolve); }; } elseif (0 < $options['max_duration']) { $maxDuration = $options['max_duration']; diff --git a/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php b/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php index 757a9e8..ed282e3 100644 --- a/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php +++ b/vendor/symfony/http-client/NoPrivateNetworkHttpClient.php @@ -77,9 +77,33 @@ final class NoPrivateNetworkHttpClient implements HttpClientInterface, LoggerAwa } $subnets = $this->subnets; + $lastUrl = ''; $lastPrimaryIp = ''; - $options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastPrimaryIp): void { + $options['on_progress'] = function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use ($onProgress, $subnets, &$lastUrl, &$lastPrimaryIp): void { + if ($info['url'] !== $lastUrl) { + $host = trim(parse_url($info['url'], PHP_URL_HOST) ?: '', '[]'); + $resolve ??= static fn () => null; + + if (($ip = $host) + && !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6) + && !filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4) + && !$ip = $resolve($host) + ) { + if ($ip = @(dns_get_record($host, \DNS_A)[0]['ip'] ?? null)) { + $resolve($host, $ip); + } elseif ($ip = @(dns_get_record($host, \DNS_AAAA)[0]['ipv6'] ?? null)) { + $resolve($host, '['.$ip.']'); + } + } + + if ($ip && IpUtils::checkIp($ip, $subnets ?? self::PRIVATE_SUBNETS)) { + throw new TransportException(sprintf('Host "%s" is blocked for "%s".', $host, $info['url'])); + } + + $lastUrl = $info['url']; + } + if ($info['primary_ip'] !== $lastPrimaryIp) { if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) { throw new TransportException(sprintf('IP "%s" is blocked for "%s".', $info['primary_ip'], $info['url'])); diff --git a/vendor/symfony/http-client/Response/AmpResponse.php b/vendor/symfony/http-client/Response/AmpResponse.php index e4999b7..a9cc4d6 100644 --- a/vendor/symfony/http-client/Response/AmpResponse.php +++ b/vendor/symfony/http-client/Response/AmpResponse.php @@ -89,10 +89,17 @@ final class AmpResponse implements ResponseInterface, StreamableInterface $info['max_duration'] = $options['max_duration']; $info['debug'] = ''; + $resolve = static function (string $host, ?string $ip = null) use ($multi): ?string { + if (null !== $ip) { + $multi->dnsCache[$host] = $ip; + } + + return $multi->dnsCache[$host] ?? null; + }; $onProgress = $options['on_progress'] ?? static function () {}; - $onProgress = $this->onProgress = static function () use (&$info, $onProgress) { + $onProgress = $this->onProgress = static function () use (&$info, $onProgress, $resolve) { $info['total_time'] = microtime(true) - $info['start_time']; - $onProgress((int) $info['size_download'], ((int) (1 + $info['download_content_length']) ?: 1) - 1, (array) $info); + $onProgress((int) $info['size_download'], ((int) (1 + $info['download_content_length']) ?: 1) - 1, (array) $info, $resolve); }; $pauseDeferred = new Deferred(); diff --git a/vendor/symfony/http-client/Response/AsyncContext.php b/vendor/symfony/http-client/Response/AsyncContext.php index 3c5397c..de1562d 100644 --- a/vendor/symfony/http-client/Response/AsyncContext.php +++ b/vendor/symfony/http-client/Response/AsyncContext.php @@ -156,8 +156,8 @@ final class AsyncContext $this->info['previous_info'][] = $info = $this->response->getInfo(); if (null !== $onProgress = $options['on_progress'] ?? null) { $thisInfo = &$this->info; - $options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) { - $onProgress($dlNow, $dlSize, $thisInfo + $info); + $options['on_progress'] = static function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$thisInfo, $onProgress) { + $onProgress($dlNow, $dlSize, $thisInfo + $info, $resolve); }; } if (0 < ($info['max_duration'] ?? 0) && 0 < ($info['total_time'] ?? 0)) { diff --git a/vendor/symfony/http-client/Response/AsyncResponse.php b/vendor/symfony/http-client/Response/AsyncResponse.php index 890e2e9..de52ce0 100644 --- a/vendor/symfony/http-client/Response/AsyncResponse.php +++ b/vendor/symfony/http-client/Response/AsyncResponse.php @@ -51,8 +51,8 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface if (null !== $onProgress = $options['on_progress'] ?? null) { $thisInfo = &$this->info; - $options['on_progress'] = static function (int $dlNow, int $dlSize, array $info) use (&$thisInfo, $onProgress) { - $onProgress($dlNow, $dlSize, $thisInfo + $info); + $options['on_progress'] = static function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$thisInfo, $onProgress) { + $onProgress($dlNow, $dlSize, $thisInfo + $info, $resolve); }; } $this->response = $client->request($method, $url, ['buffer' => false] + $options); diff --git a/vendor/symfony/http-client/Response/CurlResponse.php b/vendor/symfony/http-client/Response/CurlResponse.php index 633b74a..1db51da 100644 --- a/vendor/symfony/http-client/Response/CurlResponse.php +++ b/vendor/symfony/http-client/Response/CurlResponse.php @@ -115,13 +115,20 @@ final class CurlResponse implements ResponseInterface, StreamableInterface curl_pause($ch, \CURLPAUSE_CONT); if ($onProgress = $options['on_progress']) { + $resolve = static function (string $host, ?string $ip = null) use ($multi): ?string { + if (null !== $ip) { + $multi->dnsCache->hostnames[$host] = $ip; + } + + return $multi->dnsCache->hostnames[$host] ?? null; + }; $url = isset($info['url']) ? ['url' => $info['url']] : []; curl_setopt($ch, \CURLOPT_NOPROGRESS, false); - curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION, static function ($ch, $dlSize, $dlNow) use ($onProgress, &$info, $url, $multi, $debugBuffer) { + curl_setopt($ch, \CURLOPT_PROGRESSFUNCTION, static function ($ch, $dlSize, $dlNow) use ($onProgress, &$info, $url, $multi, $debugBuffer, $resolve) { try { rewind($debugBuffer); $debug = ['debug' => stream_get_contents($debugBuffer)]; - $onProgress($dlNow, $dlSize, $url + curl_getinfo($ch) + $info + $debug); + $onProgress($dlNow, $dlSize, $url + curl_getinfo($ch) + $info + $debug, $resolve); } catch (\Throwable $e) { $multi->handlesActivity[(int) $ch][] = null; $multi->handlesActivity[(int) $ch][] = $e; diff --git a/vendor/symfony/http-client/TraceableHttpClient.php b/vendor/symfony/http-client/TraceableHttpClient.php index 0c1f05a..f83a5ca 100644 --- a/vendor/symfony/http-client/TraceableHttpClient.php +++ b/vendor/symfony/http-client/TraceableHttpClient.php @@ -58,11 +58,11 @@ final class TraceableHttpClient implements HttpClientInterface, ResetInterface, $content = false; } - $options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use (&$traceInfo, $onProgress) { + $options['on_progress'] = function (int $dlNow, int $dlSize, array $info, ?\Closure $resolve = null) use (&$traceInfo, $onProgress) { $traceInfo = $info; if (null !== $onProgress) { - $onProgress($dlNow, $dlSize, $info); + $onProgress($dlNow, $dlSize, $info, $resolve); } }; diff --git a/vendor/symfony/string/Inflector/EnglishInflector.php b/vendor/symfony/string/Inflector/EnglishInflector.php index 9557e35..ecd51d4 100644 --- a/vendor/symfony/string/Inflector/EnglishInflector.php +++ b/vendor/symfony/string/Inflector/EnglishInflector.php @@ -348,14 +348,14 @@ final class EnglishInflector implements InflectorInterface // indices (index) ['xedni', 5, false, true, ['indicies', 'indexes']], + // fax (faxes, faxxes) + ['xaf', 3, true, true, ['faxes', 'faxxes']], + // boxes (box) ['xo', 2, false, true, 'oxes'], - // indexes (index), matrixes (matrix) - ['x', 1, true, false, ['cies', 'xes']], - - // appendices (appendix) - ['xi', 2, false, true, 'ices'], + // indexes (index), matrixes (matrix), appendices (appendix) + ['x', 1, true, false, ['ces', 'xes']], // babies (baby) ['y', 1, false, true, 'ies'], diff --git a/vendor/symfony/var-dumper/Caster/ClassStub.php b/vendor/symfony/var-dumper/Caster/ClassStub.php index 48f8483..27c24c9 100644 --- a/vendor/symfony/var-dumper/Caster/ClassStub.php +++ b/vendor/symfony/var-dumper/Caster/ClassStub.php @@ -56,7 +56,7 @@ class ClassStub extends ConstStub } if (str_contains($identifier, "@anonymous\0")) { - $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $identifier); } diff --git a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php index d3f5e12..299f512 100644 --- a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php +++ b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php @@ -288,7 +288,7 @@ class ExceptionCaster unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) { - $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { + $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $a[Caster::PREFIX_PROTECTED.'message']); } diff --git a/vendor/twig/twig/CHANGELOG b/vendor/twig/twig/CHANGELOG index 55285d6..525e238 100644 --- a/vendor/twig/twig/CHANGELOG +++ b/vendor/twig/twig/CHANGELOG @@ -1,3 +1,14 @@ +# 3.11.3 (2024-11-07) + + * Fix an infinite recursion in the sandbox code + +# 3.11.2 (2024-11-06) + + * [BC BREAK] Fix a security issue in the sandbox mode allowing an attacker to call attributes on Array-like objects + They are now checked via the property policy + * Fix a security issue in the sandbox mode allowing an attacker to be able to call `toString()` + under some circumstances on an object even if the `__toString()` method is not allowed by the security policy + # 3.11.1 (2024-09-10) * Fix a security issue when an included sandboxed template has been loaded before without the sandbox context diff --git a/vendor/twig/twig/src/Environment.php b/vendor/twig/twig/src/Environment.php index e928e63..571b461 100644 --- a/vendor/twig/twig/src/Environment.php +++ b/vendor/twig/twig/src/Environment.php @@ -43,11 +43,11 @@ use Twig\TokenParser\TokenParserInterface; */ class Environment { - public const VERSION = '3.11.1'; - public const VERSION_ID = 301101; + public const VERSION = '3.11.3'; + public const VERSION_ID = 301103; public const MAJOR_VERSION = 4; public const MINOR_VERSION = 11; - public const RELEASE_VERSION = 1; + public const RELEASE_VERSION = 3; public const EXTRA_VERSION = ''; private $charset; diff --git a/vendor/twig/twig/src/Extension/CoreExtension.php b/vendor/twig/twig/src/Extension/CoreExtension.php index 4b014b8..b077e79 100644 --- a/vendor/twig/twig/src/Extension/CoreExtension.php +++ b/vendor/twig/twig/src/Extension/CoreExtension.php @@ -57,6 +57,8 @@ use Twig\Node\Expression\Unary\NegUnary; use Twig\Node\Expression\Unary\NotUnary; use Twig\Node\Expression\Unary\PosUnary; use Twig\NodeVisitor\MacroAutoImportNodeVisitor; +use Twig\Sandbox\SecurityNotAllowedMethodError; +use Twig\Sandbox\SecurityNotAllowedPropertyError; use Twig\Source; use Twig\Template; use Twig\TemplateWrapper; @@ -82,6 +84,20 @@ use Twig\TwigTest; final class CoreExtension extends AbstractExtension { + public const ARRAY_LIKE_CLASSES = [ + 'ArrayIterator', + 'ArrayObject', + 'CachingIterator', + 'RecursiveArrayIterator', + 'RecursiveCachingIterator', + 'SplDoublyLinkedList', + 'SplFixedArray', + 'SplObjectStorage', + 'SplQueue', + 'SplStack', + 'WeakMap', + ]; + private $dateFormats = ['F j, Y H:i', '%d days']; private $numberFormat = [0, '.', ',']; private $timezone = null; @@ -1549,10 +1565,20 @@ final class CoreExtension extends AbstractExtension */ public static function getAttribute(Environment $env, Source $source, $object, $item, array $arguments = [], $type = /* Template::ANY_CALL */ 'any', $isDefinedTest = false, $ignoreStrictCheck = false, $sandboxed = false, int $lineno = -1) { + $propertyNotAllowedError = null; + // array if (/* Template::METHOD_CALL */ 'method' !== $type) { $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; + if ($sandboxed && $object instanceof \ArrayAccess && !\in_array(get_class($object), self::ARRAY_LIKE_CLASSES, true)) { + try { + $env->getExtension(SandboxExtension::class)->checkPropertyAllowed($object, $arrayItem, $lineno, $source); + } catch (SecurityNotAllowedPropertyError $propertyNotAllowedError) { + goto methodCheck; + } + } + if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) || ($object instanceof \ArrayAccess && isset($object[$arrayItem])) ) { @@ -1624,19 +1650,25 @@ final class CoreExtension extends AbstractExtension // object property if (/* Template::METHOD_CALL */ 'method' !== $type) { + if ($sandboxed) { + try { + $env->getExtension(SandboxExtension::class)->checkPropertyAllowed($object, $item, $lineno, $source); + } catch (SecurityNotAllowedPropertyError $propertyNotAllowedError) { + goto methodCheck; + } + } + if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { if ($isDefinedTest) { return true; } - if ($sandboxed) { - $env->getExtension(SandboxExtension::class)->checkPropertyAllowed($object, $item, $lineno, $source); - } - return $object->$item; } } + methodCheck: + static $cache = []; $class = \get_class($object); @@ -1695,6 +1727,10 @@ final class CoreExtension extends AbstractExtension return false; } + if ($propertyNotAllowedError) { + throw $propertyNotAllowedError; + } + if ($ignoreStrictCheck || !$env->isStrictVariables()) { return; } @@ -1702,12 +1738,24 @@ final class CoreExtension extends AbstractExtension throw new RuntimeError(\sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), $lineno, $source); } - if ($isDefinedTest) { - return true; + if ($sandboxed) { + try { + $env->getExtension(SandboxExtension::class)->checkMethodAllowed($object, $method, $lineno, $source); + } catch (SecurityNotAllowedMethodError $e) { + if ($isDefinedTest) { + return false; + } + + if ($propertyNotAllowedError) { + throw $propertyNotAllowedError; + } + + throw $e; + } } - if ($sandboxed) { - $env->getExtension(SandboxExtension::class)->checkMethodAllowed($object, $method, $lineno, $source); + if ($isDefinedTest) { + return true; } // Some objects throw exceptions when they have __call, and the method we try diff --git a/vendor/twig/twig/src/Extension/SandboxExtension.php b/vendor/twig/twig/src/Extension/SandboxExtension.php index 921df28..255f2f2 100644 --- a/vendor/twig/twig/src/Extension/SandboxExtension.php +++ b/vendor/twig/twig/src/Extension/SandboxExtension.php @@ -119,6 +119,12 @@ final class SandboxExtension extends AbstractExtension public function ensureToStringAllowed($obj, int $lineno = -1, ?Source $source = null) { + if (\is_array($obj)) { + $this->ensureToStringAllowedForArray($obj, $lineno, $source); + + return $obj; + } + if ($this->isSandboxed($source) && \is_object($obj) && method_exists($obj, '__toString')) { try { $this->policy->checkMethodAllowed($obj, '__toString'); @@ -132,4 +138,45 @@ final class SandboxExtension extends AbstractExtension return $obj; } + + private function ensureToStringAllowedForArray(array $obj, int $lineno, ?Source $source, array &$stack = []): void + { + foreach ($obj as $k => $v) { + if (!$v) { + continue; + } + + if (!\is_array($v)) { + $this->ensureToStringAllowed($v, $lineno, $source); + continue; + } + + if (\PHP_VERSION_ID < 70400) { + static $cookie; + + if ($v === $cookie ?? $cookie = new \stdClass()) { + continue; + } + + $obj[$k] = $cookie; + try { + $this->ensureToStringAllowedForArray($v, $lineno, $source, $stack); + } finally { + $obj[$k] = $v; + } + + continue; + } + + if ($r = \ReflectionReference::fromArrayElement($obj, $k)) { + if (isset($stack[$r->getId()])) { + continue; + } + + $stack[$r->getId()] = true; + } + + $this->ensureToStringAllowedForArray($v, $lineno, $source, $stack); + } + } } diff --git a/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php b/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php index 29a446b..f54f2f0 100644 --- a/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php +++ b/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php @@ -31,6 +31,7 @@ class GetAttrExpression extends AbstractExpression public function compile(Compiler $compiler): void { $env = $compiler->getEnvironment(); + $arrayAccessSandbox = false; // optimize array calls if ( @@ -44,17 +45,35 @@ class GetAttrExpression extends AbstractExpression ->raw('(('.$var.' = ') ->subcompile($this->getNode('node')) ->raw(') && is_array(') - ->raw($var) + ->raw($var); + + if (!$env->hasExtension(SandboxExtension::class)) { + $compiler + ->raw(') || ') + ->raw($var) + ->raw(' instanceof ArrayAccess ? (') + ->raw($var) + ->raw('[') + ->subcompile($this->getNode('attribute')) + ->raw('] ?? null) : null)') + ; + + return; + } + + $arrayAccessSandbox = true; + + $compiler ->raw(') || ') ->raw($var) - ->raw(' instanceof ArrayAccess ? (') + ->raw(' instanceof ArrayAccess && in_array(') + ->raw('get_class('.$var.')') + ->raw(', CoreExtension::ARRAY_LIKE_CLASSES, true) ? (') ->raw($var) ->raw('[') ->subcompile($this->getNode('attribute')) - ->raw('] ?? null) : null)') + ->raw('] ?? null) : ') ; - - return; } $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, '); @@ -83,5 +102,9 @@ class GetAttrExpression extends AbstractExpression ->raw(', ')->repr($this->getNode('node')->getTemplateLine()) ->raw(')') ; + + if ($arrayAccessSandbox) { + $compiler->raw(')'); + } } } diff --git a/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php index 6802088..7cc1c2e 100644 --- a/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php @@ -15,12 +15,14 @@ use Twig\Environment; use Twig\Node\CheckSecurityCallNode; use Twig\Node\CheckSecurityNode; use Twig\Node\CheckToStringNode; +use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\Binary\ConcatBinary; use Twig\Node\Expression\Binary\RangeBinary; use Twig\Node\Expression\FilterExpression; use Twig\Node\Expression\FunctionExpression; use Twig\Node\Expression\GetAttrExpression; use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\Unary\SpreadUnary; use Twig\Node\ModuleNode; use Twig\Node\Node; use Twig\Node\PrintNode; @@ -120,7 +122,18 @@ final class SandboxNodeVisitor implements NodeVisitorInterface { $expr = $node->getNode($name); if (($expr instanceof NameExpression || $expr instanceof GetAttrExpression) && !$expr->isGenerator()) { - $node->setNode($name, new CheckToStringNode($expr)); + // Simplify in 4.0 as the spread attribute has been removed there + $new = new CheckToStringNode($expr); + if ($expr->hasAttribute('spread')) { + $new->setAttribute('spread', $expr->getAttribute('spread')); + } + $node->setNode($name, $new); + } elseif ($expr instanceof SpreadUnary) { + $this->wrapNode($expr, 'node'); + } elseif ($expr instanceof ArrayExpression) { + foreach ($expr as $name => $_) { + $this->wrapNode($expr, $name); + } } }