فهرست منبع

[#591] Support PHP 5.2 in Zend_Xml_Security

The patch for ZF2015-06 heavily relied on:

- closures
- ability to invoke arbitrary callables as functions
- shortcut ternary operator

none of which are supported in PHP 5.2. This patch provides PHP 5.2
compatiblity.
Matthew Weier O'Phinney 10 سال پیش
والد
کامیت
a0d47cb100
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);
+    }
+}