WIP - more bugfixes and start of testsuite reimplementation
authorgggeek <giunta.gaetano@gmail.com>
Tue, 16 Dec 2014 01:01:58 +0000 (01:01 +0000)
committergggeek <giunta.gaetano@gmail.com>
Tue, 16 Dec 2014 01:01:58 +0000 (01:01 +0000)
15 files changed:
composer.json
src/Client.php
src/Request.php
src/Response.php
src/Server.php
src/Wrapper.php
test/benchmark.php [deleted file]
test/parse_args.php [deleted file]
test/testsuite.php [deleted file]
tests/InvalidHostTest.php [new file with mode: 0644]
tests/LocalhostTest.php [new file with mode: 0644]
tests/ParsingBugsTest.php [new file with mode: 0644]
tests/benchmark.php [new file with mode: 0644]
tests/parse_args.php [new file with mode: 0644]
tests/verify_compat.php [moved from test/verify_compat.php with 100% similarity]

index db3c149..3064490 100644 (file)
@@ -9,7 +9,7 @@
         "ext-xml": "*"
     },
     "require-dev": {
-        "phpunit/phpunit": "4.3.*"
+        "phpunit/phpunit": ">=4.0.0"
     },
     "suggest": {
         "ext-curl": "Needed for HTTPS and HTTP 1.1 support, NTLM Auth etc...",
index a31c732..c12d407 100644 (file)
@@ -59,7 +59,7 @@ class Client
     /// Charset encoding to be used in serializing request. NULL = use ASCII
     public $request_charset_encoding = '';
     /**
-     * Decides the content of xmlrpcresp objects returned by calls to send()
+     * Decides the content of Response objects returned by calls to send()
      * valid strings are 'xmlrpcvals', 'phpvals' or 'xml'
      */
     public $return_type = 'xmlrpcvals';
@@ -324,7 +324,7 @@ class Client
      * @param mixed $msg The request object, or an array of requests for using multicall, or the complete xml representation of a request
      * @param integer $timeout Connection timeout, in seconds, If unspecified, a platform specific timeout will apply
      * @param string $method if left unspecified, the http protocol chosen during creation of the object will be used
-     * @return xmlrpcresp
+     * @return Response
      */
     public function& send($msg, $timeout=0, $method='')
     {
@@ -337,7 +337,7 @@ class Client
 
         if(is_array($msg))
         {
-            // $msg is an array of xmlrpcmsg's
+            // $msg is an array of Requests
             $r = $this->multicall($msg, $timeout, $method);
             return $r;
         }
@@ -348,7 +348,7 @@ class Client
             $msg = $n;
         }
 
-        // where msg is an xmlrpcmsg
+        // where msg is a Request
         $msg->debug=$this->debug;
 
         if($method == 'https')
@@ -908,7 +908,7 @@ class Client
      * NB: trying to shoehorn extra functionality into existing syntax has resulted
      * in pretty much convoluted code...
      *
-     * @param array $msgs an array of xmlrpcmsg objects
+     * @param Request[] $msgs an array of Request objects
      * @param integer $timeout connection timeout (in seconds)
      * @param string $method the http protocol variant to be used
      * @param boolean fallback When true, upon receiving an error during multicall, multiple single calls will be attempted
@@ -939,7 +939,7 @@ class Client
                 }
                 else
                 {
-                    if (is_a($results, 'xmlrpcresp'))
+                    if (is_a($results, '\PhpXmlRpc\Response'))
                     {
                         $result = $results;
                     }
index 00db29c..7051931 100644 (file)
@@ -4,7 +4,6 @@ namespace PhpXmlRpc;
 
 use PhpXmlRpc\Helper\Http;
 use PhpXmlRpc\Helper\XMLParser;
-use PhpXmlRpc\Helper\Encoder;
 
 class Request
 {
index 6532547..fe945c1 100644 (file)
@@ -26,7 +26,7 @@ class Response
      *
      * @todo add check that $val / $fcode / $fstr 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 xmlrpc_client::send() inside which creator is called...
+     * php val, or a complete xml chunk, depending on usage of Client::send() inside which creator is called...
      */
     function __construct($val, $fcode = 0, $fstr = '', $valtyp='')
     {
@@ -85,7 +85,7 @@ class Response
 
     /**
      * Returns the value received by the server.
-     * @return mixed the xmlrpcval object returned by the server. Might be an xml string or php value if the response has been created by specially configured xmlrpc_client objects
+     * @return mixed the xmlrpcval object returned by the server. Might be an xml string or php value if the response has been created by specially configured Client objects
      */
     public function value()
     {
@@ -99,7 +99,7 @@ class Response
      * NB: cookies sent as 'expired' by the server (i.e. with an expiry date in the past)
      * are still present in the array. It is up to the user-defined code to decide
      * how to use the received cookies, and whether they have to be sent back with the next
-     * request to the server (using xmlrpc_client::setCookie) or not
+     * request to the server (using Client::setCookie) or not
      * @return array array of cookies received from the server
      */
     public function cookies()
@@ -150,7 +150,7 @@ Charset::instance()->encode_entities($this->errstr, PhpXmlRpc::$xmlrpc_internale
                 else
                 {
                     /// @todo try to build something serializable?
-                    die('cannot serialize xmlrpcresp objects whose content is native php values');
+                    die('cannot serialize xmlrpc response objects whose content is native php values');
                 }
             }
             else
index 56fd6e8..7f42b16 100644 (file)
@@ -4,58 +4,6 @@ namespace PhpXmlRpc;
 
 use PhpXmlRpc\Helper\XMLParser;
 use PhpXmlRpc\Helper\Charset;
-use PhpXmlRpc\Helper\Encoder;
-
-/**
-* Error handler used to track errors that occur during server-side execution of PHP code.
-* This allows to report back to the client whether an internal error has occurred or not
-* using an xmlrpc response object, instead of letting the client deal with the html junk
-* that a PHP execution error on the server generally entails.
-*
-* NB: in fact a user defined error handler can only handle WARNING, NOTICE and USER_* errors.
-*
-*/
-function _xmlrpcs_errorHandler($errcode, $errstring, $filename=null, $lineno=null, $context=null)
-{
-    // obey the @ protocol
-    if (error_reporting() == 0)
-        return;
-
-    //if($errcode != E_NOTICE && $errcode != E_WARNING && $errcode != E_USER_NOTICE && $errcode != E_USER_WARNING)
-    if($errcode != E_STRICT)
-    {
-        \PhpXmlRpc\Server::error_occurred($errstring);
-    }
-    // Try to avoid as much as possible disruption to the previous error handling
-    // mechanism in place
-    if($GLOBALS['_xmlrpcs_prev_ehandler'] == '')
-    {
-        // The previous error handler was the default: all we should do is log error
-        // to the default error log (if level high enough)
-        if(ini_get('log_errors') && (intval(ini_get('error_reporting')) & $errcode))
-        {
-            error_log($errstring);
-        }
-    }
-    else
-    {
-        // Pass control on to previous error handler, trying to avoid loops...
-        if($GLOBALS['_xmlrpcs_prev_ehandler'] != '_xmlrpcs_errorHandler')
-        {
-            // NB: this code will NOT work on php < 4.0.2: only 2 params were used for error handlers
-            if(is_array($GLOBALS['_xmlrpcs_prev_ehandler']))
-            {
-                // the following works both with static class methods and plain object methods as error handler
-                call_user_func_array($GLOBALS['_xmlrpcs_prev_ehandler'], array($errcode, $errstring, $filename, $lineno, $context));
-            }
-            else
-            {
-                $GLOBALS['_xmlrpcs_prev_ehandler']($errcode, $errstring, $filename, $lineno, $context);
-            }
-        }
-    }
-}
-
 
 class Server
 {
@@ -421,7 +369,7 @@ class Server
 
     /**
     * Parse http headers received along with xmlrpc request. If needed, inflate request
-    * @return mixed null on success or an xmlrpcresp
+    * @return mixed null on success or a Response
     */
     protected function parseRequestHeaders(&$data, &$req_encoding, &$resp_encoding, &$resp_compression)
     {
@@ -544,7 +492,7 @@ class Server
     * php function registered with the server
     * @param string $data the xml request
     * @param string $req_encoding (optional) the charset encoding of the xml request
-    * @return xmlrpcresp
+    * @return Response
     */
     public function parseRequest($data, $req_encoding='')
     {
@@ -658,10 +606,10 @@ class Server
 
     /**
     * Execute a method invoked by the client, checking parameters used
-    * @param mixed $m either an xmlrpcmsg obj or a method name
+    * @param mixed $m either a Request obj or a method name
     * @param array $params array with method parameters as php types (if m is method name only)
     * @param array $paramtypes array with xmlrpc types of method parameters (if m is method name only)
-    * @return xmlrpcresp
+    * @return Response
     */
     protected function execute($m, $params=null, $paramtypes=null)
     {
@@ -728,7 +676,7 @@ class Server
         // processing of user function, and log them as part of response
         if($this->debug > 2)
         {
-            $GLOBALS['_xmlrpcs_prev_ehandler'] = set_error_handler('_xmlrpcs_errorHandler');
+            $GLOBALS['_xmlrpcs_prev_ehandler'] = set_error_handler(array('\PhpXmlRpc\Server', '_xmlrpcs_errorHandler'));
         }
         try
         {
@@ -743,9 +691,9 @@ class Server
                 {
                     $r = call_user_func($func, $m);
                 }
-                if (!is_a($r, 'xmlrpcresp'))
+                if (!is_a($r, 'PhpXmlRpc\Response'))
                 {
-                    error_log("XML-RPC: ".__METHOD__.": function $func registered as method handler does not return an xmlrpcresp object");
+                    error_log("XML-RPC: ".__METHOD__.": function $func registered as method handler does not return an xmlrpc response object");
                     if (is_a($r, 'PhpXmlRpc\Value'))
                     {
                         $r = new Response($r);
@@ -755,7 +703,7 @@ class Server
                         $r = new Response(
                             0,
                             PhpXmlRpc::$xmlrpcerr['server_error'],
-                            PhpXmlRpc::$xmlrpcstr['server_error'] . ": function does not return xmlrpcresp object"
+                            PhpXmlRpc::$xmlrpcstr['server_error'] . ": function does not return xmlrpc response object"
                         );
                     }
                 }
@@ -792,8 +740,8 @@ class Server
                         $r = call_user_func_array($func, $params);
                     }
                 }
-                // the return type can be either an xmlrpcresp object or a plain php value...
-                if (!is_a($r, 'xmlrpcresp'))
+                // the return type can be either a Response object or a plain php value...
+                if (!is_a($r, '\PhpXmlRpc\Response'))
                 {
                     // what should we assume here about automatic encoding of datetimes
                     // and php classes instances???
@@ -1181,4 +1129,54 @@ class Server
 
         return new Response(new Value($result, 'array'));
     }
+
+    /**
+     * Error handler used to track errors that occur during server-side execution of PHP code.
+     * This allows to report back to the client whether an internal error has occurred or not
+     * using an xmlrpc response object, instead of letting the client deal with the html junk
+     * that a PHP execution error on the server generally entails.
+     *
+     * NB: in fact a user defined error handler can only handle WARNING, NOTICE and USER_* errors.
+     *
+     */
+    public static function _xmlrpcs_errorHandler($errcode, $errstring, $filename=null, $lineno=null, $context=null)
+    {
+        // obey the @ protocol
+        if (error_reporting() == 0)
+            return;
+
+        //if($errcode != E_NOTICE && $errcode != E_WARNING && $errcode != E_USER_NOTICE && $errcode != E_USER_WARNING)
+        if($errcode != E_STRICT)
+        {
+            \PhpXmlRpc\Server::error_occurred($errstring);
+        }
+        // Try to avoid as much as possible disruption to the previous error handling
+        // mechanism in place
+        if($GLOBALS['_xmlrpcs_prev_ehandler'] == '')
+        {
+            // The previous error handler was the default: all we should do is log error
+            // to the default error log (if level high enough)
+            if(ini_get('log_errors') && (intval(ini_get('error_reporting')) & $errcode))
+            {
+                error_log($errstring);
+            }
+        }
+        else
+        {
+            // Pass control on to previous error handler, trying to avoid loops...
+            if($GLOBALS['_xmlrpcs_prev_ehandler'] != array('\PhpXmlRpc\Server', '_xmlrpcs_errorHandler'))
+            {
+                if(is_array($GLOBALS['_xmlrpcs_prev_ehandler']))
+                {
+                    // the following works both with static class methods and plain object methods as error handler
+                    call_user_func_array($GLOBALS['_xmlrpcs_prev_ehandler'], array($errcode, $errstring, $filename, $lineno, $context));
+                }
+                else
+                {
+                    $GLOBALS['_xmlrpcs_prev_ehandler']($errcode, $errstring, $filename, $lineno, $context);
+                }
+            }
+        }
+    }
+
 }
index ff1bbba..3b7addd 100644 (file)
@@ -122,7 +122,7 @@ class Wrapper
     *   function prototype is not considered valid (to be fixed?)
     *
     * Note that since rel. 2.0RC3 the preferred method to have the server call 'standard'
-    * php functions (ie. functions not expecting a single xmlrpcmsg obj as parameter)
+    * php functions (ie. functions not expecting a single Request obj as parameter)
     * is by making use of the functions_parameters_type class member.
     *
     * @param string $funcname the name of the PHP user function to be exposed as xmlrpc method; array($obj, 'methodname') and array('class', 'methodname') are ok too
@@ -518,7 +518,7 @@ class Wrapper
     /**
     * Given an xmlrpc client and a method name, register a php wrapper function
     * that will call it and return results using native php types for both
-    * params and results. The generated php function will return an xmlrpcresp
+    * params and results. The generated php function will return a Response
     * object for failed xmlrpc calls
     *
     * Known limitations:
@@ -538,7 +538,7 @@ class Wrapper
     * An extra 'debug' param is appended to param list of xmlrpc method, useful
     * for debugging purposes.
     *
-    * @param xmlrpc_client $client     an xmlrpc client set up correctly to communicate with target server
+    * @param Client        $client     an xmlrpc client set up correctly to communicate with target server
     * @param string        $methodname the xmlrpc method to be mapped to a php function
     * @param array         $extra_options array of options that specify conversion details. valid options include
     *        integer       signum      the index of the method signature to use in mapping (if method exposes many sigs)
@@ -548,7 +548,7 @@ class Wrapper
     *        string        return_source if true return php code w. function definition instead fo function name
     *        bool          encode_php_objs let php objects be sent to server using the 'improved' xmlrpc notation, so server can deserialize them as php objects
     *        bool          decode_php_objs --- WARNING !!! possible security hazard. only use it with trusted servers ---
-    *        mixed         return_on_fault a php value to be returned when the xmlrpc call fails/returns a fault response (by default the xmlrpcresp object is returned in this case). If a string is used, '%faultCode%' and '%faultString%' tokens will be substituted with actual error values
+    *        mixed         return_on_fault a php value to be returned when the xmlrpc call fails/returns a fault response (by default the Response object is returned in this case). If a string is used, '%faultCode%' and '%faultString%' tokens will be substituted with actual error values
     *        bool          debug        set it to 1 or 2 to see debug results of querying server for method synopsis
     * @return string                   the name of the generated php function (or false) - OR AN ARRAY...
     */
@@ -688,7 +688,7 @@ class Wrapper
     * Similar to wrap_xmlrpc_method, but will generate a php class that wraps
     * all xmlrpc methods exposed by the remote server as own methods.
     * For more details see wrap_xmlrpc_method.
-    * @param xmlrpc_client $client the client obj all set to query the desired server
+    * @param Client $client the client obj all set to query the desired server
     * @param array $extra_options list of options for wrapped code
     * @return mixed false on error, the name of the created class if all ok or an array with code, class name and comments (if the appropriatevoption is set in extra_options)
     */
diff --git a/test/benchmark.php b/test/benchmark.php
deleted file mode 100644 (file)
index 8c0f694..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-<?php
-/**
- * Benchamrking suite for the PHP-XMLRPC lib
- * @author Gaetano Giunta
- * @copyright (c) 2005-2014 G. Giunta
- * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt
- *
- * @todo add a test for response ok in call testing?
- **/
-
-    include_once(__DIR__.'/../vendor/autoload.php');
-
-    include(__DIR__.'/parse_args.php');
-
-    // Set up PHP structures to be used in many tests
-    $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
-    $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
-    $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
-    $keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
-
-    $test_results=array();
-    $xd = extension_loaded('xdebug') && ini_get('xdebug.profiler_enable');
-    if ($xd)
-        $num_tests = 1;
-    else
-        $num_tests = 10;
-
-    $title = 'XML-RPC Benchmark Tests';
-
-    if(isset($_SERVER['REQUEST_METHOD']))
-    {
-        echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n<head>\n<title>$title</title>\n</head>\n<body>\n<h1>$title</h1>\n<pre>\n";
-    }
-    else
-    {
-        echo "$title\n\n";
-    }
-
-    if(isset($_SERVER['REQUEST_METHOD']))
-    {
-        echo "<h3>Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."</h3>\n";
-        if ($xd) echo "<h4>XDEBUG profiling enabled: skipping remote tests. Trace file is: ".htmlspecialchars(xdebug_get_profiler_filename())."</h4>\n";
-        flush();
-        ob_flush();
-    }
-    else
-    {
-        echo "Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."\n";
-        if ($xd) echo "XDEBUG profiling enabled: skipping remote tests\nTrace file is: ".xdebug_get_profiler_filename()."\n";
-    }
-
-    // test 'old style' data encoding vs. 'automatic style' encoding
-    begin_test('Data encoding (large array)', 'manual encoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        $vals = array();
-        for ($j = 0; $j < 10; $j++)
-        {
-            $valarray = array();
-            foreach ($data[$j] as $key => $val)
-            {
-                $values = array();
-                $values[] = new xmlrpcval($val[0], 'int');
-                $values[] = new xmlrpcval($val[1], 'double');
-                $values[] = new xmlrpcval($val[2], 'string');
-                $values[] = new xmlrpcval($val[3], 'boolean');
-                $values[] = new xmlrpcval($val[4], 'dateTime.iso8601');
-                $values[] = new xmlrpcval($val[5], 'int');
-                $values[] = new xmlrpcval($val[6], 'double');
-                $values[] = new xmlrpcval($val[7], 'string');
-                $values[] = new xmlrpcval($val[8], 'boolean');
-                $values[] = new xmlrpcval($val[9], 'dateTime.iso8601');
-                $valarray[$key] = new xmlrpcval($values, 'array');
-            }
-            $vals[] = new xmlrpcval($valarray, 'struct');
-        }
-        $value = new xmlrpcval($vals, 'array');
-        $out = $value->serialize();
-    }
-    end_test('Data encoding (large array)', 'manual encoding', $out);
-
-    begin_test('Data encoding (large array)', 'automatic encoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        $value = php_xmlrpc_encode($data, array('auto_dates'));
-        $out = $value->serialize();
-    }
-    end_test('Data encoding (large array)', 'automatic encoding', $out);
-
-    if (function_exists('xmlrpc_set_type'))
-    {
-    begin_test('Data encoding (large array)', 'xmlrpc-epi encoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        for ($j = 0; $j < 10; $j++)
-            foreach ($keys as $k)
-            {
-                xmlrpc_set_type($data[$j][$k][4], 'datetime');
-                xmlrpc_set_type($data[$j][$k][8], 'datetime');
-            }
-        $out = xmlrpc_encode($data);
-    }
-    end_test('Data encoding (large array)', 'xmlrpc-epi encoding', $out);
-    }
-
-    // test 'old style' data decoding vs. 'automatic style' decoding
-    $dummy = new xmlrpcmsg('');
-    $out = new xmlrpcresp($value);
-    $in = '<?xml version="1.0" ?>'."\n".$out->serialize();
-
-    begin_test('Data decoding (large array)', 'manual decoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        $response =& $dummy->ParseResponse($in, true);
-        $value = $response->value();
-        $result = array();
-        for ($k = 0; $k < $value->arraysize(); $k++)
-        {
-            $val1 = $value->arraymem($k);
-            $out = array();
-            while (list($name, $val) = $val1->structeach())
-            {
-                $out[$name] = array();
-                for ($j = 0; $j < $val->arraysize(); $j++)
-                {
-                    $data = $val->arraymem($j);
-                    $out[$name][] = $data->scalarval();
-                }
-            } // while
-            $result[] = $out;
-        }
-    }
-    end_test('Data decoding (large array)', 'manual decoding', $result);
-
-    begin_test('Data decoding (large array)', 'automatic decoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        $response =& $dummy->ParseResponse($in, true, 'phpvals');
-        $value = $response->value();
-    }
-    end_test('Data decoding (large array)', 'automatic decoding', $value);
-
-    if (function_exists('xmlrpc_decode'))
-    {
-    begin_test('Data decoding (large array)', 'xmlrpc-epi decoding');
-    for ($i = 0; $i < $num_tests; $i++)
-    {
-        $response =& $dummy->ParseResponse($in, true, 'xml');
-        $value = xmlrpc_decode($response->value());
-    }
-    end_test('Data decoding (large array)', 'xmlrpc-epi decoding', $value);
-    }
-
-    if (!$xd) {
-
-    /// test multicall vs. many calls vs. keep-alives
-    $value = php_xmlrpc_encode($data1, array('auto_dates'));
-    $msg = new xmlrpcmsg('interopEchoTests.echoValue', array($value));
-    $msgs=array();
-    for ($i = 0; $i < 25; $i++)
-        $msgs[] = $msg;
-    $server = explode(':', $LOCALSERVER);
-    if(count($server) > 1)
-    {
-        $c = new xmlrpc_client($URI, $server[0], $server[1]);
-    }
-    else
-    {
-        $c = new xmlrpc_client($URI, $LOCALSERVER);
-    }
-    // do not interfere with http compression
-    $c->accepted_compression = array();
-    //$c->debug=true;
-
-    if (function_exists('gzinflate')) {
-        $c->accepted_compression = null;
-    }
-    begin_test('Repeated send (small array)', 'http 10');
-    $response = array();
-    for ($i = 0; $i < 25; $i++)
-    {
-        $resp =& $c->send($msg);
-        $response[] = $resp->value();
-    }
-    end_test('Repeated send (small array)', 'http 10', $response);
-
-    if (function_exists('curl_init'))
-    {
-        begin_test('Repeated send (small array)', 'http 11 w. keep-alive');
-        $response = array();
-        for ($i = 0; $i < 25; $i++)
-        {
-            $resp =& $c->send($msg, 10, 'http11');
-            $response[] = $resp->value();
-        }
-        end_test('Repeated send (small array)', 'http 11 w. keep-alive', $response);
-
-        $c->keepalive = false;
-        begin_test('Repeated send (small array)', 'http 11');
-        $response = array();
-        for ($i = 0; $i < 25; $i++)
-        {
-            $resp =& $c->send($msg, 10, 'http11');
-            $response[] = $resp->value();
-        }
-        end_test('Repeated send (small array)', 'http 11', $response);
-    }
-
-    begin_test('Repeated send (small array)', 'multicall');
-    $response =& $c->send($msgs);
-    foreach ($response as $key =>& $val)
-    {
-        $val = $val->value();
-    }
-    end_test('Repeated send (small array)', 'multicall', $response);
-
-    if (function_exists('gzinflate'))
-    {
-        $c->accepted_compression = array('gzip');
-        $c->request_compression = 'gzip';
-
-        begin_test('Repeated send (small array)', 'http 10 w. compression');
-        $response = array();
-        for ($i = 0; $i < 25; $i++)
-        {
-            $resp =& $c->send($msg);
-            $response[] = $resp->value();
-        }
-        end_test('Repeated send (small array)', 'http 10 w. compression', $response);
-
-        if (function_exists('curl_init'))
-        {
-            begin_test('Repeated send (small array)', 'http 11 w. keep-alive and compression');
-            $response = array();
-            for ($i = 0; $i < 25; $i++)
-            {
-                $resp =& $c->send($msg, 10, 'http11');
-                $response[] = $resp->value();
-            }
-            end_test('Repeated send (small array)', 'http 11 w. keep-alive and compression', $response);
-
-            $c->keepalive = false;
-            begin_test('Repeated send (small array)', 'http 11 w. compression');
-            $response = array();
-            for ($i = 0; $i < 25; $i++)
-            {
-                $resp =& $c->send($msg, 10, 'http11');
-                $response[] = $resp->value();
-            }
-            end_test('Repeated send (small array)', 'http 11 w. compression', $response);
-        }
-
-        begin_test('Repeated send (small array)', 'multicall w. compression');
-        $response =& $c->send($msgs);
-        foreach ($response as $key =>& $val)
-        {
-            $val = $val->value();
-        }
-        end_test('Repeated send (small array)', 'multicall w. compression', $response);
-    }
-
-    } // end of 'if no xdebug profiling'
-
-    function begin_test($test_name, $test_case)
-    {
-        global $test_results;
-        if (!isset($test_results[$test_name]))
-            $test_results[$test_name]=array();
-        $test_results[$test_name][$test_case] = array();
-        $test_results[$test_name][$test_case]['time'] = microtime(true);
-    }
-
-    function end_test($test_name, $test_case, $test_result)
-    {
-        global $test_results;
-        $end = microtime(true);
-        if (!isset($test_results[$test_name][$test_case]))
-            trigger_error('ending test that was not sterted');
-        $test_results[$test_name][$test_case]['time'] = $end - $test_results[$test_name][$test_case]['time'];
-        $test_results[$test_name][$test_case]['result'] = $test_result;
-        echo '.';
-        flush();
-        ob_flush();
-    }
-
-
-    echo "\n";
-    foreach($test_results as $test => $results)
-    {
-        echo "\nTEST: $test\n";
-        foreach ($results as $case => $data)
-            echo "  $case: {$data['time']} secs - Output data CRC: ".crc32(serialize($data['result']))."\n";
-    }
-
-
-    if(isset($_SERVER['REQUEST_METHOD']))
-    {
-        echo "\n</pre>\n</body>\n</html>\n";
-    }
diff --git a/test/parse_args.php b/test/parse_args.php
deleted file mode 100644 (file)
index f8e2f55..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-<?php
-/**
- * Common parameter parsing for benchmarks and tests scripts
- *
- * @param integer DEBUG
- * @param string  LOCALSERVER
- * @param string  URI
- * @param string  HTTPSSERVER
- * @param string  HTTPSSURI
- * @param string  PROXY
- *
- * @copyright (C) 2007-20013 G. Giunta
- * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt
- **/
-
-    // check for command line vs web page input params
-    if(!isset($_SERVER['REQUEST_METHOD']))
-    {
-        if(isset($argv))
-        {
-            foreach($argv as $param)
-            {
-                $param = explode('=', $param);
-                if(count($param) > 1)
-                {
-                    $$param[0]=$param[1];
-                }
-            }
-        }
-    }
-    elseif(!ini_get('register_globals'))
-    {
-        // play nice to 'safe' PHP installations with register globals OFF
-        // NB: we might as well consider using $_GET stuff later on...
-        extract($_GET);
-        extract($_POST);
-    }
-
-    if(!isset($DEBUG))
-    {
-        $DEBUG = 0;
-    }
-    else
-    {
-        $DEBUG = intval($DEBUG);
-    }
-
-    if(!isset($LOCALSERVER))
-    {
-        if(isset($HTTP_HOST))
-        {
-            $LOCALSERVER = $HTTP_HOST;
-        }
-        elseif(isset($_SERVER['HTTP_HOST']))
-        {
-            $LOCALSERVER = $_SERVER['HTTP_HOST'];
-        }
-        else
-        {
-            $LOCALSERVER = 'localhost';
-        }
-    }
-    if(!isset($HTTPSSERVER))
-    {
-        $HTTPSSERVER = 'xmlrpc.usefulinc.com';
-    }
-    if(!isset($HTTPSURI))
-    {
-        $HTTPSURI = '/server.php';
-    }
-    if(!isset($HTTPSIGNOREPEER))
-    {
-        $HTTPSIGNOREPEER = false;
-    }
-    if(!isset($PROXY))
-    {
-        $PROXYSERVER = null;
-    }
-    else
-    {
-        $arr = explode(':',$PROXY);
-        $PROXYSERVER = $arr[0];
-        if(count($arr) > 1)
-        {
-            $PROXYPORT = $arr[1];
-        }
-        else
-        {
-            $PROXYPORT = 8080;
-        }
-    }
-    // used to silence testsuite warnings about proxy code not being tested
-    if(!isset($NOPROXY))
-    {
-        $NOPROXY = false;
-    }
-    if(!isset($URI))
-    {
-        // GUESTIMATE the url of local demo server
-        // play nice to php 3 and 4-5 in retrieving URL of server.php
-        /// @todo filter out query string from REQUEST_URI
-        if(isset($REQUEST_URI))
-        {
-            $URI = str_replace('/test/testsuite.php', '/demo/server/server.php', $REQUEST_URI);
-            $URI = str_replace('/testsuite.php', '/server.php', $URI);
-            $URI = str_replace('/test/benchmark.php', '/demo/server/server.php', $URI);
-            $URI = str_replace('/benchmark.php', '/server.php', $URI);
-        }
-        elseif(isset($_SERVER['PHP_SELF']) && isset($_SERVER['REQUEST_METHOD']))
-        {
-            $URI = str_replace('/test/testsuite.php', '/demo/server/server.php', $_SERVER['PHP_SELF']);
-            $URI = str_replace('/testsuite.php', '/server.php', $URI);
-            $URI = str_replace('/test/benchmark.php', '/demo/server/server.php', $URI);
-            $URI = str_replace('/benchmark.php', '/server.php', $URI);
-        }
-        else
-        {
-            $URI = '/demo/server/server.php';
-        }
-    }
-    if($URI[0] != '/')
-    {
-        $URI = '/'.$URI;
-    }
-    if(!isset($LOCALPATH))
-    {
-        $LOCALPATH = __DIR__;
-    }
diff --git a/test/testsuite.php b/test/testsuite.php
deleted file mode 100644 (file)
index 34069e2..0000000
+++ /dev/null
@@ -1,1550 +0,0 @@
-<?php
-
-include_once(__DIR__.'/../vendor/autoload.php');
-
-include_once(__DIR__.'/../lib/xmlrpc.inc');
-include_once(__DIR__.'/../lib/xmlrpcs.inc');
-include_once(__DIR__.'/../lib/xmlrpc_wrappers.inc');
-
-include(__DIR__.'/parse_args.php');
-
-//require_once 'PHPUnit/TestDecorator.php';
-
-// let testsuite run for the needed time
-if ((int)ini_get('max_execution_time') < 180)
-    ini_set('max_execution_time', 180);
-
-$suite = new PHPUnit_Framework_TestSuite();
-
-// array with list of failed tests
-$failed_tests = array();
-
-class LocalhostTests extends PHPUnit_Framework_TestCase
-{
-    var $client = null;
-    var $method = 'http';
-    var $timeout = 10;
-    var $request_compression = null;
-    var $accepted_compression = '';
-
-    static function fail($message = '')
-    {
-        parent::fail($message);
-        // save in global var that this particular test has failed
-        // (but only if not called from subclass objects / multitests)
-        if (function_exists('debug_backtrace') && strtolower(get_class($this)) == 'localhosttests')
-        {
-            global $failed_tests;
-            $trace = debug_backtrace();
-            for ($i = 0; $i < count($trace); $i++)
-            {
-                if (strpos($trace[$i]['function'], 'test') === 0)
-                {
-                    $failed_tests[$trace[$i]['function']] = true;
-                    break;
-                }
-            }
-        }
-    }
-
-    function setUp()
-    {
-        global $DEBUG, $LOCALSERVER, $URI;
-        $server = explode(':', $LOCALSERVER);
-        if(count($server) > 1)
-        {
-            $this->client=new xmlrpc_client($URI, $server[0], $server[1]);
-        }
-        else
-        {
-            $this->client=new xmlrpc_client($URI, $LOCALSERVER);
-        }
-        if($DEBUG)
-        {
-            $this->client->setDebug($DEBUG);
-        }
-        $this->client->request_compression = $this->request_compression;
-        $this->client->accepted_compression = $this->accepted_compression;
-    }
-
-    function send($msg, $errrorcode=0, $return_response=false)
-    {
-        $r = $this->client->send($msg, $this->timeout, $this->method);
-        // for multicall, return directly array of responses
-        if(is_array($r))
-        {
-            return $r;
-        }
-        $this->assertEquals($r->faultCode(), $errrorcode, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
-        if(!$r->faultCode())
-        {
-            if($return_response)
-                return $r;
-            else
-                return $r->value();
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    function testString()
-    {
-        $sendstring="here are 3 \"entities\": < > & " .
-            "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
-            " - isn't that great? \\\"hackery\\\" at it's best " .
-            " also don't want to miss out on \$item[0]. ".
-            "The real weird stuff follows: CRLF here".chr(13).chr(10).
-            "a simple CR here".chr(13).
-            "a simple LF here".chr(10).
-            "and then LFCR".chr(10).chr(13).
-            "last but not least weird names: G".chr(252)."nter, El".chr(232)."ne, and an xml comment closing tag: -->";
-        $f=new xmlrpcmsg('examples.stringecho', array(
-            new xmlrpcval($sendstring, 'string')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
-            // so we relax our tests...
-            $l1 = strlen($sendstring);
-            $l2 = strlen($v->scalarval());
-            if ($l1 == $l2)
-                $this->assertEquals($sendstring, $v->scalarval());
-            else
-                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
-        }
-    }
-
-    function testAddingDoubles()
-    {
-        // note that rounding errors mean we
-        // keep precision to sensible levels here ;-)
-        $a=12.13; $b=-23.98;
-        $f=new xmlrpcmsg('examples.addtwodouble',array(
-            new xmlrpcval($a, 'double'),
-            new xmlrpcval($b, 'double')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            $this->assertEquals($a+$b,$v->scalarval());
-        }
-    }
-
-    function testAdding()
-    {
-        $f=new xmlrpcmsg('examples.addtwo',array(
-            new xmlrpcval(12, 'int'),
-            new xmlrpcval(-23, 'int')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            $this->assertEquals(12-23, $v->scalarval());
-        }
-    }
-
-    function testInvalidNumber()
-    {
-        $f=new xmlrpcmsg('examples.addtwo',array(
-            new xmlrpcval('fred', 'int'),
-            new xmlrpcval("\"; exec('ls')", 'int')
-        ));
-        $v=$this->send($f);
-        /// @todo a fault condition should be generated here
-        /// by the server, which we pick up on
-        if($v)
-        {
-            $this->assertEquals(0, $v->scalarval());
-        }
-    }
-
-    function testBoolean()
-    {
-        $f=new xmlrpcmsg('examples.invertBooleans', array(
-            new xmlrpcval(array(
-                new xmlrpcval(true, 'boolean'),
-                new xmlrpcval(false, 'boolean'),
-                new xmlrpcval(1, 'boolean'),
-                new xmlrpcval(0, 'boolean'),
-                //new xmlrpcval('true', 'boolean'),
-                //new xmlrpcval('false', 'boolean')
-            ),
-            'array'
-            )));
-        $answer='0101';
-        $v=$this->send($f);
-        if($v)
-        {
-            $sz=$v->arraysize();
-            $got='';
-            for($i=0; $i<$sz; $i++)
-            {
-                $b=$v->arraymem($i);
-                if($b->scalarval())
-                {
-                    $got.='1';
-                }
-                else
-                {
-                    $got.='0';
-                }
-            }
-            $this->assertEquals($answer, $got);
-        }
-    }
-
-    function testBase64()
-    {
-        $sendstring='Mary had a little lamb,
-Whose fleece was white as snow,
-And everywhere that Mary went
-the lamb was sure to go.
-
-Mary had a little lamb
-She tied it to a pylon
-Ten thousand volts went down its back
-And turned it into nylon';
-        $f=new xmlrpcmsg('examples.decode64',array(
-            new xmlrpcval($sendstring, 'base64')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            if (strlen($sendstring) == strlen($v->scalarval()))
-                $this->assertEquals($sendstring, $v->scalarval());
-            else
-                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
-        }
-    }
-
-    function testDateTime()
-    {
-        $time = time();
-        $t1 = new xmlrpcval($time, 'dateTime.iso8601');
-        $t2 = new xmlrpcval(iso8601_encode($time), 'dateTime.iso8601');
-        $this->assertEquals($t1->serialize(), $t2->serialize());
-        if (class_exists('DateTime'))
-        {
-            $datetime = new DateTime();
-            // skip this test for php 5.2. It is a bit harder there to build a DateTime from unix timestamp with proper TZ info
-            if(is_callable(array($datetime,'setTimestamp')))
-            {
-                $t3 = new xmlrpcval($datetime->setTimestamp($time), 'dateTime.iso8601');
-                $this->assertEquals($t1->serialize(), $t3->serialize());
-            }
-        }
-    }
-
-    function testCountEntities()
-    {
-        $sendstring = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
-        $f = new xmlrpcmsg('validator1.countTheEntities',array(
-            new xmlrpcval($sendstring, 'string')
-        ));
-        $v = $this->send($f);
-        if($v)
-        {
-            $got = '';
-            $expected = '37210';
-            $expect_array = array('ctLeftAngleBrackets','ctRightAngleBrackets','ctAmpersands','ctApostrophes','ctQuotes');
-            while(list(,$val) = each($expect_array))
-            {
-                $b = $v->structmem($val);
-                $got .= $b->me['int'];
-            }
-            $this->assertEquals($expected, $got);
-        }
-    }
-
-    function _multicall_msg($method, $params)
-    {
-        $struct['methodName'] = new xmlrpcval($method, 'string');
-        $struct['params'] = new xmlrpcval($params, 'array');
-        return new xmlrpcval($struct, 'struct');
-    }
-
-    function testServerMulticall()
-    {
-        // We manually construct a system.multicall() call to ensure
-        // that the server supports it.
-
-        // NB: This test will NOT pass if server does not support system.multicall.
-
-        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
-        $good1 = $this->_multicall_msg(
-            'system.methodHelp',
-            array(php_xmlrpc_encode('system.listMethods')));
-        $bad = $this->_multicall_msg(
-            'test.nosuch',
-            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
-        $recursive = $this->_multicall_msg(
-            'system.multicall',
-            array(new xmlrpcval(array(), 'array')));
-        $good2 = $this->_multicall_msg(
-            'system.methodSignature',
-            array(php_xmlrpc_encode('system.listMethods')));
-        $arg = new xmlrpcval(
-            array($good1, $bad, $recursive, $good2),
-            'array'
-        );
-
-        $f = new xmlrpcmsg('system.multicall', array($arg));
-        $v = $this->send($f);
-        if($v)
-        {
-            //$this->assertTrue($r->faultCode() == 0, "fault from system.multicall");
-            $this->assertTrue($v->arraysize() == 4, "bad number of return values");
-
-            $r1 = $v->arraymem(0);
-            $this->assertTrue(
-                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
-                "did not get array of size 1 from good1"
-            );
-
-            $r2 = $v->arraymem(1);
-            $this->assertTrue(
-                $r2->kindOf() == 'struct',
-                "no fault from bad"
-            );
-
-            $r3 = $v->arraymem(2);
-            $this->assertTrue(
-                $r3->kindOf() == 'struct',
-                "recursive system.multicall did not fail"
-            );
-
-            $r4 = $v->arraymem(3);
-            $this->assertTrue(
-                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
-                "did not get array of size 1 from good2"
-            );
-        }
-    }
-
-    function testClientMulticall1()
-    {
-        // NB: This test will NOT pass if server does not support system.multicall.
-
-        $this->client->no_multicall = false;
-
-        $good1 = new xmlrpcmsg('system.methodHelp',
-            array(php_xmlrpc_encode('system.listMethods')));
-        $bad = new xmlrpcmsg('test.nosuch',
-            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
-        $recursive = new xmlrpcmsg('system.multicall',
-            array(new xmlrpcval(array(), 'array')));
-        $good2 = new xmlrpcmsg('system.methodSignature',
-            array(php_xmlrpc_encode('system.listMethods'))
-        );
-
-        $r = $this->send(array($good1, $bad, $recursive, $good2));
-        if($r)
-        {
-            $this->assertTrue(count($r) == 4, "wrong number of return values");
-        }
-
-        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
-        if(!$r[0]->faultCode())
-        {
-            $val = $r[0]->value();
-            $this->assertTrue(
-                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
-                "good1 did not return string"
-            );
-        }
-        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
-        $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
-        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
-        if(!$r[3]->faultCode())
-        {
-            $val = $r[3]->value();
-            $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
-        }
-        // This is the only assert in this test which should fail
-        // if the test server does not support system.multicall.
-        $this->assertTrue($this->client->no_multicall == false,
-            "server does not support system.multicall"
-        );
-    }
-
-    function testClientMulticall2()
-    {
-        // NB: This test will NOT pass if server does not support system.multicall.
-
-        $this->client->no_multicall = true;
-
-        $good1 = new xmlrpcmsg('system.methodHelp',
-            array(php_xmlrpc_encode('system.listMethods')));
-        $bad = new xmlrpcmsg('test.nosuch',
-            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
-        $recursive = new xmlrpcmsg('system.multicall',
-            array(new xmlrpcval(array(), 'array')));
-        $good2 = new xmlrpcmsg('system.methodSignature',
-            array(php_xmlrpc_encode('system.listMethods'))
-        );
-
-        $r = $this->send(array($good1, $bad, $recursive, $good2));
-        if($r)
-        {
-            $this->assertTrue(count($r) == 4, "wrong number of return values");
-        }
-
-        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
-        if(!$r[0]->faultCode())
-        {
-            $val = $r[0]->value();
-            $this->assertTrue(
-                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
-                "good1 did not return string");
-        }
-        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
-        $this->assertTrue($r[2]->faultCode() == 0, "fault from (non recursive) system.multicall");
-        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
-        if(!$r[3]->faultCode())
-        {
-            $val = $r[3]->value();
-            $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
-        }
-    }
-
-    function testClientMulticall3()
-    {
-        // NB: This test will NOT pass if server does not support system.multicall.
-
-        $this->client->return_type = 'phpvals';
-        $this->client->no_multicall = false;
-
-        $good1 = new xmlrpcmsg('system.methodHelp',
-            array(php_xmlrpc_encode('system.listMethods')));
-        $bad = new xmlrpcmsg('test.nosuch',
-            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
-        $recursive = new xmlrpcmsg('system.multicall',
-            array(new xmlrpcval(array(), 'array')));
-        $good2 = new xmlrpcmsg('system.methodSignature',
-            array(php_xmlrpc_encode('system.listMethods'))
-        );
-
-        $r = $this->send(array($good1, $bad, $recursive, $good2));
-        if($r)
-        {
-            $this->assertTrue(count($r) == 4, "wrong number of return values");
-        }
-        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
-        if(!$r[0]->faultCode())
-        {
-            $val = $r[0]->value();
-            $this->assertTrue(
-                is_string($val) , "good1 did not return string");
-        }
-        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
-        $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
-        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
-        if(!$r[3]->faultCode())
-        {
-            $val = $r[3]->value();
-            $this->assertTrue(is_array($val), "good2 did not return array");
-        }
-        $this->client->return_type = 'xmlrpcvals';
-    }
-
-    function testCatchWarnings()
-    {
-        $f = new xmlrpcmsg('examples.generatePHPWarning', array(
-            new xmlrpcval('whatever', 'string')
-        ));
-        $v = $this->send($f);
-        if($v)
-        {
-            $this->assertEquals($v->scalarval(), true);
-        }
-    }
-
-    function testCatchExceptions()
-    {
-        global $URI;
-        $f = new xmlrpcmsg('examples.raiseException', array(
-            new xmlrpcval('whatever', 'string')
-        ));
-        $v = $this->send($f, $GLOBALS['xmlrpcerr']['server_error']);
-        $this->client->path = $URI.'?EXCEPTION_HANDLING=1';
-        $v = $this->send($f, 1);
-        $this->client->path = $URI.'?EXCEPTION_HANDLING=2';
-        $v = $this->send($f, $GLOBALS['xmlrpcerr']['invalid_return']);
-    }
-
-    function testZeroParams()
-    {
-        $f = new xmlrpcmsg('system.listMethods');
-        $v = $this->send($f);
-    }
-
-    function testCodeInjectionServerSide()
-    {
-        $f = new xmlrpcmsg('system.MethodHelp');
-        $f->payload = "<?xml version=\"1.0\"?><methodCall><methodName>validator1.echoStructTest</methodName><params><param><value><struct><member><name>','')); echo('gotcha!'); die(); //</name></member></struct></value></param></params></methodCall>";
-        $v = $this->send($f);
-        //$v = $r->faultCode();
-        if ($v)
-        {
-            $this->assertEquals(0, $v->structsize());
-        }
-    }
-
-    function testAutoRegisteredFunction()
-    {
-        $f=new xmlrpcmsg('examples.php.getStateName',array(
-            new xmlrpcval(23, 'int')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            $this->assertEquals('Michigan', $v->scalarval());
-        }
-        else
-        {
-            $this->fail('Note: server can only auto register functions if running with PHP 5.0.3 and up');
-        }
-    }
-
-    function testAutoRegisteredClass()
-    {
-        $f=new xmlrpcmsg('examples.php2.getStateName',array(
-            new xmlrpcval(23, 'int')
-        ));
-        $v=$this->send($f);
-        if($v)
-        {
-            $this->assertEquals('Michigan', $v->scalarval());
-            $f=new xmlrpcmsg('examples.php3.getStateName',array(
-            new xmlrpcval(23, 'int')
-        ));
-            $v=$this->send($f);
-            if($v)
-            {
-                $this->assertEquals('Michigan', $v->scalarval());
-            }
-        }
-        else
-        {
-            $this->fail('Note: server can only auto register class methods if running with PHP 5.0.3 and up');
-        }
-    }
-
-    function testAutoRegisteredMethod()
-    {
-        // make a 'deep client copy' as the original one might have many properties set
-        $func=wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 1));
-        if($func == '')
-        {
-            $this->fail('Registration of examples.getStateName failed');
-        }
-        else
-        {
-            $v=$func(23);
-            // work around bug in current version of phpunit
-            if(is_object($v))
-            {
-                $v = var_export($v, true);
-            }
-            $this->assertEquals('Michigan', $v);
-        }
-    }
-
-    function testGetCookies()
-    {
-        // let server set to us some cookies we tell it
-        $cookies = array(
-            //'c1' => array(),
-            'c2' => array('value' => 'c2'),
-            'c3' => array('value' => 'c3', 'expires' => time()+60*60*24*30),
-            'c4' => array('value' => 'c4', 'expires' => time()+60*60*24*30, 'path' => '/'),
-            'c5' => array('value' => 'c5', 'expires' => time()+60*60*24*30, 'path' => '/', 'domain' => 'localhost'),
-        );
-        $cookiesval = php_xmlrpc_encode($cookies);
-        $f=new xmlrpcmsg('examples.setcookies',array($cookiesval));
-        $r=$this->send($f, 0, true);
-        if($r)
-        {
-            $v = $r->value();
-            $this->assertEquals(1, $v->scalarval());
-            // now check if we decoded the cookies as we had set them
-            $rcookies = $r->cookies();
-            // remove extra cookies which might have been set by proxies
-            foreach($rcookies as $c => $v)
-                if(!in_array($c, array('c2', 'c3', 'c4', 'c5')))
-                    unset($rcookies[$c]);
-            foreach($cookies as $c => $v)
-                // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
-                // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
-                if(isset($v['expires']))
-                {
-                    if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-'))
-                    {
-                        $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
-                    }
-                    else
-                    {
-                        $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
-                    }
-                }
-            $this->assertEquals($cookies, $rcookies);
-        }
-    }
-
-    function testSetCookies()
-    {
-        // let server set to us some cookies we tell it
-        $cookies = array(
-            'c0' => null,
-            'c1' => 1,
-            'c2' => '2 3',
-            'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-'
-        );
-        $f=new xmlrpcmsg('examples.getcookies',array());
-        foreach ($cookies as $cookie => $val)
-        {
-            $this->client->setCookie($cookie, $val);
-            $cookies[$cookie] = (string) $cookies[$cookie];
-        }
-        $r = $this->client->send($f, $this->timeout, $this->method);
-        $this->assertEquals($r->faultCode(), 0, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
-        if(!$r->faultCode())
-        {
-            $v = $r->value();
-            $v = php_xmlrpc_decode($v);
-            // on IIS and Apache getallheaders returns something slightly different...
-            $this->assertEquals($v, $cookies);
-        }
-    }
-
-    function testSendTwiceSameMsg()
-    {
-        $f=new xmlrpcmsg('examples.stringecho', array(
-            new xmlrpcval('hello world', 'string')
-        ));
-        $v1 = $this->send($f);
-        $v2 = $this->send($f);
-        //$v = $r->faultCode();
-        if ($v1 && $v2)
-        {
-            $this->assertEquals($v2, $v1);
-        }
-    }
-}
-
-class LocalHostMultiTests extends LocalhostTests
-{
-    function _runtests()
-    {
-        global $failed_tests;
-        foreach(get_class_methods('LocalhostTests') as $meth)
-        {
-            if(strpos($meth, 'test') === 0 && $meth != 'testHttps' && $meth != 'testCatchExceptions')
-            {
-                if (!isset($failed_tests[$meth]))
-                {
-                    $this->$meth();
-                }
-            }
-            if ($this->_failed)
-            {
-                break;
-            }
-        }
-    }
-
-    function testDeflate()
-    {
-        if(!function_exists('gzdeflate'))
-        {
-            $this->fail('Zlib missing: cannot test deflate functionality');
-            return;
-        }
-        $this->client->accepted_compression = array('deflate');
-        $this->client->request_compression = 'deflate';
-        $this->_runtests();
-    }
-
-    function testGzip()
-    {
-        if(!function_exists('gzdeflate'))
-        {
-            $this->fail('Zlib missing: cannot test gzip functionality');
-            return;
-        }
-        $this->client->accepted_compression = array('gzip');
-        $this->client->request_compression = 'gzip';
-        $this->_runtests();
-    }
-
-    function testKeepAlives()
-    {
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test http 1.1');
-            return;
-        }
-        $this->method = 'http11';
-        $this->client->keepalive = true;
-        $this->_runtests();
-    }
-
-    function testProxy()
-    {
-        global $PROXYSERVER, $PROXYPORT, $NOPROXY;
-        if ($PROXYSERVER)
-        {
-            $this->client->setProxy($PROXYSERVER, $PROXYPORT);
-            $this->_runtests();
-        }
-        else
-            if (!$NOPROXY)
-                $this->fail('PROXY definition missing: cannot test proxy');
-    }
-
-    function testHttp11()
-    {
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test http 1.1');
-            return;
-        }
-        $this->method = 'http11'; // not an error the double assignment!
-        $this->client->method = 'http11';
-        //$this->client->verifyhost = 0;
-        //$this->client->verifypeer = 0;
-        $this->client->keepalive = false;
-        $this->_runtests();
-    }
-
-    function testHttp11Gzip()
-    {
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test http 1.1');
-            return;
-        }
-        $this->method = 'http11'; // not an error the double assignment!
-        $this->client->method = 'http11';
-        $this->client->keepalive = false;
-        $this->client->accepted_compression = array('gzip');
-        $this->client->request_compression = 'gzip';
-        $this->_runtests();
-    }
-
-    function testHttp11Deflate()
-    {
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test http 1.1');
-            return;
-        }
-        $this->method = 'http11'; // not an error the double assignment!
-        $this->client->method = 'http11';
-        $this->client->keepalive = false;
-        $this->client->accepted_compression = array('deflate');
-        $this->client->request_compression = 'deflate';
-        $this->_runtests();
-    }
-
-    function testHttp11Proxy()
-    {
-        global $PROXYSERVER, $PROXYPORT, $NOPROXY;
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test http 1.1 w. proxy');
-            return;
-        }
-        else if ($PROXYSERVER == '')
-        {
-            if (!$NOPROXY)
-                $this->fail('PROXY definition missing: cannot test proxy w. http 1.1');
-            return;
-        }
-        $this->method = 'http11'; // not an error the double assignment!
-        $this->client->method = 'http11';
-        $this->client->setProxy($PROXYSERVER, $PROXYPORT);
-        //$this->client->verifyhost = 0;
-        //$this->client->verifypeer = 0;
-        $this->client->keepalive = false;
-        $this->_runtests();
-    }
-
-    function testHttps()
-    {
-        global $HTTPSSERVER, $HTTPSURI, $HTTPSIGNOREPEER;
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test https functionality');
-            return;
-        }
-        $this->client->server = $HTTPSSERVER;
-        $this->method = 'https';
-        $this->client->method = 'https';
-        $this->client->path = $HTTPSURI;
-        $this->client->setSSLVerifyPeer( !$HTTPSIGNOREPEER );
-        // silence warning with newish php versions
-        $this->client->setSSLVerifyHost(2);
-        $this->_runtests();
-    }
-
-    function testHttpsProxy()
-    {
-        global $HTTPSSERVER, $HTTPSURI, $PROXYSERVER, $PROXYPORT, $NOPROXY;
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test https functionality');
-            return;
-        }
-        else if ($PROXYSERVER == '')
-        {
-            if (!$NOPROXY)
-                $this->fail('PROXY definition missing: cannot test proxy w. http 1.1');
-            return;
-        }
-        $this->client->server = $HTTPSSERVER;
-        $this->method = 'https';
-        $this->client->method = 'https';
-        $this->client->setProxy($PROXYSERVER, $PROXYPORT);
-        $this->client->path = $HTTPSURI;
-        $this->_runtests();
-    }
-
-    function testUTF8Responses()
-    {
-        global $URI;
-        //$this->client->path = strpos($URI, '?') === null ? $URI.'?RESPONSE_ENCODING=UTF-8' : $URI.'&RESPONSE_ENCODING=UTF-8';
-        $this->client->path = $URI.'?RESPONSE_ENCODING=UTF-8';
-        $this->_runtests();
-    }
-
-    function testUTF8Requests()
-    {
-        $this->client->request_charset_encoding = 'UTF-8';
-        $this->_runtests();
-    }
-
-    function testISOResponses()
-    {
-        global $URI;
-        //$this->client->path = strpos($URI, '?') === null ? $URI.'?RESPONSE_ENCODING=UTF-8' : $URI.'&RESPONSE_ENCODING=UTF-8';
-        $this->client->path = $URI.'?RESPONSE_ENCODING=ISO-8859-1';
-        $this->_runtests();
-    }
-
-    function testISORequests()
-    {
-        $this->client->request_charset_encoding = 'ISO-8859-1';
-        $this->_runtests();
-    }
-}
-
-class ParsingBugsTests extends PHPUnit_Framework_TestCase
-{
-    function testMinusOneString()
-    {
-        $v=new xmlrpcval('-1');
-        $u=new xmlrpcval('-1', 'string');
-        $this->assertEquals($u->scalarval(), $v->scalarval());
-    }
-
-    function testUnicodeInMemberName(){
-        $str = "G".chr(252)."nter, El".chr(232)."ne";
-        $v = array($str => new xmlrpcval(1));
-        $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
-        $r = $r->serialize();
-        $m = new xmlrpcmsg('dummy');
-        $r = $m->parseResponse($r);
-        $v = $r->value();
-        $this->assertEquals($v->structmemexists($str), true);
-    }
-
-    function testUnicodeInErrorString()
-    {
-        $response = utf8_encode(
-'<?xml version="1.0"?>
-<!-- $Id -->
-<!-- found by G. giunta, covers what happens when lib receives
-  UTF8 chars in response text and comments -->
-<!-- ���&#224;&#252;&#232; -->
-<methodResponse>
-<fault>
-<value>
-<struct>
-<member>
-<name>faultCode</name>
-<value><int>888</int></value>
-</member>
-<member>
-<name>faultString</name>
-<value><string>���&#224;&#252;&#232;</string></value>
-</member>
-</struct>
-</value>
-</fault>
-</methodResponse>');
-        $m=new xmlrpcmsg('dummy');
-        $r=$m->parseResponse($response);
-        $v=$r->faultString();
-        $this->assertEquals('���àüè', $v);
-    }
-
-    function testValidNumbers()
-    {
-        $m=new xmlrpcmsg('dummy');
-        $fp=
-'<?xml version="1.0"?>
-<methodResponse>
-<params>
-<param>
-<value>
-<struct>
-<member>
-<name>integer1</name>
-<value><int>01</int></value>
-</member>
-<member>
-<name>float1</name>
-<value><double>01.10</double></value>
-</member>
-<member>
-<name>integer2</name>
-<value><int>+1</int></value>
-</member>
-<member>
-<name>float2</name>
-<value><double>+1.10</double></value>
-</member>
-<member>
-<name>float3</name>
-<value><double>-1.10e2</double></value>
-</member>
-</struct>
-</value>
-</param>
-</params>
-</methodResponse>';
-        $r=$m->parseResponse($fp);
-        $v=$r->value();
-        $s=$v->structmem('integer1');
-        $t=$v->structmem('float1');
-        $u=$v->structmem('integer2');
-        $w=$v->structmem('float2');
-        $x=$v->structmem('float3');
-        $this->assertEquals(1, $s->scalarval());
-        $this->assertEquals(1.1, $t->scalarval());
-        $this->assertEquals(1, $u->scalarval());
-        $this->assertEquals(1.1, $w->scalarval());
-        $this->assertEquals(-110.0, $x->scalarval());
-    }
-
-    function testAddScalarToStruct()
-    {
-        $v=new xmlrpcval(array('a' => 'b'), 'struct');
-        // use @ operator in case error_log gets on screen
-        $r= @$v->addscalar('c');
-        $this->assertEquals(0, $r);
-    }
-
-    function testAddStructToStruct()
-    {
-        $v=new xmlrpcval(array('a' => new xmlrpcval('b')), 'struct');
-        $r=$v->addstruct(array('b' => new xmlrpcval('c')));
-        $this->assertEquals(2, $v->structsize());
-        $this->assertEquals(1, $r);
-        $r=$v->addstruct(array('b' => new xmlrpcval('b')));
-        $this->assertEquals(2, $v->structsize());
-    }
-
-    function testAddArrayToArray()
-    {
-        $v=new xmlrpcval(array(new xmlrpcval('a'), new xmlrpcval('b')), 'array');
-        $r=$v->addarray(array(new xmlrpcval('b'), new xmlrpcval('c')));
-        $this->assertEquals(4, $v->arraysize());
-        $this->assertEquals(1, $r);
-    }
-
-    function testEncodeArray()
-    {
-        $r=range(1, 100);
-        $v = php_xmlrpc_encode($r);
-        $this->assertEquals('array', $v->kindof());
-    }
-
-    function testEncodeRecursive()
-    {
-        $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
-        $this->assertEquals('scalar', $v->kindof());
-    }
-
-    function testBrokenRequests()
-    {
-        $s = new xmlrpc_server();
-        // omitting the 'params' tag: not tolerated by the lib anymore
-$f = '<?xml version="1.0"?>
-<methodCall>
-<methodName>system.methodHelp</methodName>
-<param>
-<value><string>system.methodHelp</string></value>
-</param>
-</methodCall>';
-        $r = $s->parserequest($f);
-        $this->assertEquals(15, $r->faultCode());
-        // omitting a 'param' tag
-$f = '<?xml version="1.0"?>
-<methodCall>
-<methodName>system.methodHelp</methodName>
-<params>
-<value><string>system.methodHelp</string></value>
-</params>
-</methodCall>';
-        $r = $s->parserequest($f);
-        $this->assertEquals(15, $r->faultCode());
-        // omitting a 'value' tag
-$f = '<?xml version="1.0"?>
-<methodCall>
-<methodName>system.methodHelp</methodName>
-<params>
-<param><string>system.methodHelp</string></param>
-</params>
-</methodCall>';
-        $r = $s->parserequest($f);
-        $this->assertEquals(15, $r->faultCode());
-    }
-
-    function testBrokenResponses()
-    {
-        $m=new xmlrpcmsg('dummy');
-        //$m->debug = 1;
-        // omitting the 'params' tag: no more tolerated by the lib...
-$f = '<?xml version="1.0"?>
-<methodResponse>
-<param>
-<value><string>system.methodHelp</string></value>
-</param>
-</methodResponse>';
-        $r = $m->parseResponse($f);
-        $this->assertEquals(2, $r->faultCode());
-        // omitting the 'param' tag: no more tolerated by the lib...
-$f = '<?xml version="1.0"?>
-<methodResponse>
-<params>
-<value><string>system.methodHelp</string></value>
-</params>
-</methodResponse>';
-        $r = $m->parseResponse($f);
-        $this->assertEquals(2, $r->faultCode());
-        // omitting a 'value' tag: KO
-$f = '<?xml version="1.0"?>
-<methodResponse>
-<params>
-<param><string>system.methodHelp</string></param>
-</params>
-</methodResponse>';
-        $r = $m->parseResponse($f);
-        $this->assertEquals(2, $r->faultCode());
-    }
-
-    function testBuggyHttp()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = 'HTTP/1.1 100 Welcome to the jungle
-
-HTTP/1.0 200 OK
-X-Content-Marx-Brothers: Harpo
-        Chico and Groucho
-Content-Length: who knows?
-
-
-
-<?xml version="1.0"?>
-<!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
-<methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
-
-
-and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
-<script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
- ';
-        $r = $s->parseResponse($f);
-        $v = $r->value();
-        $s = $v->structmem('content');
-        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
-    }
-
-    function testStringBug()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?>
-<!-- $Id -->
-<!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
- covers what happens when there\'s character data after </string>
- and before </value> -->
-<methodResponse>
-<params>
-<param>
-<value>
-<struct>
-<member>
-<name>success</name>
-<value>
-<boolean>1</boolean>
-</value>
-</member>
-<member>
-<name>sessionID</name>
-<value>
-<string>S300510007I</string>
-</value>
-</member>
-</struct>
-</value>
-</param>
-</params>
-</methodResponse> ';
-        $r = $s->parseResponse($f);
-        $v = $r->value();
-        $s = $v->structmem('sessionID');
-        $this->assertEquals('S300510007I', $s->scalarval());
-    }
-
-    function testWhiteSpace()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
-
-
-and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->value();
-        $s = $v->structmem('content');
-        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
-    }
-
-    function testDoubleDataInArrayTag()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
-<data></data>
-<data></data>
-</array></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->faultCode();
-        $this->assertEquals(2, $v);
-$f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
-<data><value>Hello world</value></data>
-<data></data>
-</array></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->faultCode();
-        $this->assertEquals(2, $v);
-    }
-
-    function testDoubleStuffInValueTag()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?><methodResponse><params><param><value>
-<string>hello world</string>
-<array><data></data></array>
-</value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->faultCode();
-        $this->assertEquals(2, $v);
-$f = '<?xml version="1.0"?><methodResponse><params><param><value>
-<string>hello</string>
-<string>world</string>
-</value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->faultCode();
-        $this->assertEquals(2, $v);
-$f = '<?xml version="1.0"?><methodResponse><params><param><value>
-<string>hello</string>
-<struct><member><name>hello><value>world</value></member></struct>
-</value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f);
-        $v = $r->faultCode();
-        $this->assertEquals(2, $v);
-    }
-
-    function testAutodecodeResponse()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
-
-
-and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f, true, 'phpvals');
-        $v = $r->value();
-        $s = $v['content'];
-        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
-    }
-
-    function testNoDecodeResponse()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
-
-
-and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
-        $r = $s->parseResponse($f, true, 'xml');
-        $v = $r->value();
-        $this->assertEquals($f, $v);
-    }
-
-    function testAutoCoDec()
-    {
-        $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
-        $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
-        $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
-        //$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
-        $v1 = php_xmlrpc_encode($data, array('auto_dates'));
-        $v2 = php_xmlrpc_decode_xml($v1->serialize());
-        $this->assertEquals($v1, $v2);
-        $r1 = new xmlrpcresp($v1);
-        $r2 = php_xmlrpc_decode_xml($r1->serialize());
-        $r2->serialize(); // needed to set internal member payload
-        $this->assertEquals($r1, $r2);
-        $m1 = new xmlrpcmsg('hello dolly', array($v1));
-        $m2 = php_xmlrpc_decode_xml($m1->serialize());
-        $m2->serialize(); // needed to set internal member payload
-        $this->assertEquals($m1, $m2);
-    }
-
-    function testUTF8Request()
-    {
-        $sendstring='κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
-        $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
-        $f = new xmlrpcval($sendstring, 'string');
-        $v=$f->serialize();
-        $this->assertEquals("<value><string>&#954;&#8057;&#963;&#956;&#949;</string></value>\n", $v);
-        $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
-    }
-
-    function testUTF8Response()
-    {
-        $s = new xmlrpcmsg('dummy');
-$f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=UTF-8\r\n\r\n".'<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('������').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f, false, 'phpvals');
-        $v = $r->value();
-        $v = $v['content'];
-        $this->assertEquals("������", $v);
-$f = '<?xml version="1.0" encoding="utf-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
-<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('������').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
-';
-        $r = $s->parseResponse($f, false, 'phpvals');
-        $v = $r->value();
-        $v = $v['content'];
-        $this->assertEquals("������", $v);
-    }
-
-    function testUTF8IntString()
-    {
-        $v=new xmlrpcval(100, 'int');
-        $s=$v->serialize('UTF-8');
-        $this->assertequals("<value><int>100</int></value>\n", $s);
-    }
-
-    function testStringInt()
-    {
-        $v=new xmlrpcval('hello world', 'int');
-        $s=$v->serialize();
-        $this->assertequals("<value><int>0</int></value>\n", $s);
-    }
-
-    function testStructMemExists()
-    {
-        $v=php_xmlrpc_encode(array('hello' => 'world'));
-        $b=$v->structmemexists('hello');
-        $this->assertequals(true, $b);
-        $b=$v->structmemexists('world');
-        $this->assertequals(false, $b);
-    }
-
-    function testNilvalue()
-    {
-        // default case: we do not accept nil values received
-        $v = new xmlrpcval('hello', 'null');
-        $r = new xmlrpcresp($v);
-        $s = $r->serialize();
-        $m = new xmlrpcmsg('dummy');
-        $r = $m->parseresponse($s);
-        $this->assertequals(2, $r->faultCode());
-        // enable reception of nil values
-        $GLOBALS['xmlrpc_null_extension'] = true;
-        $r = $m->parseresponse($s);
-        $v = $r->value();
-        $this->assertequals('null', $v->scalartyp());
-        // test with the apache version: EX:NIL
-        $GLOBALS['xmlrpc_null_apache_encoding'] = true;
-        // serialization
-        $v = new xmlrpcval('hello', 'null');
-        $s = $v->serialize();
-        $this->assertequals(1, preg_match( '#<value><ex:nil/></value>#', $s ));
-        // deserialization
-        $r = new xmlrpcresp($v);
-        $s = $r->serialize();
-        $r = $m->parseresponse($s);
-        $v = $r->value();
-        $this->assertequals('null', $v->scalartyp());
-        $GLOBALS['xmlrpc_null_extension'] = false;
-        $r = $m->parseresponse($s);
-        $this->assertequals(2, $r->faultCode());
-    }
-
-    function TestLocale()
-    {
-        $locale = setlocale(LC_NUMERIC, 0);
-        /// @todo on php 5.3/win setting locale to german does not seem to set decimal separator to comma...
-        if (setlocale(LC_NUMERIC,'deu', 'de_DE@euro', 'de_DE', 'de', 'ge') !== false)
-        {
-            $v = new xmlrpcval(1.1, 'double');
-            if (strpos($v->scalarval(), ',') == 1)
-            {
-                $r = $v->serialize();
-                $this->assertequals(false, strpos($r, ','));
-            }
-            setlocale(LC_NUMERIC, $locale);
-        }
-    }
-}
-
-class InvalidHostTests extends PHPUnit_Framework_TestCase
-{
-    var $client = null;
-
-    function setUp()
-    {
-        global $DEBUG,$LOCALSERVER;
-        $this->client=new xmlrpc_client('/NOTEXIST.php', $LOCALSERVER, 80);
-        if($DEBUG)
-        {
-            $this->client->setDebug($DEBUG);
-        }
-    }
-
-    function test404()
-    {
-        $f = new xmlrpcmsg('examples.echo',array(
-            new xmlrpcval('hello', 'string')
-        ));
-        $r = $this->client->send($f, 5);
-        $this->assertEquals(5, $r->faultCode());
-    }
-
-    function testSrvNotFound()
-    {
-        $f = new xmlrpcmsg('examples.echo',array(
-            new xmlrpcval('hello', 'string')
-        ));
-        $this->client->server .= 'XXX';
-        $r = $this->client->send($f, 5);
-        $this->assertEquals(5, $r->faultCode());
-    }
-
-    function testCurlKAErr()
-    {
-        global $LOCALSERVER, $URI;
-        if(!function_exists('curl_init'))
-        {
-            $this->fail('CURL missing: cannot test curl keepalive errors');
-            return;
-        }
-        $f = new xmlrpcmsg('examples.stringecho',array(
-            new xmlrpcval('hello', 'string')
-        ));
-        // test 2 calls w. keepalive: 1st time connection ko, second time ok
-        $this->client->server .= 'XXX';
-        $this->client->keepalive = true;
-        $r = $this->client->send($f, 5, 'http11');
-        // in case we have a "universal dns resolver" getting in the way, we might get a 302 instead of a 404
-        $this->assertTrue($r->faultCode() === 8 || $r->faultCode() == 5);
-
-        // now test a successful connection
-        $server = explode(':', $LOCALSERVER);
-        if(count($server) > 1)
-        {
-            $this->client->port = $server[1];
-        }
-        $this->client->server = $server[0];
-        $this->client->path = $URI;
-
-        $r = $this->client->send($f, 5, 'http11');
-        $this->assertEquals(0, $r->faultCode());
-        $ro = $r->value();
-        is_object( $ro ) && $this->assertEquals('hello', $ro->scalarVal());
-    }
-}
-
-
-$suite->addTest(new LocalhostTests('testString'));
-$suite->addTest(new LocalhostTests('testAdding'));
-$suite->addTest(new LocalhostTests('testAddingDoubles'));
-$suite->addTest(new LocalhostTests('testInvalidNumber'));
-$suite->addTest(new LocalhostTests('testBoolean'));
-$suite->addTest(new LocalhostTests('testCountEntities'));
-$suite->addTest(new LocalhostTests('testBase64'));
-$suite->addTest(new LocalhostTests('testDateTime'));
-$suite->addTest(new LocalhostTests('testServerMulticall'));
-$suite->addTest(new LocalhostTests('testClientMulticall1'));
-$suite->addTest(new LocalhostTests('testClientMulticall2'));
-$suite->addTest(new LocalhostTests('testClientMulticall3'));
-$suite->addTest(new LocalhostTests('testCatchWarnings'));
-$suite->addTest(new LocalhostTests('testCatchExceptions'));
-$suite->addTest(new LocalhostTests('testZeroParams'));
-$suite->addTest(new LocalhostTests('testCodeInjectionServerSide'));
-$suite->addTest(new LocalhostTests('testAutoRegisteredFunction'));
-$suite->addTest(new LocalhostTests('testAutoRegisteredMethod'));
-$suite->addTest(new LocalhostTests('testSetCookies'));
-$suite->addTest(new LocalhostTests('testGetCookies'));
-$suite->addTest(new LocalhostTests('testSendTwiceSameMsg'));
-
-$suite->addTest(new LocalhostMultiTests('testUTF8Requests'));
-$suite->addTest(new LocalhostMultiTests('testUTF8Responses'));
-$suite->addTest(new LocalhostMultiTests('testISORequests'));
-$suite->addTest(new LocalhostMultiTests('testISOResponses'));
-$suite->addTest(new LocalhostMultiTests('testGzip'));
-$suite->addTest(new LocalhostMultiTests('testDeflate'));
-$suite->addTest(new LocalhostMultiTests('testProxy'));
-$suite->addTest(new LocalhostMultiTests('testHttp11'));
-$suite->addTest(new LocalhostMultiTests('testHttp11Gzip'));
-$suite->addTest(new LocalhostMultiTests('testHttp11Deflate'));
-$suite->addTest(new LocalhostMultiTests('testKeepAlives'));
-$suite->addTest(new LocalhostMultiTests('testHttp11Proxy'));
-$suite->addTest(new LocalhostMultiTests('testHttps'));
-$suite->addTest(new LocalhostMultiTests('testHttpsProxy'));
-
-$suite->addTest(new InvalidHostTests('test404'));
-//$suite->addTest(new InvalidHostTests('testSrvNotFound'));
-$suite->addTest(new InvalidHostTests('testCurlKAErr'));
-
-$suite->addTest(new ParsingBugsTests('testMinusOneString'));
-$suite->addTest(new ParsingBugsTests('testUnicodeInMemberName'));
-$suite->addTest(new ParsingBugsTests('testUnicodeInErrorString'));
-$suite->addTest(new ParsingBugsTests('testValidNumbers'));
-$suite->addTest(new ParsingBugsTests('testAddScalarToStruct'));
-$suite->addTest(new ParsingBugsTests('testAddStructToStruct'));
-$suite->addTest(new ParsingBugsTests('testAddArrayToArray'));
-$suite->addTest(new ParsingBugsTests('testEncodeArray'));
-$suite->addTest(new ParsingBugsTests('testEncodeRecursive'));
-$suite->addTest(new ParsingBugsTests('testBrokenrequests'));
-$suite->addTest(new ParsingBugsTests('testBrokenresponses'));
-$suite->addTest(new ParsingBugsTests('testBuggyHttp'));
-$suite->addTest(new ParsingBugsTests('testStringBug'));
-$suite->addTest(new ParsingBugsTests('testWhiteSpace'));
-$suite->addTest(new ParsingBugsTests('testAutodecodeResponse'));
-$suite->addTest(new ParsingBugsTests('testNoDecodeResponse'));
-$suite->addTest(new ParsingBugsTests('testAutoCoDec'));
-$suite->addTest(new ParsingBugsTests('testUTF8Response'));
-$suite->addTest(new ParsingBugsTests('testUTF8Request'));
-$suite->addTest(new ParsingBugsTests('testUTF8IntString'));
-$suite->addTest(new ParsingBugsTests('testStringInt'));
-$suite->addTest(new ParsingBugsTests('testStructMemExists'));
-$suite->addTest(new ParsingBugsTests('testDoubleDataInArrayTag'));
-$suite->addTest(new ParsingBugsTests('testDoubleStuffInValueTag'));
-$suite->addTest(new ParsingBugsTests('testNilValue'));
-$suite->addTest(new ParsingBugsTests('testLocale'));
-
-$title = 'XML-RPC Unit Tests';
-
-if(isset($only))
-{
-    $suite = new PHPUnit_TestSuite($only);
-}
-
-if(isset($_SERVER['REQUEST_METHOD']))
-{
-    echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n<head>\n<title>$title</title>\n</head>\n<body>\n<h1>$title</h1>\n";
-}
-else
-{
-    echo "$title\n\n";
-}
-
-if(isset($_SERVER['REQUEST_METHOD']))
-{
-    echo "<h3>Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."</h3>\n";
-    echo '<h3>Running '.$suite->count().' tests (some of which are multiple) against servers: http://'.htmlspecialchars($LOCALSERVER.$URI).' and https://'.htmlspecialchars($HTTPSSERVER.$HTTPSURI)."\n ...</h3>\n";
-    flush();
-    @ob_flush();
-}
-else
-{
-    echo "Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."\n";
-    echo 'Running '.$suite->count().' tests (some of which are multiple) against servers: http://'.$LOCALSERVER.$URI.' and https://'.$HTTPSSERVER.$HTTPSURI."\n\n";
-}
-
-// do some basic timing measurement
-list($micro, $sec) = explode(' ', microtime());
-$start_time = $sec + $micro;
-
-//$PHPUnit = new PHPUnit;
-//$result = $PHPUnit->run($suite, ($DEBUG == 0 ? '.' : '<hr/>'));
-$result = $suite->run();
-
-list($micro, $sec) = explode(' ', microtime());
-$end_time = $sec + $micro;
-
-if(!isset($_SERVER['REQUEST_METHOD']))
-{
-    echo $result->toString()."\n";
-}
-
-if(isset($_SERVER['REQUEST_METHOD']))
-{
-    echo '<h3>'.$result->failureCount()." test failures</h3>\n";
-    printf("Time spent: %.2f secs<br/>\n", $end_time - $start_time);
-}
-else
-{
-    echo $result->failureCount()." test failures\n";
-    printf("Time spent: %.2f secs\n", $end_time - $start_time);
-}
-
-if($result->failureCount() && !$DEBUG)
-{
-    $target = strpos($_SERVER['PHP_SELF'], '?') ? $_SERVER['PHP_SELF'].'&amp;DEBUG=1' : $_SERVER['PHP_SELF'].'?DEBUG=1';
-    $t2 = strpos($_SERVER['PHP_SELF'], '?') ? $_SERVER['PHP_SELF'].'&amp;DEBUG=2' : $_SERVER['PHP_SELF'].'?DEBUG=2';
-    if(isset($_SERVER['REQUEST_METHOD']))
-    {
-        echo '<p>Run testsuite with <a href="'.$target.'">DEBUG=1</a> to have more detail about tests results. Or with <a href="'.$t2.'">DEBUG=2</a> for even more.</p>'."\n";
-    }
-    else
-    {
-        echo "Run testsuite with DEBUG=1 (or 2) to have more detail about tests results\n";
-    }
-}
-
-if(isset($_SERVER['REQUEST_METHOD']))
-{
-?>
-<a href="#" onclick="if (document.getElementById('opts').style.display == 'block') document.getElementById('opts').style.display = 'none'; else document.getElementById('opts').style.display = 'block';">More options...</a>
-<div id="opts" style="display: none;">
-<form method="GET" style="border: 1px solid silver; margin: 5px; padding: 5px; font-family: monospace;">
-HTTP Server:&nbsp;&nbsp;<input name="LOCALSERVER" size="30" value="<?php echo htmlspecialchars($LOCALSERVER); ?>"/> Path: <input name="URI"  size="30" value="<?php echo htmlspecialchars($URI); ?>"/><br/>
-HTTPS Server: <input name="HTTPSSERVER" size="30" value="<?php echo htmlspecialchars($HTTPSSERVER); ?>"/> Path: <input name="HTTPSURI"  size="30" value="<?php echo htmlspecialchars($HTTPSURI); ?>"/> Do not verify cert: <input name="HTTPSIGNOREPEER" value="true" type="checkbox" <?php if ($HTTPSIGNOREPEER) echo 'checked="checked"'; ?>/><br/>
-
-Proxy Server: <input name="PROXY" size="30" value="<?php echo isset($PROXY) ? htmlspecialchars($PROXY) : ''; ?>"/> <input type="submit" value="Run Testsuite"/>
-</form>
-</div>
-<?php
-    echo $result->toHTML()."\n</body>\n</html>\n";
-}
-else
-{
-    exit($result->failureCount());
-}
diff --git a/tests/InvalidHostTest.php b/tests/InvalidHostTest.php
new file mode 100644 (file)
index 0000000..fb89b43
--- /dev/null
@@ -0,0 +1,82 @@
+<?php
+
+include_once(__DIR__.'/../lib/xmlrpc.inc');
+
+include_once(__DIR__.'/parse_args.php');
+
+class InvalidHostTest extends PHPUnit_Framework_TestCase
+{
+    var $client = null;
+    var $args = array();
+
+    function setUp()
+    {
+        $this->args = argParser::getArgs();
+
+        $this->client = new xmlrpc_client('/NOTEXIST.php', $this->args['LOCALSERVER'], 80);
+        if($this->args['DEBUG'])
+        {
+            $this->client->setDebug($this->args['DEBUG']);
+        }
+    }
+
+    function test404()
+    {
+        $f = new xmlrpcmsg('examples.echo',array(
+            new xmlrpcval('hello', 'string')
+        ));
+        $r = $this->client->send($f, 5);
+        $this->assertEquals(5, $r->faultCode());
+    }
+
+    function testSrvNotFound()
+    {
+        $f = new xmlrpcmsg('examples.echo',array(
+            new xmlrpcval('hello', 'string')
+        ));
+        $this->client->server .= 'XXX';
+        $r = $this->client->send($f, 5);
+        // make sure there's no freaking catchall DNS in effect
+        $dnsinfo = dns_get_record($this->client->server);
+        if($dnsinfo)
+        {
+            $this->markTestSkipped('Seems like there is a catchall DNS in effect: host ' . $this->client->server . ' found');
+        }
+        else
+        {
+            $this->assertEquals(5, $r->faultCode());
+        }
+    }
+
+    function testCurlKAErr()
+    {
+        if(!function_exists('curl_init'))
+        {
+            $this->markTestSkipped('CURL missing: cannot test curl keepalive errors');
+            return;
+        }
+        $f = new xmlrpcmsg('examples.stringecho',array(
+            new xmlrpcval('hello', 'string')
+        ));
+        // test 2 calls w. keepalive: 1st time connection ko, second time ok
+        $this->client->server .= 'XXX';
+        $this->client->keepalive = true;
+        $r = $this->client->send($f, 5, 'http11');
+        // in case we have a "universal dns resolver" getting in the way, we might get a 302 instead of a 404
+        $this->assertTrue($r->faultCode() === 8 || $r->faultCode() == 5);
+
+        // now test a successful connection
+        $server = explode(':', $this->args['LOCALSERVER']);
+        if(count($server) > 1)
+        {
+            $this->client->port = $server[1];
+        }
+        $this->client->server = $server[0];
+        $this->client->path = $this->args['URI'];
+
+        $r = $this->client->send($f, 5, 'http11');
+        $this->assertEquals(0, $r->faultCode());
+        $ro = $r->value();
+        is_object( $ro ) && $this->assertEquals('hello', $ro->scalarVal());
+    }
+}
diff --git a/tests/LocalhostTest.php b/tests/LocalhostTest.php
new file mode 100644 (file)
index 0000000..2802524
--- /dev/null
@@ -0,0 +1,627 @@
+<?php
+
+include_once(__DIR__.'/../lib/xmlrpc.inc');
+include_once(__DIR__.'/../lib/xmlrpc_wrappers.inc');
+
+include_once(__DIR__.'/parse_args.php');
+
+class LocalhostTest extends PHPUnit_Framework_TestCase
+{
+    var $client = null;
+    var $method = 'http';
+    var $timeout = 10;
+    var $request_compression = null;
+    var $accepted_compression = '';
+    var $args = array();
+
+    static function fail($message = '')
+    {
+        // save in global var that this particular test has failed
+        // (but only if not called from subclass objects / multitests)
+        if (function_exists('debug_backtrace') && strtolower(get_called_class()) == 'localhosttests')
+        {
+            global $failed_tests;
+            $trace = debug_backtrace();
+            for ($i = 0; $i < count($trace); $i++)
+            {
+                if (strpos($trace[$i]['function'], 'test') === 0)
+                {
+                    $failed_tests[$trace[$i]['function']] = true;
+                    break;
+                }
+            }
+        }
+
+        parent::fail($message);
+    }
+
+    /**
+     * @todo be smarter with setup, do not use global variables anymore
+     */
+    function setUp()
+    {
+        $this->args = argParser::getArgs();
+
+        $server = explode(':', $this->args['LOCALSERVER']);
+        if(count($server) > 1)
+        {
+            $this->client=new xmlrpc_client(['URI'], $server[0], $server[1]);
+        }
+        else
+        {
+            $this->client=new xmlrpc_client($this->args['URI'], $this->args['LOCALSERVER']);
+        }
+        if($this->args['DEBUG'])
+        {
+            $this->client->setDebug($this->args['DEBUG']);
+        }
+        $this->client->request_compression = $this->request_compression;
+        $this->client->accepted_compression = $this->accepted_compression;
+    }
+
+    function send($msg, $errrorcode=0, $return_response=false)
+    {
+        $r = $this->client->send($msg, $this->timeout, $this->method);
+        // for multicall, return directly array of responses
+        if(is_array($r))
+        {
+            return $r;
+        }
+        $this->assertEquals($r->faultCode(), $errrorcode, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
+        if(!$r->faultCode())
+        {
+            if($return_response)
+                return $r;
+            else
+                return $r->value();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    function testString()
+    {
+        $sendstring="here are 3 \"entities\": < > & " .
+            "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
+            " - isn't that great? \\\"hackery\\\" at it's best " .
+            " also don't want to miss out on \$item[0]. ".
+            "The real weird stuff follows: CRLF here".chr(13).chr(10).
+            "a simple CR here".chr(13).
+            "a simple LF here".chr(10).
+            "and then LFCR".chr(10).chr(13).
+            "last but not least weird names: G".chr(252)."nter, El".chr(232)."ne, and an xml comment closing tag: -->";
+        $f=new xmlrpcmsg('examples.stringecho', array(
+            new xmlrpcval($sendstring, 'string')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
+            // so we relax our tests...
+            $l1 = strlen($sendstring);
+            $l2 = strlen($v->scalarval());
+            if ($l1 == $l2)
+                $this->assertEquals($sendstring, $v->scalarval());
+            else
+                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
+        }
+    }
+
+    function testAddingDoubles()
+    {
+        // note that rounding errors mean we
+        // keep precision to sensible levels here ;-)
+        $a=12.13; $b=-23.98;
+        $f=new xmlrpcmsg('examples.addtwodouble',array(
+            new xmlrpcval($a, 'double'),
+            new xmlrpcval($b, 'double')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            $this->assertEquals($a+$b,$v->scalarval());
+        }
+    }
+
+    function testAdding()
+    {
+        $f=new xmlrpcmsg('examples.addtwo',array(
+            new xmlrpcval(12, 'int'),
+            new xmlrpcval(-23, 'int')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            $this->assertEquals(12-23, $v->scalarval());
+        }
+    }
+
+    function testInvalidNumber()
+    {
+        $f=new xmlrpcmsg('examples.addtwo',array(
+            new xmlrpcval('fred', 'int'),
+            new xmlrpcval("\"; exec('ls')", 'int')
+        ));
+        $v=$this->send($f);
+        /// @todo a fault condition should be generated here
+        /// by the server, which we pick up on
+        if($v)
+        {
+            $this->assertEquals(0, $v->scalarval());
+        }
+    }
+
+    function testBoolean()
+    {
+        $f=new xmlrpcmsg('examples.invertBooleans', array(
+            new xmlrpcval(array(
+                new xmlrpcval(true, 'boolean'),
+                new xmlrpcval(false, 'boolean'),
+                new xmlrpcval(1, 'boolean'),
+                new xmlrpcval(0, 'boolean'),
+                //new xmlrpcval('true', 'boolean'),
+                //new xmlrpcval('false', 'boolean')
+            ),
+            'array'
+            )));
+        $answer='0101';
+        $v=$this->send($f);
+        if($v)
+        {
+            $sz=$v->arraysize();
+            $got='';
+            for($i=0; $i<$sz; $i++)
+            {
+                $b=$v->arraymem($i);
+                if($b->scalarval())
+                {
+                    $got.='1';
+                }
+                else
+                {
+                    $got.='0';
+                }
+            }
+            $this->assertEquals($answer, $got);
+        }
+    }
+
+    function testBase64()
+    {
+        $sendstring='Mary had a little lamb,
+Whose fleece was white as snow,
+And everywhere that Mary went
+the lamb was sure to go.
+
+Mary had a little lamb
+She tied it to a pylon
+Ten thousand volts went down its back
+And turned it into nylon';
+        $f=new xmlrpcmsg('examples.decode64',array(
+            new xmlrpcval($sendstring, 'base64')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            if (strlen($sendstring) == strlen($v->scalarval()))
+                $this->assertEquals($sendstring, $v->scalarval());
+            else
+                $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendstring), $v->scalarval());
+        }
+    }
+
+    function testDateTime()
+    {
+        $time = time();
+        $t1 = new xmlrpcval($time, 'dateTime.iso8601');
+        $t2 = new xmlrpcval(iso8601_encode($time), 'dateTime.iso8601');
+        $this->assertEquals($t1->serialize(), $t2->serialize());
+        if (class_exists('DateTime'))
+        {
+            $datetime = new DateTime();
+            // skip this test for php 5.2. It is a bit harder there to build a DateTime from unix timestamp with proper TZ info
+            if(is_callable(array($datetime,'setTimestamp')))
+            {
+                $t3 = new xmlrpcval($datetime->setTimestamp($time), 'dateTime.iso8601');
+                $this->assertEquals($t1->serialize(), $t3->serialize());
+            }
+        }
+    }
+
+    function testCountEntities()
+    {
+        $sendstring = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
+        $f = new xmlrpcmsg('validator1.countTheEntities',array(
+            new xmlrpcval($sendstring, 'string')
+        ));
+        $v = $this->send($f);
+        if($v)
+        {
+            $got = '';
+            $expected = '37210';
+            $expect_array = array('ctLeftAngleBrackets','ctRightAngleBrackets','ctAmpersands','ctApostrophes','ctQuotes');
+            while(list(,$val) = each($expect_array))
+            {
+                $b = $v->structmem($val);
+                $got .= $b->me['int'];
+            }
+            $this->assertEquals($expected, $got);
+        }
+    }
+
+    function _multicall_msg($method, $params)
+    {
+        $struct['methodName'] = new xmlrpcval($method, 'string');
+        $struct['params'] = new xmlrpcval($params, 'array');
+        return new xmlrpcval($struct, 'struct');
+    }
+
+    function testServerMulticall()
+    {
+        // We manually construct a system.multicall() call to ensure
+        // that the server supports it.
+
+        // NB: This test will NOT pass if server does not support system.multicall.
+
+        // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
+        $good1 = $this->_multicall_msg(
+            'system.methodHelp',
+            array(php_xmlrpc_encode('system.listMethods')));
+        $bad = $this->_multicall_msg(
+            'test.nosuch',
+            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
+        $recursive = $this->_multicall_msg(
+            'system.multicall',
+            array(new xmlrpcval(array(), 'array')));
+        $good2 = $this->_multicall_msg(
+            'system.methodSignature',
+            array(php_xmlrpc_encode('system.listMethods')));
+        $arg = new xmlrpcval(
+            array($good1, $bad, $recursive, $good2),
+            'array'
+        );
+
+        $f = new xmlrpcmsg('system.multicall', array($arg));
+        $v = $this->send($f);
+        if($v)
+        {
+            //$this->assertTrue($r->faultCode() == 0, "fault from system.multicall");
+            $this->assertTrue($v->arraysize() == 4, "bad number of return values");
+
+            $r1 = $v->arraymem(0);
+            $this->assertTrue(
+                $r1->kindOf() == 'array' && $r1->arraysize() == 1,
+                "did not get array of size 1 from good1"
+            );
+
+            $r2 = $v->arraymem(1);
+            $this->assertTrue(
+                $r2->kindOf() == 'struct',
+                "no fault from bad"
+            );
+
+            $r3 = $v->arraymem(2);
+            $this->assertTrue(
+                $r3->kindOf() == 'struct',
+                "recursive system.multicall did not fail"
+            );
+
+            $r4 = $v->arraymem(3);
+            $this->assertTrue(
+                $r4->kindOf() == 'array' && $r4->arraysize() == 1,
+                "did not get array of size 1 from good2"
+            );
+        }
+    }
+
+    function testClientMulticall1()
+    {
+        // NB: This test will NOT pass if server does not support system.multicall.
+
+        $this->client->no_multicall = false;
+
+        $good1 = new xmlrpcmsg('system.methodHelp',
+            array(php_xmlrpc_encode('system.listMethods')));
+        $bad = new xmlrpcmsg('test.nosuch',
+            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
+        $recursive = new xmlrpcmsg('system.multicall',
+            array(new xmlrpcval(array(), 'array')));
+        $good2 = new xmlrpcmsg('system.methodSignature',
+            array(php_xmlrpc_encode('system.listMethods'))
+        );
+
+        $r = $this->send(array($good1, $bad, $recursive, $good2));
+        if($r)
+        {
+            $this->assertTrue(count($r) == 4, "wrong number of return values");
+        }
+
+        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
+        if(!$r[0]->faultCode())
+        {
+            $val = $r[0]->value();
+            $this->assertTrue(
+                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
+                "good1 did not return string"
+            );
+        }
+        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
+        $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
+        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
+        if(!$r[3]->faultCode())
+        {
+            $val = $r[3]->value();
+            $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
+        }
+        // This is the only assert in this test which should fail
+        // if the test server does not support system.multicall.
+        $this->assertTrue($this->client->no_multicall == false,
+            "server does not support system.multicall"
+        );
+    }
+
+    function testClientMulticall2()
+    {
+        // NB: This test will NOT pass if server does not support system.multicall.
+
+        $this->client->no_multicall = true;
+
+        $good1 = new xmlrpcmsg('system.methodHelp',
+            array(php_xmlrpc_encode('system.listMethods')));
+        $bad = new xmlrpcmsg('test.nosuch',
+            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
+        $recursive = new xmlrpcmsg('system.multicall',
+            array(new xmlrpcval(array(), 'array')));
+        $good2 = new xmlrpcmsg('system.methodSignature',
+            array(php_xmlrpc_encode('system.listMethods'))
+        );
+
+        $r = $this->send(array($good1, $bad, $recursive, $good2));
+        if($r)
+        {
+            $this->assertTrue(count($r) == 4, "wrong number of return values");
+        }
+
+        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
+        if(!$r[0]->faultCode())
+        {
+            $val = $r[0]->value();
+            $this->assertTrue(
+                $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
+                "good1 did not return string");
+        }
+        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
+        $this->assertTrue($r[2]->faultCode() == 0, "fault from (non recursive) system.multicall");
+        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
+        if(!$r[3]->faultCode())
+        {
+            $val = $r[3]->value();
+            $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
+        }
+    }
+
+    function testClientMulticall3()
+    {
+        // NB: This test will NOT pass if server does not support system.multicall.
+
+        $this->client->return_type = 'phpvals';
+        $this->client->no_multicall = false;
+
+        $good1 = new xmlrpcmsg('system.methodHelp',
+            array(php_xmlrpc_encode('system.listMethods')));
+        $bad = new xmlrpcmsg('test.nosuch',
+            array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
+        $recursive = new xmlrpcmsg('system.multicall',
+            array(new xmlrpcval(array(), 'array')));
+        $good2 = new xmlrpcmsg('system.methodSignature',
+            array(php_xmlrpc_encode('system.listMethods'))
+        );
+
+        $r = $this->send(array($good1, $bad, $recursive, $good2));
+        if($r)
+        {
+            $this->assertTrue(count($r) == 4, "wrong number of return values");
+        }
+        $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
+        if(!$r[0]->faultCode())
+        {
+            $val = $r[0]->value();
+            $this->assertTrue(
+                is_string($val) , "good1 did not return string");
+        }
+        $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
+        $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
+        $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
+        if(!$r[3]->faultCode())
+        {
+            $val = $r[3]->value();
+            $this->assertTrue(is_array($val), "good2 did not return array");
+        }
+        $this->client->return_type = 'xmlrpcvals';
+    }
+
+    function testCatchWarnings()
+    {
+        $f = new xmlrpcmsg('examples.generatePHPWarning', array(
+            new xmlrpcval('whatever', 'string')
+        ));
+        $v = $this->send($f);
+        if($v)
+        {
+            $this->assertEquals($v->scalarval(), true);
+        }
+    }
+
+    function testCatchExceptions()
+    {
+        $f = new xmlrpcmsg('examples.raiseException', array(
+            new xmlrpcval('whatever', 'string')
+        ));
+        $v = $this->send($f, $GLOBALS['xmlrpcerr']['server_error']);
+        $this->client->path = $this->args['URI'].'?EXCEPTION_HANDLING=1';
+        $v = $this->send($f, 1);
+        $this->client->path = $this->args['URI'].'?EXCEPTION_HANDLING=2';
+        $v = $this->send($f, $GLOBALS['xmlrpcerr']['invalid_return']);
+    }
+
+    function testZeroParams()
+    {
+        $f = new xmlrpcmsg('system.listMethods');
+        $v = $this->send($f);
+    }
+
+    function testCodeInjectionServerSide()
+    {
+        $f = new xmlrpcmsg('system.MethodHelp');
+        $f->payload = "<?xml version=\"1.0\"?><methodCall><methodName>validator1.echoStructTest</methodName><params><param><value><struct><member><name>','')); echo('gotcha!'); die(); //</name></member></struct></value></param></params></methodCall>";
+        $v = $this->send($f);
+        //$v = $r->faultCode();
+        if ($v)
+        {
+            $this->assertEquals(0, $v->structsize());
+        }
+    }
+
+    function testAutoRegisteredFunction()
+    {
+        $f=new xmlrpcmsg('examples.php.getStateName',array(
+            new xmlrpcval(23, 'int')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            $this->assertEquals('Michigan', $v->scalarval());
+        }
+        else
+        {
+            $this->fail('Note: server can only auto register functions if running with PHP 5.0.3 and up');
+        }
+    }
+
+    function testAutoRegisteredClass()
+    {
+        $f=new xmlrpcmsg('examples.php2.getStateName',array(
+            new xmlrpcval(23, 'int')
+        ));
+        $v=$this->send($f);
+        if($v)
+        {
+            $this->assertEquals('Michigan', $v->scalarval());
+            $f=new xmlrpcmsg('examples.php3.getStateName',array(
+            new xmlrpcval(23, 'int')
+        ));
+            $v=$this->send($f);
+            if($v)
+            {
+                $this->assertEquals('Michigan', $v->scalarval());
+            }
+        }
+        else
+        {
+            $this->fail('Note: server can only auto register class methods if running with PHP 5.0.3 and up');
+        }
+    }
+
+    function testAutoRegisteredMethod()
+    {
+        // make a 'deep client copy' as the original one might have many properties set
+        $func=wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 1));
+        if($func == '')
+        {
+            $this->fail('Registration of examples.getStateName failed');
+        }
+        else
+        {
+            $v=$func(23);
+            // work around bug in current version of phpunit
+            if(is_object($v))
+            {
+                $v = var_export($v, true);
+            }
+            $this->assertEquals('Michigan', $v);
+        }
+    }
+
+    function testGetCookies()
+    {
+        // let server set to us some cookies we tell it
+        $cookies = array(
+            //'c1' => array(),
+            'c2' => array('value' => 'c2'),
+            'c3' => array('value' => 'c3', 'expires' => time()+60*60*24*30),
+            'c4' => array('value' => 'c4', 'expires' => time()+60*60*24*30, 'path' => '/'),
+            'c5' => array('value' => 'c5', 'expires' => time()+60*60*24*30, 'path' => '/', 'domain' => 'localhost'),
+        );
+        $cookiesval = php_xmlrpc_encode($cookies);
+        $f=new xmlrpcmsg('examples.setcookies',array($cookiesval));
+        $r=$this->send($f, 0, true);
+        if($r)
+        {
+            $v = $r->value();
+            $this->assertEquals(1, $v->scalarval());
+            // now check if we decoded the cookies as we had set them
+            $rcookies = $r->cookies();
+            // remove extra cookies which might have been set by proxies
+            foreach($rcookies as $c => $v)
+                if(!in_array($c, array('c2', 'c3', 'c4', 'c5')))
+                    unset($rcookies[$c]);
+            foreach($cookies as $c => $v)
+                // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
+                // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
+                if(isset($v['expires']))
+                {
+                    if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-'))
+                    {
+                        $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
+                    }
+                    else
+                    {
+                        $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T' ,$cookies[$c]['expires']);
+                    }
+                }
+            $this->assertEquals($cookies, $rcookies);
+        }
+    }
+
+    function testSetCookies()
+    {
+        // let server set to us some cookies we tell it
+        $cookies = array(
+            'c0' => null,
+            'c1' => 1,
+            'c2' => '2 3',
+            'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-'
+        );
+        $f=new xmlrpcmsg('examples.getcookies',array());
+        foreach ($cookies as $cookie => $val)
+        {
+            $this->client->setCookie($cookie, $val);
+            $cookies[$cookie] = (string) $cookies[$cookie];
+        }
+        $r = $this->client->send($f, $this->timeout, $this->method);
+        $this->assertEquals($r->faultCode(), 0, 'Error '.$r->faultCode().' connecting to server: '.$r->faultString());
+        if(!$r->faultCode())
+        {
+            $v = $r->value();
+            $v = php_xmlrpc_decode($v);
+            // on IIS and Apache getallheaders returns something slightly different...
+            $this->assertEquals($v, $cookies);
+        }
+    }
+
+    function testSendTwiceSameMsg()
+    {
+        $f=new xmlrpcmsg('examples.stringecho', array(
+            new xmlrpcval('hello world', 'string')
+        ));
+        $v1 = $this->send($f);
+        $v2 = $this->send($f);
+        //$v = $r->faultCode();
+        if ($v1 && $v2)
+        {
+            $this->assertEquals($v2, $v1);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/ParsingBugsTest.php b/tests/ParsingBugsTest.php
new file mode 100644 (file)
index 0000000..93626c7
--- /dev/null
@@ -0,0 +1,502 @@
+<?php
+/**
+ * NB: do not let your IDE fool you. The correct encoding for this file is NOT UTF8
+ */
+
+include_once(__DIR__.'/../lib/xmlrpc.inc');
+include_once(__DIR__.'/../lib/xmlrpcs.inc');
+
+class ParsingBugsTests extends PHPUnit_Framework_TestCase
+{
+    function testMinusOneString()
+    {
+        $v = new xmlrpcval('-1');
+        $u = new xmlrpcval('-1', 'string');
+        $this->assertEquals($u->scalarval(), $v->scalarval());
+    }
+
+    function testUnicodeInMemberName(){
+        $str = "G".chr(252)."nter, El".chr(232)."ne";
+        $v = array($str => new xmlrpcval(1));
+        $r = new xmlrpcresp(new xmlrpcval($v, 'struct'));
+        $r = $r->serialize();
+        $m = new xmlrpcmsg('dummy');
+        $r = $m->parseResponse($r);
+        $v = $r->value();
+        $this->assertEquals($v->structmemexists($str), true);
+    }
+
+    function testUnicodeInErrorString()
+    {
+        $response = utf8_encode(
+            '<?xml version="1.0"?>
+<!-- $Id -->
+<!-- found by G. giunta, covers what happens when lib receives
+  UTF8 chars in response text and comments -->
+<!-- '.chr(224).chr(252).chr(232).'&#224;&#252;&#232; -->
+<methodResponse>
+<fault>
+<value>
+<struct>
+<member>
+<name>faultCode</name>
+<value><int>888</int></value>
+</member>
+<member>
+<name>faultString</name>
+<value><string>'.chr(224).chr(252).chr(232).'&#224;&#252;&#232;</string></value>
+</member>
+</struct>
+</value>
+</fault>
+</methodResponse>');
+        $m = new xmlrpcmsg('dummy');
+        $r = $m->parseResponse($response);
+        $v = $r->faultString();
+        $this->assertEquals(chr(224).chr(252).chr(232).chr(224).chr(252).chr(232), $v);
+    }
+
+    function testValidNumbers()
+    {
+        $m = new xmlrpcmsg('dummy');
+        $fp=
+            '<?xml version="1.0"?>
+<methodResponse>
+<params>
+<param>
+<value>
+<struct>
+<member>
+<name>integer1</name>
+<value><int>01</int></value>
+</member>
+<member>
+<name>float1</name>
+<value><double>01.10</double></value>
+</member>
+<member>
+<name>integer2</name>
+<value><int>+1</int></value>
+</member>
+<member>
+<name>float2</name>
+<value><double>+1.10</double></value>
+</member>
+<member>
+<name>float3</name>
+<value><double>-1.10e2</double></value>
+</member>
+</struct>
+</value>
+</param>
+</params>
+</methodResponse>';
+        $r=$m->parseResponse($fp);
+        $v=$r->value();
+        $s=$v->structmem('integer1');
+        $t=$v->structmem('float1');
+        $u=$v->structmem('integer2');
+        $w=$v->structmem('float2');
+        $x=$v->structmem('float3');
+        $this->assertEquals(1, $s->scalarval());
+        $this->assertEquals(1.1, $t->scalarval());
+        $this->assertEquals(1, $u->scalarval());
+        $this->assertEquals(1.1, $w->scalarval());
+        $this->assertEquals(-110.0, $x->scalarval());
+    }
+
+    function testAddScalarToStruct()
+    {
+        $v = new xmlrpcval(array('a' => 'b'), 'struct');
+        // use @ operator in case error_log gets on screen
+        $r =  @$v->addscalar('c');
+        $this->assertEquals(0, $r);
+    }
+
+    function testAddStructToStruct()
+    {
+        $v = new xmlrpcval(array('a' => new xmlrpcval('b')), 'struct');
+        $r = $v->addstruct(array('b' => new xmlrpcval('c')));
+        $this->assertEquals(2, $v->structsize());
+        $this->assertEquals(1, $r);
+        $r = $v->addstruct(array('b' => new xmlrpcval('b')));
+        $this->assertEquals(2, $v->structsize());
+    }
+
+    function testAddArrayToArray()
+    {
+        $v = new xmlrpcval(array(new xmlrpcval('a'), new xmlrpcval('b')), 'array');
+        $r = $v->addarray(array(new xmlrpcval('b'), new xmlrpcval('c')));
+        $this->assertEquals(4, $v->arraysize());
+        $this->assertEquals(1, $r);
+    }
+
+    function testEncodeArray()
+    {
+        $r = range(1, 100);
+        $v = php_xmlrpc_encode($r);
+        $this->assertEquals('array', $v->kindof());
+    }
+
+    function testEncodeRecursive()
+    {
+        $v = php_xmlrpc_encode(php_xmlrpc_encode('a simple string'));
+        $this->assertEquals('scalar', $v->kindof());
+    }
+
+    function testBrokenRequests()
+    {
+        $s = new xmlrpc_server();
+        // omitting the 'params' tag: not tolerated by the lib anymore
+        $f = '<?xml version="1.0"?>
+<methodCall>
+<methodName>system.methodHelp</methodName>
+<param>
+<value><string>system.methodHelp</string></value>
+</param>
+</methodCall>';
+        $r = $s->parserequest($f);
+        $this->assertEquals(15, $r->faultCode());
+        // omitting a 'param' tag
+        $f = '<?xml version="1.0"?>
+<methodCall>
+<methodName>system.methodHelp</methodName>
+<params>
+<value><string>system.methodHelp</string></value>
+</params>
+</methodCall>';
+        $r = $s->parserequest($f);
+        $this->assertEquals(15, $r->faultCode());
+        // omitting a 'value' tag
+        $f = '<?xml version="1.0"?>
+<methodCall>
+<methodName>system.methodHelp</methodName>
+<params>
+<param><string>system.methodHelp</string></param>
+</params>
+</methodCall>';
+        $r = $s->parserequest($f);
+        $this->assertEquals(15, $r->faultCode());
+    }
+
+    function testBrokenResponses()
+    {
+        $m = new xmlrpcmsg('dummy');
+        //$m->debug = 1;
+        // omitting the 'params' tag: no more tolerated by the lib...
+        $f = '<?xml version="1.0"?>
+<methodResponse>
+<param>
+<value><string>system.methodHelp</string></value>
+</param>
+</methodResponse>';
+        $r = $m->parseResponse($f);
+        $this->assertEquals(2, $r->faultCode());
+        // omitting the 'param' tag: no more tolerated by the lib...
+        $f = '<?xml version="1.0"?>
+<methodResponse>
+<params>
+<value><string>system.methodHelp</string></value>
+</params>
+</methodResponse>';
+        $r = $m->parseResponse($f);
+        $this->assertEquals(2, $r->faultCode());
+        // omitting a 'value' tag: KO
+        $f = '<?xml version="1.0"?>
+<methodResponse>
+<params>
+<param><string>system.methodHelp</string></param>
+</params>
+</methodResponse>';
+        $r = $m->parseResponse($f);
+        $this->assertEquals(2, $r->faultCode());
+    }
+
+    function testBuggyHttp()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = 'HTTP/1.1 100 Welcome to the jungle
+
+HTTP/1.0 200 OK
+X-Content-Marx-Brothers: Harpo
+        Chico and Groucho
+Content-Length: who knows?
+
+
+
+<?xml version="1.0"?>
+<!-- First of all, let\'s check out if the lib properly handles a commented </methodResponse> tag... -->
+<methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
+
+
+and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
+<script type="text\javascript">document.write(\'Hello, my name is added nag, I\\\'m happy to serve your content for free\');</script>
+ ';
+        $r = $s->parseResponse($f);
+        $v = $r->value();
+        $s = $v->structmem('content');
+        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
+    }
+
+    function testStringBug()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?>
+<!-- $Id -->
+<!-- found by 2z69xks7bpy001@sneakemail.com, amongst others
+ covers what happens when there\'s character data after </string>
+ and before </value> -->
+<methodResponse>
+<params>
+<param>
+<value>
+<struct>
+<member>
+<name>success</name>
+<value>
+<boolean>1</boolean>
+</value>
+</member>
+<member>
+<name>sessionID</name>
+<value>
+<string>S300510007I</string>
+</value>
+</member>
+</struct>
+</value>
+</param>
+</params>
+</methodResponse> ';
+        $r = $s->parseResponse($f);
+        $v = $r->value();
+        $s = $v->structmem('sessionID');
+        $this->assertEquals('S300510007I', $s->scalarval());
+    }
+
+    function testWhiteSpace()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
+
+
+and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->value();
+        $s = $v->structmem('content');
+        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s->scalarval());
+    }
+
+    function testDoubleDataInArrayTag()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
+<data></data>
+<data></data>
+</array></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->faultCode();
+        $this->assertEquals(2, $v);
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value><array>
+<data><value>Hello world</value></data>
+<data></data>
+</array></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->faultCode();
+        $this->assertEquals(2, $v);
+    }
+
+    function testDoubleStuffInValueTag()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value>
+<string>hello world</string>
+<array><data></data></array>
+</value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->faultCode();
+        $this->assertEquals(2, $v);
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value>
+<string>hello</string>
+<string>world</string>
+</value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->faultCode();
+        $this->assertEquals(2, $v);
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value>
+<string>hello</string>
+<struct><member><name>hello><value>world</value></member></struct>
+</value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f);
+        $v = $r->faultCode();
+        $this->assertEquals(2, $v);
+    }
+
+    function testAutodecodeResponse()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
+
+
+and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f, true, 'phpvals');
+        $v = $r->value();
+        $s = $v['content'];
+        $this->assertEquals("hello world. 2 newlines follow\n\n\nand there they were.", $s);
+    }
+
+    function testNoDecodeResponse()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = '<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>hello world. 2 newlines follow
+
+
+and there they were.</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>';
+        $r = $s->parseResponse($f, true, 'xml');
+        $v = $r->value();
+        $this->assertEquals($f, $v);
+    }
+
+    function testAutoCoDec()
+    {
+        $data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
+        $data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
+        $data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
+        //$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
+        $v1 = php_xmlrpc_encode($data, array('auto_dates'));
+        $v2 = php_xmlrpc_decode_xml($v1->serialize());
+        $this->assertEquals($v1, $v2);
+        $r1 = new PhpXmlRpc\Response($v1);
+        $r2 = php_xmlrpc_decode_xml($r1->serialize());
+        $r2->serialize(); // needed to set internal member payload
+        $this->assertEquals($r1, $r2);
+        $m1 = new PhpXmlRpc\Request('hello dolly', array($v1));
+        $m2 = php_xmlrpc_decode_xml($m1->serialize());
+        $m2->serialize(); // needed to set internal member payload
+        $this->assertEquals($m1, $m2);
+    }
+
+    function testUTF8Request()
+    {
+        $sendstring='κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
+        $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';
+        \PhpXmlRpc\PhpXmlRpc::importGlobals();
+        $f = new xmlrpcval($sendstring, 'string');
+        $v = $f->serialize();
+        $this->assertEquals("<value><string>&#954;&#8057;&#963;&#956;&#949;</string></value>\n", $v);
+        $GLOBALS['xmlrpc_internalencoding'] = 'ISO-8859-1';
+        \PhpXmlRpc\PhpXmlRpc::importGlobals();
+    }
+
+    function testUTF8Response()
+    {
+        $s = new xmlrpcmsg('dummy');
+        $f = "HTTP/1.1 200 OK\r\nContent-type: text/xml; charset=UTF-8\r\n\r\n".'<?xml version="1.0"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('àüèàüè').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f, false, 'phpvals');
+        $v = $r->value();
+        $v = $v['content'];
+        $this->assertEquals("àüèàüè", $v);
+        $f = '<?xml version="1.0" encoding="utf-8"?><methodResponse><params><param><value><struct><member><name>userid</name><value>311127</value></member>
+<member><name>dateCreated</name><value><dateTime.iso8601>20011126T09:17:52</dateTime.iso8601></value></member><member><name>content</name><value>'.utf8_encode('àüèàüè').'</value></member><member><name>postid</name><value>7414222</value></member></struct></value></param></params></methodResponse>
+';
+        $r = $s->parseResponse($f, false, 'phpvals');
+        $v = $r->value();
+        $v = $v['content'];
+        $this->assertEquals("àüèàüè", $v);
+    }
+
+    function testUTF8IntString()
+    {
+        $v = new xmlrpcval(100, 'int');
+        $s = $v->serialize('UTF-8');
+        $this->assertequals("<value><int>100</int></value>\n", $s);
+    }
+
+    function testStringInt()
+    {
+        $v = new xmlrpcval('hello world', 'int');
+        $s = $v->serialize();
+        $this->assertequals("<value><int>0</int></value>\n", $s);
+    }
+
+    function testStructMemExists()
+    {
+        $v = php_xmlrpc_encode(array('hello' => 'world'));
+        $b = $v->structmemexists('hello');
+        $this->assertequals(true, $b);
+        $b = $v->structmemexists('world');
+        $this->assertequals(false, $b);
+    }
+
+    function testNilvalue()
+    {
+        // default case: we do not accept nil values received
+        $v = new xmlrpcval('hello', 'null');
+        $r = new xmlrpcresp($v);
+        $s = $r->serialize();
+        $m = new xmlrpcmsg('dummy');
+        $r = $m->parseresponse($s);
+        $this->assertequals(2, $r->faultCode());
+        // enable reception of nil values
+        $GLOBALS['xmlrpc_null_extension'] = true;
+        \PhpXmlRpc\PhpXmlRpc::importGlobals();
+        $r = $m->parseresponse($s);
+        $v = $r->value();
+        $this->assertequals('null', $v->scalartyp());
+        // test with the apache version: EX:NIL
+        $GLOBALS['xmlrpc_null_apache_encoding'] = true;
+        \PhpXmlRpc\PhpXmlRpc::importGlobals();
+        // serialization
+        $v = new xmlrpcval('hello', 'null');
+        $s = $v->serialize();
+        $this->assertequals(1, preg_match( '#<value><ex:nil/></value>#', $s ));
+        // deserialization
+        $r = new xmlrpcresp($v);
+        $s = $r->serialize();
+        $r = $m->parseresponse($s);
+        $v = $r->value();
+        $this->assertequals('null', $v->scalartyp());
+        $GLOBALS['xmlrpc_null_extension'] = false;
+        \PhpXmlRpc\PhpXmlRpc::importGlobals();
+        $r = $m->parseresponse($s);
+        $this->assertequals(2, $r->faultCode());
+    }
+
+    function TestLocale()
+    {
+        $locale = setlocale(LC_NUMERIC, 0);
+        /// @todo on php 5.3/win setting locale to german does not seem to set decimal separator to comma...
+        if (setlocale(LC_NUMERIC,'deu', 'de_DE@euro', 'de_DE', 'de', 'ge') !== false)
+        {
+            $v = new xmlrpcval(1.1, 'double');
+            if (strpos($v->scalarval(), ',') == 1)
+            {
+                $r = $v->serialize();
+                $this->assertequals(false, strpos($r, ','));
+                setlocale(LC_NUMERIC, $locale);
+            }
+            else
+            {
+                setlocale(LC_NUMERIC, $locale);
+                $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
+            }
+        }
+        else
+        {
+            $this->markTestSkipped('did not find a locale which sets decimal separator to comma');
+        }
+    }
+}
diff --git a/tests/benchmark.php b/tests/benchmark.php
new file mode 100644 (file)
index 0000000..a762e5f
--- /dev/null
@@ -0,0 +1,307 @@
+<?php
+/**
+ * Benchamrking suite for the PHP-XMLRPC lib
+ * @author Gaetano Giunta
+ * @copyright (c) 2005-2014 G. Giunta
+ * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt
+ *
+ * @todo add a test for response ok in call testing?
+ **/
+
+include_once(__DIR__.'/../vendor/autoload.php');
+
+include_once(__DIR__.'/../lib/xmlrpc.inc');
+
+include(__DIR__.'/parse_args.php');
+$args = argParser::getArgs();
+
+function begin_test($test_name, $test_case)
+{
+    global $test_results;
+    if (!isset($test_results[$test_name]))
+        $test_results[$test_name]=array();
+    $test_results[$test_name][$test_case] = array();
+    $test_results[$test_name][$test_case]['time'] = microtime(true);
+}
+
+function end_test($test_name, $test_case, $test_result)
+{
+    global $test_results;
+    $end = microtime(true);
+    if (!isset($test_results[$test_name][$test_case]))
+        trigger_error('ending test that was not sterted');
+    $test_results[$test_name][$test_case]['time'] = $end - $test_results[$test_name][$test_case]['time'];
+    $test_results[$test_name][$test_case]['result'] = $test_result;
+    echo '.';
+    flush();
+    @ob_flush();
+}
+
+// Set up PHP structures to be used in many tests
+
+$data1 = array(1, 1.0, 'hello world', true, '20051021T23:43:00', -1, 11.0, '~!@#$%^&*()_+|', false, '20051021T23:43:00');
+$data2 = array('zero' => $data1, 'one' => $data1, 'two' => $data1, 'three' => $data1, 'four' => $data1, 'five' => $data1, 'six' => $data1, 'seven' => $data1, 'eight' => $data1, 'nine' => $data1);
+$data = array($data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2, $data2);
+$keys = array('zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
+
+// Begin execution
+
+$test_results=array();
+$is_web = isset($_SERVER['REQUEST_METHOD']);
+$xd = extension_loaded('xdebug') && ini_get('xdebug.profiler_enable');
+if ($xd)
+    $num_tests = 1;
+else
+    $num_tests = 10;
+
+$title = 'XML-RPC Benchmark Tests';
+
+if($is_web)
+{
+    echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n<head>\n<title>$title</title>\n</head>\n<body>\n<h1>$title</h1>\n<pre>\n";
+}
+else
+{
+    echo "$title\n\n";
+}
+
+if($is_web)
+{
+    echo "<h3>Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."</h3>\n";
+    if ($xd) echo "<h4>XDEBUG profiling enabled: skipping remote tests. Trace file is: ".htmlspecialchars(xdebug_get_profiler_filename())."</h4>\n";
+    flush();
+    ob_flush();
+}
+else
+{
+    echo "Using lib version: $xmlrpcVersion on PHP version: ".phpversion()."\n";
+    if ($xd) echo "XDEBUG profiling enabled: skipping remote tests\nTrace file is: ".xdebug_get_profiler_filename()."\n";
+}
+
+// test 'old style' data encoding vs. 'automatic style' encoding
+begin_test('Data encoding (large array)', 'manual encoding');
+for ($i = 0; $i < $num_tests; $i++)
+{
+    $vals = array();
+    for ($j = 0; $j < 10; $j++)
+    {
+        $valarray = array();
+        foreach ($data[$j] as $key => $val)
+        {
+            $values = array();
+            $values[] = new xmlrpcval($val[0], 'int');
+            $values[] = new xmlrpcval($val[1], 'double');
+            $values[] = new xmlrpcval($val[2], 'string');
+            $values[] = new xmlrpcval($val[3], 'boolean');
+            $values[] = new xmlrpcval($val[4], 'dateTime.iso8601');
+            $values[] = new xmlrpcval($val[5], 'int');
+            $values[] = new xmlrpcval($val[6], 'double');
+            $values[] = new xmlrpcval($val[7], 'string');
+            $values[] = new xmlrpcval($val[8], 'boolean');
+            $values[] = new xmlrpcval($val[9], 'dateTime.iso8601');
+            $valarray[$key] = new xmlrpcval($values, 'array');
+        }
+        $vals[] = new xmlrpcval($valarray, 'struct');
+    }
+    $value = new xmlrpcval($vals, 'array');
+    $out = $value->serialize();
+}
+end_test('Data encoding (large array)', 'manual encoding', $out);
+
+begin_test('Data encoding (large array)', 'automatic encoding');
+for ($i = 0; $i < $num_tests; $i++)
+{
+    $value = php_xmlrpc_encode($data, array('auto_dates'));
+    $out = $value->serialize();
+}
+end_test('Data encoding (large array)', 'automatic encoding', $out);
+
+if (function_exists('xmlrpc_set_type'))
+{
+    begin_test('Data encoding (large array)', 'xmlrpc-epi encoding');
+    for ($i = 0; $i < $num_tests; $i++)
+    {
+        for ($j = 0; $j < 10; $j++)
+            foreach ($keys as $k)
+            {
+                xmlrpc_set_type($data[$j][$k][4], 'datetime');
+                xmlrpc_set_type($data[$j][$k][8], 'datetime');
+            }
+        $out = xmlrpc_encode($data);
+    }
+    end_test('Data encoding (large array)', 'xmlrpc-epi encoding', $out);
+}
+
+// test 'old style' data decoding vs. 'automatic style' decoding
+$dummy = new xmlrpcmsg('');
+$out = new xmlrpcresp($value);
+$in = '<?xml version="1.0" ?>'."\n".$out->serialize();
+
+begin_test('Data decoding (large array)', 'manual decoding');
+for ($i = 0; $i < $num_tests; $i++)
+{
+    $response = $dummy->ParseResponse($in, true);
+    $value = $response->value();
+    $result = array();
+    for ($k = 0; $k < $value->arraysize(); $k++)
+    {
+        $val1 = $value->arraymem($k);
+        $out = array();
+        while (list($name, $val) = $val1->structeach())
+        {
+            $out[$name] = array();
+            for ($j = 0; $j < $val->arraysize(); $j++)
+            {
+                $data = $val->arraymem($j);
+                $out[$name][] = $data->scalarval();
+            }
+        } // while
+        $result[] = $out;
+    }
+}
+end_test('Data decoding (large array)', 'manual decoding', $result);
+
+begin_test('Data decoding (large array)', 'automatic decoding');
+for ($i = 0; $i < $num_tests; $i++)
+{
+    $response = $dummy->ParseResponse($in, true, 'phpvals');
+    $value = $response->value();
+}
+end_test('Data decoding (large array)', 'automatic decoding', $value);
+
+if (function_exists('xmlrpc_decode'))
+{
+    begin_test('Data decoding (large array)', 'xmlrpc-epi decoding');
+    for ($i = 0; $i < $num_tests; $i++)
+    {
+        $response = $dummy->ParseResponse($in, true, 'xml');
+        $value = xmlrpc_decode($response->value());
+    }
+    end_test('Data decoding (large array)', 'xmlrpc-epi decoding', $value);
+}
+
+if (!$xd)
+{
+
+    /// test multicall vs. many calls vs. keep-alives
+    $value = php_xmlrpc_encode($data1, array('auto_dates'));
+    $msg = new xmlrpcmsg('interopEchoTests.echoValue', array($value));
+    $msgs=array();
+    for ($i = 0; $i < 25; $i++)
+        $msgs[] = $msg;
+    $server = explode(':', $args['LOCALSERVER']);
+    if(count($server) > 1)
+    {
+        $c = new xmlrpc_client($args['URI'], $server[0], $server[1]);
+    }
+    else
+    {
+        $c = new xmlrpc_client($args['URI'], $args['LOCALSERVER']);
+    }
+    // do not interfere with http compression
+    $c->accepted_compression = array();
+    //$c->debug=true;
+
+    if (function_exists('gzinflate')) {
+        $c->accepted_compression = null;
+    }
+    begin_test('Repeated send (small array)', 'http 10');
+    $response = array();
+    for ($i = 0; $i < 25; $i++)
+    {
+        $resp = $c->send($msg);
+        $response[] = $resp->value();
+    }
+    end_test('Repeated send (small array)', 'http 10', $response);
+
+    if (function_exists('curl_init'))
+    {
+        begin_test('Repeated send (small array)', 'http 11 w. keep-alive');
+        $response = array();
+        for ($i = 0; $i < 25; $i++)
+        {
+            $resp = $c->send($msg, 10, 'http11');
+            $response[] = $resp->value();
+        }
+        end_test('Repeated send (small array)', 'http 11 w. keep-alive', $response);
+
+        $c->keepalive = false;
+        begin_test('Repeated send (small array)', 'http 11');
+        $response = array();
+        for ($i = 0; $i < 25; $i++)
+        {
+            $resp = $c->send($msg, 10, 'http11');
+            $response[] = $resp->value();
+        }
+        end_test('Repeated send (small array)', 'http 11', $response);
+    }
+
+    begin_test('Repeated send (small array)', 'multicall');
+    $response = $c->send($msgs);
+    foreach ($response as $key =>& $val)
+    {
+        $val = $val->value();
+    }
+    end_test('Repeated send (small array)', 'multicall', $response);
+
+    if (function_exists('gzinflate'))
+    {
+        $c->accepted_compression = array('gzip');
+        $c->request_compression = 'gzip';
+
+        begin_test('Repeated send (small array)', 'http 10 w. compression');
+        $response = array();
+        for ($i = 0; $i < 25; $i++)
+        {
+            $resp = $c->send($msg);
+            $response[] = $resp->value();
+        }
+        end_test('Repeated send (small array)', 'http 10 w. compression', $response);
+
+        if (function_exists('curl_init'))
+        {
+            begin_test('Repeated send (small array)', 'http 11 w. keep-alive and compression');
+            $response = array();
+            for ($i = 0; $i < 25; $i++)
+            {
+                $resp = $c->send($msg, 10, 'http11');
+                $response[] = $resp->value();
+            }
+            end_test('Repeated send (small array)', 'http 11 w. keep-alive and compression', $response);
+
+            $c->keepalive = false;
+            begin_test('Repeated send (small array)', 'http 11 w. compression');
+            $response = array();
+            for ($i = 0; $i < 25; $i++)
+            {
+                $resp = $c->send($msg, 10, 'http11');
+                $response[] = $resp->value();
+            }
+            end_test('Repeated send (small array)', 'http 11 w. compression', $response);
+        }
+
+        begin_test('Repeated send (small array)', 'multicall w. compression');
+        $response = $c->send($msgs);
+        foreach ($response as $key =>& $val)
+        {
+            $val = $val->value();
+        }
+        end_test('Repeated send (small array)', 'multicall w. compression', $response);
+    }
+
+} // end of 'if no xdebug profiling'
+
+
+echo "\n";
+foreach($test_results as $test => $results)
+{
+    echo "\nTEST: $test\n";
+    foreach ($results as $case => $data)
+        echo "  $case: {$data['time']} secs - Output data CRC: ".crc32(serialize($data['result']))."\n";
+}
+
+
+if($is_web)
+{
+    echo "\n</pre>\n</body>\n</html>\n";
+}
diff --git a/tests/parse_args.php b/tests/parse_args.php
new file mode 100644 (file)
index 0000000..18b6bc3
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Common parameter parsing for benchmarks and tests scripts
+ *
+ * @param integer DEBUG
+ * @param string  LOCALSERVER
+ * @param string  URI
+ * @param string  HTTPSSERVER
+ * @param string  HTTPSSURI
+ * @param string  PROXY
+ * @param string  NOPROXY
+ *
+ * @copyright (C) 2007-20014 G. Giunta
+ * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt
+ **/
+
+class argParser
+{
+    static public function getArgs()
+    {
+        global $argv;
+
+        $args = array(
+            'DEBUG' => 0,
+            'LOCALSERVER' => 'localhost',
+            'HTTPSSERVER' => 'gggeek.ssl.altervista.org',
+            'HTTPSURI' => '/sw/xmlrpc/demo/server/server.php',
+            'HTTPSIGNOREPEER' => false,
+            'PROXYSERVER' => null,
+            'NOPROXY' => false,
+            'LOCALPATH' => __DIR__
+        );
+
+        // check for command line vs web page input params
+        if(!isset($_SERVER['REQUEST_METHOD']))
+        {
+            if(isset($argv))
+            {
+                foreach($argv as $param)
+                {
+                    $param = explode('=', $param);
+                    if(count($param) > 1)
+                    {
+                        $pname = strtoupper(ltrim($param[0], '-'));
+                        $$pname=$param[1];
+                    }
+                }
+            }
+        }
+        else
+        {
+            // NB: we might as well consider using $_GET stuff later on...
+            extract($_GET);
+            extract($_POST);
+        }
+
+        if(isset($DEBUG))
+        {
+            $args['DEBUG'] = intval($DEBUG);
+        }
+        if(isset($LOCALSERVER))
+        {
+            $args['LOCALSERVER'] = $LOCALSERVER;
+        }
+        else
+        {
+            if(isset($HTTP_HOST))
+            {
+                $args['LOCALSERVER'] = $HTTP_HOST;
+            }
+            elseif(isset($_SERVER['HTTP_HOST']))
+            {
+                $args['LOCALSERVER'] = $_SERVER['HTTP_HOST'];
+            }
+        }
+        if(isset($HTTPSSERVER))
+        {
+            $args['HTTPSSERVER'] = $HTTPSSERVER;
+        }
+        if(isset($HTTPSURI))
+        {
+            $args['HTTPSURI'] = $HTTPSURI;
+        }
+        if(isset($HTTPSIGNOREPEER))
+        {
+            $args['HTTPSIGNOREPEER'] = bool($HTTPSIGNOREPEER);
+        }
+        if(isset($PROXY))
+        {
+            $arr = explode(':', $PROXY);
+            $args['PROXYSERVER'] = $arr[0];
+            if(count($arr) > 1)
+            {
+                $args['PROXYPORT'] = $arr[1];
+            }
+            else
+            {
+                $args['PROXYPORT'] = 8080;
+            }
+        }
+        // used to silence testsuite warnings about proxy code not being tested
+        if(isset($NOPROXY))
+        {
+            $args['NOPROXY'] = true;
+        }
+        if(!isset($URI))
+        {
+            // GUESTIMATE the url of local demo server
+            // play nice to php 3 and 4-5 in retrieving URL of server.php
+            /// @todo filter out query string from REQUEST_URI
+            if(isset($REQUEST_URI))
+            {
+                $URI = str_replace('/tests/testsuite.php', '/demo/server/server.php', $REQUEST_URI);
+                $URI = str_replace('/testsuite.php', '/server.php', $URI);
+                $URI = str_replace('/tests/benchmark.php', '/demo/server/server.php', $URI);
+                $URI = str_replace('/benchmark.php', '/server.php', $URI);
+            }
+            elseif(isset($_SERVER['PHP_SELF']) && isset($_SERVER['REQUEST_METHOD']))
+            {
+                $URI = str_replace('/tests/testsuite.php', '/demo/server/server.php', $_SERVER['PHP_SELF']);
+                $URI = str_replace('/testsuite.php', '/server.php', $URI);
+                $URI = str_replace('/tests/benchmark.php', '/demo/server/server.php', $URI);
+                $URI = str_replace('/benchmark.php', '/server.php', $URI);
+            }
+            else
+            {
+                $URI = '/demo/server/server.php';
+            }
+        }
+        if($URI[0] != '/')
+        {
+            $URI = '/'.$URI;
+        }
+        $args['URI'] = $URI;
+        if(isset($LOCALPATH))
+        {
+            $args['LOCALPATH'] =$LOCALPATH;
+        }
+
+        return $args;
+    }
+
+}
\ No newline at end of file