diff --git a/CHANGELOG-2.3.md b/CHANGELOG-2.3.md index 12b4efd248..675302718a 100644 --- a/CHANGELOG-2.3.md +++ b/CHANGELOG-2.3.md @@ -7,6 +7,16 @@ in 2.3 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.3.0...v2.3.1 +* 2.3.27 (2015-04-01) + + * security #14167 CVE-2015-2308 (nicolas-grekas) + * security #14166 CVE-2015-2309 (neclimdul) + * bug #14010 Replace GET parameters when changed in form (WouterJ) + * bug #13991 [Dependency Injection] Improve PhpDumper Performance for huge Containers (BattleRattle) + * bug #13997 [2.3+][Form][DoctrineBridge] Improved loading of entities and documents (guilhermeblanco) + * bug #13953 [Translation][MoFileLoader] fixed load empty translation. (aitboudad) + * bug #13912 [DependencyInjection] Highest precedence for user parameters (lyrixx) + * 2.3.26 (2015-03-17) * bug #13927 Fixing wrong variable name from #13519 (weaverryan) diff --git a/CHANGELOG-2.6.md b/CHANGELOG-2.6.md index 56fd84de3c..8bd1c85aff 100644 --- a/CHANGELOG-2.6.md +++ b/CHANGELOG-2.6.md @@ -7,6 +7,26 @@ in 2.6 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.6.0...v2.6.1 +* 2.6.6 (2015-04-01) + + * security #14167 CVE-2015-2308 (nicolas-grekas) + * security #14166 CVE-2015-2309 (neclimdul) + * bug #14126 [VarDumper] Fix toggle action to see source excerpt (nicolas-grekas) + * bug #14114 [VarDumper] Fix dumping references as properties (nicolas-grekas) + * bug #14074 [VarDumper] Fix dumping ThrowingCasterException (nicolas-grekas) + * bug #12948 [Form] [TwigBridge] Bootstrap layout whitespace control (mvar) + * bug #14046 [Security] StringUtils::equals() arguments in RememberMe Cookie based implementation are confused (zerkms) + * bug #14010 Replace GET parameters when changed in form (WouterJ) + * bug #13991 [Dependency Injection] Improve PhpDumper Performance for huge Containers (BattleRattle) + * bug #13886 [FrameworkBundle][debug:config] added support for dynamic configurations... (aitboudad) + * bug #14013 [DependencyInjection] prevent inlining service configurators (xabbuh) + * bug #14012 [DomCrawler] Improve namespace discovery performance (jakzal) + * bug #13997 [2.3+][Form][DoctrineBridge] Improved loading of entities and documents (guilhermeblanco) + * bug #13978 [WebProfilerBundle] Fix javascript toolbar on IE8 (romainneutron) + * bug #13987 [WebProfilerBundle] fixed undefined buttons variable. (aitboudad) + * bug #13953 [Translation][MoFileLoader] fixed load empty translation. (aitboudad) + * bug #13912 [DependencyInjection] Highest precedence for user parameters (lyrixx) + * 2.6.5 (2015-03-17) * bug #13944 [HttpKernel] UriSigner::buildUrl - default params for http_build_query (Jakub Simon) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 09feceb7b6..d773ad7ebb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,8 +11,8 @@ Symfony is the result of the work of many people who made the code better - Jordi Boggiano (seldaek) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) - - Christophe Coevoet (stof) - Nicolas Grekas (nicolas-grekas) + - Christophe Coevoet (stof) - Jakub Zalas (jakubzalas) - Pascal Borreli (pborreli) - Hugo Hamon (hhamon) @@ -21,9 +21,9 @@ Symfony is the result of the work of many people who made the code better - Ryan Weaver (weaverryan) - Lukas Kahwe Smith (lsmith) - Romain Neutron (romain) + - Christian Flothmann (xabbuh) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - - Christian Flothmann (xabbuh) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - Martin Hasoň (hason) @@ -37,16 +37,16 @@ Symfony is the result of the work of many people who made the code better - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) + - Abdellatif Ait boudad (aitboudad) - Francis Besset (francisbesset) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik + - Kévin Dunglas (dunglas) + - Sarah Khalil (saro0h) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - - Kévin Dunglas (dunglas) - Florin Patan (florinpatan) - - Abdellatif Ait Boudad (aitboudad) - - Sarah Khalil (saro0h) - Eric Clemmons (ericclemmons) - Andrej Hudec (pulzarraider) - Deni @@ -61,13 +61,14 @@ Symfony is the result of the work of many people who made the code better - Daniel Holmes (dholmes) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Kevin Bond (kbond) - John Wards (johnwards) - Fran Moreno (franmomu) - - Antoine Hérault (herzult) - - Kevin Bond (kbond) - - Toni Uebernickel (havvg) - Luis Cordova (cordoval) + - Antoine Hérault (herzult) + - Toni Uebernickel (havvg) - Arnaud Le Blanc (arnaud-lb) + - Gábor Egyed (1ed) - Tim Nagel (merk) - Brice BERNARD (brikou) - marc.weistroff @@ -78,7 +79,6 @@ Symfony is the result of the work of many people who made the code better - Colin Frei - Jérôme Tamarelle (gromnan) - Adrien Brault (adrienbrault) - - Gábor Egyed (1ed) - excelwebzone - Jacob Dreesen (jdreesen) - Fabien Pennequin (fabienpennequin) @@ -93,26 +93,29 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - David Buchmann (dbu) + - Guilherme Blanco (guilhermeblanco) - Jérémy DERUSSÉ (jderusse) - Pablo Godel (pgodel) - Eric GELOEN (gelo) - Jérémie Augustin (jaugustin) - Rafael Dohms (rdohms) - - Guilherme Blanco (guilhermeblanco) - Tigran Azatyan (tigranazatyan) - Javier Eguiluz (javier.eguiluz) - Arnaud Kleinpeter (nanocom) - Richard Shank (iampersistent) + - Dariusz Ruminski - Clemens Tolboom - Helmer Aaviksoo - Sebastiaan Stok (sstok) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) + - Issei Murasawa (issei_m) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba - Rouven Weßling (realityking) + - Andréia Bohner (andreia) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - Dorian Villet (gnutix) @@ -123,14 +126,12 @@ Symfony is the result of the work of many people who made the code better - Benjamin Dulau (dbenjamin) - Matthias Pigulla (mpdude) - Andreas Hucks (meandmymonkey) - - Andréia Bohner (andreia) - Noel Guilbert (noel) - Joel Wurtz (brouznouf) - Charles Sarrazin (csarrazi) - bronze1man - sun (sun) - Larry Garfield (crell) - - Issei Murasawa (issei_m) - Martin Schuhfuß (usefulthink) - Thomas Rabaix (rande) - Matthieu Bontemps (mbontemps) @@ -163,6 +164,7 @@ Symfony is the result of the work of many people who made the code better - Xavier Montaña Carreras (xmontana) - Michele Orselli (orso) - Chris Wilkinson (thewilkybarkid) + - Joshua Thijssen - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA @@ -181,16 +183,18 @@ Symfony is the result of the work of many people who made the code better - Jeremy Livingston (jeremylivingston) - Nikita Konstantinov - Wodor Wodorski + - Matthieu Auger (matthieuauger) - julien pauli (jpauli) - Beau Simensen (simensen) - Robert Kiss (kepten) + - John Kary (johnkary) - Ruben Gonzalez (rubenrua) - Kim Hemsø Rasmussen (kimhemsoe) - Florian Lonqueu-Brochard (florianlb) - Tom Van Looy (tvlooy) - Wouter Van Hecke - - Joshua Thijssen - Peter Kruithof (pkruithof) + - Vladimir Reznichenko (kalessil) - Michael Holm (hollo) - Warnar Boekkooi (boekkooi) - Marc Weistroff (futurecat) @@ -222,7 +226,6 @@ Symfony is the result of the work of many people who made the code better - Marco Pivetta (ocramius) - Ricard Clau (ricardclau) - Erin Millard - - John Kary (johnkary) - Matthew Lewinski (lewinski) - alquerci - Francesco Levorato @@ -232,7 +235,6 @@ Symfony is the result of the work of many people who made the code better - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Felix Labrecque - - Vladimir Reznichenko (kalessil) - Yaroslav Kiliba - Sébastien Lavoie (lavoiesl) - Terje Bråten @@ -283,7 +285,6 @@ Symfony is the result of the work of many people who made the code better - Brian King - Michel Salib (michelsalib) - geoffrey - - Matthieu Auger (matthieuauger) - Lorenz Schori - Jeanmonod David (jeanmonod) - Jan Schumann @@ -309,7 +310,6 @@ Symfony is the result of the work of many people who made the code better - Christian Schmidt - Marcin Sikoń (marphi) - franek (franek) - - Dariusz Ruminski - Adam Harvey - Diego Saint Esteben (dii3g0) - Alex Bakhturin @@ -336,6 +336,7 @@ Symfony is the result of the work of many people who made the code better - mmoreram - Markus Lanthaler (lanthaler) - Vicent Soria Durá (vicentgodella) + - Anthony Ferrara - Ioan Negulescu - Jakub Škvára (jskvara) - Daniel Beyer @@ -343,9 +344,11 @@ Symfony is the result of the work of many people who made the code better - alexpods - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) + - Scott Arciszewski - Norbert Orzechowicz (norzechowicz) - Tobias Nyholm (tobias) - Matthijs van den Bos (matthijs) + - Loick Piera (pyrech) - Lenard Palko - Nils Adermann (naderman) - Gábor Fási @@ -371,9 +374,11 @@ Symfony is the result of the work of many people who made the code better - Zach Badgett (zachbadgett) - Aurélien Fredouelle - Pavel Campr (pcampr) + - Maxime Steinhausser (ogizanagi) - Disquedur - Geoffrey Tran (geoff) - Jan Behrens + - Mantas Var (mvar) - Sebastian Krebs - Christopher Davis (chrisguitarguy) - Thomas Lallement (raziel057) @@ -387,6 +392,7 @@ Symfony is the result of the work of many people who made the code better - Max Rath (drak3) - Stéphane Escandell (sescandell) - Sinan Eldem + - Alexandre Dupuy (satchette) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) - Asmir Mustafic (goetas) @@ -484,7 +490,6 @@ Symfony is the result of the work of many people who made the code better - Xavier Lacot (xavier) - Olivier Maisonneuve (olineuve) - Francis Turmel (fturmel) - - Loick Piera (pyrech) - cgonzalez - Ben - Jayson Xu (superjavason) @@ -506,6 +511,7 @@ Symfony is the result of the work of many people who made the code better - Fabian Vogler (fabian) - Korvin Szanto - Maksim Kotlyar (makasim) + - Ivan Kurnosov - Neil Ferreira - Dmitry Parnas (parnas) - DQNEO @@ -516,6 +522,7 @@ Symfony is the result of the work of many people who made the code better - David Romaní - Patrick Allaert - Gustavo Falco (gfalco) + - Matt Robinson (inanimatt) - Aleksey Podskrebyshev - David Marín Carreño (davefx) - Jörn Lang (j.lang) @@ -580,6 +587,7 @@ Symfony is the result of the work of many people who made the code better - Michael Tibben - Sander Marechal - Radosław Benkel + - Marcos Sánchez - ttomor - Mei Gwilym (meigwilym) - Michael H. Arieli (excelwebzone) @@ -622,6 +630,7 @@ Symfony is the result of the work of many people who made the code better - nacho - Piotr Antosik (antek88) - Artem Lopata + - Samuel ROZE (sroze) - Marcos Quesada (marcos_quesada) - Matthew Vickery (mattvick) - Dan Finnie @@ -675,6 +684,7 @@ Symfony is the result of the work of many people who made the code better - Yannick - Eduardo García Sanz (coma) - Sebastian Grodzicki (sgrodzicki) + - Michael Lee (zerustech) - Roy Van Ginneken - David de Boer (ddeboer) - Gilles Doge (gido) @@ -721,6 +731,7 @@ Symfony is the result of the work of many people who made the code better - Malaney J. Hill - Christian Flach (cmfcmf) - Cédric Girard (enk_) + - Lars Ambrosius Wallenborn (larsborn) - Oriol Mangas Abellan (oriolman) - Sebastian Göttschkes (sgoettschkes) - Tatsuya Tsuruoka @@ -847,6 +858,7 @@ Symfony is the result of the work of many people who made the code better - Gunnar Lium (gunnarlium) - Tiago Garcia (tiagojsag) - Artiom + - Jakub Simon - Bouke Haarsma - Martin Eckhardt - Denis Zunke @@ -876,7 +888,6 @@ Symfony is the result of the work of many people who made the code better - Vasily Khayrulin (sirian) - Stefan Koopmanschap (skoop) - Stefan Hüsges (tronsha) - - Ivan Kurnosov - stloyd - Chris Tickner - Andrew Coulton @@ -905,7 +916,6 @@ Symfony is the result of the work of many people who made the code better - Julius Beckmann - Romain Dorgueil - Grayson Koonce (breerly) - - Matt Robinson (inanimatt) - Karim Cassam Chenaï (ka) - Nicolas Bastien (nicolas_bastien) - Andy Stanberry @@ -992,6 +1002,7 @@ Symfony is the result of the work of many people who made the code better - grifx - Robert Campbell - Matt Lehner + - Hidde Wieringa - Hein Zaw Htet™ - Ruben Kruiswijk - Michael J @@ -1048,9 +1059,7 @@ Symfony is the result of the work of many people who made the code better - Muriel (metalmumu) - Michaël Perrin (michael.perrin) - Michael Pohlers (mick_the_big) - - Mantas Var (mvar) - Cayetano Soriano Gallego (neoshadybeat) - - Maxime Steinhausser (ogizanagi) - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) - Cyrille Jouineau (tuxosaurus) @@ -1128,6 +1137,7 @@ Symfony is the result of the work of many people who made the code better - Brian Freytag - Skorney - mieszko4 + - Neophy7e - Arrilot - Markus Staab - Pierre-Louis LAUNAY @@ -1140,6 +1150,8 @@ Symfony is the result of the work of many people who made the code better - Sema - Thorsten Hallwas - Michael Squires + - Norman Soetbeer + - Benjamin Long - Matt Janssen - Peter Gribanov - kwiateusz @@ -1235,6 +1247,7 @@ Symfony is the result of the work of many people who made the code better - Vincent (vincent1870) - Eugene Babushkin (warl) - Xavier Amado (xamado) + - Jesper Søndergaard Pedersen (zerrvox) - Florent Cailhol - szymek - craigmarvelley diff --git a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php index 5185a75998..55991dbf4f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php @@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\Container; class ContainerAwareEventManagerTest extends \PHPUnit_Framework_TestCase { + private $container; + private $evm; + protected function setUp() { $this->container = new Container(); diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index c2eb2632f4..e076a15ae5 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -212,6 +212,9 @@ class CodeExtension extends \Twig_Extension }, $text); } + /** + * {@inheritdoc} + */ public function getName() { return 'code'; diff --git a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php index 4d9919d16c..1da12aaf5e 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php @@ -81,6 +81,9 @@ class HttpKernelExtension extends \Twig_Extension return new ControllerReference($controller, $attributes, $query); } + /** + * {@inheritdoc} + */ public function getName() { return 'http_kernel'; diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 237c36c190..7469183e75 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -89,9 +89,7 @@ class RoutingExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php index c414e21fe8..b13d7c0f85 100644 --- a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php @@ -52,9 +52,7 @@ class SecurityExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index 0fde3a675d..f1f2fbd20b 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -99,9 +99,7 @@ class TranslationExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index 63d658da3b..fc9bf0e9e3 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -56,9 +56,7 @@ class YamlExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 82cde1c319..8a73424d94 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -156,10 +156,7 @@ class Configuration implements ConfigurationInterface ->booleanNode('test')->end() ->scalarNode('default_locale')->defaultValue('en')->end() ->arrayNode('trusted_hosts') - ->beforeNormalization() - ->ifTrue(function ($v) { return is_string($v); }) - ->then(function ($v) { return array($v); }) - ->end() + ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end() ->prototype('scalar')->end() ->end() ->end() @@ -426,7 +423,7 @@ class Configuration implements ConfigurationInterface ->addDefaultChildrenIfNoneSet() ->prototype('scalar')->defaultValue('FrameworkBundle:Form')->end() ->validate() - ->ifTrue(function ($v) {return !in_array('FrameworkBundle:Form', $v); }) + ->ifNotInArray(array('FrameworkBundle:Form')) ->then(function ($v) { return array_merge(array('FrameworkBundle:Form'), $v); }) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml index 39266eab03..9d70124fbe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml @@ -16,7 +16,7 @@ - + null null true null diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php index d4a855d53b..8f0d54eada 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php @@ -58,9 +58,7 @@ class ActionsHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 1b9c5232f4..9c83d03bda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -205,9 +205,7 @@ class CodeHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php index 4aba0c202f..a4a80726b4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php @@ -83,9 +83,7 @@ class RequestHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php index 830e5c9019..d54caaf395 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php @@ -50,9 +50,7 @@ class RouterHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php index 3558b9ce04..941355c3ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php @@ -86,9 +86,7 @@ class SessionHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php index 30816d736f..2c2641a885 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php @@ -50,9 +50,7 @@ class TranslatorHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php index ee3d3ddc66..c32099a043 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php @@ -76,9 +76,7 @@ class LogoutUrlHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php index d43d2eb8f7..7df8511f8a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php @@ -43,9 +43,7 @@ class SecurityHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index 794144eb5d..2f00e5f4ea 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -81,7 +81,7 @@ class Configuration implements ConfigurationInterface ->prototype('scalar')->defaultValue('form_div_layout.html.twig')->end() ->example(array('MyBundle::form.html.twig')) ->validate() - ->ifTrue(function ($v) { return !in_array('form_div_layout.html.twig', $v); }) + ->ifNotInArray(array('form_div_layout.html.twig')) ->then(function ($v) { return array_merge(array('form_div_layout.html.twig'), $v); }) diff --git a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php index 9a1ad01653..a6b22759c5 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php @@ -77,6 +77,9 @@ class ActionsExtension extends \Twig_Extension ); } + /** + * {@inheritdoc} + */ public function getName() { return 'actions'; diff --git a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php index 98c7fe3890..1ad38f33bf 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php @@ -83,9 +83,7 @@ class AssetsExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig index 013ac6aa2a..f6c195e08a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig @@ -88,10 +88,13 @@ {% if collector.logs %}
    - {% for log in collector.logs if priority >= 0 and log.priority >= priority or priority < 0 and log.context.type|default(0) == priority %} -
  • - {{ logger.display_message(loop.index, log) }} -
  • + {% for log in collector.logs %} + {% set is_deprecation = log.context.level is defined and log.context.type is defined and (constant('E_DEPRECATED') == log.context.type or constant('E_USER_DEPRECATED') == log.context.type) %} + {% if priority == '-100' ? is_deprecation : log.priority >= priority %} +
  • + {{ logger.display_message(loop.index, log, is_deprecation) }} +
  • + {% endif %} {% else %}
  • No logs available for this priority.
  • {% endfor %} @@ -104,15 +107,18 @@ {% endblock %} -{% macro display_message(log_index, log) %} - {% if log.context.level is defined and log.context.type is defined and (constant('E_DEPRECATED') == log.context.type or constant('E_USER_DEPRECATED') == log.context.type) %} - DEPRECATION - {{ log.message }} - {% set id = 'sf-call-stack-' ~ log_index %} - - - + - - {% for index, call in log.context.stack if index > 1 %} +{% macro display_message(log_index, log, is_deprecation) %} + {% if is_deprecation %} + {% set stack = log.context.stack|default([]) %} + + {% if stack %} + + + + + + {% endif %} + + {% for index, call in stack if index > 1 %} {% if index == 2 %} {% endif %} {% endfor %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 35df28e031..4e2d815707 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -199,7 +199,7 @@ } {% if excluded_ajax_paths is defined %} - if (window.XMLHttpRequest && XMLHttpRequest.addEventListener) { + if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { var proxied = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index ca39b2d17d..11ac33378f 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -834,7 +834,7 @@ class Application $input->setInteractive(false); } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) { $inputStream = $this->getHelperSet()->get('question')->getInputStream(); - if (!@posix_isatty($inputStream)) { + if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { $input->setInteractive(false); } } diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index d65dc1fdd9..7baa745329 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -240,7 +240,7 @@ class ErrorHandler } /** - * Sets the error levels that are to be thrown. + * Sets the PHP error levels that throw an exception when a PHP error occurs. * * @param int $levels A bit field of E_* constants for thrown errors * @param bool $replace Replace or amend the previous value @@ -263,7 +263,7 @@ class ErrorHandler } /** - * Sets the error levels that are logged or thrown with their local scope. + * Sets the PHP error levels for which local variables are preserved. * * @param int $levels A bit field of E_* constants for scoped errors * @param bool $replace Replace or amend the previous value @@ -282,7 +282,7 @@ class ErrorHandler } /** - * Sets the error levels that are logged with their stack trace. + * Sets the PHP error levels for which the stack trace is preserved. * * @param int $levels A bit field of E_* constants for traced errors * @param bool $replace Replace or amend the previous value @@ -356,69 +356,71 @@ class ErrorHandler $throw = $this->thrownErrors & $type & $level; $type &= $level | $this->screamedErrors; - if ($type && ($log || $throw)) { - if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) { - $e = $context; // Whatever the signature of the method, - unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 - $context = $e; - } + if (!$type || (!$log && !$throw)) { + return $type && $log; + } - if ($throw) { - if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) { - // Checking for class existence is a work around for https://bugs.php.net/42098 - $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context); - } else { - $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line); - } + if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) { + $e = $context; // Whatever the signature of the method, + unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 + $context = $e; + } - if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { - // Exceptions thrown from error handlers are sometimes not caught by the exception - // handler and shutdown handlers are bypassed before 5.4.8/5.3.18. - // We temporarily re-enable display_errors to prevent any blank page related to this bug. - - $throw->errorHandlerCanary = new ErrorHandlerCanary(); - } - - throw $throw; - } - - // For duplicated errors, log the trace only once - $e = md5("{$type}/{$line}/{$file}\x00{$message}", true); - $trace = true; - - if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) { - $trace = false; + if ($throw) { + if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) { + // Checking for class existence is a work around for https://bugs.php.net/42098 + $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context); } else { - $this->loggedTraces[$e] = 1; + $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line); } - $e = compact('type', 'file', 'line', 'level'); + if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { + // Exceptions thrown from error handlers are sometimes not caught by the exception + // handler and shutdown handlers are bypassed before 5.4.8/5.3.18. + // We temporarily re-enable display_errors to prevent any blank page related to this bug. - if ($type & $level) { - if ($this->scopedErrors & $type) { - $e['context'] = $context; - if ($trace) { - $e['stack'] = debug_backtrace(true); // Provide object - } - } elseif ($trace) { - $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - } + $throw->errorHandlerCanary = new ErrorHandlerCanary(); } - if ($this->isRecursive) { - $log = 0; - } elseif (self::$stackedErrorLevels) { - self::$stackedErrors[] = array($this->loggers[$type], $message, $e); - } else { - try { - $this->isRecursive = true; - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e); - $this->isRecursive = false; - } catch (\Exception $e) { - $this->isRecursive = false; + throw $throw; + } - throw $e; + // For duplicated errors, log the trace only once + $e = md5("{$type}/{$line}/{$file}\x00{$message}", true); + $trace = true; + + if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) { + $trace = false; + } else { + $this->loggedTraces[$e] = 1; + } + + $e = compact('type', 'file', 'line', 'level'); + + if ($type & $level) { + if ($this->scopedErrors & $type) { + $e['scope_vars'] = $context; + if ($trace) { + $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT); } + } elseif ($trace) { + $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + } + } + + if ($this->isRecursive) { + $log = 0; + } elseif (self::$stackedErrorLevels) { + self::$stackedErrors[] = array($this->loggers[$type], $message, $e); + } else { + try { + $this->isRecursive = true; + $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e); + $this->isRecursive = false; + } catch (\Exception $e) { + $this->isRecursive = false; + + throw $e; } } @@ -487,40 +489,44 @@ class ErrorHandler public static function handleFatalError(array $error = null) { self::$reservedMemory = ''; + $handler = set_error_handler('var_dump', 0); $handler = is_array($handler) ? $handler[0] : null; restore_error_handler(); - if ($handler instanceof self) { - if (null === $error) { - $error = error_get_last(); - } - try { - while (self::$stackedErrorLevels) { - static::unstackErrors(); - } - } catch (\Exception $exception) { - // Handled below - } + if (!$handler instanceof self) { + return; + } - if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) { - // Let's not throw anymore but keep logging - $handler->throwAt(0, true); + if (null === $error) { + $error = error_get_last(); + } - if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false); - } else { - $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true); - } - } elseif (!isset($exception)) { - return; + try { + while (self::$stackedErrorLevels) { + static::unstackErrors(); } + } catch (\Exception $exception) { + // Handled below + } - try { - $handler->handleException($exception, $error); - } catch (FatalErrorException $e) { - // Ignore this re-throw + if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) { + // Let's not throw anymore but keep logging + $handler->throwAt(0, true); + + if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { + $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false); + } else { + $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true); } + } elseif (!isset($exception)) { + return; + } + + try { + $handler->handleException($exception, $error); + } catch (FatalErrorException $e) { + // Ignore this re-throw } } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 5f7acce96f..2bad0590fa 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -833,7 +833,7 @@ class Request $clientIps = array(); $ip = $this->server->get('REMOTE_ADDR'); - if (!self::$trustedProxies) { + if (!$this->isFromTrustedProxy()) { return array($ip); } @@ -1000,7 +1000,7 @@ class Request */ public function getPort() { - if (self::$trustedProxies) { + if ($this->isFromTrustedProxy()) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { return $port; } @@ -1236,7 +1236,7 @@ class Request */ public function isSecure() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); } @@ -1264,7 +1264,7 @@ class Request */ public function getHost() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { $elements = explode(',', $host); $host = $elements[count($elements) - 1]; @@ -1981,4 +1981,9 @@ class Request return new static($query, $request, $attributes, $cookies, $files, $server, $content); } + + private function isFromTrustedProxy() + { + return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index dd1eae2488..95320bbca8 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -743,35 +743,37 @@ class RequestTest extends \PHPUnit_Framework_TestCase 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '8443', )); - $port = $request->getPort(); - - $this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.'); + $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'https', )); - $port = $request->getPort(); - - $this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'http', )); - $port = $request->getPort(); - - $this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.'); + $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'On', )); - $port = $request->getPort(); - $this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => '1', )); - $port = $request->getPort(); - $this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'something-else', @@ -1066,6 +1068,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase $request->headers->set('X_FORWARDED_PROTO', 'https'); Request::setTrustedProxies(array('1.1.1.1')); + $this->assertFalse($request->isSecure()); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertTrue($request->isSecure()); Request::setTrustedProxies(array()); @@ -1544,7 +1548,15 @@ class RequestTest extends \PHPUnit_Framework_TestCase $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); + // trusted proxy via setTrustedProxies() + Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2')); + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + // check various X_FORWARDED_PROTO header values + Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); $request->headers->set('X_FORWARDED_PROTO', 'ssl'); $this->assertTrue($request->isSecure()); diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php index dfb1759af6..f7031b81fa 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php @@ -29,6 +29,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; class Esi implements SurrogateInterface { private $contentTypes; + private $phpEscapeMap = array( + array('', '', '', ''), + ); /** * Constructor. @@ -209,10 +213,34 @@ class Esi implements SurrogateInterface // we don't use a proper XML parser here as we can have ESI tags in a plain text response $content = $response->getContent(); - $content = str_replace(array('', ''), $content); - $content = preg_replace_callback('##', array($this, 'handleEsiIncludeTag'), $content); - $content = preg_replace('#]*(?:/|#', '', $content); $content = preg_replace('#.*?#', '', $content); + $content = preg_replace('#]*(?:/|#', '', $content); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = array(); + preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['src'])) { + throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); + } + + $chunks[$i] = sprintf('surrogate->handle($this, %s, %s, %s) ?>'."\n", + var_export($options['src'], true), + var_export(isset($options['alt']) ? $options['alt'] : '', true), + isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'ESI'); @@ -265,32 +293,4 @@ class Esi implements SurrogateInterface } } } - - /** - * Handles an ESI include tag (called internally). - * - * @param array $attributes An array containing the attributes. - * - * @return string The response content for the include. - * - * @throws \RuntimeException - */ - private function handleEsiIncludeTag($attributes) - { - $options = array(); - preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['src'])) { - throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); - } - - return sprintf('surrogate->handle($this, %s, %s, %s) ?>'."\n", - var_export($options['src'], true), - var_export(isset($options['alt']) ? $options['alt'] : '', true), - isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' - ); - } } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php index 1fc203e595..7bb54cff62 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php @@ -23,6 +23,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; class Ssi implements SurrogateInterface { private $contentTypes; + private $phpEscapeMap = array( + array('', '', '', ''), + ); /** * Constructor. @@ -122,8 +126,30 @@ class Ssi implements SurrogateInterface // we don't use a proper XML parser here as we can have SSI tags in a plain text response $content = $response->getContent(); - $content = str_replace(array('', ''), $content); - $content = preg_replace_callback('##', array($this, 'handleIncludeTag'), $content); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = array(); + preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['virtual'])) { + throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); + } + + $chunks[$i] = sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", + var_export($options['virtual'], true) + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'SSI'); @@ -166,30 +192,4 @@ class Ssi implements SurrogateInterface } } } - - /** - * Handles an SSI include tag (called internally). - * - * @param array $attributes An array containing the attributes. - * - * @return string The response content for the include. - * - * @throws \RuntimeException - */ - private function handleIncludeTag($attributes) - { - $options = array(); - preg_match_all('/(virtual)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['virtual'])) { - throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); - } - - return sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", - var_export($options['virtual'], true) - ); - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php index a90a8f1c92..00a9367600 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php @@ -124,10 +124,10 @@ class EsiTest extends \PHPUnit_Framework_TestCase $esi = new Esi(); $request = Request::create('/'); - $response = new Response('foo <%= "lala" %>'); + $response = new Response(''); $esi->process($request, $response); - $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); + $this->assertEquals('php cript language=php>', $response->getContent()); } /** diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php index bb208cd86c..07b70dcee8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php @@ -113,10 +113,10 @@ class SsiTest extends \PHPUnit_Framework_TestCase $ssi = new Ssi(); $request = Request::create('/'); - $response = new Response('foo <%= "lala" %>'); + $response = new Response(''); $ssi->process($request, $response); - $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); + $this->assertEquals('php cript language=php>', $response->getContent()); } /** diff --git a/src/Symfony/Component/PropertyAccess/StringUtil.php b/src/Symfony/Component/PropertyAccess/StringUtil.php index 5fa1b1734f..2160f0f422 100644 --- a/src/Symfony/Component/PropertyAccess/StringUtil.php +++ b/src/Symfony/Component/PropertyAccess/StringUtil.php @@ -60,6 +60,9 @@ class StringUtil // indices (index), appendices (appendix), prices (price) array('seci', 4, false, true, array('ex', 'ix', 'ice')), + // movies (movie) + array('seivom', 6, true, true, 'movie'), + // babies (baby) array('sei', 3, false, true, 'y'), diff --git a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php index 7c6376dbd6..73922cd72a 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php @@ -99,6 +99,7 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase array('men', 'man'), array('mice', 'mouse'), array('moves', 'move'), + array('movies', 'movie'), array('nebulae', 'nebula'), array('neuroses', array('neuros', 'neurose', 'neurosis')), array('oases', array('oas', 'oase', 'oasis')),