From a8f93d5ce43365c83361071a847cb977f3ede519 Mon Sep 17 00:00:00 2001 From: gggeek Date: Wed, 30 Dec 2020 12:51:34 +0000 Subject: [PATCH] improve wrapping, encoding and handling of system dmap --- src/Encoder.php | 2 +- src/Server.php | 44 +++++++++++++++++++++++++++++++------------- src/Wrapper.php | 9 ++++++++- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/Encoder.php b/src/Encoder.php index 3b69f1a..82deef0 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -180,7 +180,7 @@ class Encoder if (is_a($phpVal, 'PhpXmlRpc\Value')) { $xmlrpcVal = $phpVal; } elseif (is_a($phpVal, 'DateTimeInterface')) { - $xmlrpcVal = new Value($phpVal->format('Ymd\TH:i:s'), Value::$xmlrpcStruct); + $xmlrpcVal = new Value($phpVal->format('Ymd\TH:i:s'), Value::$xmlrpcDateTime); } elseif (in_array('extension_api', $options) && $phpVal instanceof \stdClass && isset($phpVal->xmlrpc_type)) { // Handle the 'pre-converted' base64 and datetime values if (isset($phpVal->scalar)) { diff --git a/src/Server.php b/src/Server.php index ffbe21e..117e71e 100644 --- a/src/Server.php +++ b/src/Server.php @@ -296,6 +296,8 @@ class Server * @param array $sig the array of valid method signatures * @param string $doc method documentation * @param array $sigDoc the array of valid method signatures docs (one string per param, one for return type) + * + * @todo raise a warning if the user tries to register a 'system.' method */ public function add_to_map($methodName, $function, $sig = null, $doc = false, $sigDoc = false) { @@ -317,7 +319,7 @@ class Server * @param array|Request $in array of either xmlrpc value objects or xmlrpc type definitions * @param array $sigs array of known signatures to match against * - * @return array + * @return array int, string */ protected function verifySignature($in, $sigs) { @@ -572,7 +574,7 @@ class Server } else { $methName = $req; } - $sysCall = $this->allow_system_funcs && (strpos($methName, "system.") === 0); + $sysCall = $this->isSyscall($methName); $dmap = $sysCall ? $this->getSystemDispatchMap() : $this->dmap; if (!isset($dmap[$methName]['function'])) { @@ -741,13 +743,26 @@ class Server } } + /** + * @param string $methName + * @return bool + */ + protected function isSyscall($methName) + { + return (strpos($methName, "system.") === 0); + } + /* Functions that implement system.XXX methods of xmlrpc servers */ /** - * @return array + * @return array[] */ public function getSystemDispatchMap() { + if (!$this->allow_system_funcs) { + return array(); + } + return array( 'system.listMethods' => array( 'function' => 'PhpXmlRpc\Server::_xmlrpcs_listMethods', @@ -778,14 +793,14 @@ class Server 'system.getCapabilities' => array( 'function' => 'PhpXmlRpc\Server::_xmlrpcs_getCapabilities', 'signature' => array(array(Value::$xmlrpcStruct)), - 'docstring' => 'This method lists all the capabilites that the XML-RPC server has: the (more or less standard) extensions to the xmlrpc spec that it adheres to', + 'docstring' => 'This method lists all the capabilities that the XML-RPC server has: the (more or less standard) extensions to the xmlrpc spec that it adheres to', 'signature_docs' => array(array('list of capabilities, described as structs with a version number and url for the spec')), ), ); } /** - * @return array + * @return array[] */ public function getCapabilities() { @@ -841,10 +856,8 @@ class Server foreach ($server->dmap as $key => $val) { $outAr[] = new Value($key, 'string'); } - if ($server->allow_system_funcs) { - foreach ($server->getSystemDispatchMap() as $key => $val) { - $outAr[] = new Value($key, 'string'); - } + foreach ($server->getSystemDispatchMap() as $key => $val) { + $outAr[] = new Value($key, 'string'); } return new Response(new Value($outAr, 'array')); @@ -864,7 +877,7 @@ class Server } else { $methName = $req; } - if (strpos($methName, "system.") === 0) { + if ($server->isSyscall($methName)) { $dmap = $server->getSystemDispatchMap(); } else { $dmap = $server->dmap; @@ -906,7 +919,7 @@ class Server } else { $methName = $req; } - if (strpos($methName, "system.") === 0) { + if ($server->isSyscall($methName)) { $dmap = $server->getSystemDispatchMap(); } else { $dmap = $server->dmap; @@ -1014,12 +1027,17 @@ class Server return static::_xmlrpcs_multicall_error('notarray'); } - // this is a real dirty and simplistic hack, since we might have received a + // this is a simplistic hack, since we might have received // base64 or datetime values, but they will be listed as strings here... $pt = array(); $wrapper = new Wrapper(); foreach ($call['params'] as $val) { - $pt[] = $wrapper->php2XmlrpcType(gettype($val)); + // support EPI-encoded base64 and datetime values + if ($val instanceof \stdClass && isset($val->xmlrpc_type)) { + $pt[] = $val->xmlrpc_type == 'datetime' ? Value::$xmlrpcDateTime : $val->xmlrpc_type; + } else { + $pt[] = $wrapper->php2XmlrpcType(gettype($val)); + } } $result = $server->execute($call['methodName'], $call['params'], $pt); diff --git a/src/Wrapper.php b/src/Wrapper.php index a3572ae..bf624e4 100644 --- a/src/Wrapper.php +++ b/src/Wrapper.php @@ -16,6 +16,7 @@ use PhpXmlRpc\Helper\Logger; * @todo use some better templating system for code generation? * @todo implement method wrapping with preservation of php objs in calls * @todo when wrapping methods without obj rebuilding, use return_type = 'phpvals' (faster) + * @todo add support for 'epivals' mode */ class Wrapper { @@ -28,12 +29,14 @@ class Wrapper * Notes: * - for php 'resource' types returns empty string, since resources cannot be serialized; * - for php class names returns 'struct', since php objects can be serialized as xmlrpc structs - * - for php arrays always return array, even though arrays sometimes serialize as json structs + * - for php arrays always return array, even though arrays sometimes serialize as structs... * - for 'void' and 'null' returns 'undefined' * * @param string $phpType * * @return string + * + * @todo support notation `something[]` as 'array' */ public function php2XmlrpcType($phpType) { @@ -53,6 +56,7 @@ class Wrapper case 'true': return Value::$xmlrpcBoolean; case Value::$xmlrpcArray: // 'array': + case 'array[]'; return Value::$xmlrpcArray; case 'object': case Value::$xmlrpcStruct: // 'struct' @@ -63,6 +67,9 @@ class Wrapper return ''; default: if (class_exists($phpType)) { + if (is_a($phpType, 'DateTimeInterface')) { + return Value::$xmlrpcDateTime; + } return Value::$xmlrpcStruct; } else { // unknown: might be any 'extended' xmlrpc type -- 2.43.0