Explorar o código

ZF-6445: Adding support for XML/RPC big integers

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@17933 44c647ce-9c0f-0410-b52a-842ac1e357ba
lars %!s(int64=16) %!d(string=hai) anos
pai
achega
6b70409f70

+ 44 - 13
library/Zend/XmlRpc/Value.php

@@ -75,6 +75,8 @@ abstract class Zend_XmlRpc_Value
      */
      */
     const XMLRPC_TYPE_I4       = 'i4';
     const XMLRPC_TYPE_I4       = 'i4';
     const XMLRPC_TYPE_INTEGER  = 'int';
     const XMLRPC_TYPE_INTEGER  = 'int';
+    const XMLRPC_TYPE_I8       = 'i8';
+    const XMLRPC_TYPE_APACHEI8 = 'ex:i8';
     const XMLRPC_TYPE_DOUBLE   = 'double';
     const XMLRPC_TYPE_DOUBLE   = 'double';
     const XMLRPC_TYPE_BOOLEAN  = 'boolean';
     const XMLRPC_TYPE_BOOLEAN  = 'boolean';
     const XMLRPC_TYPE_STRING   = 'string';
     const XMLRPC_TYPE_STRING   = 'string';
@@ -164,6 +166,11 @@ abstract class Zend_XmlRpc_Value
             case self::XMLRPC_TYPE_INTEGER:
             case self::XMLRPC_TYPE_INTEGER:
                 return new Zend_XmlRpc_Value_Integer($value);
                 return new Zend_XmlRpc_Value_Integer($value);
 
 
+            case self::XMLRPC_TYPE_I8:
+                // fall through to the next case
+            case self::XMLRPC_TYPE_APACHEI8:
+                return new Zend_XmlRpc_Value_BigInteger($value);
+
             case self::XMLRPC_TYPE_DOUBLE:
             case self::XMLRPC_TYPE_DOUBLE:
                 return new Zend_XmlRpc_Value_Double($value);
                 return new Zend_XmlRpc_Value_Double($value);
 
 
@@ -231,6 +238,10 @@ abstract class Zend_XmlRpc_Value
                 require_once 'Zend/XmlRpc/Value/Integer.php';
                 require_once 'Zend/XmlRpc/Value/Integer.php';
                 return new Zend_XmlRpc_Value_Integer($value);
                 return new Zend_XmlRpc_Value_Integer($value);
 
 
+            case 'i8':
+                require_once 'Zend/XmlRpc/Value/BigInteger.php';
+                return new Zend_XmlRpc_Value_BigInteger($value);
+
             case 'double':
             case 'double':
                 require_once 'Zend/XmlRpc/Value/Double.php';
                 require_once 'Zend/XmlRpc/Value/Double.php';
                 return new Zend_XmlRpc_Value_Double($value);
                 return new Zend_XmlRpc_Value_Double($value);
