Refactoring ongoing: move http headers parsing away from response into http class...
authorgggeek <giunta.gaetano@gmail.com>
Tue, 24 Mar 2015 13:51:49 +0000 (13:51 +0000)
committergggeek <giunta.gaetano@gmail.com>
Tue, 24 Mar 2015 13:51:49 +0000 (13:51 +0000)
demo/server/proxy.php
demo/server/server.php
lib/xmlrpc.inc
src/Helper/Charset.php
src/Helper/Http.php
src/Request.php
src/Response.php
src/Server.php
src/Value.php

index 64ad459..4f860de 100644 (file)
@@ -8,28 +8,30 @@
  * @copyright (C) 2006-2015 G. Giunta
  * @license code licensed under the BSD License: see file license.txt
  */
-include_once __DIR__ . "/../../vendor/autoload.php";
 
-include_once __DIR__ . "/../../lib/xmlrpc.inc";
-include_once __DIR__ . "/../../lib/xmlrpcs.inc";
+include_once __DIR__ . "/../../src/Autoloader.php";
+PhpXmlRpc\Autoloader::register();
 
 /**
  * Forward an xmlrpc request to another server, and return to client the response received.
  *
- * @param xmlrpcmsg $m (see method docs below for a description of the expected parameters)
+ * @param PhpXmlRpc\Request $req (see method docs below for a description of the expected parameters)
  *
- * @return xmlrpcresp
+ * @return PhpXmlRpc\Response
  */
