📄 xmlrpcs.inc
字号:
// check if request body has been compressed and decompress it
if($content_encoding != '' && strlen($data))
{
if($content_encoding == 'deflate' || $content_encoding == 'gzip')
{
// if decoding works, use it. else assume data wasn't gzencoded
if(function_exists('gzinflate') && in_array($content_encoding, $this->accepted_compression))
{
if($content_encoding == 'deflate' && $degzdata = @gzuncompress($data))
{
$data = $degzdata;
if($this->debug > 1)
{
$this->debugmsg("\n+++INFLATED REQUEST+++[".strlen($data)." chars]+++\n" . $data . "\n+++END+++");
}
}
elseif($content_encoding == 'gzip' && $degzdata = @gzinflate(substr($data, 10)))
{
$data = $degzdata;
if($this->debug > 1)
$this->debugmsg("+++INFLATED REQUEST+++[".strlen($data)." chars]+++\n" . $data . "\n+++END+++");
}
else
{
$r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_decompress_fail'], $GLOBALS['xmlrpcstr']['server_decompress_fail']);
return $r;
}
}
else
{
//error_log('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.');
$r =& new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_cannot_decompress'], $GLOBALS['xmlrpcstr']['server_cannot_decompress']);
return $r;
}
}
}
// check if client specified accepted charsets, and if we know how to fulfill
// the request
if ($this->response_charset_encoding == 'auto')
{
$resp_encoding = '';
if (isset($_SERVER['HTTP_ACCEPT_CHARSET']))
{
// here we should check if we can match the client-requested encoding
// with the encodings we know we can generate.
/// @todo we should parse q=0.x preferences instead of getting first charset specified...
$client_accepted_charsets = explode(',', strtoupper($_SERVER['HTTP_ACCEPT_CHARSET']));
// Give preference to internal encoding
$known_charsets = array($this->internal_encoding, 'UTF-8', 'ISO-8859-1', 'US-ASCII');
foreach ($known_charsets as $charset)
{
foreach ($client_accepted_charsets as $accepted)
if (strpos($accepted, $charset) === 0)
{
$resp_encoding = $charset;
break;
}
if ($resp_encoding)
break;
}
}
}
else
{
$resp_encoding = $this->response_charset_encoding;
}
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']))
{
$resp_compression = $_SERVER['HTTP_ACCEPT_ENCODING'];
}
else
{
$resp_compression = '';
}
// 'guestimate' request encoding
/// @todo check if mbstring is enabled and automagic input conversion is on: it might mingle with this check???
$req_encoding = guess_encoding(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '',
$data);
return null;
}
/**
* Parse an xml chunk containing an xmlrpc request and execute the corresponding
* 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
* @access private
*/
function parseRequest($data, $req_encoding='')
{
// 2005/05/07 commented and moved into caller function code
//if($data=='')
//{
// $data=$GLOBALS['HTTP_RAW_POST_DATA'];
//}
// G. Giunta 2005/02/13: we do NOT expect to receive html entities
// so we do not try to convert them into xml character entities
//$data = xmlrpc_html_entity_xlate($data);
$GLOBALS['_xh']=array();
$GLOBALS['_xh']['ac']='';
$GLOBALS['_xh']['stack']=array();
$GLOBALS['_xh']['valuestack'] = array();
$GLOBALS['_xh']['params']=array();
$GLOBALS['_xh']['pt']=array();
$GLOBALS['_xh']['isf']=0;
$GLOBALS['_xh']['isf_reason']='';
$GLOBALS['_xh']['method']=false; // so we can check later if we got a methodname or not
$GLOBALS['_xh']['rt']='';
// decompose incoming XML into request structure
if ($req_encoding != '')
{
if (!in_array($req_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
// the following code might be better for mb_string enabled installs, but
// makes the lib about 200% slower...
//if (!is_valid_charset($req_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
{
error_log('XML-RPC: xmlrpc_server::parseRequest: invalid charset encoding of received request: '.$req_encoding);
$req_encoding = $GLOBALS['xmlrpc_defencoding'];
}
/// @BUG this will fail on PHP 5 if charset is not specified in the xml prologue,
// the encoding is not UTF8 and there are non-ascii chars in the text...
$parser = xml_parser_create($req_encoding);
}
else
{
$parser = xml_parser_create();
}
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
// G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell
// the xml parser to give us back data in the expected charset
xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']);
if ($this->functions_parameters_type != 'xmlrpcvals')
xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast');
else
xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');
xml_set_character_data_handler($parser, 'xmlrpc_cd');
xml_set_default_handler($parser, 'xmlrpc_dh');
if(!xml_parse($parser, $data, 1))
{
// return XML error as a faultCode
$r=&new xmlrpcresp(0,
$GLOBALS['xmlrpcerrxml']+xml_get_error_code($parser),
sprintf('XML error: %s at line %d, column %d',
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser), xml_get_current_column_number($parser)));
xml_parser_free($parser);
}
elseif ($GLOBALS['_xh']['isf'])
{
xml_parser_free($parser);
$r=&new xmlrpcresp(0,
$GLOBALS['xmlrpcerr']['invalid_request'],
$GLOBALS['xmlrpcstr']['invalid_request'] . ' ' . $GLOBALS['_xh']['isf_reason']);
}
else
{
xml_parser_free($parser);
if ($this->functions_parameters_type != 'xmlrpcvals')
{
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']);
}
else
{
// build an xmlrpcmsg object with data parsed from xml
$m=&new xmlrpcmsg($GLOBALS['_xh']['method']);
// now add parameters in
for($i=0; $i<count($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;
}
/**
* Execute a method invoked by the client, checking parameters used
* @param mixed $m either an xmlrpcmsg 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
* @access private
*/
function execute($m, $params=null, $paramtypes=null)
{
if (is_object($m))
{
$methName = $m->method();
}
else
{
$methName = $m;
}
$sysCall = $this->allow_system_funcs && (strpos($methName, "system.") === 0);
$dmap = $sysCall ? $GLOBALS['_xmlrpcs_dmap'] : $this->dmap;
if(!isset($dmap[$methName]['function']))
{
// No such method
return new xmlrpcresp(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 xmlrpcresp(
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: xmlrpc_server::execute: function $func registered as method handler is not callable");
return new xmlrpcresp(
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: xmlrpc_server::execute: function $func registered as method handler does not return an xmlrpcresp object");
if (is_a($r, 'xmlrpcval'))
{
$r =& new xmlrpcresp($r);
}
else
{
$r =& new xmlrpcresp(
0,
$GLOBALS['xmlrpcerr']['server_error'],
$GLOBALS['xmlrpcstr']['server_error'] . ": function does not return 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 xmlrpcresp(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 xmlrpcresp(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 xmlrpcresp(php_xmlrpc_encode($r, array('auto_dates')));
}
}
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;
}
/**
* add a string to the 'internal debug message' (separate from 'user debug message')
* @param string $strings
* @access private
*/
function debugmsg($string)
{
$this->debug_info .= $string."\n";
}
/**
* @access private
*/
function xml_header($charset_encoding='')
{
if ($charset_encoding != '')
{
return "<?xml version=\"1.0\" encoding=\"$charset_encoding\"?" . ">\n";
}
else
{
return "<?xml version=\"1.0\"?" . ">\n";
}
}
/**
* A debugging routine: just echoes back the input packet as a string value
* DEPRECATED!
*/
function echoInput()
{
$r=&new xmlrpcresp(new xmlrpcval( "'Aha said I: '" . $GLOBALS['HTTP_RAW_POST_DATA'], 'string'));
print $r->serialize();
}
}
?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -