diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php index 202c0ce239ac..827c41598c4d 100755 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Engine.php @@ -27,7 +27,6 @@ class Engine extends BaseEngine { protected $container; protected $escaper; - protected $level; /** * Constructor. @@ -39,7 +38,6 @@ class Engine extends BaseEngine */ public function __construct(ContainerInterface $container, LoaderInterface $loader, array $renderers = array(), $escaper = false) { - $this->level = 0; $this->container = $container; $this->escaper = $escaper; @@ -61,8 +59,6 @@ public function __construct(ContainerInterface $container, LoaderInterface $load public function render($name, array $parameters = array()) { - ++$this->level; - list(, $options) = $this->splitTemplateName($name); $renderer = $options['renderer']; @@ -73,17 +69,10 @@ public function render($name, array $parameters = array()) } if ('php' === $renderer) { - // escape only once - if (1 === $this->level && !isset($parameters['_data'])) { - $parameters = $this->escapeParameters($parameters); - } + $parameters = $this->escapeParameters($parameters); } - $content = parent::render($name, $parameters); - - --$this->level; - - return $content; + return parent::render($name, $parameters); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/EngineTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/EngineTest.php index 230bdb0575aa..aa793581b8c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/EngineTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/EngineTest.php @@ -13,9 +13,50 @@ use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\Templating\Engine; +use Symfony\Component\Templating\Storage\StringStorage; +use Symfony\Component\Templating\Storage\Storage; +use Symfony\Component\Templating\Renderer\PhpRenderer; +use Symfony\Component\OutputEscaper\Escaper; + +// simulate the rendering of another controller +function foo($engine) +{ + return $engine->render('FooBundle:Foo:tpl1.php', array('foo' => 'foo
')); +} class EngineTest extends TestCase { + public function testRenderEscaping() + { + $templates = array( + 'tpl1' => '', + 'tpl2' => 'render("FooBundle:Foo:tpl1.php", array("foo" => $foo)) ?>', + 'tpl3' => 'render("FooBundle:Foo:tpl1.php", array("foo" => "foo
")) ?>', + 'tpl4' => '', + ); + + $loader = $this->getMock('Symfony\Component\Templating\Loader\LoaderInterface'); + $loader->expects($this->exactly(4)) + ->method('load') + ->with($this->anything(), $this->anything()) + ->will($this->onConsecutiveCalls( + new StringStorage($templates['tpl1']), + new StringStorage($templates['tpl2']), + new StringStorage($templates['tpl3']), + new StringStorage($templates['tpl4']) + )) + ; + + $engine = new Engine($this->getContainerMock(), $loader, array('php' => new PhpRenderer()), 'htmlspecialchars'); + + $this->assertEquals('foo <br />', $engine->render('FooBundle:Foo:tpl1.php', array('foo' => 'foo
'))); + $this->assertEquals('foo <br />', $engine->render('FooBundle:Foo:tpl1.php', array('foo' => 'foo
'))); + + $this->assertEquals('foo <br />foo <br />', $engine->render('FooBundle:Foo:tpl2.php', array('foo' => 'foo
'))); + $this->assertEquals('foo <br />foo <br />', $engine->render('FooBundle:Foo:tpl3.php', array('foo' => 'foo
'))); + $this->assertEquals('foo <br />foo <br />', $engine->render('FooBundle:Foo:tpl4.php', array('foo' => 'foo
'))); + } + /** * @dataProvider getSplitTemplateNameTests */ diff --git a/src/Symfony/Component/OutputEscaper/Escaper.php b/src/Symfony/Component/OutputEscaper/Escaper.php index f929270b8ce0..1ef1a53280ea 100644 --- a/src/Symfony/Component/OutputEscaper/Escaper.php +++ b/src/Symfony/Component/OutputEscaper/Escaper.php @@ -206,6 +206,9 @@ static public function getCharset() /** * Adds a named escaper. * + * Warning: An escaper must be able to deal with + * double-escaping correctly. + * * @param string $name The escaper name * @param mixed $escaper A PHP callable */ @@ -262,7 +265,7 @@ function ($value) { // Numbers and boolean values get turned into strings which can cause problems // with type comparisons (e.g. === or is_int() etc). - return is_string($value) ? htmlspecialchars($value, ENT_QUOTES, Escaper::getCharset()) : $value; + return is_string($value) ? htmlspecialchars($value, ENT_QUOTES, Escaper::getCharset(), false) : $value; }, 'entities' => @@ -276,7 +279,7 @@ function ($value) { // Numbers and boolean values get turned into strings which can cause problems // with type comparisons (e.g. === or is_int() etc). - return is_string($value) ? htmlentities($value, ENT_QUOTES, Escaper::getCharset()) : $value; + return is_string($value) ? htmlentities($value, ENT_QUOTES, Escaper::getCharset(), false) : $value; }, 'raw' =>