/** * <MethodDescription> * * @param type <description> * * @return type <description> */ function dispatch($msg = NULL) { # ensure correct invocation if (is_null($msg) || !is_a($msg, 'jsonrpcmsg')) { return $this->throw_exception('functions_parameters_type must not be ' . 'phpvals.'); } # get decoded parameters $len = $msg->getNumParams(); $argument_array = array(); for ($i = 0; $i < $len; ++$i) { $argument_array[] = php_jsonrpc_decode($msg->getParam($i)); } # return result return new jsonrpcresp(php_jsonrpc_encode($this->invoke($msg->method(), $argument_array))); }
function encode($object) { if (function_exists('json_encode') && JSON_LIB_ENCODE == 'native') { return json_encode($object); } else { if (JSON_LIB_ENCODE == 'services_JSON') { require_once dirname(__FILE__) . '/json.php'; $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); return $json->encode($object); } else { if (JSON_LIB_ENCODE == 'jsonrpc') { require_once dirname(__FILE__) . '/jsonrpc/xmlrpc.php'; require_once dirname(__FILE__) . '/jsonrpc/jsonrpc.php'; $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8'; $GLOBALS['xmlrpc_internalencoding'] = 'iso-8859-7'; return php_jsonrpc_encode($value, array()); } } } }
end_test('Data decoding (large array)', 'Zend decoding', $value); } if (function_exists('json_decode')) { begin_test('Data decoding (large array)', 'native decoding'); for ($i = 0; $i < $num_tests; $i++) { // to be fair to phpxmlrpc, we add http checks to every lib $response = $dummy->ParseResponse($in, true, 'json'); $value = json_decode($response->value(), true); // we do NO error checking here: bound to be faster... $value = $value['result']; } end_test('Data decoding (large array)', 'native decoding', $value); } if ($test_http && !$xd) { /// test many calls vs. keep-alives $value = php_jsonrpc_encode($data1); $msg =& new jsonrpcmsg('interopEchoTests.echoValue', array($value)); $msgs = array(); for ($i = 0; $i < 25; $i++) { $msgs[] = $msg; } $server = split(':', $LOCALSERVER); if (count($server) > 1) { $c =& new jsonrpc_client($URI, $server[0], $server[1]); } else { $c =& new jsonrpc_client($URI, $LOCALSERVER); } // do not interfere with http compression $c->accepted_compression = array(); //$c->debug=true; if (function_exists('gzinflate')) {
/** * Note: syntax differs from overridden method, by adding an ID param * @access private */ function execute($m, $params = null, $paramtypes = null, $msgID = null) { if (is_object($m)) { // watch out: if $m is an xmlrpcmsg obj, this will raise a warning: no id memeber... $methName = $m->method(); $msgID = $m->id; } else { $methName = $m; } $sysCall = $this->allow_system_funcs && ereg("^system\\.", $methName); $dmap = $sysCall ? $GLOBALS['_xmlrpcs_dmap'] : $this->dmap; if (!isset($dmap[$methName]['function'])) { // No such method return new jsonrpcresp(0, $GLOBALS['xmlrpcerr']['unknown_method'], $GLOBALS['xmlrpcstr']['unknown_method']); } // Check signature if (isset($dmap[$methName]['signature'])) { $sig = $dmap[$methName]['signature']; if (is_object($m)) { list($ok, $errstr) = $this->verifySignature($m, $sig); } else { list($ok, $errstr) = $this->verifySignature($paramtypes, $sig); } if (!$ok) { // Didn't match. return new jsonrpcresp(0, $GLOBALS['xmlrpcerr']['incorrect_params'], $GLOBALS['xmlrpcstr']['incorrect_params'] . ": {$errstr}"); } } $func = $dmap[$methName]['function']; // let the 'class::function' syntax be accepted in dispatch maps if (is_string($func) && strpos($func, '::')) { $func = explode('::', $func); } // verify that function to be invoked is in fact callable if (!is_callable($func)) { error_log("XML-RPC: jsonrpc_server::execute: function {$func} registered as method handler is not callable"); return new jsonrpcresp(0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error'] . ": no function matches method"); } // If debug level is 3, we should catch all errors generated during // processing of user function, and log them as part of response if ($this->debug > 2) { $GLOBALS['_xmlrpcs_prev_ehandler'] = set_error_handler('_xmlrpcs_errorHandler'); } if (is_object($m)) { if ($sysCall) { $r = call_user_func($func, $this, $m); } else { $r = call_user_func($func, $m); } if (!is_a($r, 'xmlrpcresp')) { error_log("XML-RPC: jsonrpc_server::execute: function {$func} registered as method handler does not return an xmlrpcresp object"); if (is_a($r, 'xmlrpcval')) { $r = new jsonrpcresp($r); } else { $r = new jsonrpcresp(0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error'] . ": function does not return jsonrpcresp or xmlrpcresp object"); } } } else { // call a 'plain php' function if ($sysCall) { array_unshift($params, $this); $r = call_user_func_array($func, $params); } else { // 3rd API convention for method-handling functions: EPI-style if ($this->functions_parameters_type == 'epivals') { $r = call_user_func_array($func, array($methName, $params, $this->user_data)); // mimic EPI behaviour: if we get an array that looks like an error, make it // an eror response if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) { $r =& new jsonrpcresp(0, (int) $r['faultCode'], (string) $r['faultString']); } else { // functions using EPI api should NOT return resp objects, // so make sure we encode the return type correctly $r =& new jsonrpcresp(php_xmlrpc_encode($r, array('extension_api'))); } } else { $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')) { // what should we assume here about automatic encoding of datetimes // and php classes instances??? $r = new jsonrpcresp(php_jsonrpc_encode($r)); } } // here $r is either an xmlrpcresp or jsonrpcresp if (!is_a($r, 'jsonrpcresp')) { // dirty trick: user has given us back an xmlrpc response, // since he had an existing xmlrpc server with boatloads of code. // Be nice to him, and serialize the xmlrpc stuff into JSON. // We also override the content_type of the xmlrpc response, // but lack knoweledge of intented response charset... $r->content_type = 'text/plain'; $r->payload = serialize_jsonrpcresp($r, $msgID); } else { $r->id = $msgID; } if ($this->debug > 2) { // note: restore the error handler we found before calling the // user func, even if it has been changed inside the func itself if ($GLOBALS['_xmlrpcs_prev_ehandler']) { set_error_handler($GLOBALS['_xmlrpcs_prev_ehandler']); } else { restore_error_handler(); } } return $r; }
/** * Takes a php value (array or object) and returns its json representation * @param mixed $value * @return string * * @bug if value is an ISO-8859-1 string with cahrs outside of ASCII, the php extension returns NULL, and we do not... */ function json_encode($value) { $jsval = php_jsonrpc_encode($value, array()); // make sure we emulate the std php behaviour: strings to be encoded are UTF-8!!! return $jsval->serialize(); }
/** * Takes native php types and encodes them into jsonrpc PHP object format. * It will not re-encode jsonrpcval objects. * * @param mixed $php_val the value to be converted into a jsonrpcval object * @param array $options can include 'encode_php_objs' * @return jsonrpcval * @access public */ function &php_jsonrpc_encode($php_val, $options = '') { $type = gettype($php_val); switch ($type) { case 'string': $jsonrpc_val =& new jsonrpcval($php_val, $GLOBALS['xmlrpcString']); break; case 'integer': $jsonrpc_val =& new jsonrpcval($php_val, $GLOBALS['xmlrpcInt']); break; case 'double': $jsonrpc_val =& new jsonrpcval($php_val, $GLOBALS['xmlrpcDouble']); break; case 'boolean': $jsonrpc_val =& new jsonrpcval($php_val, $GLOBALS['xmlrpcBoolean']); break; case 'resource': // for compat with php json extension... // for compat with php json extension... case 'NULL': $jsonrpc_val =& new jsonrpcval($php_val, $GLOBALS['xmlrpcNull']); break; case 'array': // PHP arrays can be encoded to either objects or arrays, // depending on wheter they are hashes or plain 0..n integer indexed // A shorter one-liner would be // $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); // but execution time skyrockets! $j = 0; $arr = array(); $ko = false; foreach ($php_val as $key => $val) { $arr[$key] =& php_jsonrpc_encode($val, $options); if (!$ko && $key !== $j) { $ko = true; } $j++; } if ($ko) { $jsonrpc_val =& new jsonrpcval($arr, $GLOBALS['xmlrpcStruct']); } else { $jsonrpc_val =& new jsonrpcval($arr, $GLOBALS['xmlrpcArray']); } break; case 'object': if (is_a($php_val, 'jsonrpcval')) { $jsonrpc_val = $php_val; } else { $arr = array(); while (list($k, $v) = each($php_val)) { $arr[$k] = php_jsonrpc_encode($v, $options); } $jsonrpc_val =& new jsonrpcval($arr, $GLOBALS['xmlrpcStruct']); if (in_array('encode_php_objs', $options)) { // let's save original class name into xmlrpcval: // might be useful later on... $jsonrpc_val->_php_class = get_class($php_val); } } break; // catch "user function", "unknown type" // catch "user function", "unknown type" default: $jsonrpc_val =& new jsonrpcval(); break; } return $jsonrpc_val; }