fix bc for errors for empty requests
authorgggeek <giunta.gaetano@gmail.com>
Mon, 29 Jul 2019 13:13:20 +0000 (13:13 +0000)
committergggeek <giunta.gaetano@gmail.com>
Mon, 29 Jul 2019 13:13:20 +0000 (13:13 +0000)
src/Helper/XMLParser.php
tests/1ParsingBugsTest.php

index 56c5177..0f7e0fe 100644 (file)
@@ -69,10 +69,10 @@ class XMLParser
 
     /** @var array $parsing_options */
     protected $parsing_options = array();
-    /** @var int $accept */
-    protected $accept = 3; // self::ACCEPT_REQUEST | self::ACCEPT_RESPONSE;
-    /** @var int $maxChunkLength */
-    protected $maxChunkLength = 4194304; // 4 MB
+    /** @var int $accept self::ACCEPT_REQUEST | self::ACCEPT_RESPONSE by default */
+    protected $accept = 3;
+    /** @var int $maxChunkLength 4 MB by default. Any value below 10MB should be good */
+    protected $maxChunkLength = 4194304;
 
     /**
      * @param array $options passed to the xml parser
@@ -82,14 +82,6 @@ class XMLParser
         $this->parsing_options = $options;
     }
 
-    /**
-     * @param array $options passed to the xml parser
-     */
-    public function setParsingOptions(array $options)
-    {
-        $this->parsing_options = $options;
-    }
-
     /**
      * @param string $data
      * @param string $returnType
@@ -98,11 +90,34 @@ class XMLParser
      */
     public function parse($data, $returnType = self::RETURN_XMLRPCVALS, $accept = 3)
     {
+        $this->_xh = array(
+            'ac' => '',
+            'stack' => array(),
+            'valuestack' => array(),
+            'isf' => 0,
+            'isf_reason' => '',
+            'method' => false, // so we can check later if we got a methodname or not
+            'params' => array(),
+            'pt' => array(),
+            'rt' => '',
+        );
+
+        $len = strlen($data);
+
+        // we test for empty documents here to save on resource allocation and simply the chunked-parsing loop below
+        if ($len == 0) {
+            $this->_xh['isf'] = 3;
+            $this->_xh['isf_reason'] = 'XML error 5: empty document';
+            return;
+        }
+
         $parser = xml_parser_create();
 
         foreach ($this->parsing_options as $key => $val) {
             xml_parser_set_option($parser, $key, $val);
         }
+        // always set this, in case someone tries to disable it via options...
+        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 1);
 
         xml_set_object($parser, $this);
 
@@ -117,19 +132,7 @@ class XMLParser
 
         $this->accept = $accept;
 
-        $this->_xh = array(
-            'ac' => '',
-            'stack' => array(),
-            'valuestack' => array(),
-            'isf' => 0,
-            'isf_reason' => '',
-            'method' => false, // so we can check later if we got a methodname or not
-            'params' => array(),
-            'pt' => array(),
-            'rt' => '',
-        );
-
-        $len = strlen($data);
+        // @see ticket #70 - we have to parse big xml docks in chunks to avoid errors
         for ($offset = 0; $offset < $len; $offset += $this->maxChunkLength) {
             $chunk = substr($data, $offset, $this->maxChunkLength);
             // error handling: xml not well formed
index 10b5acb..bfa79e7 100644 (file)
@@ -639,4 +639,22 @@ and there they were.</value></member><member><name>postid</name><value>7414222</
             $i++;
         }
     }
+
+    function testBigXML()
+    {
+        // nb: make sure that  the serialized xml corresponding to this is > 10MB in size
+        $data = array();
+        for ($i = 0; $i < 500000; $i++ ) {
+            $data[] = 'hello world';
+        }
+
+        $encoder = new \PhpXmlRpc\Encoder();
+        $val = $encoder->encode($data);
+        $req = new \PhpXmlRpc\Request('test', array($val));
+        $xml = $req->serialize();
+        $parser = new \PhpXmlRpc\Helper\XMLParser();
+        $parser->parse($xml);
+
+        $this->assertequals(0, $parser->_xh['isf']);
+    }
 }