From 7b2e2df5ec61065de79903df3fc197f9e5f64855 Mon Sep 17 00:00:00 2001 From: Lance Chen Date: Tue, 10 Feb 2015 04:14:34 +0800 Subject: [PATCH 01/20] Handled bearer authorization header in REDIRECT_ form Apache rewrite module renames client request header (`HTTP_`) by prepending `REDIRECT_` to it. http basic authentication and http digest authentication are properly processed in REDIRECT_ form, while bearer is processed in HTTP_ form, but dropped in REDIRECT_ form. --- src/Symfony/Component/HttpFoundation/ServerBag.php | 7 +++++++ .../Component/HttpFoundation/Tests/ServerBagTest.php | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/ServerBag.php b/src/Symfony/Component/HttpFoundation/ServerBag.php index 6a4f2c2b16..fa1cb2fc9f 100644 --- a/src/Symfony/Component/HttpFoundation/ServerBag.php +++ b/src/Symfony/Component/HttpFoundation/ServerBag.php @@ -75,6 +75,13 @@ class ServerBag extends ParameterBag // 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. + * http://php.net/manual/en/reserved.variables.server.php + */ + $headers['AUTHORIZATION'] = $authorizationHeader; } } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php index 7bc8f02c30..20773c4d7a 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php @@ -141,4 +141,14 @@ class ServerBagTest extends \PHPUnit_Framework_TestCase 'AUTHORIZATION' => $headerContent, ), $bag->getHeaders()); } + + public function testOAuthBearerAuthWithRedirect() + { + $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo'; + $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => $headerContent)); + + $this->assertEquals(array( + 'AUTHORIZATION' => $headerContent, + ), $bag->getHeaders()); + } } From 6d403a7795c67613c805ebd4a1a787f0cf7c09fe Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Tue, 21 Apr 2015 20:02:11 +0100 Subject: [PATCH 02/20] [Framework] added test for Router commands. --- .../Tests/Command/RouterDebugCommandTest.php | 89 ++++++++++++++++++ .../Tests/Command/RouterMatchCommandTest.php | 93 +++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php new file mode 100644 index 0000000000..bf5e183caa --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class RouterDebugCommandTest extends \PHPUnit_Framework_TestCase +{ + public function testDebugAllRoutes() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('name' => null)); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('[router] Current routes', $tester->getDisplay()); + } + + public function testDebugSingleRoute() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('name' => 'foo')); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('[router] Route "foo"', $tester->getDisplay()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testDebugInvalidRoute() + { + $this->createCommandTester()->execute(array('name' => 'test')); + } + + /** + * @return CommandTester + */ + private function createCommandTester() + { + $application = new Application(); + + $command = new RouterDebugCommand(); + $command->setContainer($this->getContainer()); + $application->add($command); + + return new CommandTester($application->find('router:debug')); + } + + private function getContainer() + { + $routeCollection = new RouteCollection(); + $routeCollection->add('foo', new Route('foo')); + $router = $this->getMock('Symfony\Component\Routing\RouterInterface'); + $router + ->expects($this->atLeastOnce()) + ->method('getRouteCollection') + ->will($this->returnValue($routeCollection)) + ; + + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container + ->expects($this->once()) + ->method('has') + ->with('router') + ->will($this->returnValue(true)) + ; + $container + ->expects($this->atLeastOnce()) + ->method('get') + ->with('router') + ->will($this->returnValue($router)) + ; + + return $container; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php new file mode 100644 index 0000000000..918ba02f6d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; +use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +class RouterMatchCommandTest extends \PHPUnit_Framework_TestCase +{ + public function testWithMatchPath() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('path_info' => '/foo', 'foo')); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('[router] Route "foo"', $tester->getDisplay()); + } + + public function testWithNotMatchPath() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('path_info' => '/test', 'foo')); + + $this->assertEquals(1, $ret, 'Returns 1 in case of failure'); + $this->assertContains('None of the routes match the path "/test"', $tester->getDisplay()); + } + + /** + * @return CommandTester + */ + private function createCommandTester() + { + $application = new Application(); + + $command = new RouterMatchCommand(); + $command->setContainer($this->getContainer()); + $application->add($command); + + $command = new RouterDebugCommand(); + $command->setContainer($this->getContainer()); + $application->add($command); + + return new CommandTester($application->find('router:match')); + } + + private function getContainer() + { + $routeCollection = new RouteCollection(); + $routeCollection->add('foo', new Route('foo')); + $requestContext = new RequestContext(); + $router = $this->getMock('Symfony\Component\Routing\RouterInterface'); + $router + ->expects($this->any()) + ->method('getRouteCollection') + ->will($this->returnValue($routeCollection)) + ; + $router + ->expects($this->any()) + ->method('getContext') + ->will($this->returnValue($requestContext)) + ; + + $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $container + ->expects($this->once()) + ->method('has') + ->with('router') + ->will($this->returnValue(true)) + ; + $container + ->expects($this->atLeastOnce()) + ->method('get') + ->with('router') + ->will($this->returnValue($router)) + ; + + return $container; + } +} From 34c780f7e7c117e2e134dabc29b2020500e6c48a Mon Sep 17 00:00:00 2001 From: MatTheCat Date: Sun, 10 May 2015 23:45:50 +0200 Subject: [PATCH 03/20] [Security][Translation] fixes #14584 --- .../Security/Resources/translations/security.fr.xlf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Security/Resources/translations/security.fr.xlf b/src/Symfony/Component/Security/Resources/translations/security.fr.xlf index f3965d3fb3..5a77c6e9ff 100644 --- a/src/Symfony/Component/Security/Resources/translations/security.fr.xlf +++ b/src/Symfony/Component/Security/Resources/translations/security.fr.xlf @@ -8,7 +8,7 @@ Authentication credentials could not be found. - Les droits d'authentification n'ont pas pu être trouvés. + Les identifiants d'authentification n'ont pas pu être trouvés. Authentication request could not be processed due to a system problem. @@ -16,7 +16,7 @@ Invalid credentials. - Droits invalides. + Identifiants invalides. Cookie has already been used by someone else. @@ -24,7 +24,7 @@ Not privileged to request the resource. - Pas de privilèges pour accéder à la ressource. + Privilèges insuffisants pour accéder à la ressource. Invalid CSRF token. @@ -40,7 +40,7 @@ No session available, it either timed out or cookies are not enabled. - Pas de session disponible, celle-ci a expiré ou les cookies ne sont pas activés. + Aucune session disponible, celle-ci a expiré ou les cookies ne sont pas activés. No token could be found. @@ -48,7 +48,7 @@ Username could not be found. - Le nom d'utilisateur ne peut pas être trouvé. + Le nom d'utilisateur n'a pas pu être trouvé. Account has expired. @@ -56,7 +56,7 @@ Credentials have expired. - Les droits ont expirés. + Les identifiants ont expiré. Account is disabled. From 5930800cfd904db6e8c646e5e90756d346268c96 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Thu, 14 May 2015 15:46:43 +0100 Subject: [PATCH 04/20] [HttpKernel] Handle an array vary header in the http cache store --- src/Symfony/Component/HttpKernel/HttpCache/Store.php | 2 +- .../Component/HttpKernel/Tests/HttpCache/StoreTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index fcd9a25254..4901e2cf29 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -127,7 +127,7 @@ class Store implements StoreInterface // find a cached entry that matches the request. $match = null; foreach ($entries as $entry) { - if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? $entry[1]['vary'][0] : '', $request->headers->all(), $entry[0])) { + if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) { $match = $entry; break; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index f1efcda3fe..b0ac57adc2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -168,6 +168,16 @@ class StoreTest extends \PHPUnit_Framework_TestCase $this->assertNull($this->store->lookup($req2)); } + public function testDoesNotReturnEntriesThatSlightlyVaryWithLookup() + { + $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bam')); + $res = new Response('test', 200, array('Vary' => array('Foo', 'Bar'))); + $this->store->write($req1, $res); + + $this->assertNull($this->store->lookup($req2)); + } + public function testStoresMultipleResponsesForEachVaryCombination() { $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); From ec89cfd226097a53d41b422a7c3c02cd573b7e0f Mon Sep 17 00:00:00 2001 From: Antoine Makdessi Date: Fri, 15 May 2015 16:06:52 +0200 Subject: [PATCH 05/20] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f07f64d466..de0feaacd0 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ work for you: Installation ------------ -The best way to install Symfony is to download the Symfony Standard Edition -available at . +The best way to install Symfony is to use the [official Symfony Installer][7]. +It allows you to start a new project based on the version you want. Documentation ------------- @@ -64,3 +64,4 @@ Information on how to run the Symfony test suite can be found in the [4]: https://symfony.com/doc/current/contributing/code/patches.html#check-list [5]: https://symfony.com/doc/current/contributing/code/patches.html#make-a-pull-request [6]: https://symfony.com/doc/master/contributing/code/tests.html +[7]: https://symfony.com/doc/current/book/installation.html#installing-the-symfony-installer From 294cbb75214aa612f63caa2b711a36f80f03b1f7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 16 May 2015 14:34:16 +0200 Subject: [PATCH 06/20] fixed typo --- src/Symfony/Component/Serializer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/README.md b/src/Symfony/Component/Serializer/README.md index 4d8ab012e9..156a288426 100644 --- a/src/Symfony/Component/Serializer/README.md +++ b/src/Symfony/Component/Serializer/README.md @@ -1,7 +1,7 @@ Serializer Component ==================== -With the Serializer component its possible to handle serializing data structures, +With the Serializer component it's possible to handle serializing data structures, including object graphs, into array structures or other formats like XML and JSON. It can also handle deserializing XML and JSON back to object graphs. From 7259d726761a6bfff379d87b9d2b36fe2200558b Mon Sep 17 00:00:00 2001 From: Kovacs Nicolas Date: Tue, 10 Feb 2015 11:19:29 +0100 Subject: [PATCH 07/20] WebProfiler break words WebProfiler CSS word-break: break-all; --- src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css b/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css index fa4d076917..6b81755056 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/public/css/body.css @@ -52,6 +52,7 @@ build: 56 background-color: #FFFFFF; border: 1px solid #dfdfdf; padding: 40px 50px; + word-break: break-all; } .sf-reset h2 { font-size: 16px; From cafb0d7b11ba78072888c2dd71b088425072164b Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Tue, 7 Apr 2015 19:26:50 +0100 Subject: [PATCH 08/20] [TwigBundle] Refresh twig paths when resources change. --- .../Bundle/TwigBundle/DependencyInjection/TwigExtension.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 9b6f806f04..a8c89f3b9d 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -66,22 +67,26 @@ class TwigExtension extends Extension } else { $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace)); } + $container->addResource(new DirectoryResource($path)); } // register bundles as Twig namespaces foreach ($container->getParameter('kernel.bundles') as $bundle => $class) { if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$bundle.'/views')) { $this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle); + $container->addResource(new DirectoryResource($dir)); } $reflection = new \ReflectionClass($class); if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/views')) { $this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle); + $container->addResource(new DirectoryResource($dir)); } } if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) { $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir)); + $container->addResource(new DirectoryResource($dir)); } if (!empty($config['globals'])) { From 4a4eda93c81f4a0bc9a4ebf00da7aa69e9ee29a4 Mon Sep 17 00:00:00 2001 From: Arnaud Kleinpeter Date: Mon, 18 May 2015 19:58:47 +0200 Subject: [PATCH 09/20] [Console] Delete duplicate test in CommandTest There is no __get method in the Command class, and the deleted test was duplicated with the preceding one. --- .../Component/Console/Tests/Command/CommandTest.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 1249dbc5c4..1ae12874ba 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -167,15 +167,6 @@ class CommandTest extends \PHPUnit_Framework_TestCase $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper'); } - public function testGet() - { - $application = new Application(); - $command = new \TestCommand(); - $command->setApplication($application); - $formatterHelper = new FormatterHelper(); - $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->__get() returns the correct helper'); - } - public function testMergeApplicationDefinition() { $application1 = new Application(); From 991e65c96f82074c0178c1957025ecfcfa6801cb Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 12 May 2015 18:59:01 +0100 Subject: [PATCH 10/20] [DomCrawler] Throw an exception if a form field path is incomplete. --- .../DomCrawler/FormFieldRegistry.php | 6 +++-- .../Component/DomCrawler/Tests/FormTest.php | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php index 6a38e86691..edb2788910 100644 --- a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php +++ b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php @@ -124,13 +124,15 @@ class FormFieldRegistry public function set($name, $value) { $target = &$this->get($name); - if (!is_array($value) || $target instanceof Field\ChoiceFormField) { + if ((!is_array($value) && $target instanceof Field\FormField) || $target instanceof Field\ChoiceFormField) { $target->setValue($value); - } else { + } elseif (is_array($value)) { $fields = self::create($name, $value); foreach ($fields->all() as $k => $v) { $this->set($k, $v); } + } else { + throw new \InvalidArgumentException(sprintf('Cannot set value on a compound field "%s".', $name)); } } diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index a85a846ba2..c657e3639e 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -787,6 +787,31 @@ class FormTest extends \PHPUnit_Framework_TestCase )); } + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Cannot set value on a compound field "foo[bar]". + */ + public function testFormRegistrySetValueOnCompoundField() + { + $registry = new FormFieldRegistry(); + $registry->add($this->getFormFieldMock('foo[bar][baz]')); + + $registry->set('foo[bar]', 'fbb'); + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Unreachable field "0" + */ + public function testFormRegistrySetArrayOnNotCompoundField() + { + + $registry = new FormFieldRegistry(); + $registry->add($this->getFormFieldMock('bar')); + + $registry->set('bar', array('baz')); + } + public function testDifferentFieldTypesWithSameName() { $dom = new \DOMDocument(); From 7a4394e77110453ca2e1aa2d4fd3cb9da28a8d32 Mon Sep 17 00:00:00 2001 From: Thomas Schulz Date: Mon, 18 May 2015 16:39:35 +0200 Subject: [PATCH 11/20] [FrameworkBundle] Removed unnecessary parameter in TemplateController Response::setPublic doesn't have any parameters, so this parameter call is not needed. --- .../Bundle/FrameworkBundle/Controller/TemplateController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php index bed6824611..16d15f9023 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php @@ -47,7 +47,7 @@ class TemplateController extends ContainerAware if ($private) { $response->setPrivate(); } elseif ($private === false || (null === $private && ($maxAge || $sharedAge))) { - $response->setPublic($private); + $response->setPublic(); } return $response; From 385a6b799f430b1d53f7928459018d2a3582137b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 19 May 2015 17:07:30 -0700 Subject: [PATCH 12/20] Fix HTML escaping of to-source links --- .../Bridge/Twig/Extension/CodeExtension.php | 2 +- .../Templating/Helper/CodeHelper.php | 17 +++++++++-------- .../Component/Debug/ExceptionHandler.php | 7 ++++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 651d75f26f..d9ba2c05bd 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -49,7 +49,7 @@ class CodeExtension extends \Twig_Extension new \Twig_SimpleFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))), new \Twig_SimpleFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('file_link', array($this, 'getFileLink'), array('is_safe' => array('html'))), + new \Twig_SimpleFilter('file_link', array($this, 'getFileLink')), ); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 78c0b462f2..87aede2273 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -154,24 +154,25 @@ class CodeHelper extends Helper */ public function formatFile($file, $line, $text = null) { + if (PHP_VERSION_ID >= 50400) { + $flags = ENT_QUOTES | ENT_SUBSTITUTE; + } else { + $flags = ENT_QUOTES; + } + if (null === $text) { $file = trim($file); $fileStr = $file; if (0 === strpos($fileStr, $this->rootDir)) { $fileStr = str_replace($this->rootDir, '', str_replace('\\', '/', $fileStr)); - $fileStr = sprintf('kernel.root_dir/%s', $this->rootDir, $fileStr); + $fileStr = htmlspecialchars($fileStr, $flags, $this->charset); + $fileStr = sprintf('kernel.root_dir/%s', htmlspecialchars($this->rootDir, $flags, $this->charset), $fileStr); } - $text = "$fileStr at line $line"; + $text = sprintf('%s at line %d', $fileStr, $line); } if (false !== $link = $this->getFileLink($file, $line)) { - if (PHP_VERSION_ID >= 50400) { - $flags = ENT_QUOTES | ENT_SUBSTITUTE; - } else { - $flags = ENT_QUOTES; - } - return sprintf('%s', htmlspecialchars($link, $flags, $this->charset), $text); } diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index a96bbe1020..0b962b0e88 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -157,10 +157,11 @@ EOF } if (isset($trace['file']) && isset($trace['line'])) { if ($linkFormat = ini_get('xdebug.file_link_format')) { - $link = str_replace(array('%f', '%l'), array($trace['file'], $trace['line']), $linkFormat); - $content .= sprintf(' in %s line %s', $link, $trace['file'], $trace['line']); + $link = strtr($linkFormat, array('%f' => $trace['file'], '%l' => $trace['line'])); + $link = htmlspecialchars($link, $flags, $this->charset); + $content .= sprintf(' in %s line %d', $link, htmlspecialchars($trace['file'], $flags, $this->charset), $trace['line']); } else { - $content .= sprintf(' in %s line %s', $trace['file'], $trace['line']); + $content .= sprintf(' in %s line %d', htmlspecialchars($trace['file'], $flags, $this->charset), $trace['line']); } } $content .= "\n"; From 921ecff9e2b4632057435c17d7aa950d42a6c0d0 Mon Sep 17 00:00:00 2001 From: Ivan Kurnosov Date: Tue, 19 May 2015 22:18:22 +1200 Subject: [PATCH 13/20] [HttpFoundation] IpUtils::checkIp4() should allow networks --- src/Symfony/Component/HttpFoundation/IpUtils.php | 4 ++++ src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 68e9421d94..fb906b6812 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -62,6 +62,10 @@ class IpUtils public static function checkIp4($requestIp, $ip) { if (false !== strpos($ip, '/')) { + if ('0.0.0.0/0' === $ip) { + return true; + } + list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 32) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index 726ba6a347..0002478246 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -34,6 +34,9 @@ class IpUtilsTest extends \PHPUnit_Framework_TestCase array(true, '192.168.1.1', array('1.2.3.4/1', '192.168.1.0/24')), array(true, '192.168.1.1', array('192.168.1.0/24', '1.2.3.4/1')), array(false, '192.168.1.1', array('1.2.3.4/1', '4.3.2.1/1')), + array(true, '1.2.3.4', '0.0.0.0/0'), + array(false, '1.2.3.4', '256.256.256/0'), + array(false, '1.2.3.4', '192.168.1.0/0'), ); } From 9ee74eaef02458074a6366329e5c509f27feb4d4 Mon Sep 17 00:00:00 2001 From: Alessandro Siragusa Date: Sat, 9 May 2015 01:05:57 +0200 Subject: [PATCH 14/20] Avoid redirection to XHR URIs --- .../Component/Security/Http/Firewall/ExceptionListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index fac5dc1088..57321fb24b 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -194,7 +194,7 @@ class ExceptionListener protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example - if ($request->hasSession() && $request->isMethodSafe()) { + if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) { $request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri()); } } From f24a6dd43a4cdd435f6db95c427897595b11c312 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Mon, 13 Apr 2015 12:21:56 +0200 Subject: [PATCH 15/20] [HttpFoundation] Fix baseUrl when script filename is contained in pathInfo --- .../Component/HttpFoundation/Request.php | 2 +- .../HttpFoundation/Tests/RequestTest.php | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 75ef72d0c7..89db66a77e 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1712,7 +1712,7 @@ class Request return $prefix; } - if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl).'/')) { + if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/').'/')) { // directory portion of $baseUrl matches return rtrim($prefix, '/'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index a1a123426b..eb0a4040f0 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1320,6 +1320,26 @@ class RequestTest extends \PHPUnit_Framework_TestCase public function getBaseUrlData() { return array( + array( + '/fruit/strawberry/1234index.php/blah', + array( + 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php', + 'SCRIPT_NAME' => '/fruit/index.php', + 'PHP_SELF' => '/fruit/index.php', + ), + '/fruit', + '/strawberry/1234index.php/blah', + ), + array( + '/fruit/strawberry/1234index.php/blah', + array( + 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php', + 'SCRIPT_NAME' => '/index.php', + 'PHP_SELF' => '/index.php', + ), + '', + '/fruit/strawberry/1234index.php/blah', + ), array( '/foo%20bar/', array( From 70b4964e4e9431fc135638682b375bce0c5619a5 Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Wed, 20 May 2015 07:26:55 +0000 Subject: [PATCH 16/20] [console][formater] allow format toString object. --- .../Console/Formatter/OutputFormatter.php | 1 + .../Tests/Formatter/OutputFormatterTest.php | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 90b1970f4b..a053ac6ba0 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -142,6 +142,7 @@ class OutputFormatter implements OutputFormatterInterface */ public function format($message) { + $message = (string) $message; $offset = 0; $output = ''; $tagRegex = '[a-z][a-z0-9_=;-]*'; diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 3542680a88..03b789402b 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -166,6 +166,14 @@ class OutputFormatterTest extends \PHPUnit_Framework_TestCase $this->assertEquals("\033[37;41msome error\033[0m".$long, $formatter->format('some error'.$long)); } + public function testFormatToStringObject() + { + $formatter = new OutputFormatter(false); + $this->assertEquals( + 'some info', $formatter->format(new TableCell()) + ); + } + public function testNotDecoratedFormatter() { $formatter = new OutputFormatter(false); @@ -255,3 +263,11 @@ EOF )); } } + +class TableCell +{ + public function __toString() + { + return 'some info'; + } +} From 464c39a77f21fae62898433393bbd497643822eb Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Sun, 17 May 2015 22:37:53 +0200 Subject: [PATCH 17/20] [Security] AbstractRememberMeServices::encodeCookie() validates cookie parts --- .../RememberMe/AbstractRememberMeServices.php | 8 +++++ .../TokenBasedRememberMeServices.php | 4 --- .../AbstractRememberMeServicesTest.php | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index b14e36da4f..16f7831e7c 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -268,9 +268,17 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface * @param array $cookieParts * * @return string + * + * @throws \InvalidArgumentException When $cookieParts contain the cookie delimiter. Extending class should either remove or escape it. */ protected function encodeCookie(array $cookieParts) { + foreach ($cookieParts as $cookiePart) { + if (false !== strpos($cookiePart, self::COOKIE_DELIMITER)) { + throw new \InvalidArgumentException(sprintf('$cookieParts should not contain the cookie delimiter "%s"', self::COOKIE_DELIMITER)); + } + } + return base64_encode(implode(self::COOKIE_DELIMITER, $cookieParts)); } diff --git a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php index 3d2cf12cb0..a129b1d984 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php @@ -119,8 +119,6 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices * @param int $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * - * @throws \RuntimeException if username contains invalid chars - * * @return string */ protected function generateCookieValue($class, $username, $expires, $password) @@ -141,8 +139,6 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices * @param int $expires The Unix timestamp when the cookie expires * @param string $password The encoded password * - * @throws \RuntimeException when the private key is empty - * * @return string */ protected function generateCookieHash($class, $username, $expires, $password) diff --git a/src/Symfony/Component/Security/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php b/src/Symfony/Component/Security/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php index 0f64730b7b..70ff6a0df4 100644 --- a/src/Symfony/Component/Security/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Tests/Http/RememberMe/AbstractRememberMeServicesTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Tests\Http\RememberMe; use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices; class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase { @@ -236,6 +237,30 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase ); } + public function testEncodeCookieAndDecodeCookieAreInvertible() + { + $cookieParts = array('aa', 'bb', 'cc'); + $service = $this->getService(); + + $encoded = $this->callProtected($service, 'encodeCookie', array($cookieParts)); + $this->assertInternalType('string', $encoded); + + $decoded = $this->callProtected($service, 'decodeCookie', array($encoded)); + $this->assertSame($cookieParts, $decoded); + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage cookie delimiter + */ + public function testThereShouldBeNoCookieDelimiterInCookieParts() + { + $cookieParts = array('aa', 'b'.AbstractRememberMeServices::COOKIE_DELIMITER.'b', 'cc'); + $service = $this->getService(); + + $this->callProtected($service, 'encodeCookie', array($cookieParts)); + } + protected function getService($userProvider = null, $options = array(), $logger = null) { if (null === $userProvider) { @@ -258,4 +283,13 @@ class AbstractRememberMeServicesTest extends \PHPUnit_Framework_TestCase return $provider; } + + private function callProtected($object, $method, array $args) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionMethod = $reflection->getMethod($method); + $reflectionMethod->setAccessible(true); + + return $reflectionMethod->invokeArgs($object, $args); + } } From 63a97363507c188943eb43478e1f3dde277c0b32 Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Sat, 16 May 2015 18:06:19 +0200 Subject: [PATCH 18/20] [Security] TokenBasedRememberMeServices test to show why encoding username is required --- .../TokenBasedRememberMeServices.php | 2 ++ .../TokenBasedRememberMeServicesTest.php | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php index 3d2cf12cb0..605b359112 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php @@ -125,6 +125,8 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices */ protected function generateCookieValue($class, $username, $expires, $password) { + // $username is encoded because it might contain COOKIE_DELIMITER, + // we assume other values don't return $this->encodeCookie(array( $class, base64_encode($username), diff --git a/src/Symfony/Component/Security/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php b/src/Symfony/Component/Security/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php index 4606003fa0..511ddcccfd 100644 --- a/src/Symfony/Component/Security/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Tests/Http/RememberMe/TokenBasedRememberMeServicesTest.php @@ -105,7 +105,12 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase $this->assertTrue($request->attributes->get(RememberMeServicesInterface::COOKIE_ATTR_NAME)->isCleared()); } - public function testAutoLogin() + /** + * @dataProvider provideUsernamesForAutoLogin + * + * @param string $username + */ + public function testAutoLogin($username) { $user = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); $user @@ -123,13 +128,13 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase $userProvider ->expects($this->once()) ->method('loadUserByUsername') - ->with($this->equalTo('foouser')) + ->with($this->equalTo($username)) ->will($this->returnValue($user)) ; $service = $this->getService($userProvider, array('name' => 'foo', 'always_remember_me' => true, 'lifetime' => 3600)); $request = new Request(); - $request->cookies->set('foo', $this->getCookie('fooclass', 'foouser', time() + 3600, 'foopass')); + $request->cookies->set('foo', $this->getCookie('fooclass', $username, time() + 3600, 'foopass')); $returnedToken = $service->autoLogin($request); @@ -138,6 +143,14 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase $this->assertEquals('fookey', $returnedToken->getKey()); } + public function provideUsernamesForAutoLogin() + { + return array( + array('foouser', 'Simple username'), + array('foo'.TokenBasedRememberMeServices::COOKIE_DELIMITER.'user', 'Username might contain the delimiter'), + ); + } + public function testLogout() { $service = $this->getService(null, array('name' => 'foo', 'path' => null, 'domain' => null)); From 44469d01d1a766d9322732b4768bca29b452da13 Mon Sep 17 00:00:00 2001 From: Diego Saint Esteben Date: Thu, 21 May 2015 18:12:55 -0300 Subject: [PATCH 19/20] Check instance of FormBuilderInterface instead of FormBuilder --- src/Symfony/Component/Form/FormBuilder.php | 4 ++-- src/Symfony/Component/Form/Tests/FormBuilderTest.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index 8b5b919413..81c9ad5f6d 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -62,7 +62,7 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - if ($child instanceof self) { + if ($child instanceof FormBuilderInterface) { $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists @@ -72,7 +72,7 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB } if (!is_string($child) && !is_int($child)) { - throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); + throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilderInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { diff --git a/src/Symfony/Component/Form/Tests/FormBuilderTest.php b/src/Symfony/Component/Form/Tests/FormBuilderTest.php index da691838c3..8c7b96587d 100644 --- a/src/Symfony/Component/Form/Tests/FormBuilderTest.php +++ b/src/Symfony/Component/Form/Tests/FormBuilderTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\ButtonBuilder; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\SubmitButtonBuilder; class FormBuilderTest extends \PHPUnit_Framework_TestCase { @@ -154,6 +156,12 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase $this->builder->create('foo'); } + public function testAddButton() + { + $this->builder->add(new ButtonBuilder('reset')); + $this->builder->add(new SubmitButtonBuilder('submit')); + } + public function testGetUnknown() { $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); From 6ac8d29d185498e11a1e132dac8b0030b704b87b Mon Sep 17 00:00:00 2001 From: Possum Date: Fri, 22 May 2015 12:24:03 +0200 Subject: [PATCH 20/20] Fix typo --- .../Component/Intl/DateFormatter/IntlDateFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php index 7636be9a34..9b08d1a378 100644 --- a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php +++ b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php @@ -119,7 +119,7 @@ class IntlDateFormatter /** * @var bool */ - private $unitializedTimeZoneId = false; + private $uninitializedTimeZoneId = false; /** * @var string @@ -371,7 +371,7 @@ class IntlDateFormatter */ public function getTimeZoneId() { - if (!$this->unitializedTimeZoneId) { + if (!$this->uninitializedTimeZoneId) { return $this->timeZoneId; } @@ -551,7 +551,7 @@ class IntlDateFormatter $timeZoneId = getenv('TZ') ?: 'UTC'; } - $this->unitializedTimeZoneId = true; + $this->uninitializedTimeZoneId = true; } // Backup original passed time zone