For the extremely lazy coder, helper functions have been added that allow to convert a php function into an xmlrpc method, and a remotely exposed xmlrpc method into a local php function - or a set of methods into a php class. Note that these comes with many caveat.
stringwrap_xmlrpc_method( | $client, |
$methodname, | |
$extra_options) ; |
stringwrap_xmlrpc_method( | $client, |
$methodname, | |
$signum, | |
$timeout, | |
$protocol, | |
$funcname) ; |
Given an xmlrpc server and a method name, creates a php wrapper function that will call the remote method and return results using native php types for both params and results. The generated php function will return an xmlrpcresp object for failed xmlrpc calls.
The second syntax is deprecated, and is listed here only for backward compatibility.
The server must support the
system.methodSignature
xmlrpc method call for
this function to work.
The client
param must be a valid
xmlrpc_client object, previously created with the address of the
target xmlrpc server, and to which the preferred communication options
have been set.
The optional parameters can be passed as array key,value pairs
in the extra_options
param.
The signum
optional param has the purpose
of indicating which method signature to use, if the given server
method has multiple signatures (defaults to 0).
The timeout
and
protocol
optional params are the same as in the
xmlrpc_client::send()
method.
If set, the optional new_function_name
parameter indicates which name should be used for the generated
function. In case it is not set the function name will be
auto-generated.
If the return_source
optional parameter is
set, the function will return the php source code to build the wrapper
function, instead of evaluating it (useful to save the code and use it
later as stand-alone xmlrpc client).
If the encode_php_objs
optional parameter is
set, instances of php objects later passed as parameters to the newly
created function will receive a 'special' treatment that allows the
server to rebuild them as php objects instead of simple arrays. Note
that this entails using a "slightly augmented" version of the xmlrpc
protocol (ie. using element attributes), which might not be understood
by xmlrpc servers implemented using other libraries.
If the decode_php_objs
optional parameter is
set, instances of php objects that have been appropriately encoded by
the server using a coordinate option will be deserialized as php
objects instead of simple arrays (the same class definition should be
present server side and client side).
Note that this might pose a security risk, since in order to rebuild the object instances their constructor method has to be invoked, and this means that the remote server can trigger execution of unforeseen php code on the client: not really a code injection, but almost. Please enable this option only when you trust the remote server.
In case of an error during generation of the wrapper function, FALSE is returned, otherwise the name (or source code) of the new function.
Known limitations: server must support
system.methodsignature
for the wanted xmlrpc
method; for methods that expose multiple signatures, only one can be
picked; for remote calls with nested xmlrpc params, the caller of the
generated php function has to encode on its own the params passed to
the php function if these are structs or arrays whose (sub)members
include values of type base64.
Note: calling the generated php function 'might' be slow: a new xmlrpc client is created on every invocation and an xmlrpc-connection opened+closed. An extra 'debug' param is appended to the parameter list of the generated php function, useful for debugging purposes.
Example usage:
$c = new xmlrpc_client('http://phpxmlrpc.sourceforge.net/server.php');
$function = wrap_xmlrpc_method($client, 'examples.getStateName');
if (!$function)
die('Cannot introspect remote method');
else {
$stateno = 15;
$statename = $function($a);
if (is_a($statename, 'xmlrpcresp')) // call failed
{
echo 'Call failed: '.$statename->faultCode().'. Calling again with debug on';
$function($a, true);
}
else
echo "OK, state nr. $stateno is $statename";
}
arraywrap_php_function( | string$funcname, |
string$wrapper_function_name, | |
array$extra_options) ; |
Given a user-defined PHP function, create a PHP 'wrapper' function that can be exposed as xmlrpc method from an xmlrpc_server object and called from remote clients, and return the appropriate definition to be added to a server's dispatch map.
The optional $wrapper_function_name
specifies the name that will be used for the auto-generated
function.
Since php is a typeless language, to infer types of input and output parameters, it relies on parsing the javadoc-style comment block associated with the given function. Usage of xmlrpc native types (such as datetime.dateTime.iso8601 and base64) in the docblock @param tag is also allowed, if you need the php function to receive/send data in that particular format (note that base64 encoding/decoding is transparently carried out by the lib, while datetime vals are passed around as strings).
Known limitations: only works for user-defined functions, not for PHP internal functions (reflection does not support retrieving number/type of params for those); the wrapped php function will not be able to programmatically return an xmlrpc error response.
If the return_source
optional parameter is
set, the function will return the php source code to build the wrapper
function, instead of evaluating it (useful to save the code and use it
later in a stand-alone xmlrpc server). It will be in the stored in the
source
member of the returned array.
If the suppress_warnings
optional parameter
is set, any runtime warning generated while processing the
user-defined php function will be catched and not be printed in the
generated xml response.
If the extra_options
array contains the
encode_php_objs
value, wrapped functions returning
php objects will generate "special" xmlrpc responses: when the xmlrpc
decoding of those responses is carried out by this same lib, using the
appropriate param in php_xmlrpc_decode(), the objects will be
rebuilt.
In short: php objects can be serialized, too (except for their resource members), using this function. Other libs might choke on the very same xml that will be generated in this case (i.e. it has a nonstandard attribute on struct element tags)
If the decode_php_objs
optional parameter is
set, instances of php objects that have been appropriately encoded by
the client using a coordinate option will be deserialized and passed
to the user function as php objects instead of simple arrays (the same
class definition should be present server side and client
side).
Note that this might pose a security risk, since in order to rebuild the object instances their constructor method has to be invoked, and this means that the remote client can trigger execution of unforeseen php code on the server: not really a code injection, but almost. Please enable this option only when you trust the remote clients.
Example usage:
<?php /**
* State name from state number decoder. NB: do NOT remove this comment block.
* @param integer $stateno the state number
* @return string the name of the state (or error description)
*/
function findstate($stateno)
{
global $stateNames;
if (isset($stateNames[$stateno-1]))
{
return $stateNames[$stateno-1];
}
else
{
return "I don't have a state for the index '" . $stateno . "'";
}
}
// wrap php function, build xmlrpc server
$methods = array();
$findstate_sig = wrap_php_function('findstate');
if ($findstate_sig)
$methods['examples.getStateName'] = $findstate_sig;
$srv = new xmlrpc_server($methods);