@@ -267,7 +278,7 @@ abstract class Zend_XmlRpc_Value
     {
     {
         if (!$xml instanceof SimpleXMLElement) {
         if (!$xml instanceof SimpleXMLElement) {
             try {
             try {
-                $xml = @new SimpleXMLElement($xml);
+                $xml = new SimpleXMLElement($xml);
             } catch (Exception $e) {
             } catch (Exception $e) {
                 // The given string is not a valid XML
                 // The given string is not a valid XML
                 require_once 'Zend/XmlRpc/Value/Exception.php';
                 require_once 'Zend/XmlRpc/Value/Exception.php';
@@ -275,8 +286,22 @@ abstract class Zend_XmlRpc_Value
             }
             }
         }
         }
 
 
-        // Get the key (tag name) and value from the simple xml object and convert the value to an XML-RPC native value
+        $type = null;
+        $value = null;
         list($type, $value) = each($xml);
         list($type, $value) = each($xml);
+
+        if (!$type and $value === null) {
+            $namespaces = array('ex' => 'http://ws.apache.org/xmlrpc/namespaces/extensions');
+            foreach ($namespaces as $namespaceName => $namespaceUri) {
+                $namespaceXml = $xml->children($namespaceUri);
+                list($type, $value) = each($namespaceXml);
+                if ($type !== null) {
+                    $type = $namespaceName . ':' . $type;
+                    break;
+                }
+            }
+        }
+
         if (!$type) {    // If no type was specified, the default is string
         if (!$type) {    // If no type was specified, the default is string
             $type = self::XMLRPC_TYPE_STRING;
             $type = self::XMLRPC_TYPE_STRING;
         }
         }
@@ -287,30 +312,36 @@ abstract class Zend_XmlRpc_Value
                 // Fall through to the next case
                 // Fall through to the next case
             case self::XMLRPC_TYPE_INTEGER:
             case self::XMLRPC_TYPE_INTEGER:
                 require_once 'Zend/XmlRpc/Value/Integer.php';
                 require_once 'Zend/XmlRpc/Value/Integer.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Integer($value);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Integer($value);
+                break;
+            case self::XMLRPC_TYPE_APACHEI8:
+                // Fall through to the next case
+            case self::XMLRPC_TYPE_I8:
+                require_once 'Zend/XmlRpc/Value/BigInteger.php';
+                $xmlrpcValue = new Zend_XmlRpc_Value_BigInteger($value);
                 break;
                 break;
             case self::XMLRPC_TYPE_DOUBLE:
             case self::XMLRPC_TYPE_DOUBLE:
                 require_once 'Zend/XmlRpc/Value/Double.php';
                 require_once 'Zend/XmlRpc/Value/Double.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Double($value);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Double($value);
                 break;
                 break;
             case self::XMLRPC_TYPE_BOOLEAN:
             case self::XMLRPC_TYPE_BOOLEAN:
                 require_once 'Zend/XmlRpc/Value/Boolean.php';
                 require_once 'Zend/XmlRpc/Value/Boolean.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Boolean($value);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Boolean($value);
                 break;
                 break;
             case self::XMLRPC_TYPE_STRING:
             case self::XMLRPC_TYPE_STRING:
                 require_once 'Zend/XmlRpc/Value/String.php';
                 require_once 'Zend/XmlRpc/Value/String.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_String($value);
+                $xmlrpcValue = new Zend_XmlRpc_Value_String($value);
                 break;
                 break;
             case self::XMLRPC_TYPE_DATETIME:  // The value should already be in a iso8601 format
             case self::XMLRPC_TYPE_DATETIME:  // The value should already be in a iso8601 format
                 require_once 'Zend/XmlRpc/Value/DateTime.php';
                 require_once 'Zend/XmlRpc/Value/DateTime.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_DateTime($value);
+                $xmlrpcValue = new Zend_XmlRpc_Value_DateTime($value);
                 break;
                 break;
             case self::XMLRPC_TYPE_BASE64:    // The value should already be base64 encoded
             case self::XMLRPC_TYPE_BASE64:    // The value should already be base64 encoded
                 require_once 'Zend/XmlRpc/Value/Base64.php';
                 require_once 'Zend/XmlRpc/Value/Base64.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Base64($value ,true);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Base64($value, true);
                 break;
                 break;
             case self::XMLRPC_TYPE_NIL:    // The value should always be NULL
             case self::XMLRPC_TYPE_NIL:    // The value should always be NULL
-                $xmlrpc_val = new Zend_XmlRpc_Value_Nil();
+                $xmlrpcValue = new Zend_XmlRpc_Value_Nil();
                 break;
                 break;
             case self::XMLRPC_TYPE_ARRAY:
             case self::XMLRPC_TYPE_ARRAY:
                 // PHP 5.2.4 introduced a regression in how empty($xml->value)
                 // PHP 5.2.4 introduced a regression in how empty($xml->value)
@@ -334,7 +365,7 @@ abstract class Zend_XmlRpc_Value
                     $values[] = self::_xmlStringToNativeXmlRpc($element);
                     $values[] = self::_xmlStringToNativeXmlRpc($element);
                 }
                 }
                 require_once 'Zend/XmlRpc/Value/Array.php';
                 require_once 'Zend/XmlRpc/Value/Array.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Array($values);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Array($values);
                 break;
                 break;
             case self::XMLRPC_TYPE_STRUCT:
             case self::XMLRPC_TYPE_STRUCT:
                 $values = array();
                 $values = array();
