"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...",
/// 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';
* @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='')
{
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;
}
$msg = $n;
}
- // where msg is an xmlrpcmsg
+ // where msg is a Request
$msg->debug=$this->debug;
if($method == 'https')
* 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
}
else
{
- if (is_a($results, 'xmlrpcresp'))
+ if (is_a($results, '\PhpXmlRpc\Response'))
{
$result = $results;
}
use PhpXmlRpc\Helper\Http;
use PhpXmlRpc\Helper\XMLParser;
-use PhpXmlRpc\Helper\Encoder;
class Request
{
*
* @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='')
{
/**
* 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()
{
* 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()
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
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
{
/**
* 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)
{
* 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='')
{
/**
* 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)
{
// 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
{
{
$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);
$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"
);
}
}
$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???
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);
+ }
+ }
+ }
+ }
+
}
* 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
/**
* 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:
* 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)
* 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...
*/
* 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)
*/
+++ /dev/null
-<?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";
- }
+++ /dev/null
-<?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__;
- }
+++ /dev/null
-<?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 -->
-<!-- ���àüè -->
-<methodResponse>
-<fault>
-<value>
-<struct>
-<member>
-<name>faultCode</name>
-<value><int>888</int></value>
-</member>
-<member>
-<name>faultString</name>
-<value><string>���àüè</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>κόσμε</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'].'&DEBUG=1' : $_SERVER['PHP_SELF'].'?DEBUG=1';
- $t2 = strpos($_SERVER['PHP_SELF'], '?') ? $_SERVER['PHP_SELF'].'&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: <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());
-}
--- /dev/null
+<?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());
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+<?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).'àüè -->
+<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).'àüè</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>κόσμε</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');
+ }
+ }
+}
--- /dev/null
+<?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";
+}
--- /dev/null
+<?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