WIP more support for xmlrpc-polyfill
authorgggeek <giunta.gaetano@gmail.com>
Wed, 30 Dec 2020 10:59:38 +0000 (10:59 +0000)
committergggeek <giunta.gaetano@gmail.com>
Wed, 30 Dec 2020 10:59:38 +0000 (10:59 +0000)
src/Helper/Charset.php
src/Helper/Logger.php
src/Helper/XMLParser.php
src/Server.php
tests/3LocalhostTest.php

index 2f41143..22604d2 100644 (file)
@@ -9,9 +9,13 @@ class Charset
     // tables used for transcoding different charsets into us-ascii xml
     protected $xml_iso88591_Entities = array("in" => array(), "out" => array());
 
-    /// @todo add to iso table the characters from cp_1252 range, i.e. 128 to 159?
-    /// These will NOT be present in true ISO-8859-1, but will save the unwary windows user from sending junk
-    /// (though no luck when receiving them...)
+    /// @todo should we add to the latin-1 table the characters from cp_1252 range, i.e. 128 to 159 ?
+    ///       Those will NOT be present in true ISO-8859-1, but will save the unwary windows user from sending junk
+    ///       (though no luck when receiving them...)
+    ///       Note also that, apparently, while 'ISO/IEC 8859-1' has no characters defined for bytes 128 to 159,
+    ///       IANA ISO-8859-1 does have well-defined 'C1' control codes for those - wikipedia's page on latin-1 says:
+    ///       "ISO-8859-1 is the IANA preferred name for this standard when supplemented with the C0 and C1 control codes from ISO/IEC 6429."
+    ///       Check what mbstring/iconv do by default with those?
     /*
     protected $xml_cp1252_Entities = array('in' => array(), out' => array(
         '&#x20AC;', '?',        '&#x201A;', '&#x0192;',
@@ -37,6 +41,7 @@ class Charset
 
     /**
      * This class is singleton for performance reasons.
+     * @todo can't we just make $xml_iso88591_Entities a static variable instead ?
      *
      * @return Charset
      */
@@ -49,6 +54,9 @@ class Charset
         return self::$instance;
     }
 
