diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md
index f5471bf653f4b..335dfd82e4186 100644
--- a/CHANGELOG-2.7.md
+++ b/CHANGELOG-2.7.md
@@ -7,6 +7,17 @@ in 2.7 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1
+* 2.7.32 (2017-07-17)
+
+ * security #23507 [Security] validate empty passwords again (xabbuh)
+ * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor)
+ * bug #23468 [DI] Handle root namespace in service definitions (ro0NL)
+ * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr)
+ * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz)
+ * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh)
+ * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz)
+ * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas)
+
* 2.7.31 (2017-07-05)
* bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 3e670f8d67e90..47a6cf9986dcf 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -19,13 +19,13 @@ Symfony is the result of the work of many people who made the code better
- Ryan Weaver (weaverryan)
- Javier Eguiluz (javier.eguiluz)
- Hugo Hamon (hhamon)
- - Abdellatif Ait boudad (aitboudad)
- Maxime Steinhausser (ogizanagi)
+ - Abdellatif Ait boudad (aitboudad)
- Robin Chalas (chalas_r)
- Romain Neutron (romain)
- Pascal Borreli (pborreli)
- - Wouter De Jong (wouterj)
- Grégoire Pineau (lyrixx)
+ - Wouter De Jong (wouterj)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
@@ -35,8 +35,8 @@ Symfony is the result of the work of many people who made the code better
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- Eriksen Costa (eriksencosta)
- - Jules Pietri (heah)
- Roland Franssen (ro0)
+ - Jules Pietri (heah)
- Sarah Khalil (saro0h)
- Guilhem Niot (energetick)
- Jonathan Wage (jwage)
@@ -93,6 +93,7 @@ Symfony is the result of the work of many people who made the code better
- Maxime STEINHAUSSER
- Alexander M. Turek (derrabus)
- Michal Piotrowski (eventhorizon)
+ - Dany Maillard (maidmaid)
- Issei Murasawa (issei_m)
- Tim Nagel (merk)
- Brice BERNARD (brikou)
@@ -133,7 +134,6 @@ Symfony is the result of the work of many people who made the code better
- Guilherme Blanco (guilhermeblanco)
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
- - Dany Maillard (maidmaid)
- Andréia Bohner (andreia)
- Rafael Dohms (rdohms)
- Arnaud Kleinpeter (nanocom)
@@ -141,6 +141,7 @@ Symfony is the result of the work of many people who made the code better
- David Maicher (dmaicher)
- Mikael Pajunen
- Joel Wurtz (brouznouf)
+ - Jérôme Vasseur (jvasseur)
- Grégoire Paris (greg0ire)
- Philipp Wahala (hifi)
- Vyacheslav Pavlov
@@ -150,7 +151,6 @@ Symfony is the result of the work of many people who made the code better
- Thomas Rabaix (rande)
- Rouven Weßling (realityking)
- Teoh Han Hui (teohhanhui)
- - Jérôme Vasseur (jvasseur)
- Clemens Tolboom
- Helmer Aaviksoo
- Hiromi Hishida (77web)
@@ -162,6 +162,7 @@ Symfony is the result of the work of many people who made the code better
- Artur Kotyrba
- jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent)
- James Halsall (jaitsu)
+ - Chris Wilkinson (thewilkybarkid)
- Warnar Boekkooi (boekkooi)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
@@ -174,7 +175,6 @@ Symfony is the result of the work of many people who made the code better
- Dennis Benkert (denderello)
- Benjamin Dulau (dbenjamin)
- Mathieu Lemoine (lemoinem)
- - Chris Wilkinson (thewilkybarkid)
- Andreas Hucks (meandmymonkey)
- Noel Guilbert (noel)
- Stepan Anchugov (kix)
@@ -238,6 +238,7 @@ Symfony is the result of the work of many people who made the code better
- Alif Rachmawadi
- Kristen Gilden (kgilden)
- Pierre-Yves LEBECQ (pylebecq)
+ - Jordan Samouh (jordansamouh)
- Alex Pott
- Jakub Kucharovic (jkucharovic)
- Uwe Jäger (uwej711)
@@ -248,6 +249,7 @@ Symfony is the result of the work of many people who made the code better
- GordonsLondon
- Jan Sorgalla (jsor)
- Ray
+ - Nikolay Labinskiy (e-moe)
- Leo Feyer
- Chekote
- Thomas Adam
@@ -274,8 +276,8 @@ Symfony is the result of the work of many people who made the code better
- Marc Weistroff (futurecat)
- Christian Schmidt
- Hidde Wieringa (hiddewie)
+ - Alessandro Chitolina
- Chad Sikorra (chadsikorra)
- - Jordan Samouh (jordansamouh)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
- Manuel Kiessling (manuelkiessling)
@@ -294,7 +296,6 @@ Symfony is the result of the work of many people who made the code better
- Victor Bocharsky (bocharsky_bw)
- Jan Decavele (jandc)
- Gustavo Piltcher
- - Nikolay Labinskiy (e-moe)
- Stepan Tanasiychuk (stfalcon)
- Tiago Ribeiro (fixe)
- Hidde Boomsma (hboomsma)
@@ -309,6 +310,7 @@ Symfony is the result of the work of many people who made the code better
- Thomas Schulz (king2500)
- Dariusz Rumiński
- Berny Cantos (xphere81)
+ - Thierry Thuon (lepiaf)
- Ricard Clau (ricardclau)
- Mark Challoner (markchalloner)
- Gregor Harlan (gharlan)
@@ -327,6 +329,7 @@ Symfony is the result of the work of many people who made the code better
- Inal DJAFAR (inalgnu)
- Christian Gärtner (dagardner)
- Tomasz Kowalczyk (thunderer)
+ - Michael Babker (mbabker)
- François-Xavier de Guillebon (de-gui_f)
- Damien Alexandre (damienalexandre)
- Felix Labrecque
@@ -335,7 +338,6 @@ Symfony is the result of the work of many people who made the code better
- Robbert Klarenbeek (robbertkl)
- Thomas Calvet (fancyweb)
- Niels Keurentjes (curry684)
- - Alessandro Chitolina
- JhonnyL
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
@@ -401,6 +403,7 @@ Symfony is the result of the work of many people who made the code better
- Olivier Dolbeau (odolbeau)
- Jan Rosier (rosier)
- Thomas Royer (cydonia7)
+ - Arturs Vonda
- Josip Kruslin
- Asmir Mustafic (goetas)
- vagrant
@@ -428,6 +431,7 @@ Symfony is the result of the work of many people who made the code better
- David Badura (davidbadura)
- Zander Baldwin
- Adam Harvey
+ - Maxime Veber (nek-)
- Alex Bakhturin
- Alexander Obuhovich (aik099)
- boombatower
@@ -441,6 +445,7 @@ Symfony is the result of the work of many people who made the code better
- Gladhon
- Benoît Burnichon (bburnichon)
- Sebastian Bergmann
+ - Miroslav Sustek
- Pablo Díez (pablodip)
- Kevin McBride
- Sergio Santoro
@@ -550,7 +555,6 @@ Symfony is the result of the work of many people who made the code better
- Maxime Douailin
- Jean Pasdeloup (pasdeloup)
- Benjamin Cremer (bcremer)
- - Thierry Thuon (lepiaf)
- Javier López (loalf)
- Reinier Kip
- Geoffrey Brier (geoffrey-brier)
@@ -572,6 +576,7 @@ Symfony is the result of the work of many people who made the code better
- Alex Bogomazov (alebo)
- maxime.steinhausser
- Stefan Warman
+ - Thomas Perez (scullwm)
- Tristan Maindron (tmaindron)
- Wesley Lancel
- Ke WANG (yktd26)
@@ -580,7 +585,6 @@ Symfony is the result of the work of many people who made the code better
- Sergey Kolodyazhnyy (skolodyazhnyy)
- umpirski
- Denis Brumann (dbrumann)
- - Michael Babker (mbabker)
- Quentin de Longraye (quentinus95)
- Chris Heng (gigablah)
- Richard Bradley
@@ -590,7 +594,6 @@ Symfony is the result of the work of many people who made the code better
- Michael Devery (mickadoo)
- Antoine Corcy
- Artur Eshenbrener
- - Arturs Vonda
- Sascha Grossenbacher
- Szijarto Tamas
- Catalin Dan
@@ -620,7 +623,6 @@ Symfony is the result of the work of many people who made the code better
- develop
- ReenExe
- Mark Sonnabaum
- - Maxime Veber (nek-)
- Richard Quadling
- jochenvdv
- Arturas Smorgun (asarturas)
@@ -669,7 +671,6 @@ Symfony is the result of the work of many people who made the code better
- Christian Soronellas (theunic)
- Yosmany Garcia (yosmanyga)
- Wouter de Wild
- - Miroslav Sustek
- Degory Valentine
- Benoit Lévêque (benoit_leveque)
- Jeroen Fiege (fieg)
@@ -693,6 +694,7 @@ Symfony is the result of the work of many people who made the code better
- Jan Prieser
- Adrien Lucas (adrienlucas)
- Zhuravlev Alexander (scif)
+ - Yanick Witschi (toflar)
- James Michael DuPont
- Tom Klingenberg
- Christopher Hall (mythmakr)
@@ -834,7 +836,6 @@ Symfony is the result of the work of many people who made the code better
- Danilo Silva
- Zachary Tong (polyfractal)
- Hryhorii Hrebiniuk
- - Thomas Perez (scullwm)
- Dennis Fridrich (dfridrich)
- hamza
- dantleech
@@ -863,6 +864,7 @@ Symfony is the result of the work of many people who made the code better
- Goran Juric
- Laurent Ghirardotti (laurentg)
- Nicolas Macherey
+ - AKeeman (akeeman)
- Lin Clark
- Jeremy David (jeremy.david)
- Robin Lehrmann (robinlehrmann)
@@ -1104,6 +1106,7 @@ Symfony is the result of the work of many people who made the code better
- Max Romanovsky (maxromanovsky)
- Mathieu Morlon
- Daniel Tschinder
+ - Alexander Schranz
- Rafał Muszyński (rafmus90)
- Timothy Anido (xanido)
- Rick Prent
@@ -1411,6 +1414,7 @@ Symfony is the result of the work of many people who made the code better
- Rosio (ben-rosio)
- Simon Paarlberg (blamh)
- Jeroen Thora (bolle)
+ - Brieuc THOMAS (brieucthomas)
- Masao Maeda (brtriver)
- Darius Leskauskas (darles)
- David Joos (djoos)
@@ -1440,7 +1444,6 @@ Symfony is the result of the work of many people who made the code better
- Cyrille Jouineau (tuxosaurus)
- Yorkie Chadwick (yorkie76)
- GuillaumeVerdon
- - Yanick Witschi
- Ondrej Mirtes
- akimsko
- Youpie
diff --git a/composer.json b/composer.json
index 1770bc4f305af..a7f3bbf9078d9 100644
--- a/composer.json
+++ b/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.3.9",
+ "ext-xml": "*",
"doctrine/common": "~2.4",
"paragonie/random_compat": "~1.0",
"symfony/polyfill-apcu": "~1.1",
diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
index 90b515ee320ba..0dad40cfa0a3f 100644
--- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
@@ -72,6 +72,13 @@ public function generateAbsoluteUrl($path)
$port = ':'.$this->requestContext->getHttpsPort();
}
+ if ('#' === $path[0]) {
+ $queryString = $this->requestContext->getQueryString();
+ $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path;
+ } elseif ('?' === $path[0]) {
+ $path = $this->requestContext->getPathInfo().$path;
+ }
+
if ('/' !== $path[0]) {
$path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path;
}
@@ -82,6 +89,12 @@ public function generateAbsoluteUrl($path)
return $path;
}
+ if ('#' === $path[0]) {
+ $path = $request->getRequestUri().$path;
+ } elseif ('?' === $path[0]) {
+ $path = $request->getPathInfo().$path;
+ }
+
if (!$path || '/' !== $path[0]) {
$prefix = $request->getPathInfo();
$last = strlen($prefix) - 1;
diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
index 2485c0a88c530..9f4d7c56ea886 100644
--- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
+++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
@@ -19,16 +19,19 @@
*/
class TwigRenderer extends FormRenderer implements TwigRendererInterface
{
- /**
- * @var TwigRendererEngineInterface
- */
- private $engine;
-
public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManager = null)
{
parent::__construct($engine, $csrfTokenManager);
+ }
- $this->engine = $engine;
+ /**
+ * Returns the engine used by this renderer.
+ *
+ * @return TwigRendererEngineInterface The renderer engine
+ */
+ public function getEngine()
+ {
+ return parent::getEngine();
}
/**
@@ -36,6 +39,6 @@ public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManag
*/
public function setEnvironment(Environment $environment)
{
- $this->engine->setEnvironment($environment);
+ $this->getEngine()->setEnvironment($environment);
}
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
index 8f0c66ad78bb4..fcff0c0e1b93b 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
@@ -42,6 +42,15 @@ public function getGenerateAbsoluteUrlData()
array('http://example.com/baz', 'http://example.com/baz', '/'),
array('https://example.com/baz', 'https://example.com/baz', '/'),
array('//example.com/baz', '//example.com/baz', '/'),
+
+ array('http://localhost/foo/bar?baz', '?baz', '/foo/bar'),
+ array('http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'),
+ array('http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'),
+
+ array('http://localhost/foo/bar#baz', '#baz', '/foo/bar'),
+ array('http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'),
+ array('http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'),
+ array('http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'),
);
}
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index d4cba7fc2410b..3fde4a67247eb 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.3.9",
+ "ext-xml": "*",
"symfony/http-kernel": "~2.6",
"symfony/twig-bridge": "~2.6",
"symfony/var-dumper": "~2.6"
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index 3da10d429d4bf..6d6073f7f0bc3 100644
--- a/src/Symfony/Bundle/SecurityBundle/composer.json
+++ b/src/Symfony/Bundle/SecurityBundle/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.3.9",
+ "ext-xml": "*",
"symfony/security": "~2.7",
"symfony/security-acl": "~2.7",
"symfony/http-kernel": "~2.7"
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
index 474b6c9721e0c..70b6de5c38d5c 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
@@ -9,6 +9,9 @@
+
+
+
@@ -28,6 +31,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php
new file mode 100644
index 0000000000000..630a9a9edc01a
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php
@@ -0,0 +1,14 @@
+loadFromExtension('twig', array(
+ 'date' => array(
+ 'format' => 'Y-m-d',
+ 'interval_format' => '%d',
+ 'timezone' => 'Europe/Berlin',
+ ),
+ 'number_format' => array(
+ 'decimals' => 2,
+ 'decimal_point' => ',',
+ 'thousands_separator' => '.',
+ ),
+));
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml
new file mode 100644
index 0000000000000..1ab39e49229cd
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml
new file mode 100644
index 0000000000000..290921630f9e6
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml
@@ -0,0 +1,9 @@
+twig:
+ date:
+ format: Y-m-d
+ interval_format: '%d'
+ timezone: Europe/Berlin
+ number_format:
+ decimals: 2
+ decimal_point: ','
+ thousands_separator: .
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
index f5809cc045c42..f385ec04fd28c 100644
--- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
@@ -150,6 +150,26 @@ public function testLoadDefaultTemplateEscapingGuesserConfiguration($format)
$this->assertEquals('name', $options['autoescape']);
}
+ /**
+ * @dataProvider getFormats
+ */
+ public function testLoadCustomDateFormats($fileFormat)
+ {
+ $container = $this->createContainer();
+ $container->registerExtension(new TwigExtension());
+ $this->loadFromFile($container, 'formats', $fileFormat);
+ $this->compileContainer($container);
+
+ $environmentConfigurator = $container->getDefinition('twig.configurator.environment');
+
+ $this->assertSame('Y-m-d', $environmentConfigurator->getArgument(0));
+ $this->assertSame('%d', $environmentConfigurator->getArgument(1));
+ $this->assertSame('Europe/Berlin', $environmentConfigurator->getArgument(2));
+ $this->assertSame(2, $environmentConfigurator->getArgument(3));
+ $this->assertSame(',', $environmentConfigurator->getArgument(4));
+ $this->assertSame('.', $environmentConfigurator->getArgument(5));
+ }
+
public function testGlobalsWithDifferentTypesAndValues()
{
$globals = array(
diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php
index 42f184d532e02..c042c6a525295 100644
--- a/src/Symfony/Component/BrowserKit/Cookie.php
+++ b/src/Symfony/Component/BrowserKit/Cookie.php
@@ -62,7 +62,7 @@ public function __construct($name, $value, $expires = null, $path = null, $domai
$this->rawValue = $value;
} else {
$this->value = $value;
- $this->rawValue = urlencode($value);
+ $this->rawValue = rawurlencode($value);
}
$this->name = $name;
$this->path = empty($path) ? '/' : $path;
diff --git a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
index 38ea81220bb2c..2f5a08d104143 100644
--- a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
+++ b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
@@ -16,6 +16,21 @@
class CookieTest extends TestCase
{
+ public function testToString()
+ {
+ $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
+
+ $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
+
+ $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
+ $this->assertEquals('foo=; expires=Thu, 01 Jan 1970 00:00:01 GMT; domain=.myfoodomain.com; path=/admin/; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
+
+ $cookie = new Cookie('foo', 'bar', 0, '/', '');
+ $this->assertEquals('foo=bar; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; httponly', (string) $cookie);
+ }
+
/**
* @dataProvider getTestsForToFromString
*/
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
index f6c953f550993..7bf2e36ec2da2 100644
--- a/src/Symfony/Component/DependencyInjection/Container.php
+++ b/src/Symfony/Component/DependencyInjection/Container.php
@@ -29,16 +29,6 @@
*
* Parameter and service keys are case insensitive.
*
- * A service id can contain lowercased letters, digits, underscores, and dots.
- * Underscores are used to separate words, and dots to group services
- * under namespaces:
- *
- *
- * - request
- * - mysql_session_storage
- * - symfony.mysql_session_storage
- *
- *
* A service can also be defined by creating a method named
* getXXXService(), where XXX is the camelized version of the id:
*
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 09d22fcb5fd3d..1665f7542b7ce 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -377,15 +377,9 @@ private function addServiceReturn($id, $definition)
*/
private function addServiceInstance($id, Definition $definition)
{
- $class = $definition->getClass();
-
- if ('\\' === substr($class, 0, 1)) {
- $class = substr($class, 1);
- }
-
- $class = $this->dumpValue($class);
+ $class = $this->dumpValue($definition->getClass());
- if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
+ if (0 === strpos($class, "'") && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
}
@@ -1440,11 +1434,13 @@ private function dumpLiteralClass($class)
if (false !== strpos($class, '$')) {
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
}
- if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
+ if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
}
- return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1);
+ $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
+
+ return 0 === strpos($class, '\\') ? $class : '\\'.$class;
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
index 02018c5a0a999..5ec0deed3d3a4 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
@@ -134,8 +134,8 @@ public function testGetServiceIds()
public function testSet()
{
$sc = new Container();
- $sc->set('foo', $foo = new \stdClass());
- $this->assertSame($foo, $sc->get('foo'), '->set() sets a service');
+ $sc->set('._. \\o/', $foo = new \stdClass());
+ $this->assertSame($foo, $sc->get('._. \\o/'), '->set() sets a service');
}
public function testSetWithNullResetTheService()
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
index 41b6c375d8aab..1ce5b7b9993d8 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -339,4 +339,17 @@ public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServic
$this->addToAssertionCount(1);
}
+
+ public function testDumpHandlesLiteralClassWithRootNamespace()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', '\\stdClass');
+
+ $dumper = new PhpDumper($container);
+ eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace')));
+
+ $container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace();
+
+ $this->assertInstanceOf('stdClass', $container->get('foo'));
+ }
}
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index e60d4690738ad..bc2e3dcc2d897 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -37,7 +37,8 @@ class Filesystem
*/
public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
{
- if (stream_is_local($originFile) && !is_file($originFile)) {
+ $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
+ if ($originIsLocal && !is_file($originFile)) {
throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
}
@@ -68,11 +69,13 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
}
- // Like `cp`, preserve executable permission bits
- @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
+ if ($originIsLocal) {
+ // Like `cp`, preserve executable permission bits
+ @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
- if (stream_is_local($originFile) && $bytesCopied !== ($bytesOrigin = filesize($originFile))) {
- throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
+ if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
+ throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
+ }
}
}
}
diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php
index 91783a6ad2b50..fb1e7dfd74ea4 100644
--- a/src/Symfony/Component/HttpFoundation/Cookie.php
+++ b/src/Symfony/Component/HttpFoundation/Cookie.php
@@ -82,7 +82,7 @@ public function __toString()
if ('' === (string) $this->getValue()) {
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001);
} else {
- $str .= urlencode($this->getValue());
+ $str .= rawurlencode($this->getValue());
if (0 !== $this->getExpiresTime()) {
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime());
diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php
index 5a775ad159f3a..4118fff24c892 100644
--- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php
+++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php
@@ -83,7 +83,7 @@ public function setTargetUrl($url)
-
+
Redirecting to %1$s
diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
index f3f74f635eb40..2d9fb09d3d4b6 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
@@ -160,6 +160,9 @@ public function testToString()
$cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
+ $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
+
$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 6233186a48e22..44b7ef2bca903 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -58,11 +58,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
- const VERSION = '2.7.31';
- const VERSION_ID = 20731;
+ const VERSION = '2.7.32';
+ const VERSION_ID = 20732;
const MAJOR_VERSION = 2;
const MINOR_VERSION = 7;
- const RELEASE_VERSION = 31;
+ const RELEASE_VERSION = 32;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '05/2018';
diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
index 16de8daaeda93..4c0a7459d070c 100644
--- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
+++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
@@ -83,9 +83,9 @@ public function authenticate(TokenInterface $token)
break;
}
} catch (AccountStatusException $e) {
- $e->setToken($token);
+ $lastException = $e;
- throw $e;
+ break;
} catch (AuthenticationException $e) {
$lastException = $e;
}
diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
index 9b8105012c3d8..373369d455959 100644
--- a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
@@ -13,6 +13,9 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
+use Symfony\Component\Security\Core\AuthenticationEvents;
+use Symfony\Component\Security\Core\Event\AuthenticationEvent;
+use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
@@ -124,6 +127,50 @@ public function testEraseCredentialFlag()
$this->assertEquals('bar', $token->getCredentials());
}
+ public function testAuthenticateDispatchesAuthenticationFailureEvent()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
+ $provider->expects($this->once())->method('supports')->willReturn(true);
+ $provider->expects($this->once())->method('authenticate')->willThrowException($exception = new AuthenticationException());
+
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(AuthenticationEvents::AUTHENTICATION_FAILURE, $this->equalTo(new AuthenticationFailureEvent($token, $exception)));
+
+ $manager = new AuthenticationProviderManager(array($provider));
+ $manager->setEventDispatcher($dispatcher);
+
+ try {
+ $manager->authenticate($token);
+ $this->fail('->authenticate() should rethrow exceptions');
+ } catch (AuthenticationException $e) {
+ $this->assertSame($token, $exception->getToken());
+ }
+ }
+
+ public function testAuthenticateDispatchesAuthenticationSuccessEvent()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+
+ $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
+ $provider->expects($this->once())->method('supports')->willReturn(true);
+ $provider->expects($this->once())->method('authenticate')->willReturn($token);
+
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(AuthenticationEvents::AUTHENTICATION_SUCCESS, $this->equalTo(new AuthenticationEvent($token)));
+
+ $manager = new AuthenticationProviderManager(array($provider));
+ $manager->setEventDispatcher($dispatcher);
+
+ $this->assertSame($token, $manager->authenticate($token));
+ }
+
protected function getAuthenticationProvider($supports, $token = null, $exception = null)
{
$provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
index 7ebe65c647d99..942a4a6350f27 100644
--- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
@@ -90,6 +90,29 @@ public function testPasswordIsNotValid()
->assertRaised();
}
+ /**
+ * @dataProvider emptyPasswordData
+ */
+ public function testEmptyPasswordsAreNotValid($password)
+ {
+ $constraint = new UserPassword(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($password, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->assertRaised();
+ }
+
+ public function emptyPasswordData()
+ {
+ return array(
+ array(null),
+ array(''),
+ );
+ }
+
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
diff --git a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
index d17e3b704d981..03f38f08848ba 100644
--- a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
+++ b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
@@ -50,7 +50,7 @@ interface UserProviderInterface
public function loadUserByUsername($username);
/**
- * Refreshes the user for the account interface.
+ * Refreshes the user.
*
* It is up to the implementation to decide if the user data should be
* totally reloaded (e.g. from the database), or if the UserInterface
@@ -61,7 +61,7 @@ public function loadUserByUsername($username);
*
* @return UserInterface
*
- * @throws UnsupportedUserException if the account is not supported
+ * @throws UnsupportedUserException if the user is not supported
*/
public function refreshUser(UserInterface $user);
diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
index 5f4c146cab469..c2ab13b2f6d29 100644
--- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
+++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
@@ -40,6 +40,8 @@ public function validate($password, Constraint $constraint)
}
if (null === $password || '' === $password) {
+ $this->context->addViolation($constraint->message);
+
return;
}