From f4e42ad3d401d8ed439a0f611bf1a760cf667dd3 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Wed, 30 Sep 2020 17:56:30 +0200 Subject: [PATCH 1/8] Fix redis connection error message Use correct instance of redis to getLastError --- .../Component/Messenger/Transport/RedisExt/Connection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php index 007c2ffd9d..560200714f 100644 --- a/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php @@ -61,11 +61,11 @@ class Connection } if (null !== $auth && !$this->connection->auth($auth)) { - throw new InvalidArgumentException('Redis connection failed: '.$redis->getLastError()); + throw new InvalidArgumentException('Redis connection failed: '.$this->connection->getLastError()); } if (($dbIndex = $configuration['dbindex'] ?? self::DEFAULT_OPTIONS['dbindex']) && !$this->connection->select($dbIndex)) { - throw new InvalidArgumentException('Redis connection failed: '.$redis->getLastError()); + throw new InvalidArgumentException('Redis connection failed: '.$this->connection->getLastError()); } foreach (['stream', 'group', 'consumer'] as $key) { From 9d187c0d1a9ab33489162777d51ac9f798175cb1 Mon Sep 17 00:00:00 2001 From: Andreas Date: Wed, 30 Sep 2020 17:28:20 +0200 Subject: [PATCH 2/8] Adjust expired range check Include current second when deciding if cooke has expired. --- src/Symfony/Component/BrowserKit/Cookie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index e6159da74d..b57af03448 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -296,6 +296,6 @@ class Cookie */ public function isExpired() { - return null !== $this->expires && 0 != $this->expires && $this->expires < time(); + return null !== $this->expires && 0 != $this->expires && $this->expires <= time(); } } From 7c34f6e866ceaae45c1ea0b24db897d5f69a9c75 Mon Sep 17 00:00:00 2001 From: David Molineus Date: Tue, 29 Sep 2020 23:35:47 +0200 Subject: [PATCH 3/8] [TwigBundle] Only remove kernel exception listener if twig is used --- .../Compiler/ExceptionListenerPass.php | 18 +++-- .../Compiler/ExceptionListenerPassTest.php | 79 +++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExceptionListenerPassTest.php diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php index d06b8e8199..c21507dca8 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExceptionListenerPass.php @@ -33,15 +33,19 @@ class ExceptionListenerPass implements CompilerPassInterface // register the exception listener only if it's currently used, else use the provided by FrameworkBundle if (null === $container->getParameter('twig.exception_listener.controller') && $container->hasDefinition('exception_listener')) { $container->removeDefinition('twig.exception_listener'); - } else { - $container->removeDefinition('exception_listener'); - if ($container->hasParameter('templating.engines')) { - $engines = $container->getParameter('templating.engines'); - if (!\in_array('twig', $engines, true)) { - $container->removeDefinition('twig.exception_listener'); - } + return; + } + + if ($container->hasParameter('templating.engines')) { + $engines = $container->getParameter('templating.engines'); + if (\in_array('twig', $engines, true)) { + $container->removeDefinition('exception_listener'); + + return; } } + + $container->removeDefinition('twig.exception_listener'); } } diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExceptionListenerPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExceptionListenerPassTest.php new file mode 100644 index 0000000000..cc7558f6e6 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExceptionListenerPassTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\ExceptionListenerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Security\Http\Firewall\ExceptionListener; +use Twig\Environment; + +class ExceptionListenerPassTest extends TestCase +{ + public function testExitsWhenTwigIsNotAvailable(): void + { + $builder = new ContainerBuilder(); + $builder->register('exception_listener', ExceptionListener::class); + $builder->register('twig.exception_listener', ExceptionListener::class); + + ($pass = new ExceptionListenerPass())->process($builder); + + $this->assertTrue($builder->hasDefinition('exception_listener')); + $this->assertTrue($builder->hasDefinition('twig.exception_listener')); + } + + public function testRemovesTwigExceptionListenerWhenNoExceptionListenerControllerExists(): void + { + $builder = new ContainerBuilder(); + $builder->register('twig', Environment::class); + $builder->register('exception_listener', ExceptionListener::class); + $builder->register('twig.exception_listener', ExceptionListener::class); + $builder->setParameter('twig.exception_listener.controller', null); + + ($pass = new ExceptionListenerPass())->process($builder); + + $this->assertTrue($builder->hasDefinition('exception_listener')); + $this->assertFalse($builder->hasDefinition('twig.exception_listener')); + } + + public function testRemovesTwigExceptionListenerIfTwigIsNotUsedAsTemplateEngine(): void + { + $builder = new ContainerBuilder(); + $builder->register('twig', Environment::class); + $builder->register('exception_listener', ExceptionListener::class); + $builder->register('twig.exception_listener', ExceptionListener::class); + $builder->setParameter('twig.exception_listener.controller', 'exception_controller::showAction'); + $builder->setParameter('templating.engines', ['php']); + + ($pass = new ExceptionListenerPass())->process($builder); + + $this->assertTrue($builder->hasDefinition('exception_listener')); + $this->assertFalse($builder->hasDefinition('twig.exception_listener')); + } + + public function testRemovesKernelExceptionListenerIfTwigIsUsedAsTemplateEngine(): void + { + $builder = new ContainerBuilder(); + $builder->register('twig', Environment::class); + $builder->register('exception_listener', ExceptionListener::class); + $builder->register('twig.exception_listener', ExceptionListener::class); + $builder->setParameter('twig.exception_listener.controller', 'exception_controller::showAction'); + $builder->setParameter('templating.engines', ['twig']); + + ($pass = new ExceptionListenerPass())->process($builder); + + $this->assertFalse($builder->hasDefinition('exception_listener')); + $this->assertTrue($builder->hasDefinition('twig.exception_listener')); + } +} From 7e0cd4e62135d2e7f9260901dbdb098660c876b4 Mon Sep 17 00:00:00 2001 From: Bohan Yang Date: Thu, 1 Oct 2020 18:50:45 +0800 Subject: [PATCH 4/8] [HttpClient] Fix using https with proxies --- src/Symfony/Component/HttpClient/NativeHttpClient.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index ac6ee58246..9fcfb4ad2a 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -225,7 +225,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $resolveRedirect = self::createRedirectResolver($options, $host, $proxy, $noProxy, $info, $onProgress); $context = stream_context_create($context, ['notification' => $notification]); - self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, $noProxy); + self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, $noProxy, 'https:' === $url['scheme']); return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolveRedirect, $onProgress, $this->logger); } @@ -411,14 +411,14 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac // Authorization and Cookie headers MUST NOT follow except for the initial host name $requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; $requestHeaders[] = 'Host: '.$host.$port; - self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, $noProxy); + self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, $noProxy, 'https:' === $url['scheme']); } return implode('', $url); }; } - private static function configureHeadersAndProxy($context, string $host, array $requestHeaders, ?array $proxy, array $noProxy) + private static function configureHeadersAndProxy($context, string $host, array $requestHeaders, ?array $proxy, array $noProxy, bool $isSsl) { if (null === $proxy) { return stream_context_set_option($context, 'http', 'header', $requestHeaders); @@ -435,7 +435,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac } stream_context_set_option($context, 'http', 'proxy', $proxy['url']); - stream_context_set_option($context, 'http', 'request_fulluri', true); + stream_context_set_option($context, 'http', 'request_fulluri', !$isSsl); if (null !== $proxy['auth']) { $requestHeaders[] = 'Proxy-Authorization: '.$proxy['auth']; From bbd12fe27f83679e21d8ec6052b4cfb6d6df5d95 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 1 Oct 2020 18:21:20 +0200 Subject: [PATCH 5/8] [ErrorHandler][DebugClassLoader] Do not check Mockery mocks classes --- src/Symfony/Component/ErrorHandler/DebugClassLoader.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php index bb35bdc29e..79ab0b07d6 100644 --- a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php +++ b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php @@ -13,6 +13,7 @@ namespace Symfony\Component\ErrorHandler; use Doctrine\Common\Persistence\Proxy as LegacyProxy; use Doctrine\Persistence\Proxy; +use Mockery\MockInterface; use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; use PHPUnit\Framework\MockObject\MockObject; use Prophecy\Prophecy\ProphecySubjectInterface; @@ -306,6 +307,7 @@ class DebugClassLoader && !is_subclass_of($symbols[$i], Proxy::class) && !is_subclass_of($symbols[$i], ProxyInterface::class) && !is_subclass_of($symbols[$i], LegacyProxy::class) + && !is_subclass_of($symbols[$i], MockInterface::class) ) { $loader->checkClass($symbols[$i]); } From 826db225b7bf325619883a9bc6ba98bd7e04aecb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Oct 2020 18:25:17 +0200 Subject: [PATCH 6/8] [Routing] fix using !important and defaults/reqs in inline route definitions --- src/Symfony/Component/Routing/Route.php | 2 +- src/Symfony/Component/Routing/Tests/RouteTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index de98e1d763..7f20c794c9 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -137,7 +137,7 @@ class Route implements \Serializable public function setPath($pattern) { if (false !== strpbrk($pattern, '?<')) { - $pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { + $pattern = preg_replace_callback('#\{(!?\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { if (isset($m[3][0])) { $this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null); } diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index 4c767f9d95..c02af42ce7 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -208,6 +208,7 @@ class RouteTest extends TestCase $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null), new Route('/foo/{bar?}')); $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}')); $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}')); + $this->assertEquals((new Route('/foo/{!bar}'))->setDefault('!bar', 'baz'), new Route('/foo/{!bar?baz}')); $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?}', ['bar' => 'baz'])); $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>}')); From 1a801e8452e0cc45f2143af267b3c4e347744109 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 2 Oct 2020 09:32:33 +0200 Subject: [PATCH 7/8] [4.4] Ignore more deprecations for Mockery mocks --- src/Symfony/Bridge/Monolog/Logger.php | 4 ++-- src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php | 4 ++-- src/Symfony/Component/BrowserKit/Client.php | 2 +- src/Symfony/Component/Config/Loader/FileLoader.php | 2 +- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- src/Symfony/Component/Finder/Finder.php | 2 +- .../Core/Authentication/Token/Storage/TokenStorage.php | 2 +- .../Component/Serializer/Normalizer/AbstractNormalizer.php | 2 +- src/Symfony/Component/Translation/Extractor/PhpExtractor.php | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bridge/Monolog/Logger.php b/src/Symfony/Bridge/Monolog/Logger.php index f3a850093c..336d2e7f0d 100644 --- a/src/Symfony/Bridge/Monolog/Logger.php +++ b/src/Symfony/Bridge/Monolog/Logger.php @@ -29,7 +29,7 @@ class Logger extends BaseLogger implements DebugLoggerInterface, ResetInterface */ public function getLogs(/* Request $request = null */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "Request $request = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } @@ -47,7 +47,7 @@ class Logger extends BaseLogger implements DebugLoggerInterface, ResetInterface */ public function countErrors(/* Request $request = null */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "Request $request = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } diff --git a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php index eefdcc6d11..6eec887d6f 100644 --- a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php @@ -63,7 +63,7 @@ class DebugProcessor implements DebugLoggerInterface, ResetInterface */ public function getLogs(/* Request $request = null */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "Request $request = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } @@ -85,7 +85,7 @@ class DebugProcessor implements DebugLoggerInterface, ResetInterface */ public function countErrors(/* Request $request = null */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "Request $request = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index 4c42f53d16..ce6e34ea16 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -314,7 +314,7 @@ abstract class Client */ public function submit(Form $form, array $values = []/*, array $serverParameters = []*/) { - if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "array $serverParameters = []" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', static::class.'::'.__FUNCTION__), \E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index f006a1bef8..e87230785b 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -73,7 +73,7 @@ abstract class FileLoader extends Loader */ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null/*, $exclude = null*/) { - if (\func_num_args() < 5 && __CLASS__ !== static::class && 0 !== strpos(static::class, 'Symfony\Component\\') && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 5 && __CLASS__ !== static::class && 0 !== strpos(static::class, 'Symfony\Component\\') && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "$exclude = null" argument in version 5.0, not defining it is deprecated since Symfony 4.4.', __METHOD__), \E_USER_DEPRECATED); } $exclude = \func_num_args() >= 5 ? func_get_arg(4) : null; diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 75a978eb86..ae7369b4ec 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -536,7 +536,7 @@ class Crawler implements \Countable, \IteratorAggregate */ public function children(/* string $selector = null */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "string $selector = null" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } $selector = 0 < \func_num_args() ? func_get_arg(0) : null; diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index c97422d517..ebc6c6860e 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -440,7 +440,7 @@ class Finder implements \IteratorAggregate, \Countable */ public function sortByName(/* bool $useNaturalSort = false */) { - if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 1 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "bool $useNaturalSort = false" argument in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } $useNaturalSort = 0 < \func_num_args() && func_get_arg(0); diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php index 61ece1aaa9..7aea15c98e 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php @@ -45,7 +45,7 @@ class TokenStorage implements TokenStorageInterface, ResetInterface */ public function setToken(TokenInterface $token = null) { - if (null !== $token && !method_exists($token, 'getRoleNames') && !$token instanceof \PHPUnit\Framework\MockObject\MockObject && !$token instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (null !== $token && !method_exists($token, 'getRoleNames') && !$token instanceof \PHPUnit\Framework\MockObject\MockObject && !$token instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$token instanceof \Mockery\MockInterface) { @trigger_error(sprintf('Not implementing the "%s::getRoleNames()" method in "%s" is deprecated since Symfony 4.3.', TokenInterface::class, \get_class($token)), \E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 64f3f577d5..8830f13cf7 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -316,7 +316,7 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn */ protected function handleCircularReference($object/*, string $format = null, array $context = []*/) { - if (\func_num_args() < 2 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 2 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have two new "string $format = null" and "array $context = []" arguments in version 5.0, not defining it is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED); } $format = \func_num_args() > 1 ? func_get_arg(1) : null; diff --git a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php index 417586a935..edea36769c 100644 --- a/src/Symfony/Component/Translation/Extractor/PhpExtractor.php +++ b/src/Symfony/Component/Translation/Extractor/PhpExtractor.php @@ -200,7 +200,7 @@ class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface */ protected function parseTokens($tokens, MessageCatalogue $catalog/*, string $filename*/) { - if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) { + if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { @trigger_error(sprintf('The "%s()" method will have a new "string $filename" argument in version 5.0, not defining it is deprecated since Symfony 4.3.', __METHOD__), \E_USER_DEPRECATED); } $filename = 2 < \func_num_args() ? func_get_arg(2) : ''; From 28f301bf0345a6edf3042b8fe1b62227fa6afb5a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Oct 2020 20:00:40 +0200 Subject: [PATCH 8/8] [HttpClient] fix using proxies with NativeHttpClient --- .../Component/HttpClient/NativeHttpClient.php | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index 9fcfb4ad2a..0710b7a72b 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -171,7 +171,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $this->logger && $this->logger->info(sprintf('Request: "%s %s"', $method, implode('', $url))); - [$host, $port, $url['authority']] = self::dnsResolve($url, $this->multi, $info, $onProgress); + [$host, $port] = self::parseHostPort($url, $info); if (!isset($options['normalized_headers']['host'])) { $options['headers'][] = 'Host: '.$host.$port; @@ -198,7 +198,6 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac 'follow_location' => false, // We follow redirects ourselves - the native logic is too limited ], 'ssl' => array_filter([ - 'peer_name' => $host, 'verify_peer' => $options['verify_peer'], 'verify_peer_name' => $options['verify_host'], 'cafile' => $options['cafile'], @@ -225,7 +224,11 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $resolveRedirect = self::createRedirectResolver($options, $host, $proxy, $noProxy, $info, $onProgress); $context = stream_context_create($context, ['notification' => $notification]); - self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, $noProxy, 'https:' === $url['scheme']); + + if (!self::configureHeadersAndProxy($context, $host, $options['headers'], $proxy, $noProxy, 'https:' === $url['scheme'])) { + $ip = self::dnsResolve($host, $this->multi, $info, $onProgress); + $url['authority'] = substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host)); + } return new NativeResponse($this->multi, $context, implode('', $url), $options, $info, $resolveRedirect, $onProgress, $this->logger); } @@ -306,9 +309,9 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac } /** - * Resolves the IP of the host using the local DNS cache if possible. + * Extracts the host and the port from the URL. */ - private static function dnsResolve(array $url, NativeClientState $multi, array &$info, ?\Closure $onProgress): array + private static function parseHostPort(array $url, array &$info): array { if ($port = parse_url($url['authority'], \PHP_URL_PORT) ?: '') { $info['primary_port'] = $port; @@ -317,8 +320,14 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $info['primary_port'] = 'http:' === $url['scheme'] ? 80 : 443; } - $host = parse_url($url['authority'], \PHP_URL_HOST); + return [parse_url($url['authority'], \PHP_URL_HOST), $port]; + } + /** + * Resolves the IP of the host using the local DNS cache if possible. + */ + private static function dnsResolve($host, NativeClientState $multi, array &$info, ?\Closure $onProgress): string + { if (null === $ip = $multi->dnsCache[$host] ?? null) { $info['debug'] .= "* Hostname was NOT found in DNS cache\n"; $now = microtime(true); @@ -341,7 +350,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $onProgress(); } - return [$host, $port, substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host))]; + return $ip; } /** @@ -404,24 +413,33 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac } } - [$host, $port, $url['authority']] = self::dnsResolve($url, $multi, $info, $onProgress); - stream_context_set_option($context, 'ssl', 'peer_name', $host); + [$host, $port] = self::parseHostPort($url, $info); if (false !== (parse_url($location, \PHP_URL_HOST) ?? false)) { // Authorization and Cookie headers MUST NOT follow except for the initial host name $requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth']; $requestHeaders[] = 'Host: '.$host.$port; - self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, $noProxy, 'https:' === $url['scheme']); + $dnsResolve = !self::configureHeadersAndProxy($context, $host, $requestHeaders, $proxy, $noProxy, 'https:' === $url['scheme']); + } else { + $dnsResolve = isset(stream_context_get_options($context)['ssl']['peer_name']); + } + + if ($dnsResolve) { + $ip = self::dnsResolve($host, $multi, $info, $onProgress); + $url['authority'] = substr_replace($url['authority'], $ip, -\strlen($host) - \strlen($port), \strlen($host)); } return implode('', $url); }; } - private static function configureHeadersAndProxy($context, string $host, array $requestHeaders, ?array $proxy, array $noProxy, bool $isSsl) + private static function configureHeadersAndProxy($context, string $host, array $requestHeaders, ?array $proxy, array $noProxy, bool $isSsl): bool { if (null === $proxy) { - return stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'ssl', 'peer_name', $host); + + return false; } // Matching "no_proxy" should follow the behavior of curl @@ -430,17 +448,24 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac $dotRule = '.'.ltrim($rule, '.'); if ('*' === $rule || $host === $rule || substr($host, -\strlen($dotRule)) === $dotRule) { - return stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'http', 'proxy', null); + stream_context_set_option($context, 'http', 'request_fulluri', false); + stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'ssl', 'peer_name', $host); + + return false; } } - stream_context_set_option($context, 'http', 'proxy', $proxy['url']); - stream_context_set_option($context, 'http', 'request_fulluri', !$isSsl); - if (null !== $proxy['auth']) { $requestHeaders[] = 'Proxy-Authorization: '.$proxy['auth']; } - return stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'http', 'proxy', $proxy['url']); + stream_context_set_option($context, 'http', 'request_fulluri', !$isSsl); + stream_context_set_option($context, 'http', 'header', $requestHeaders); + stream_context_set_option($context, 'ssl', 'peer_name', null); + + return true; } }