Server : Apache System : Linux indy02.toastserver.com 3.10.0-962.3.2.lve1.5.85.el7.x86_64 #1 SMP Thu Apr 18 15:18:36 UTC 2024 x86_64 User : palandch ( 1163) PHP Version : 7.1.33 Disable Function : NONE Directory : /home/palandch/www/core/model/modx/jsonrpc/ |
<?php /** * @package modx * @subpackage jsonrpc */ /** * JSON extension to the PHP-XMLRPC lib: server components * * For more info see: * http://www.json.org/ * http://json-rpc.org/ * * @author Gaetano Giunta * @version $Id: jsonrpcs.inc,v 1.10 2007/02/15 21:48:38 ggiunta Exp $ * @copyright (c) 2005 G. Giunta * * @todo implement dispatching of multicall requests, json way * @todo test system.XXX methods, with special care to multicall * @todo support for 'ping' calls, i.e. if id is null, echo back nothing **/ // JSON RPC Server class // requires: jsonrpc.inc, xmlrpcs.inc, xmlrpc.inc // add to list of supported capaibilities the jsonrpc spec $GLOBALS['xmlrpcs_capabilities']['json-rpc'] = new xmlrpcval(array( 'specUrl' => new xmlrpcval('http://json-rpc.org/wiki/specification', 'string'), 'specVersion' => new xmlrpcval(1, 'int') ), 'struct'); // NB: if building jsonrpc-only webservers, you should at least undeclare the xmlrpc capability: // unset($GLOBALS['xmlrpcs_capabilities']['xmlrpc']); class jsonrpc_server extends xmlrpc_server { //var $allow_system_funcs = false; var $functions_parameters_type='jsonrpcvals'; function serializeDebug($charset_encoding='') { $out = ''; if ($this->debug_info != '') { $out .= "/* SERVER DEBUG INFO (BASE64 ENCODED):\n".base64_encode($this->debug_info)."\n*/\n"; } if ($GLOBALS['_xmlrpc_debuginfo'] != '') { $out .= "/* DEBUG INFO:\n\n" . json_encode_entitites($GLOBALS['_xmlrpc_debuginfo'], null, $charset_encoding) . "\n*/\n"; } return $out; } /** * 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 (!($r instanceof xmlrpcresp)) { error_log("XML-RPC: jsonrpc_server::execute: function $func registered as method handler does not return an xmlrpcresp object"); if ($r instanceof 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, (integer)$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 (!($r instanceof 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 (!($r instanceof 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 = 'application/json'; $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; } /** * @access private */ function parseRequest($data, $content_encoding='') { $GLOBALS['_xh']=array(); if (!jsonrpc_parse_req($data, $this->functions_parameters_type == 'phpvals' || $this->functions_parameters_type == 'epivals', false, $content_encoding)) { $r = new jsonrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_request'], $GLOBALS['xmlrpcstr']['invalid_request'] . ' ' . $GLOBALS['_xh']['isf_reason']); } else { if ($this->functions_parameters_type == 'phpvals' || $this->functions_parameters_type == 'epivals') { if($this->debug > 1) { $this->debugmsg("\n+++PARSED+++\n".var_export($GLOBALS['_xh']['params'], true)."\n+++END+++"); } $r = $this->execute($GLOBALS['_xh']['method'], $GLOBALS['_xh']['params'], $GLOBALS['_xh']['pt'], $GLOBALS['_xh']['id']); } else { // build an xmlrpcmsg object with data parsed from xml $m = new jsonrpcmsg($GLOBALS['_xh']['method'], 0, $GLOBALS['_xh']['id']); // now add parameters in /// @todo for more speeed, we could just substitute the array... for($i = 0; $i < sizeof($GLOBALS['_xh']['params']); $i++) { $m->addParam($GLOBALS['_xh']['params'][$i]); } if($this->debug > 1) { $this->debugmsg("\n+++PARSED+++\n".var_export($m, true)."\n+++END+++"); } $r = $this->execute($m); } } return $r; } /** * No xml header generated by the server, since we are sending json * @access private */ function xml_header($charset_encoding='') { return ''; } } ?>