* Array defining php functions exposed as xmlrpc methods by this server.
*/
protected $dmap = array();
- /*
- * Defines how functions in dmap will be invoked: either using an xmlrpc msg object
- * or plain php values.
- * valid strings are 'xmlrpcvals', 'phpvals' or 'epivals'
- */
+ /**
+ * Defines how functions in dmap will be invoked: either using an xmlrpc msg object
+ * or plain php values.
+ * valid strings are 'xmlrpcvals', 'phpvals' or 'epivals'
+ */
public $functions_parameters_type = 'xmlrpcvals';
- /*
- * Option used for fine-tuning the encoding the php values returned from
- * functions registered in the dispatch map when the functions_parameters_types
- * member is set to 'phpvals'
- * @see php_xmlrpc_encode for a list of values
- */
+ /**
+ * Option used for fine-tuning the encoding the php values returned from
+ * functions registered in the dispatch map when the functions_parameters_types
+ * member is set to 'phpvals'
+ * @see php_xmlrpc_encode for a list of values
+ */
public $phpvals_encoding_options = array('auto_dates');
- /// controls whether the server is going to echo debugging messages back to the client as comments in response body. valid values: 0,1,2,3
+ /**
+ * Controls whether the server is going to echo debugging messages back to the client as comments in response body.
+ * Valid values: 0,1,2,3
+ */
public $debug = 1;
- /*
- * Controls behaviour of server when invoked user function throws an exception:
- * 0 = catch it and return an 'internal error' xmlrpc response (default)
- * 1 = catch it and return an xmlrpc response with the error corresponding to the exception
- * 2 = allow the exception to float to the upper layers
- */
+ /**
+ * Controls behaviour of server when invoked user function throws an exception:
+ * 0 = catch it and return an 'internal error' xmlrpc response (default)
+ * 1 = catch it and return an xmlrpc response with the error corresponding to the exception
+ * 2 = allow the exception to float to the upper layers
+ */
public $exception_handling = 0;
- /*
- * When set to true, it will enable HTTP compression of the response, in case
- * the client has declared its support for compression in the request.
- */
+ /**
+ * When set to true, it will enable HTTP compression of the response, in case
+ * the client has declared its support for compression in the request.
+ */
public $compress_response = false;
- /*
- * List of http compression methods accepted by the server for requests.
- * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib
- */
+ /**
+ * List of http compression methods accepted by the server for requests.
+ * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib
+ */
public $accepted_compression = array();
/// shall we serve calls to system.* methods?
public $allow_system_funcs = true;
/// list of charset encodings natively accepted for requests
public $accepted_charset_encodings = array();
- /*
- * charset encoding to be used for response.
- * NB: if we can, we will convert the generated response from internal_encoding to the intended one.
- * can be: a supported xml encoding (only UTF-8 and ISO-8859-1 at present, unless mbstring is enabled),
- * null (leave unspecified in response, convert output stream to US_ASCII),
- * 'default' (use xmlrpc library default as specified in xmlrpc.inc, convert output stream if needed),
- * or 'auto' (use client-specified charset encoding or same as request if request headers do not specify it (unless request is US-ASCII: then use library default anyway).
- * NB: pretty dangerous if you accept every charset and do not have mbstring enabled)
- */
+ /**
+ * charset encoding to be used for response.
+ * NB: if we can, we will convert the generated response from internal_encoding to the intended one.
+ * Can be: a supported xml encoding (only UTF-8 and ISO-8859-1 at present, unless mbstring is enabled),
+ * null (leave unspecified in response, convert output stream to US_ASCII),
+ * 'default' (use xmlrpc library default as specified in xmlrpc.inc, convert output stream if needed),
+ * or 'auto' (use client-specified charset encoding or same as request if request headers do not specify it (unless request is US-ASCII: then use library default anyway).
+ * NB: pretty dangerous if you accept every charset and do not have mbstring enabled)
+ */
public $response_charset_encoding = '';
/**
* Storage for internal debug info.
*/
protected $debug_info = '';
- /*
- * Extra data passed at runtime to method handling functions. Used only by EPI layer
- */
+ /**
+ * Extra data passed at runtime to method handling functions. Used only by EPI layer
+ */
public $user_data = null;
protected static $_xmlrpc_debuginfo = '';
*
* @return mixed null on success or a Response
*/
- protected function parseRequestHeaders(&$data, &$reqEncoding, &$respEncoding, &$resp_compression)
+ protected function parseRequestHeaders(&$data, &$reqEncoding, &$respEncoding, &$respCompression)
{
// check if $_SERVER is populated: it might have been disabled via ini file
// (this is true even when in CLI mode)
}
if (isset($_SERVER['HTTP_CONTENT_ENCODING'])) {
- $content_encoding = str_replace('x-', '', $_SERVER['HTTP_CONTENT_ENCODING']);
+ $contentEncoding = str_replace('x-', '', $_SERVER['HTTP_CONTENT_ENCODING']);
} else {
- $content_encoding = '';
+ $contentEncoding = '';
}
// check if request body has been compressed and decompress it
- if ($content_encoding != '' && strlen($data)) {
- if ($content_encoding == 'deflate' || $content_encoding == 'gzip') {
+ if ($contentEncoding != '' && strlen($data)) {
+ if ($contentEncoding == 'deflate' || $contentEncoding == '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)) {
+ if (function_exists('gzinflate') && in_array($contentEncoding, $this->accepted_compression)) {
+ if ($contentEncoding == '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))) {
+ } elseif ($contentEncoding == 'gzip' && $degzdata = @gzinflate(substr($data, 10))) {
$data = $degzdata;
if ($this->debug > 1) {
$this->debugmsg("+++INFLATED REQUEST+++[" . strlen($data) . " chars]+++\n" . $data . "\n+++END+++");
// 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']));
+ $clientAcceptedCharsets = explode(',', strtoupper($_SERVER['HTTP_ACCEPT_CHARSET']));
// Give preference to internal encoding
- $known_charsets = array(PhpXmlRpc::$xmlrpc_internalencoding, 'UTF-8', 'ISO-8859-1', 'US-ASCII');
- foreach ($known_charsets as $charset) {
- foreach ($client_accepted_charsets as $accepted) {
+ $knownCharsets = array(PhpXmlRpc::$xmlrpc_internalencoding, 'UTF-8', 'ISO-8859-1', 'US-ASCII');
+ foreach ($knownCharsets as $charset) {
+ foreach ($clientAcceptedCharsets as $accepted) {
if (strpos($accepted, $charset) === 0) {
$respEncoding = $charset;
break;
}
if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
- $resp_compression = $_SERVER['HTTP_ACCEPT_ENCODING'];
+ $respCompression = $_SERVER['HTTP_ACCEPT_ENCODING'];
} else {
- $resp_compression = '';
+ $respCompression = '';
}
// 'guestimate' request encoding
/// @todo check if mbstring is enabled and automagic input conversion is on: it might mingle with this check???
- $reqEncoding = Encoder::guess_encoding(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '',
+ $reqEncoding = XMLParser::guessEncoding(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '',
$data);
return;
*/
public function parseRequest($data, $reqEncoding = '')
{
- // 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);
-
// decompose incoming XML into request structure
- if ($reqEncoding != '') {
- if (!in_array($reqEncoding, 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($reqEncoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII')))
- error_log('XML-RPC: ' . __METHOD__ . ': invalid charset encoding of received request: ' . $reqEncoding);
- $reqEncoding = PhpXmlRpc::$xmlrpc_defencoding;
+ if ($reqEncoding != '') {
+ // Since parsing will fail if charset is not specified in the xml prologue,
+ // the encoding is not UTF8 and there are non-ascii chars in the text, we try to work round that...
+ // The following code might be better for mb_string enabled installs, but
+ // makes the lib about 200% slower...
+ //if (!is_valid_charset($reqEncoding, array('UTF-8')))
+ if (!in_array($reqEncoding, array('UTF-8', 'US-ASCII')) && !XMLParser::hasEncoding($data)) {
+ if ($reqEncoding == 'ISO-8859-1') {
+ $data = utf8_encode($data);
+ } else {
+ if (extension_loaded('mbstring')) {
+ $data = mb_convert_encoding($data, 'UTF-8', $reqEncoding);
+ } else {
+ error_log('XML-RPC: ' . __METHOD__ . ': invalid charset encoding of received request: ' . $reqEncoding);
+ }
+ }
}
- /// @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...
- /// @todo use an empty string for php 5 ???
- $parser = xml_parser_create($reqEncoding);
- } else {
- $parser = xml_parser_create();
}
+ $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
$r = $this->execute($xmlRpcParser->_xh['method'], $xmlRpcParser->_xh['params'], $xmlRpcParser->_xh['pt']);
} else {
// build a Request object with data parsed from xml
- $m = new Request($xmlRpcParser->_xh['method']);
+ $req = new Request($xmlRpcParser->_xh['method']);
// now add parameters in
for ($i = 0; $i < count($xmlRpcParser->_xh['params']); $i++) {
- $m->addParam($xmlRpcParser->_xh['params'][$i]);
+ $req->addParam($xmlRpcParser->_xh['params'][$i]);
}
if ($this->debug > 1) {
- $this->debugmsg("\n+++PARSED+++\n" . var_export($m, true) . "\n+++END+++");
+ $this->debugmsg("\n+++PARSED+++\n" . var_export($req, true) . "\n+++END+++");
}
- $r = $this->execute($m);
+ $r = $this->execute($req);
}
}
/**
* Execute a method invoked by the client, checking parameters used.
*
- * @param mixed $m either a Request obj or a method name
+ * @param mixed $req 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 Response
+ *
+ * @throws \Exception in case the executed method does throw an exception (and depending on )
*/
- protected function execute($m, $params = null, $paramTypes = null)
+ protected function execute($req, $params = null, $paramTypes = null)
{
- if (is_object($m)) {
- $methName = $m->method();
+ if (is_object($req)) {
+ $methName = $req->method();
} else {
- $methName = $m;
+ $methName = $req;
}
$sysCall = $this->allow_system_funcs && (strpos($methName, "system.") === 0);
$dmap = $sysCall ? $this->getSystemDispatchMap() : $this->dmap;
// Check signature
if (isset($dmap[$methName]['signature'])) {
$sig = $dmap[$methName]['signature'];
- if (is_object($m)) {
- list($ok, $errStr) = $this->verifySignature($m, $sig);
+ if (is_object($req)) {
+ list($ok, $errStr) = $this->verifySignature($req, $sig);
} else {
list($ok, $errStr) = $this->verifySignature($paramTypes, $sig);
}
return new Response(
0,
PhpXmlRpc::$xmlrpcerr['incorrect_params'],
- PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": ${errstr}"
+ PhpXmlRpc::$xmlrpcstr['incorrect_params'] . ": ${errStr}"
);
}
}
if (is_string($func) && strpos($func, '::')) {
$func = explode('::', $func);
}
+
+ if (is_array($func)) {
+ if (is_object($func[0])) {
+ $funcName = get_class($func[0]) . '->' . $func[1];
+ } else {
+ $funcName = implode('::', $func);
+ }
+ } else if ($func instanceof \Closure) {
+ $funcName = 'Closure';
+ } else {
+ $funcName = $func;
+ }
+
// verify that function to be invoked is in fact callable
if (!is_callable($func)) {
- error_log("XML-RPC: " . __METHOD__ . ": function $func registered as method handler is not callable");
+ error_log("XML-RPC: " . __METHOD__ . ": function '$funcName' registered as method handler is not callable");
return new Response(
0,
}
try {
// Allow mixed-convention servers
- if (is_object($m)) {
+ if (is_object($req)) {
if ($sysCall) {
- $r = call_user_func($func, $this, $m);
+ $r = call_user_func($func, $this, $req);
} else {
- $r = call_user_func($func, $m);
+ $r = call_user_func($func, $req);
}
if (!is_a($r, 'PhpXmlRpc\Response')) {
- error_log("XML-RPC: " . __METHOD__ . ": function $func registered as method handler does not return an xmlrpc response object");
+ error_log("XML-RPC: " . __METHOD__ . ": function '$funcName' registered as method handler does not return an xmlrpc response object but a " . gettype($r));
if (is_a($r, 'PhpXmlRpc\Value')) {
$r = new Response($r);
} else {
);
}
- public static function _xmlrpcs_getCapabilities($server, $m = null)
+ public static function _xmlrpcs_getCapabilities($server, $req = null)
{
$outAr = array(
// xmlrpc spec: always supported
return new Response(new Value($outAr, 'struct'));
}
- public static function _xmlrpcs_listMethods($server, $m = null) // if called in plain php values mode, second param is missing
+ public static function _xmlrpcs_listMethods($server, $req = null) // if called in plain php values mode, second param is missing
{
$outAr = array();
foreach ($server->dmap as $key => $val) {
return new Response(new Value($outAr, 'array'));
}
- public static function _xmlrpcs_methodSignature($server, $m)
+ public static function _xmlrpcs_methodSignature($server, $req)
{
// let accept as parameter both an xmlrpc value or string
- if (is_object($m)) {
- $methName = $m->getParam(0);
+ if (is_object($req)) {
+ $methName = $req->getParam(0);
$methName = $methName->scalarval();
} else {
- $methName = $m;
+ $methName = $req;
}
if (strpos($methName, "system.") === 0) {
$dmap = $server->getSystemDispatchMap();
return $r;
}
- public static function _xmlrpcs_methodHelp($server, $m)
+ public static function _xmlrpcs_methodHelp($server, $req)
{
// let accept as parameter both an xmlrpc value or string
- if (is_object($m)) {
- $methName = $m->getParam(0);
+ if (is_object($req)) {
+ $methName = $req->getParam(0);
$methName = $methName->scalarval();
} else {
- $methName = $m;
+ $methName = $req;
}
if (strpos($methName, "system.") === 0) {
$dmap = $server->getSystemDispatchMap();
// base64 or datetime values, but they will be listed as strings here...
$numParams = count($call['params']);
$pt = array();
+ $wrapper = new Wrapper();
foreach ($call['params'] as $val) {
- $pt[] = php_2_xmlrpc_type(gettype($val));
+ $pt[] = $wrapper->php_2_xmlrpc_type(gettype($val));
}
$result = $server->execute($call['methodName'], $call['params'], $pt);
return new Value(array($result->value()), 'array');
}
- public static function _xmlrpcs_multicall($server, $m)
+ public static function _xmlrpcs_multicall($server, $req)
{
$result = array();
// let accept a plain list of php parameters, beside a single xmlrpc msg object
- if (is_object($m)) {
- $calls = $m->getParam(0);
+ if (is_object($req)) {
+ $calls = $req->getParam(0);
$numCalls = $calls->arraysize();
for ($i = 0; $i < $numCalls; $i++) {
$call = $calls->arraymem($i);
$result[$i] = static::_xmlrpcs_multicall_do_call($server, $call);
}
} else {
- $numCalls = count($m);
+ $numCalls = count($req);
for ($i = 0; $i < $numCalls; $i++) {
- $result[$i] = static::_xmlrpcs_multicall_do_call_phpvals($server, $m[$i]);
+ $result[$i] = static::_xmlrpcs_multicall_do_call_phpvals($server, $req[$i]);
}
}
// 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);
+ $GLOBALS['_xmlrpcs_prev_ehandler']($errCode, $errString, $filename, $lineNo, $context);
}
}
}