Просмотр исходного кода

[OutputEscaper] fixed output escaping when a variable was decorated with SafeDecorator and passed to another part of the system where decoration also happens on the same un-decorated variable

This is the case for instance when you pass a variable to a template like this:

new SafeDecorator($var);

and in the template, you pass it again to another embedded template:

$view->render('...', array('var' => $var);

The second time, $var will be escaped as the SafeDecorator wrapper will have been removed
by the escaper.
Fabien Potencier 14 лет назад
Родитель
Сommit
333504a201

+ 6 - 1
src/Symfony/Component/OutputEscaper/Escaper.php

@@ -22,6 +22,7 @@ class Escaper
     static protected $charset = 'UTF-8';
     static protected $safeClasses = array();
     static protected $escapers;
+    static protected $safeObjects = array();
 
     /**
      * Decorates a PHP variable with something that will escape any data obtained
@@ -75,6 +76,10 @@ class Escaper
         }
 
         if (is_object($value)) {
+            if (isset(self::$safeObjects[spl_object_hash($value)])) {
+                return $value;
+            }
+
             if ($value instanceof BaseEscaper) {
                 // avoid double decoration
                 $copy = clone $value;
@@ -86,7 +91,7 @@ class Escaper
             if ($value instanceof SafeDecorator) {
                 // do not escape objects marked as safe
                 // return the original object
-                return $value->getRawValue();
+                return self::$safeObjects[spl_object_hash($value->getRawValue())] = $value->getRawValue();
             }
 
             if (self::isClassMarkedAsSafe(get_class($value)) || $value instanceof SafeDecoratorInterface) {

+ 13 - 0
tests/Symfony/Tests/Component/OutputEscaper/EscaperTest.php

@@ -153,6 +153,19 @@ class EscaperTest extends \PHPUnit_Framework_TestCase
         );
         $this->assertEquals($output, Escaper::unescape($input), '::unescape() unescapes values with some escaped and unescaped values');
     }
+
+    public function testEscaperRememberSafeDecoratedObjects()
+    {
+        $object = new \stdClass();
+        $object->foo = '<br />';
+
+        $var = new SafeDecorator($object);
+        Escaper::escape('entities', $var);
+
+        $escaped = Escaper::escape('entities', $object);
+
+        $this->assertEquals('<br />', $escaped->foo);
+    }
 }
 
 class OutputEscaperTestClass