@@ -350,16 +381,16 @@ abstract class Zend_XmlRpc_Value
                     $values[(string)$member->name] = self::_xmlStringToNativeXmlRpc($member->value);
                     $values[(string)$member->name] = self::_xmlStringToNativeXmlRpc($member->value);
                 }
                 }
                 require_once 'Zend/XmlRpc/Value/Struct.php';
                 require_once 'Zend/XmlRpc/Value/Struct.php';
-                $xmlrpc_val = new Zend_XmlRpc_Value_Struct($values);
+                $xmlrpcValue = new Zend_XmlRpc_Value_Struct($values);
                 break;
                 break;
             default:
             default:
                 require_once 'Zend/XmlRpc/Value/Exception.php';
                 require_once 'Zend/XmlRpc/Value/Exception.php';
                 throw new Zend_XmlRpc_Value_Exception('Value type \''. $type .'\' parsed from the XML string is not a known XML-RPC native type');
                 throw new Zend_XmlRpc_Value_Exception('Value type \''. $type .'\' parsed from the XML string is not a known XML-RPC native type');
                 break;
                 break;
         }
         }
-        $xmlrpc_val->_setXML($xml->asXML());
+        $xmlrpcValue->_setXML($xml->asXML());
 
 
-        return $xmlrpc_val;
+        return $xmlrpcValue;
     }
     }
 
 
 
 

+ 65 - 0
library/Zend/XmlRpc/Value/BigInteger.php

@@ -0,0 +1,65 @@
+<?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_XmlRpc
+ * @subpackage Value
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Integer.php 17753 2009-08-22 16:09:37Z lars $
+ */
+
+
+/**
+ * Zend_XmlRpc_Value_Integer
+ */
+require_once 'Zend/XmlRpc/Value/Integer.php';
+
+
+/**
+ * @category   Zend
+ * @package    Zend_XmlRpc
+ * @subpackage Value
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_XmlRpc_Value_BigInteger extends Zend_XmlRpc_Value_Integer
+{
+    /**
+     * @var Zend_Crypt_Math_BigInteger
+     */
+    protected $_integer;
+
+    /**
+     * @param mixed $value
+     */
+    public function __construct($value)
+    {
+        require_once 'Zend/Crypt/Math/BigInteger.php';
+        $this->_integer = new Zend_Crypt_Math_BigInteger();
+        $this->_value = $this->_integer->init($this->_value);
+
+        $this->_type = self::XMLRPC_TYPE_I8;
+    }
+
+    /**
+     * Return bigint value object
+     *
+     * @return Zend_Crypt_Math_BigInteger
+     */
+    public function getValue()
+    {
+        return $this->_integer;
+    }
+}

+ 0 - 2
library/Zend/XmlRpc/Value/Integer.php

@@ -62,6 +62,4 @@ class Zend_XmlRpc_Value_Integer extends Zend_XmlRpc_Value_Scalar
     {
     {
         return $this->_value;
         return $this->_value;
     }
     }
-
 }
 }
-

+ 0 - 1
library/Zend/XmlRpc/Value/Scalar.php

@@ -57,4 +57,3 @@ abstract class Zend_XmlRpc_Value_Scalar extends Zend_XmlRpc_Value
         return $this->_as_xml;
         return $this->_as_xml;
     }
     }
 }
 }
-

+ 44 - 1
tests/Zend/XmlRpc/ValueTest.php

@@ -31,6 +31,7 @@ require_once "PHPUnit/Framework/TestSuite.php";
 
 
 require_once 'Zend/XmlRpc/Value.php';
 require_once 'Zend/XmlRpc/Value.php';
 require_once 'Zend/XmlRpc/Value/Scalar.php';
 require_once 'Zend/XmlRpc/Value/Scalar.php';