-function forward_request($m)
+function forward_request($req)
 {
+    $encoder = new \PhpXmlRpc\Encoder();
+
     // create client
     $timeout = 0;
-    $url = php_xmlrpc_decode($m->getParam(0));
-    $c = new PhpXmlRpc\Client($url);
-    if ($m->getNumParams() > 3) {
+    $url = $encoder->decode($req->getParam(0));
+    $client = new PhpXmlRpc\Client($url);
+
+    if ($req->getNumParams() > 3) {
         // we have to set some options onto the client.
         // Note that if we do not untaint the received values, warnings might be generated...
-        $options = php_xmlrpc_decode($m->getParam(3));
+        $options = $encoder->decode($req->getParam(3));
         foreach ($options as $key => $val) {
             switch ($key) {
                 case 'Cookie':
@@ -37,13 +39,13 @@ function forward_request($m)
                 case 'Credentials':
                     break;
                 case 'RequestCompression':
-                    $c->setRequestCompression($val);
+                    $client->setRequestCompression($val);
                     break;
                 case 'SSLVerifyHost':
-                    $c->setSSLVerifyHost($val);
+                    $client->setSSLVerifyHost($val);
                     break;
                 case 'SSLVerifyPeer':
-                    $c->setSSLVerifyPeer($val);
+                    $client->setSSLVerifyPeer($val);
                     break;
                 case 'Timeout':
                     $timeout = (integer)$val;
@@ -56,17 +58,17 @@ function forward_request($m)
     /// @todo find a way to forward client info (such as IP) to server, either
     /// - as xml comments in the payload, or
     /// - using std http header conventions, such as X-forwarded-for...
-    $method = php_xmlrpc_decode($m->getParam(1));
-    $pars = $m->getParam(2);
-    $m = new PhpXmlRpc\Request($method);
+    $reqethod = $encoder->decode($req->getParam(1));
+    $pars = $req->getParam(2);
+    $req = new PhpXmlRpc\Request($reqethod);
     for ($i = 0; $i < $pars->arraySize(); $i++) {
-        $m->addParam($pars->arraymem($i));
+        $req->addParam($pars->arraymem($i));
     }
 
     // add debug info into response we give back to caller
-    xmlrpc_debugmsg("Sending to server $url the payload: " . $m->serialize());
+    PhpXmlRpc\Server::xmlrpc_debugmsg("Sending to server $url the payload: " . $req->serialize());
 
-    return $c->send($m, $timeout);
+    return $client->send($req, $timeout);
 }
 
 // run the server
index eefaa38..03bbab5 100644 (file)
@@ -141,7 +141,7 @@ $findstate3_sig = wrap_php_function(array('xmlrpc_server_methods_container', 'fi
 
 $findstate5_sig = wrap_php_function('xmlrpc_server_methods_container::findstate');
 
-$obj = new PhpXmlRpc\Server_methods_container();
+$obj = new xmlrpc_server_methods_container();
 $findstate4_sig = wrap_php_function(array($obj, 'findstate'));
 
 $addtwo_sig = array(array($xmlrpcInt, $xmlrpcInt, $xmlrpcInt));
index 51b175d..01323fe 100644 (file)
@@ -143,9 +143,10 @@ class xmlrpc_client extends PhpXmlRpc\Client
 
 /* Expose as global functions the ones which are now class methods */
 
+/// Wrong speling, but we are adamant on backwards compatibility!
 function xmlrpc_encode_entitites($data, $srcEncoding='', $destEncoding='')
 {
-    return PhpXmlRpc\Helper\Charset::instance()->encode_entitites($data, $srcEncoding, $destEncoding);
+    return PhpXmlRpc\Helper\Charset::instance()->encodeEntitites($data, $srcEncoding, $destEncoding);
 }
 
 function iso8601_encode($timeT, $utc=0)
@@ -160,7 +161,7 @@ function iso8601_decode($iDate, $utc=0)
 
 function decode_chunked($buffer)
 {
-    return PhpXmlRpc\Helper\Http::decode_chunked($buffer);
+    return PhpXmlRpc\Helper\Http::decodeChunked($buffer);
 }
 
 function php_xmlrpc_decode($xmlrpcVal, $options=array())
index 6d5eb6a..b23b5c5 100644 (file)
@@ -87,7 +87,7 @@ class Charset
      *
      * @return string
      */
-    public function encode_entities($data, $src_encoding = '', $dest_encoding = '')
+    public function encodeEntities($data, $src_encoding = '', $dest_encoding = '')
     {
         if ($src_encoding == '') {
             // lame, but we know no better...
@@ -218,7 +218,7 @@ class Charset
      *
      * @return bool
      */
-    public function is_valid_charset($encoding, $validList)
+    public function isValidCharset($encoding, $validList)
     {
         if (is_string($validList)) {
             $validList = explode(',', $validList);
index 02bfd57..09be1f3 100644 (file)
@@ -2,10 +2,12 @@
 
 namespace PhpXmlRpc\Helper;
 
+use PhpXmlRpc\PhpXmlRpc;
+
 class Http
 {
     /**
-     * decode a string that is encoded w/ "chunked" transfer encoding
+     * Decode a string that is encoded w/ "chunked" transfer encoding
      * as defined in rfc2068 par. 19.4.6
      * code shamelessly stolen from nusoap library by Dietrich Ayala.
      *
@@ -13,7 +15,7 @@ class Http
      *
      * @return string
      */
-    public static function decode_chunked($buffer)
+    public static function decodeChunked($buffer)
     {
         // length := 0
         $length = 0;
@@ -57,4 +59,203 @@ class Http
 
         return $new;
     }
+
+    /**
+     * Parses HTTP an http response headers and separates them from the body.
+     *
+     * @param string $data the http response,headers and body. It will be stripped of headers
+     * @param bool $headersProcessed when true, we assume that response inflating and dechunking has been already carried out
+     *
+     * @return array with keys 'headers' and 'cookies'
+     * @throws \Exception
+     */
+    public function parseResponseHeaders(&$data, $headersProcessed = false, $debug=0)
+    {
+        $httpResponse = array('raw_data' => $data, 'headers'=> array(), 'cookies' => array());
+
+        // Support "web-proxy-tunelling" connections for https through proxies
+        if (preg_match('/^HTTP\/1\.[0-1] 200 Connection established/', $data)) {
+            // Look for CR/LF or simple LF as line separator,
+            // (even though it is not valid http)
+            $pos = strpos($data, "\r\n\r\n");
+            if ($pos || is_int($pos)) {
+                $bd = $pos + 4;
+            } else {
+                $pos = strpos($data, "\n\n");
+                if ($pos || is_int($pos)) {
+                    $bd = $pos + 2;
+                } else {
+                    // No separation between response headers and body: fault?
+                    $bd = 0;
+                }
+            }
+            if ($bd) {
+                // this filters out all http headers from proxy.
+                // maybe we could take them into account, too?
+                $data = substr($data, $bd);
+            } else {
+                error_log('XML-RPC: ' . __METHOD__ . ': HTTPS via proxy error, tunnel connection possibly failed');
+                throw new \Exception(PhpXmlRpc::$xmlrpcstr['http_error'] . ' (HTTPS via proxy error, tunnel connection possibly failed)', PhpXmlRpc::$xmlrpcerr['http_error']);
+            }
+        }
+
+        // Strip HTTP 1.1 100 Continue header if present
+        while (preg_match('/^HTTP\/1\.1 1[0-9]{2} /', $data)) {
+            $pos = strpos($data, 'HTTP', 12);
+            // server sent a Continue header without any (valid) content following...
+            // give the client a chance to know it
+            if (!$pos && !is_int($pos)) {
+                // works fine in php 3, 4 and 5
+
+                break;
+            }
+            $data = substr($data, $pos);
+        }
+        if (!preg_match('/^HTTP\/[0-9.]+ 200 /', $data)) {
+            $errstr = substr($data, 0, strpos($data, "\n") - 1);
+            error_log('XML-RPC: ' . __METHOD__ . ': HTTP error, got response: ' . $errstr);
+            throw new \Exception(PhpXmlRpc::$xmlrpcstr['http_error'] . ' (' . $errstr . ')', PhpXmlRpc::$xmlrpcerr['http_error']);
+        }
+
+        // be tolerant to usage of \n instead of \r\n to separate headers and data
+        // (even though it is not valid http)
+        $pos = strpos($data, "\r\n\r\n");
+        if ($pos || is_int($pos)) {
+            $bd = $pos + 4;
+        } else {
+            $pos = strpos($data, "\n\n");
+            if ($pos || is_int($pos)) {
+                $bd = $pos + 2;
+            } else {
+                // No separation between response headers and body: fault?
+                // we could take some action here instead of going on...
+                $bd = 0;
+            }
+        }
+        // be tolerant to line endings, and extra empty lines
+        $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos)));
+        while (list(, $line) = @each($ar)) {
+            // take care of multi-line headers and cookies
+            $arr = explode(':', $line, 2);
+            if (count($arr) > 1) {
+                $header_name = strtolower(trim($arr[0]));
+                /// @todo some other headers (the ones that allow a CSV list of values)
+                /// do allow many values to be passed using multiple header lines.
+                /// We should add content to $xmlrpc->_xh['headers'][$header_name]
+                /// instead of replacing it for those...
+                if ($header_name == 'set-cookie' || $header_name == 'set-cookie2') {
+                    if ($header_name == 'set-cookie2') {
+                        // version 2 cookies:
+                        // there could be many cookies on one line, comma separated
+                        $cookies = explode(',', $arr[1]);
+                    } else {
+                        $cookies = array($arr[1]);
+                    }
+                    foreach ($cookies as $cookie) {
+                        // glue together all received cookies, using a comma to separate them
+                        // (same as php does with getallheaders())
+                        if (isset($httpResponse['headers'][$header_name])) {
+                            $httpResponse['headers'][$header_name] .= ', ' . trim($cookie);
+                        } else {
+                            $httpResponse['headers'][$header_name] = trim($cookie);
+                        }
+                        // parse cookie attributes, in case user wants to correctly honour them
+                        // feature creep: only allow rfc-compliant cookie attributes?
+                        // @todo support for server sending multiple time cookie with same name, but using different PATHs
+                        $cookie = explode(';', $cookie);
+                        foreach ($cookie as $pos => $val) {
+                            $val = explode('=', $val, 2);
+                            $tag = trim($val[0]);
+                            $val = trim(@$val[1]);
+                            /// @todo with version 1 cookies, we should strip leading and trailing " chars
+                            if ($pos == 0) {
+                                $cookiename = $tag;
+                                $httpResponse['cookies'][$tag] = array();
+                                $httpResponse['cookies'][$cookiename]['value'] = urldecode($val);
+                            } else {
+                                if ($tag != 'value') {
+                                    $httpResponse['cookies'][$cookiename][$tag] = $val;
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    $httpResponse['headers'][$header_name] = trim($arr[1]);
+                }
+            } elseif (isset($header_name)) {
+                /// @todo version1 cookies might span multiple lines, thus breaking the parsing above
+                $httpResponse['headers'][$header_name] .= ' ' . trim($line);
+            }
+        }
+
+        $data = substr($data, $bd);
+
+        if ($debug && count($httpResponse['headers'])) {
+            $msg = '';
+            foreach ($httpResponse['headers'] as $header => $value) {
+                $msg .= "HEADER: $header: $value\n";
+            }
+            foreach ($httpResponse['cookies'] as $header => $value) {
+                $msg .= "COOKIE: $header={$value['value']}\n";
+            }
+            $this->debugMessage($msg);
+        }
+
+        // if CURL was used for the call, http headers have been processed,
+        // and dechunking + reinflating have been carried out
+        if (!$headersProcessed) {
+            // Decode chunked encoding sent by http 1.1 servers
+            if (isset($httpResponse['headers']['transfer-encoding']) && $httpResponse['headers']['transfer-encoding'] == 'chunked') {
+                if (!$data = Http::decodeChunked($data)) {
+                    error_log('XML-RPC: ' . __METHOD__ . ': errors occurred when trying to rebuild the chunked data received from server');
+                    throw new \Exception(PhpXmlRpc::$xmlrpcstr['dechunk_fail'], PhpXmlRpc::$xmlrpcerr['dechunk_fail']);
+                }
+            }
+
+            // Decode gzip-compressed stuff
+            // code shamelessly inspired from nusoap library by Dietrich Ayala
+            if (isset($httpResponse['headers']['content-encoding'])) {
+                $httpResponse['headers']['content-encoding'] = str_replace('x-', '', $httpResponse['headers']['content-encoding']);
+                if ($httpResponse['headers']['content-encoding'] == 'deflate' || $httpResponse['headers']['content-encoding'] == 'gzip') {
+                    // if decoding works, use it. else assume data wasn't gzencoded
+                    if (function_exists('gzinflate')) {
+                        if ($httpResponse['headers']['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
+                            $data = $degzdata;
+                            if ($debug) {
+                                $this->debugMessage("---INFLATED RESPONSE---[" . strlen($data) . " chars]---\n$data\n---END---");
+                            }
+                        } elseif ($httpResponse['headers']['content-encoding'] == 'gzip' && $degzdata = @gzinflate(substr($data, 10))) {
+                            $data = $degzdata;
+                            if ($debug) {
+                                $this->debugMessage("---INFLATED RESPONSE---[" . strlen($data) . " chars]---\n$data\n---END---");
+                            }
+                        } else {
+                            error_log('XML-RPC: ' . __METHOD__ . ': errors occurred when trying to decode the deflated data received from server');
+                            throw new \Exception(PhpXmlRpc::$xmlrpcstr['decompress_fail'], PhpXmlRpc::$xmlrpcerr['decompress_fail']);
+                        }
+                    } else {
+                        error_log('XML-RPC: ' . __METHOD__ . ': the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
+                        throw new \Exception(PhpXmlRpc::$xmlrpcstr['cannot_decompress'], PhpXmlRpc::$xmlrpcerr['cannot_decompress']);
+                    }
+                }
+            }
+        } // end of 'if needed, de-chunk, re-inflate response'
+
+        return $httpResponse;
+    }
+
+    /**
+     * Echoes a debug message, taking care of escaping it when not in console mode
+     *
+     * @param string $message
+     */
+    protected function debugMessage($message)
+    {
+        if (PHP_SAPI != 'cli') {
+            print "<PRE>\n".htmlentities($message)."\n</PRE>";
+        }
+        else {
+            print "\n$message\n";
+        }
+    }
 }
index 77567ab..17aae84 100644 (file)
@@ -153,201 +153,9 @@ class Request
         while ($data = fread($fp, 32768)) {
             $ipd .= $data;
         }
-        //fclose($fp);
         return $this->parseResponse($ipd);
     }
 
-    /**
-     * Parses HTTP headers and separates them from data.
-     *
-     * @return null|Response null on success, or a Response on error
-     */
-    private function parseResponseHeaders(&$data, $headers_processed = false)
-    {
-        $this->httpResponse['headers'] = array();
-        $this->httpResponse['cookies'] = array();
-
-        // Support "web-proxy-tunelling" connections for https through proxies
-        if (preg_match('/^HTTP\/1\.[0-1] 200 Connection established/', $data)) {
-            // Look for CR/LF or simple LF as line separator,
-            // (even though it is not valid http)
-            $pos = strpos($data, "\r\n\r\n");
-            if ($pos || is_int($pos)) {
-                $bd = $pos + 4;
-            } else {
-                $pos = strpos($data, "\n\n");
-                if ($pos || is_int($pos)) {
-                    $bd = $pos + 2;
-                } else {
-                    // No separation between response headers and body: fault?
-                    $bd = 0;
-                }
-            }
-            if ($bd) {
-                // this filters out all http headers from proxy.
-                // maybe we could take them into account, too?
-                $data = substr($data, $bd);
-            } else {
-                error_log('XML-RPC: ' . __METHOD__ . ': HTTPS via proxy error, tunnel connection possibly failed');
-                $r = new Response(0, PhpXmlRpc::$xmlrpcerr['http_error'], PhpXmlRpc::$xmlrpcstr['http_error'] . ' (HTTPS via proxy error, tunnel connection possibly failed)');
-
-                return $r;
-            }
-        }
-
-        // Strip HTTP 1.1 100 Continue header if present
-        while (preg_match('/^HTTP\/1\.1 1[0-9]{2} /', $data)) {
-            $pos = strpos($data, 'HTTP', 12);
-            // server sent a Continue header without any (valid) content following...
-            // give the client a chance to know it
-            if (!$pos && !is_int($pos)) {
-                // works fine in php 3, 4 and 5
-
-                break;
-            }
-            $data = substr($data, $pos);
-        }
-        if (!preg_match('/^HTTP\/[0-9.]+ 200 /', $data)) {
-            $errstr = substr($data, 0, strpos($data, "\n") - 1);
-            error_log('XML-RPC: ' . __METHOD__ . ': HTTP error, got response: ' . $errstr);
-            $r = new Response(0, PhpXmlRpc::$xmlrpcerr['http_error'], PhpXmlRpc::$xmlrpcstr['http_error'] . ' (' . $errstr . ')');
-
-            return $r;
-        }
-
-        // be tolerant to usage of \n instead of \r\n to separate headers and data
-        // (even though it is not valid http)
-        $pos = strpos($data, "\r\n\r\n");
-        if ($pos || is_int($pos)) {
-            $bd = $pos + 4;
-        } else {
-            $pos = strpos($data, "\n\n");
-            if ($pos || is_int($pos)) {
-                $bd = $pos + 2;
-            } else {
-                // No separation between response headers and body: fault?
-                // we could take some action here instead of going on...
-                $bd = 0;
-            }
-        }
-        // be tolerant to line endings, and extra empty lines
-        $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos)));
-        while (list(, $line) = @each($ar)) {
-            // take care of multi-line headers and cookies
-            $arr = explode(':', $line, 2);
-            if (count($arr) > 1) {
-                $header_name = strtolower(trim($arr[0]));
-                /// @todo some other headers (the ones that allow a CSV list of values)
-                /// do allow many values to be passed using multiple header lines.
-                /// We should add content to $xmlrpc->_xh['headers'][$header_name]
-                /// instead of replacing it for those...
-                if ($header_name == 'set-cookie' || $header_name == 'set-cookie2') {
-                    if ($header_name == 'set-cookie2') {
-                        // version 2 cookies:
-                        // there could be many cookies on one line, comma separated
-                        $cookies = explode(',', $arr[1]);
-                    } else {
-                        $cookies = array($arr[1]);
-                    }
-                    foreach ($cookies as $cookie) {
-                        // glue together all received cookies, using a comma to separate them
-                        // (same as php does with getallheaders())
-                        if (isset($this->httpResponse['headers'][$header_name])) {
-                            $this->httpResponse['headers'][$header_name] .= ', ' . trim($cookie);
-                        } else {
-                            $this->httpResponse['headers'][$header_name] = trim($cookie);
-                        }
-                        // parse cookie attributes, in case user wants to correctly honour them
-                        // feature creep: only allow rfc-compliant cookie attributes?
-                        // @todo support for server sending multiple time cookie with same name, but using different PATHs
-                        $cookie = explode(';', $cookie);
-                        foreach ($cookie as $pos => $val) {
-                            $val = explode('=', $val, 2);
-                            $tag = trim($val[0]);
-                            $val = trim(@$val[1]);
-                            /// @todo with version 1 cookies, we should strip leading and trailing " chars
-                            if ($pos == 0) {
-                                $cookiename = $tag;
-                                $this->httpResponse['cookies'][$tag] = array();
-                                $this->httpResponse['cookies'][$cookiename]['value'] = urldecode($val);
-                            } else {
-                                if ($tag != 'value') {
-                                    $this->httpResponse['cookies'][$cookiename][$tag] = $val;
-                                }
-                            }
-                        }
-                    }
-                } else {
-                    $this->httpResponse['headers'][$header_name] = trim($arr[1]);
-                }
-            } elseif (isset($header_name)) {
-                /// @todo version1 cookies might span multiple lines, thus breaking the parsing above
-                $this->httpResponse['headers'][$header_name] .= ' ' . trim($line);
-            }
-        }
-
-        $data = substr($data, $bd);
-
-        if ($this->debug && count($this->httpResponse['headers'])) {
-            $msg = '';
-            foreach ($this->httpResponse['headers'] as $header => $value) {
-                $msg .= "HEADER: $header: $value\n";
-            }
-            foreach ($this->httpResponse['cookies'] as $header => $value) {
-                $msg .= "COOKIE: $header={$value['value']}\n";
-            }
-            $this->debugMessage($msg);
-        }
-
-        // if CURL was used for the call, http headers have been processed,
-        // and dechunking + reinflating have been carried out
-        if (!$headers_processed) {
-            // Decode chunked encoding sent by http 1.1 servers
-            if (isset($this->httpResponse['headers']['transfer-encoding']) && $this->httpResponse['headers']['transfer-encoding'] == 'chunked') {
-                if (!$data = Http::decode_chunked($data)) {
-                    error_log('XML-RPC: ' . __METHOD__ . ': errors occurred when trying to rebuild the chunked data received from server');
-                    $r = new Response(0, PhpXmlRpc::$xmlrpcerr['dechunk_fail'], PhpXmlRpc::$xmlrpcstr['dechunk_fail']);
-
-                    return $r;
-                }
-            }
-
-            // Decode gzip-compressed stuff
-            // code shamelessly inspired from nusoap library by Dietrich Ayala
-            if (isset($this->httpResponse['headers']['content-encoding'])) {
-                $this->httpResponse['headers']['content-encoding'] = str_replace('x-', '', $this->httpResponse['headers']['content-encoding']);
-                if ($this->httpResponse['headers']['content-encoding'] == 'deflate' || $this->httpResponse['headers']['content-encoding'] == 'gzip') {
-                    // if decoding works, use it. else assume data wasn't gzencoded
-                    if (function_exists('gzinflate')) {
-                        if ($this->httpResponse['headers']['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
-                            $data = $degzdata;
-                            if ($this->debug) {
-                                $this->debugMessage("---INFLATED RESPONSE---[" . strlen($data) . " chars]---\n$data\n---END---");
-                            }
-                        } elseif ($this->httpResponse['headers']['content-encoding'] == 'gzip' && $degzdata = @gzinflate(substr($data, 10))) {
-                            $data = $degzdata;
-                            if ($this->debug) {
-                                $this->debugMessage("---INFLATED RESPONSE---[" . strlen($data) . " chars]---\n$data\n---END---");
-                            }
-                        } else {
-                            error_log('XML-RPC: ' . __METHOD__ . ': errors occurred when trying to decode the deflated data received from server');
-                            $r = new Response(0, PhpXmlRpc::$xmlrpcerr['decompress_fail'], PhpXmlRpc::$xmlrpcstr['decompress_fail']);
-
-                            return $r;
-                        }
-                    } else {
-                        error_log('XML-RPC: ' . __METHOD__ . ': the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
-                        $r = new Response(0, PhpXmlRpc::$xmlrpcerr['cannot_decompress'], PhpXmlRpc::$xmlrpcstr['cannot_decompress']);
-
-                        return $r;
-                    }
-                }
-            }
-        } // end of 'if needed, de-chunk, re-inflate response'
-
-        return;
-    }
-
     /**
      * Parse the xmlrpc response contained in the string $data and return a Response object.
      *
@@ -364,22 +172,20 @@ class Request
             $this->debugMessage("---GOT---\n$data\n---END---");
         }
 
-        $this->httpResponse = array();
-        $this->httpResponse['raw_data'] = $data;
-        $this->httpResponse['headers'] = array();
-        $this->httpResponse['cookies'] = array();
+        $this->httpResponse = array('raw_data' => $data, 'headers' => array(), 'cookies' => array());
 
         if ($data == '') {
             error_log('XML-RPC: ' . __METHOD__ . ': no response received from server.');
-            $r = new Response(0, PhpXmlRpc::$xmlrpcerr['no_data'], PhpXmlRpc::$xmlrpcstr['no_data']);
-
-            return $r;
+            return new Response(0, PhpXmlRpc::$xmlrpcerr['no_data'], PhpXmlRpc::$xmlrpcstr['no_data']);
         }
 
         // parse the HTTP headers of the response, if present, and separate them from data
         if (substr($data, 0, 4) == 'HTTP') {
-            $r = $this->parseResponseHeaders($data, $headers_processed);
-            if ($r) {
+            $httpParser = new Http();
+            try {
+                $this->httpResponse = $httpParser->parseResponseHeaders($data, $headers_processed, $this->debug);
+            } catch(\Exception $e) {
+                $r = new Response(0, $e->getCode(), $e->getMessage());
                 // failed processing of HTTP response headers
                 // save into response obj the full payload received, for debugging
                 $r->raw_data = $data;
index efadfb5..54e8db4 100644 (file)
@@ -8,7 +8,7 @@ class Response
 {
     /// @todo: do these need to be public?
     public $val = 0;
-    public $valtyp;
+    public $valType;
     public $errno = 0;
     public $errstr = '';
     public $payload;
@@ -19,25 +19,25 @@ class Response
 
     /**
      * @param mixed $val either an xmlrpcval obj, a php value or the xml serialization of an xmlrpcval (a string)
-     * @param integer $fcode set it to anything but 0 to create an error response
-     * @param string $fstr the error string, in case of an error response
-     * @param string $valtyp either 'xmlrpcvals', 'phpvals' or 'xml'
+     * @param integer $fCode set it to anything but 0 to create an error response
+     * @param string $fString the error string, in case of an error response
+     * @param string $valType either 'xmlrpcvals', 'phpvals' or 'xml'
      *
-     * @todo add check that $val / $fcode / $fstr is of correct type???
+     * @todo add check that $val / $fCode / $fString is of correct type???
      * NB: as of now we do not do it, since it might be either an xmlrpcval or a plain
      * php val, or a complete xml chunk, depending on usage of Client::send() inside which creator is called...
      */
-    public function __construct($val, $fcode = 0, $fstr = '', $valtyp = '')
+    public function __construct($val, $fCode = 0, $fString = '', $valType = '')
     {
-        if ($fcode != 0) {
+        if ($fCode != 0) {
             // error response
-            $this->errno = $fcode;
-            $this->errstr = $fstr;
-            //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later.
+            $this->errno = $fCode;
+            $this->errstr = $fString;
+            //$this->errstr = htmlspecialchars($fString); // XXX: encoding probably shouldn't be done here; fix later.
         } else {
             // successful response
             $this->val = $val;
-            if ($valtyp == '') {
+            if ($valType == '') {
                 // user did not declare type of response value: try to guess it
                 if (is_object($this->val) && is_a($this->val, 'PhpXmlRpc\Value')) {
                     $this->valtyp = 'xmlrpcvals';
@@ -48,7 +48,7 @@ class Response
                 }
             } else {
                 // user declares type of resp value: believe him
-                $this->valtyp = $valtyp;
+                $this->valtyp = $valType;
             }
         }
     }
@@ -102,14 +102,14 @@ class Response
     /**
      * Returns xml representation of the response. XML prologue not included.
      *
-     * @param string $charset_encoding the charset to be used for serialization. if null, US-ASCII is assumed
+     * @param string $charsetEncoding the charset to be used for serialization. if null, US-ASCII is assumed
      *
      * @return string the xml representation of the response
      */
-    public function serialize($charset_encoding = '')
+    public function serialize($charsetEncoding = '')
     {
-        if ($charset_encoding != '') {
-            $this->content_type = 'text/xml; charset=' . $charset_encoding;
+        if ($charsetEncoding != '') {
+            $this->content_type = 'text/xml; charset=' . $charsetEncoding;
         } else {
             $this->content_type = 'text/xml';
         }
@@ -121,11 +121,10 @@ class Response
         if ($this->errno) {
             // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients
             // by xml-encoding non ascii chars
-            $charsetEncoder =
             $result .= "<fault>\n" .
                 "<value>\n<struct><member><name>faultCode</name>\n<value><int>" . $this->errno .
                 "</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string>" .
-                Charset::instance()->encode_entities($this->errstr, PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "</string></value>\n</member>\n" .
+                Charset::instance()->encodeEntities($this->errstr, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</string></value>\n</member>\n" .
                 "</struct>\n</value>\n</fault>";
         } else {
             if (!is_object($this->val) || !is_a($this->val, 'PhpXmlRpc\Value')) {
@@ -139,7 +138,7 @@ class Response
                 }
             } else {
                 $result .= "<params>\n<param>\n" .
-                    $this->val->serialize($charset_encoding) .
+                    $this->val->serialize($charsetEncoding) .
                     "</param>\n</params>";
             }
         }
index 7d345aa..3a8f558 100644 (file)
@@ -160,7 +160,7 @@ class Server
             $out .= "<!-- SERVER DEBUG INFO (BASE64 ENCODED):\n" . base64_encode($this->debug_info) . "\n-->\n";
         }
         if (static::$_xmlrpc_debuginfo != '') {
-            $out .= "<!-- DEBUG INFO:\n" . Charset::instance()->encode_entities(str_replace('--', '_-', static::$_xmlrpc_debuginfo), PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "\n-->\n";
+            $out .= "<!-- DEBUG INFO:\n" . Charset::instance()->encodeEntities(str_replace('--', '_-', static::$_xmlrpc_debuginfo), PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "\n-->\n";
             // NB: a better solution MIGHT be to use CDATA, but we need to insert it
             // into return payload AFTER the beginning tag
             //$out .= "<![CDATA[ DEBUG INFO:\n\n" . str_replace(']]>', ']_]_>', static::$_xmlrpc_debuginfo) . "\n]]>\n";
index 0f39a67..b9d34fe 100644 (file)
@@ -42,8 +42,8 @@ class Value
      */
     public function __construct($val = -1, $type = '')
     {
-        /// @todo: optimization creep - do not call addXX, do it all inline.
-        /// downside: booleans will not be coerced anymore
+        // optimization creep - do not call addXX, do it all inline.
+        // downside: booleans will not be coerced anymore
         if ($val !== -1 || $type != '') {
             // optimization creep: inlined all work done by constructor
             switch ($type) {
@@ -73,7 +73,8 @@ class Value
                 default:
                     error_log("XML-RPC: " . __METHOD__ . ": not a known type ($type)");
             }
-            /*if($type=='')
+            /* was:
+            if($type=='')
             {
                 $type='string';
             }
@@ -107,7 +108,7 @@ class Value
             $typeof = static::$xmlrpcTypes[$type];
         }
 
-        if ($typeof != 1) {
+        if ($typeof !== 1) {
             error_log("XML-RPC: " . __METHOD__ . ": not a scalar type ($type)");
 
             return 0;
@@ -135,10 +136,6 @@ class Value
                 return 0;
             case 2:
                 // we're adding a scalar value to an array here
-                //$ar=$this->me['array'];
-                //$ar[]=new Value($val, $type);
-                //$this->me['array']=$ar;
-                // Faster (?) avoid all the costly array-copy-by-val done here...
                 $this->me['array'][] = new Value($val, $type);
 
                 return 1;
@@ -249,7 +246,7 @@ class Value
                     case static::$xmlrpcString:
                         // G. Giunta 2005/2/13: do NOT use htmlentities, since
                         // it will produce named html entities, which are invalid xml
-                        $rs .= "<${typ}>" . Charset::instance()->encode_entities($val, PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "</${typ}>";
+                        $rs .= "<${typ}>" . Charset::instance()->encodeEntities($val, PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "</${typ}>";
                         break;
                     case static::$xmlrpcInt:
                     case static::$xmlrpcI4:
@@ -297,7 +294,7 @@ class Value
                 }
                 $charsetEncoder = Charset::instance();
                 foreach ($val as $key2 => $val2) {
-                    $rs .= '<member><name>' . $charsetEncoder->encode_entities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "</name>\n";
+                    $rs .= '<member><name>' . $charsetEncoder->encodeEntities($key2, PhpXmlRpc::$xmlrpc_internalencoding, $charset_encoding) . "</name>\n";
                     //$rs.=$this->serializeval($val2);
                     $rs .= $val2->serialize($charset_encoding);
                     $rs .= "</member>\n";