Add support for i8
[plcapi.git] / src / Helper / XMLParser.php
index 58acdaf..b7d137f 100644 (file)
@@ -40,6 +40,8 @@ class XMLParser
         'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'),
         'BOOLEAN' => array('VALUE'),
         'I4' => array('VALUE'),
+        'I8' => array('VALUE'),
+        'EX:I8' => array('VALUE'),
         'INT' => array('VALUE'),
         'STRING' => array('VALUE'),
         'DOUBLE' => array('VALUE'),
@@ -100,6 +102,16 @@ class XMLParser
                     $this->_xh['lv'] = 1;
                     $this->_xh['php_class'] = null;
                     break;
+                case 'I8':
+                case 'EX:I8':
+                    if (PHP_INT_SIZE === 4) {
+                        /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!!
+                        $this->_xh['isf'] = 2;
+                        $this->_xh['isf_reason'] = "Received i8 element but php is compiled in 32 bit mode";
+
+                        return;
+                    }
+                // fall through voluntarily
                 case 'I4':
                 case 'INT':
                 case 'STRING':
@@ -108,7 +120,7 @@ class XMLParser
                 case 'DATETIME.ISO8601':
                 case 'BASE64':
                     if ($this->_xh['vt'] != 'value') {
-                        //two data elements inside a value: an error occurred!
+                        // two data elements inside a value: an error occurred!
                         $this->_xh['isf'] = 2;
                         $this->_xh['isf_reason'] = "$name element following a {$this->_xh['vt']} element inside a single value";
 
@@ -259,6 +271,8 @@ class XMLParser
                     break;
                 case 'BOOLEAN':
                 case 'I4':
+                case 'I8':
+                case 'EX:I8':
                 case 'INT':
                 case 'STRING':
                 case 'DOUBLE':
@@ -271,7 +285,7 @@ class XMLParser
                         $this->_xh['value'] = $this->_xh['ac'];
                     } elseif ($name == 'DATETIME.ISO8601') {
                         if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $this->_xh['ac'])) {
-                            error_log('XML-RPC: invalid value received in DATETIME: ' . $this->_xh['ac']);
+                            error_log('XML-RPC: ' . __METHOD__ . ': invalid value received in DATETIME: ' . $this->_xh['ac']);
                         }
                         $this->_xh['vt'] = Value::$xmlrpcDateTime;
                         $this->_xh['value'] = $this->_xh['ac'];
@@ -290,7 +304,7 @@ class XMLParser
                         } else {
                             // log if receiving something strange, even though we set the value to false anyway
                             if ($this->_xh['ac'] != '0' && strcasecmp($this->_xh['ac'], 'false') != 0) {
-                                error_log('XML-RPC: invalid value received in BOOLEAN: ' . $this->_xh['ac']);
+                                error_log('XML-RPC: ' . __METHOD__ . ': invalid value received in BOOLEAN: ' . $this->_xh['ac']);
                             }
                             $this->_xh['value'] = false;
                         }
@@ -300,43 +314,40 @@ class XMLParser
                         // NOTE: regexp could be much stricter than this...
                         if (!preg_match('/^[+-eE0123456789 \t.]+$/', $this->_xh['ac'])) {
                             /// @todo: find a better way of throwing an error than this!
-                            error_log('XML-RPC: non numeric value received in DOUBLE: ' . $this->_xh['ac']);
+                            error_log('XML-RPC: ' . __METHOD__ . ': non numeric value received in DOUBLE: ' . $this->_xh['ac']);
                             $this->_xh['value'] = 'ERROR_NON_NUMERIC_FOUND';
                         } else {
                             // it's ok, add it on
                             $this->_xh['value'] = (double)$this->_xh['ac'];
                         }
                     } else {
-                        // we have an I4/INT
+                        // we have an I4/I8/INT
                         // we must check that only 0123456789-<space> are characters here
                         if (!preg_match('/^[+-]?[0123456789 \t]+$/', $this->_xh['ac'])) {
                             /// @todo find a better way of throwing an error than this!
-                            error_log('XML-RPC: non numeric value received in INT: ' . $this->_xh['ac']);
+                            error_log('XML-RPC: ' . __METHOD__ . ': non numeric value received in INT: ' . $this->_xh['ac']);
                             $this->_xh['value'] = 'ERROR_NON_NUMERIC_FOUND';
                         } else {
                             // it's ok, add it on
                             $this->_xh['value'] = (int)$this->_xh['ac'];
                         }
                     }
-                    //$this->_xh['ac']=''; // is this necessary?
                     $this->_xh['lv'] = 3; // indicate we've found a value
                     break;
                 case 'NAME':
                     $this->_xh['valuestack'][count($this->_xh['valuestack']) - 1]['name'] = $this->_xh['ac'];
                     break;
                 case 'MEMBER':
