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

Merge pull request #591 from weierophinney/hotfix/591

ZF2015-06 fix broke the ZF on PHP 5.2
Frank Brückner 10 лет назад
Родитель
Сommit
d81d3820eb
3 измененных файлов с 161 добавлено и 37 удалено
  1. 119 33
      library/Zend/Xml/Security.php
  2. 5 4
      tests/Zend/Xml/MultibyteTest.php
  3. 37 0
      tests/Zend/Xml/TestAsset/Security.php

+ 119 - 33
library/Zend/Xml/Security.php

@@ -189,10 +189,10 @@ class Zend_Xml_Security
     protected static function getEntityComparison($xml)
     {
         $encodingMap = self::getAsciiEncodingMap();
-        return array_map(function ($encoding) use ($encodingMap) {
-            $generator   = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap['UTF-8'];
-            return $generator('<!ENTITY');
-        }, self::detectXmlEncoding($xml, self::detectStringEncoding($xml)));
+        return array_map(
+            array(__CLASS__, 'generateEntityComparison'),
+            self::detectXmlEncoding($xml, self::detectStringEncoding($xml))
+        );
     }
 
     /**
@@ -206,7 +206,8 @@ class Zend_Xml_Security
      */
     protected static function detectStringEncoding($xml)
     {
-        return self::detectBom($xml) ?: self::detectXmlStringEncoding($xml);
+        $encoding = self::detectBom($xml);
+        return ($encoding) ? $encoding : self::detectXmlStringEncoding($xml);
     }
 
     /**
@@ -238,7 +239,7 @@ class Zend_Xml_Security
     protected static function detectXmlStringEncoding($xml)
     {
         foreach (self::getAsciiEncodingMap() as $encoding => $generator) {
-            $prefix = $generator('<' . '?xml');
+            $prefix = call_user_func($generator, '<' . '?xml');
             if (0 === strncmp($xml, $prefix, strlen($prefix))) {
                 return $encoding;
             }
@@ -266,9 +267,9 @@ class Zend_Xml_Security
     {
         $encodingMap = self::getAsciiEncodingMap();
         $generator   = $encodingMap[$fileEncoding];
-        $encAttr     = $generator('encoding="');
-        $quote       = $generator('"');
-        $close       = $generator('>');
+        $encAttr     = call_user_func($generator, 'encoding="');
+        $quote       = call_user_func($generator, '"');
+        $close       = call_user_func($generator, '>');
 
         $closePos    = strpos($xml, $close);
         if (false === $closePos) {
@@ -353,30 +354,14 @@ class Zend_Xml_Security
     protected static function getAsciiEncodingMap()
     {
         return array(
-            'UTF-32BE'   => function ($ascii) {
-                return preg_replace('/(.)/', "\0\0\0\\1", $ascii);
-            },
-            'UTF-32LE'   => function ($ascii) {
-                return preg_replace('/(.)/', "\\1\0\0\0", $ascii);
-            },
-            'UTF-32odd1' => function ($ascii) {
-                return preg_replace('/(.)/', "\0\\1\0\0", $ascii);
-            },
-            'UTF-32odd2' => function ($ascii) {
-                return preg_replace('/(.)/', "\0\0\\1\0", $ascii);
-            },
-            'UTF-16BE'   => function ($ascii) {
-                return preg_replace('/(.)/', "\0\\1", $ascii);
-            },
-            'UTF-16LE'   => function ($ascii) {
-                return preg_replace('/(.)/', "\\1\0", $ascii);
-            },
-            'UTF-8'      => function ($ascii) {
-                return $ascii;
-            },
-            'GB-18030'   => function ($ascii) {
-                return $ascii;
-            },
+            'UTF-32BE'   => array(__CLASS__, 'encodeToUTF32BE'),
+            'UTF-32LE'   => array(__CLASS__, 'encodeToUTF32LE'),
+            'UTF-32odd1' => array(__CLASS__, 'encodeToUTF32odd1'),
+            'UTF-32odd2' => array(__CLASS__, 'encodeToUTF32odd2'),
+            'UTF-16BE'   => array(__CLASS__, 'encodeToUTF16BE'),
+            'UTF-16LE'   => array(__CLASS__, 'encodeToUTF16LE'),
+            'UTF-8'      => array(__CLASS__, 'encodeToUTF8'),
+            'GB-18030'   => array(__CLASS__, 'encodeToUTF8'),
         );
     }
 
@@ -399,4 +384,105 @@ class Zend_Xml_Security
         }
         return $substr;
     }
+
+    /**
+     * Generate an entity comparison based on the given encoding.
+     *
+     * This patch is internal only, and public only so it can be used as a
+     * callable to pass to array_map.
+     *
+     * @internal
+     * @param string $encoding
+     * @return string
+     */
+    public static function generateEntityComparison($encoding)
+    {
+        $encodingMap = self::getAsciiEncodingMap();
+        $generator   = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap['UTF-8'];
+        return call_user_func($generator, '<!ENTITY');
+    }
+
+    /**
+     * Encode an ASCII string to UTF-32BE
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF32BE($ascii)
+    {
+        return preg_replace('/(.)/', "\0\0\0\\1", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-32LE
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF32LE($ascii)
+    {
+        return preg_replace('/(.)/', "\\1\0\0\0", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-32odd1
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF32odd1($ascii)
+    {
+        return preg_replace('/(.)/', "\0\\1\0\0", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-32odd2
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF32odd2($ascii)
+    {
+        return preg_replace('/(.)/', "\0\0\\1\0", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-16BE
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF16BE($ascii)
+    {
+        return preg_replace('/(.)/', "\0\\1", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-16LE
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF16LE($ascii)
+    {
+        return preg_replace('/(.)/', "\\1\0", $ascii);
+    }
+
+    /**
+     * Encode an ASCII string to UTF-8
+     *
+     * @internal
+     * @param string $ascii
+     * @return string
+     */
+    public static function encodeToUTF8($ascii)
+    {
+        return $ascii;
+    }
 }

+ 5 - 4
tests/Zend/Xml/MultibyteTest.php

@@ -25,9 +25,12 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
 }
 
 /**
+ * This is a class that overrides Zend_Xml_Security to mark the heuristicScan()
+ * method as public, allowing us to test it.
+ *
  * @see Zend_Xml_Security
  */
-require_once 'Zend/Xml/Security.php';
+require_once 'Zend/Xml/TestAsset/Security.php';
 
 require_once 'Zend/Xml/Exception.php';
 
@@ -80,9 +83,7 @@ XML;
      */
     public function invokeHeuristicScan($xml)
     {
-        $r = new ReflectionMethod('Zend_Xml_Security', 'heuristicScan');
-        $r->setAccessible(true);
-        return $r->invoke(null, $xml);
+        return Zend_Xml_TestAsset_Security::heuristicScan($xml);
     }
 
     /**

+ 37 - 0
tests/Zend/Xml/TestAsset/Security.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Xml_Security
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+require_once 'Zend/Xml/Security.php';
+
+class Zend_Xml_TestAsset_Security extends Zend_Xml_Security
+{
+    /**
+     * Override heuristic scan to make it public for testing.
+     *
+     * @param string $xml
+     * @throws Zend_Xml_Exception If entity expansion or external entity declaration was discovered.
+     */
+    public static function heuristicScan($xml)
+    {
+        parent::heuristicScan($xml);
+    }
+}