+require_once 'Zend/XmlRpc/Value/BigInteger.php';
 require_once 'Zend/XmlRpc/Value/Collection.php';
 require_once 'Zend/XmlRpc/Value/Collection.php';
 require_once 'Zend/XmlRpc/Value/Array.php';
 require_once 'Zend/XmlRpc/Value/Array.php';
 require_once 'Zend/XmlRpc/Value/Base64.php';
 require_once 'Zend/XmlRpc/Value/Base64.php';
@@ -41,6 +42,7 @@ require_once 'Zend/XmlRpc/Value/Integer.php';
 require_once 'Zend/XmlRpc/Value/String.php';
 require_once 'Zend/XmlRpc/Value/String.php';
 require_once 'Zend/XmlRpc/Value/Nil.php';
 require_once 'Zend/XmlRpc/Value/Nil.php';
 require_once 'Zend/XmlRpc/Value/Struct.php';
 require_once 'Zend/XmlRpc/Value/Struct.php';
+require_once 'Zend/Crypt/Math/BigInteger.php';
 
 
 /**
 /**
  * Test case for Zend_XmlRpc_Value
  * Test case for Zend_XmlRpc_Value
@@ -130,7 +132,6 @@ class Zend_XmlRpc_ValueTest extends PHPUnit_Framework_TestCase
         foreach ($xmls as $xml) {
         foreach ($xmls as $xml) {
             $val = Zend_XmlRpc_Value::getXmlRpcValue($xml,
             $val = Zend_XmlRpc_Value::getXmlRpcValue($xml,
                                         Zend_XmlRpc_Value::XML_STRING);
                                         Zend_XmlRpc_Value::XML_STRING);
-
             $this->assertXmlRpcType('integer', $val);
             $this->assertXmlRpcType('integer', $val);
             $this->assertEquals('int', $val->getType());
             $this->assertEquals('int', $val->getType());
             $this->assertSame($native, $val->getValue());
             $this->assertSame($native, $val->getValue());
@@ -157,6 +158,48 @@ class Zend_XmlRpc_ValueTest extends PHPUnit_Framework_TestCase
         Zend_XmlRpc_Value::getXmlRpcValue(PHP_INT_MAX + 1, Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER);
         Zend_XmlRpc_Value::getXmlRpcValue(PHP_INT_MAX + 1, Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER);
     }
     }
 
 
+    // BigInteger
+
+    /**
+     * @group ZF-6445
+     */
+    public function testMarshalBigIntegerFromFromXmlRpc()
+    {
+        $bigInt = (string)(PHP_INT_MAX + 1);
+        $native = new Zend_Crypt_Math_BigInteger();
+        $native->init($bigInt);
+
+        $xmlStrings = array("<value><i8>$bigInt</i8></value>",
+                            "<value><ex:i8 xmlns:ex=\"http://ws.apache.org/xmlrpc/namespaces/extensions\">$bigInt</ex:i8></value>");
+
+        foreach ($xmlStrings as $xml) {
+            $value = Zend_XmlRpc_Value::getXmlRpcValue($xml, Zend_XmlRpc_Value::XML_STRING);
+            $this->assertEquals($native, $value->getValue());
+            $this->assertEquals('i8', $value->getType());
+            $this->assertType('DOMElement', $value->getAsDOM());
+            $this->assertEquals($this->wrapXml($xml), $value->saveXml());
+        }
+    }
+
+    /**
+     * @group ZF-6445
+     */
+    public function testMarshalBigIntegerFromNative()
+    {
+        $native = (string)(PHP_INT_MAX + 1);
+        $types = array(Zend_XmlRpc_Value::XMLRPC_TYPE_APACHEI8,
+                        Zend_XmlRpc_Value::XMLRPC_TYPE_I8);
+
+        $bigInt = new Zend_Crypt_Math_BigInteger();
+        $bigInt->init($native);
+
+        foreach ($types as $type) {
+            $value = Zend_XmlRpc_Value::getXmlRpcValue($native, $type);
+            $this->assertSame('i8', $value->getType());
+            $this->assertEquals($bigInt, $value->getValue());
+        }
+    }
+
     // Double
     // Double
 
 
     public function testFactoryAutodetectsFloat()
     public function testFactoryAutodetectsFloat()