-                    //$this->_xh['ac']=''; // is this necessary?
                     // add to array in the stack the last element built,
                     // unless no VALUE was found
                     if ($this->_xh['vt']) {
                         $vscount = count($this->_xh['valuestack']);
                         $this->_xh['valuestack'][$vscount - 1]['values'][$this->_xh['valuestack'][$vscount - 1]['name']] = $this->_xh['value'];
                     } else {
-                        error_log('XML-RPC: missing VALUE inside STRUCT in received xml');
+                        error_log('XML-RPC: ' . __METHOD__ . ': missing VALUE inside STRUCT in received xml');
                     }
                     break;
                 case 'DATA':
-                    //$this->_xh['ac']=''; // is this necessary?
                     $this->_xh['vt'] = null; // reset this to check for 2 data elements in a row - even if they're empty
                     break;
                 case 'STRUCT':
@@ -356,7 +367,7 @@ class XMLParser
                         $this->_xh['params'][] = $this->_xh['value'];
                         $this->_xh['pt'][] = $this->_xh['vt'];
                     } else {
-                        error_log('XML-RPC: missing VALUE inside PARAM in received xml');
+                        error_log('XML-RPC: ' . __METHOD__ . ': missing VALUE inside PARAM in received xml');
                     }
                     break;
                 case 'METHODNAME':
@@ -402,18 +413,6 @@ class XMLParser
             // "lookforvalue==3" means that we've found an entire value
             // and should discard any further character data
             if ($this->_xh['lv'] != 3) {
-                // G. Giunta 2006-08-23: useless change of 'lv' from 1 to 2
-                //if($this->_xh['lv']==1)
-                //{
-                // if we've found text and we're just in a <value> then
-                // say we've found a value
-                //$this->_xh['lv']=2;
-                //}
-                // we always initialize the accumulator before starting parsing, anyway...
-                //if(!@isset($this->_xh['ac']))
-                //{
-                //    $this->_xh['ac'] = '';
-                //}
                 $this->_xh['ac'] .= $data;
             }
         }
@@ -428,11 +427,6 @@ class XMLParser
         // skip processing if xml fault already detected
         if ($this->_xh['isf'] < 2) {
             if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') {
-                // G. Giunta 2006-08-25: useless change of 'lv' from 1 to 2
-                //if($this->_xh['lv']==1)
-                //{
-                //    $this->_xh['lv']=2;
-                //}
                 $this->_xh['ac'] .= $data;
             }
         }
@@ -446,11 +440,18 @@ class XMLParser
      * NB: according to the spec (RFC 3023), if text/xml content-type is received over HTTP without a content-type,
      * we SHOULD assume it is strictly US-ASCII. But we try to be more tolerant of non conforming (legacy?) clients/servers,
      * which will be most probably using UTF-8 anyway...
+     * In order of importance checks:
+     * 1. http headers
+     * 2. BOM
+     * 3. XML declaration
+     * 4. guesses using mb_detect_encoding()
      *
      * @param string $httpHeader the http Content-type header
      * @param string $xmlChunk xml content buffer
-     * @param string $encodingPrefs comma separated list of character encodings to be used as default (when mb extension is enabled)
-     * @return string
+     * @param string $encodingPrefs comma separated list of character encodings to be used as default (when mb extension is enabled).
+     *                              This can also be set globally using PhpXmlRpc::$xmlrpc_detectencodings
+     * @return string the encoding determined. Null if it can't be determined and mbstring is enabled,
+     *                PhpXmlRpc::$xmlrpc_defencoding if it can't be determined and mbstring is not enabled
      *
      * @todo explore usage of mb_http_input(): does it detect http headers + post data? if so, use it instead of hand-detection!!!
      */
@@ -459,10 +460,10 @@ class XMLParser
         // discussion: see http://www.yale.edu/pclt/encoding/
         // 1 - test if encoding is specified in HTTP HEADERS
 
-        //Details:
+        // Details:
         // LWS:           (\13\10)?( |\t)+
         // token:         (any char but excluded stuff)+
-        // quoted string: " (any char but double quotes and cointrol chars)* "
+        // quoted string: " (any char but double quotes and control chars)* "
         // header:        Content-type = ...; charset=value(; ...)*
         //   where value is of type token, no LWS allowed between 'charset' and value
         // Note: we do not check for invalid chars in VALUE:
@@ -502,8 +503,10 @@ class XMLParser
         }
 
         // 4 - if mbstring is available, let it do the guesswork
-        // NB: we favour finding an encoding that is compatible with what we can process
         if (extension_loaded('mbstring')) {
+            if ($encodingPrefs == null && PhpXmlRpc::$xmlrpc_detectencodings != null) {
+                $encodingPrefs = PhpXmlRpc::$xmlrpc_detectencodings;
+            }
             if ($encodingPrefs) {
                 $enc = mb_detect_encoding($xmlChunk, $encodingPrefs);
             } else {