+    /**
+     * @todo move the creation of the charset tables to be on-demand. This saves memory and time when latin-1 is not used at all
+     */
     private function __construct()
     {
         for ($i = 0; $i < 32; $i++) {
index 12932e7..01804c8 100644 (file)
@@ -59,6 +59,7 @@ class Logger
 
     /**
      * Writes a message to the error log
+     * @param string $message
      */
     public function errorLog($message)
     {
index 9e7efdd..10ffaa4 100644 (file)
@@ -11,6 +11,7 @@ use PhpXmlRpc\Value;
 class XMLParser
 {
     const RETURN_XMLRPCVALS = 'xmlrpcvals';
+    const RETURN_EPIVALS = 'epivals';
     const RETURN_PHP = 'phpvals';
 
     const ACCEPT_REQUEST = 1;
@@ -122,10 +123,15 @@ class XMLParser
 
         xml_set_object($parser, $this);
 
-        if ($returnType == self::RETURN_PHP) {
-            xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
-        } else {
-            xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
+        switch($returnType) {
+            case self::RETURN_PHP:
+                xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
+                break;
+            case self::RETURN_EPIVALS:
+                xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_epi');
+                break;
+            default:
+                xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
         }
 
         xml_set_character_data_handler($parser, 'xmlrpc_cd');
@@ -331,9 +337,9 @@ class XMLParser
      * xml parser handler function for close element tags.
      * @param resource $parser
      * @param string $name
-     * @param bool $rebuildXmlrpcvals
+     * @param int $rebuildXmlrpcvals >1 for rebuilding xmlrpcvals, 0 for rebuilding php values, -1 for xmlrpc-extension compatibility
      */
-    public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = true)
+    public function xmlrpc_ee($parser, $name, $rebuildXmlrpcvals = 1)
     {
         if ($this->_xh['isf'] < 2) {
             // push this element name from stack
@@ -350,7 +356,7 @@ class XMLParser
                         $this->_xh['vt'] = Value::$xmlrpcString;
                     }
 
-                    if ($rebuildXmlrpcvals) {
+                    if ($rebuildXmlrpcvals > 0) {
                         // build the xmlrpc val out of the data received, and substitute it
                         $temp = new Value($this->_xh['value'], $this->_xh['vt']);
                         // in case we got info about underlying php class, save it
@@ -358,27 +364,33 @@ class XMLParser
                         if (isset($this->_xh['php_class'])) {
                             $temp->_php_class = $this->_xh['php_class'];
                         }
-                        // check if we are inside an array or struct:
-                        // if value just built is inside an array, let's move it into array on the stack
-                        $vscount = count($this->_xh['valuestack']);
-                        if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
-                            $this->_xh['valuestack'][$vscount - 1]['values'][] = $temp;
-                        } else {
-                            $this->_xh['value'] = $temp;
+                        $this->_xh['value'] = $temp;
+                    } elseif ($rebuildXmlrpcvals < 0) {
+                        if ($this->_xh['vt'] == Value::$xmlrpcDateTime) {
+                            $this->_xh['value'] = (object)array(
+                                'xmlrpc_type' => 'datetime',
+                                'scalar' => $this->_xh['value'],
+                                'timestamp' => \PhpXmlRpc\Helper\Date::iso8601Decode($this->_xh['value'])
+                            );
+                        } elseif ($this->_xh['vt'] == Value::$xmlrpcBase64) {
+                            $this->_xh['value'] = (object)array(
+                                'xmlrpc_type' => 'base64',
+                                'scalar' => $this->_xh['value']
+                            );
                         }
                     } else {
-                        /// @todo this needs to treat correctly php-serialized objects,
+                        /// @todo this should handle php-serialized objects,
                         /// since std deserializing is done by php_xmlrpc_decode,
                         /// which we will not be calling...
-                        if (isset($this->_xh['php_class'])) {
-                        }
+                        //if (isset($this->_xh['php_class'])) {
+                        //}
+                    }
 
-                        // check if we are inside an array or struct:
-                        // if value just built is inside an array, let's move it into array on the stack
-                        $vscount = count($this->_xh['valuestack']);
-                        if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
-                            $this->_xh['valuestack'][$vscount - 1]['values'][] = $this->_xh['value'];
-                        }
+                    // check if we are inside an array or struct:
+                    // if value just built is inside an array, let's move it into array on the stack
+                    $vscount = count($this->_xh['valuestack']);
+                    if ($vscount && $this->_xh['valuestack'][$vscount - 1]['type'] == 'ARRAY') {
+                        $this->_xh['valuestack'][$vscount - 1]['values'][] = $this->_xh['value'];
                     }
                     break;
                 case 'BOOLEAN':
@@ -514,7 +526,17 @@ class XMLParser
      */
     public function xmlrpc_ee_fast($parser, $name)
     {
-        $this->xmlrpc_ee($parser, $name, false);
+        $this->xmlrpc_ee($parser, $name, 0);
+    }
+
+    /**
+     * Used in decoding xmlrpc requests/responses while building xmlrpc-extension Values (plain php for all but base64 and datetime).
+     * @param resource $parser
+     * @param string $name
+     */
+    public function xmlrpc_ee_epi($parser, $name)
+    {
+        $this->xmlrpc_ee($parser, $name, -1);
     }
 
     /**
index 3516f94..ffbe21e 100644 (file)
@@ -664,7 +664,7 @@ class Server
                     if ($this->functions_parameters_type == 'epivals') {
                         $r = call_user_func_array($func, array($methName, $params, $this->user_data));
                         // mimic EPI behaviour: if we get an array that looks like an error, make it
-                        // an eror response
+                        // an error response
                         if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) {
                             $r = new Response(0, (integer)$r['faultCode'], (string)$r['faultString']);
                         } else {
index 2ec0150..5f4c63a 100644 (file)
@@ -125,7 +125,7 @@ class LocalhostTest extends PhpXmlRpc_PolyfillTestCase
 
     /**
      * @param PhpXmlRpc\Request|array $msg
-     * @param int|array $errorCode
+     * @param int|array $errorCode expected error codes
      * @param bool $returnResponse
      * @return mixed|\PhpXmlRpc\Response|\PhpXmlRpc\Response[]|\PhpXmlRpc\Value|string|null
      */