X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fxmlrpc_wrappers.inc;h=9d901a4863cd5307962baf26521522f90c9b5107;hb=e885361eab7c181fe3b2e6923ced3de43ba3e285;hp=8b5bac90b51b3c778a02b853d096717bbe5e5eb9;hpb=b9d3e26af8fa9e6b6bca20a5769fe0abbecce3c1;p=plcapi.git diff --git a/lib/xmlrpc_wrappers.inc b/lib/xmlrpc_wrappers.inc index 8b5bac9..9d901a4 100644 --- a/lib/xmlrpc_wrappers.inc +++ b/lib/xmlrpc_wrappers.inc @@ -3,9 +3,8 @@ * PHP-XMLRPC "wrapper" functions * Generate stubs to transparently access xmlrpc methods as php functions and viceversa * - * @version $Id: xmlrpc_wrappers.inc,v 1.13 2008/09/20 01:23:47 ggiunta Exp $ * @author Gaetano Giunta - * @copyright (C) 2006-2009 G. Giunta + * @copyright (C) 2006-2014 G. Giunta * @license code licensed under the BSD License: http://phpxmlrpc.sourceforge.net/license.txt * * @todo separate introspection from code generation for func-2-method wrapping @@ -22,6 +21,7 @@ * accepted come from javadoc blocks), return corresponding phpxmlrpc type. * NB: 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 sometiles serialize as json structs * @param string $phptype * @return string */ @@ -105,7 +105,6 @@ * carried out by the lib, while datetime vals are passed around as strings) * * Known limitations: - * - requires PHP 5.0.3 + * - only works for user-defined functions, not for PHP internal functions * (reflection does not support retrieving number/type of params for those) * - functions returning php objects will generate special xmlrpc responses: @@ -149,36 +148,33 @@ $decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false; $catch_warnings = isset($extra_options['suppress_warnings']) && $extra_options['suppress_warnings'] ? '@' : ''; - if(version_compare(phpversion(), '5.0.3') == -1) + $exists = false; + if (is_string($funcname) && strpos($funcname, '::') !== false) { - // up to php 5.0.3 some useful reflection methods were missing - error_log('XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3'); - return false; + $funcname = explode('::', $funcname); + } + if(is_array($funcname)) + { + if(count($funcname) < 2 || (!is_string($funcname[0]) && !is_object($funcname[0]))) + { + error_log('XML-RPC: syntax for function to be wrapped is wrong'); + return false; + } + if(is_string($funcname[0])) + { + $plainfuncname = implode('::', $funcname); + } + elseif(is_object($funcname[0])) + { + $plainfuncname = get_class($funcname[0]) . '->' . $funcname[1]; + } + $exists = method_exists($funcname[0], $funcname[1]); + } + else + { + $plainfuncname = $funcname; + $exists = function_exists($funcname); } - - $exists = false; - if(is_array($funcname)) - { - if(count($funcname) < 2 || (!is_string($funcname[0]) && !is_object($funcname[0]))) - { - error_log('XML-RPC: syntax for function to be wrapped is wrong'); - return false; - } - if(is_string($funcname[0])) - { - $plainfuncname = implode('::', $funcname); - } - elseif(is_object($funcname[0])) - { - $plainfuncname = get_class($funcname[0]) . '->' . $funcname[1]; - } - $exists = method_exists($funcname[0], $funcname[1]); - } - else - { - $plainfuncname = $funcname; - $exists = function_exists($funcname); - } if(!$exists) { @@ -192,10 +188,10 @@ { if(is_array($funcname)) { - if(is_string($funcname[0])) - $xmlrpcfuncname = "{$prefix}_".implode('_', $funcname); - else - $xmlrpcfuncname = "{$prefix}_".get_class($funcname[0]) . '_' . $funcname[1]; + if(is_string($funcname[0])) + $xmlrpcfuncname = "{$prefix}_".implode('_', $funcname); + else + $xmlrpcfuncname = "{$prefix}_".get_class($funcname[0]) . '_' . $funcname[1]; } else { @@ -214,38 +210,38 @@ // start to introspect PHP code if(is_array($funcname)) { - $func =& new ReflectionMethod($funcname[0], $funcname[1]); - if($func->isPrivate()) - { - error_log('XML-RPC: method to be wrapped is private: '.$plainfuncname); - return false; - } - if($func->isProtected()) - { - error_log('XML-RPC: method to be wrapped is protected: '.$plainfuncname); - return false; - } - if($func->isConstructor()) - { - error_log('XML-RPC: method to be wrapped is the constructor: '.$plainfuncname); - return false; - } - if($func->isDestructor()) - { - error_log('XML-RPC: method to be wrapped is the destructor: '.$plainfuncname); - return false; - } - if($func->isAbstract()) - { - error_log('XML-RPC: method to be wrapped is abstract: '.$plainfuncname); - return false; - } - /// @todo add more checks for static vs. nonstatic? - } + $func = new ReflectionMethod($funcname[0], $funcname[1]); + if($func->isPrivate()) + { + error_log('XML-RPC: method to be wrapped is private: '.$plainfuncname); + return false; + } + if($func->isProtected()) + { + error_log('XML-RPC: method to be wrapped is protected: '.$plainfuncname); + return false; + } + if($func->isConstructor()) + { + error_log('XML-RPC: method to be wrapped is the constructor: '.$plainfuncname); + return false; + } + if($func->isDestructor()) + { + error_log('XML-RPC: method to be wrapped is the destructor: '.$plainfuncname); + return false; + } + if($func->isAbstract()) + { + error_log('XML-RPC: method to be wrapped is abstract: '.$plainfuncname); + return false; + } + /// @todo add more checks for static vs. nonstatic? + } else { - $func =& new ReflectionFunction($funcname); - } + $func = new ReflectionFunction($funcname); + } if($func->isInternal()) { // Note: from PHP 5.1.0 onward, we will possibly be able to use invokeargs @@ -398,17 +394,17 @@ $innercode .= "\$np = false;\n"; // since there are no closures in php, if we are given an object instance, - // we store a pointer to it in a global var... + // we store a pointer to it in a global var... if ( is_array($funcname) && is_object($funcname[0]) ) { - $GLOBALS['xmlrpcWPFObjHolder'][$xmlrpcfuncname] =& $funcname[0]; - $innercode .= "\$obj =& \$GLOBALS['xmlrpcWPFObjHolder']['$xmlrpcfuncname'];\n"; - $realfuncname = '$obj->'.$funcname[1]; + $GLOBALS['xmlrpcWPFObjHolder'][$xmlrpcfuncname] =& $funcname[0]; + $innercode .= "\$obj =& \$GLOBALS['xmlrpcWPFObjHolder']['$xmlrpcfuncname'];\n"; + $realfuncname = '$obj->'.$funcname[1]; } else { - $realfuncname = $plainfuncname; - } + $realfuncname = $plainfuncname; + } foreach($parsvariations as $pars) { $innercode .= "if (\$paramcount == " . count($pars) . ") \$retval = {$catch_warnings}$realfuncname(" . implode(',', $pars) . "); else\n"; @@ -472,66 +468,59 @@ } } - /** - * Given a user-defined PHP class or php object, map its methods onto a list of + /** + * Given a user-defined PHP class or php object, map its methods onto a list of * PHP 'wrapper' functions that can be exposed as xmlrpc methods from an xmlrpc_server * object and called from remote clients (as well as their corresponding signature info). * - * @param mixed $classname the name of the class whose methods are to be exposed as xmlrpc methods, or an object instance of that class - * @param array $extra_options see the docs for wrap_php_method for more options - * string method_type 'static', 'nonstatic', 'all' and 'auto' (default); the latter will switch between static and non-static depending on wheter $classname is a class name or object instance - * @return array or false on failure - * - * @todo get_class_methods will return both static and non-static methods. - * we have to differentiate the action, depending on wheter we recived a class name or object - */ - function wrap_php_class($classname, $extra_options=array()) - { + * @param mixed $classname the name of the class whose methods are to be exposed as xmlrpc methods, or an object instance of that class + * @param array $extra_options see the docs for wrap_php_method for more options + * string method_type 'static', 'nonstatic', 'all' and 'auto' (default); the latter will switch between static and non-static depending on wheter $classname is a class name or object instance + * @return array or false on failure + * + * @todo get_class_methods will return both static and non-static methods. + * we have to differentiate the action, depending on whether we received a class name or object + */ + function wrap_php_class($classname, $extra_options=array()) + { $methodfilter = isset($extra_options['method_filter']) ? $extra_options['method_filter'] : ''; $methodtype = isset($extra_options['method_type']) ? $extra_options['method_type'] : 'auto'; - if(version_compare(phpversion(), '5.0.3') == -1) - { - // up to php 5.0.3 some useful reflection methods were missing - error_log('XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3'); - return false; - } - - $result = array(); + $result = array(); $mlist = get_class_methods($classname); foreach($mlist as $mname) { - if ($methodfilter == '' || preg_match($methodfilter, $mname)) - { - // echo $mlist."\n"; - $func =& new ReflectionMethod($classname, $mname); - if(!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract()) - { - if(($func->isStatic && ($methodtype == 'all' || $methodtype == 'static' || ($methodtype == 'auto' && is_string($classname)))) || - (!$func->isStatic && ($methodtype == 'all' || $methodtype == 'nonstatic' || ($methodtype == 'auto' && is_object($classname))))) - { - $methodwrap = wrap_php_function(array($classname, $mname), '', $extra_options); - if ( $methodwrap ) - { - $result[$methodwrap['function']] = $methodwrap['function']; - } - } - } + if ($methodfilter == '' || preg_match($methodfilter, $mname)) + { + // echo $mlist."\n"; + $func = new ReflectionMethod($classname, $mname); + if(!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract()) + { + if(($func->isStatic && ($methodtype == 'all' || $methodtype == 'static' || ($methodtype == 'auto' && is_string($classname)))) || + (!$func->isStatic && ($methodtype == 'all' || $methodtype == 'nonstatic' || ($methodtype == 'auto' && is_object($classname))))) + { + $methodwrap = wrap_php_function(array($classname, $mname), '', $extra_options); + if ( $methodwrap ) + { + $result[$methodwrap['function']] = $methodwrap['function']; + } + } + } } } - return $result; - } + return $result; + } /** * Given an xmlrpc client and a method name, register a php wrapper function * that will call it and return results using native php types for both * params and results. The generated php function will return an xmlrpcresp - * oject for failed xmlrpc calls + * object for failed xmlrpc calls * * Known limitations: * - server must support system.methodsignature for the wanted xmlrpc method * - for methods that expose many signatures, only one can be picked (we - * could in priciple check if signatures differ only by number of params + * could in principle check if signatures differ only by number of params * and not by type, but it would be more complication than we can spare time) * - 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 @@ -547,11 +536,11 @@ * * @param xmlrpc_client $client an xmlrpc client set up correctly to communicate with target server * @param string $methodname the xmlrpc method to be mapped to a php function - * @param array $extra_options array of options that specify conversion details. valid ptions include + * @param array $extra_options array of options that specify conversion details. valid options include * integer signum the index of the method signature to use in mapping (if method exposes many sigs) * integer timeout timeout (in secs) to be used when executing function/calling remote method * string protocol 'http' (default), 'http11' or 'https' - * string new_function_name the name of php function to create. If unsepcified, lib will pick an appropriate name + * string new_function_name the name of php function to create. If unspecified, lib will pick an appropriate name * string return_source if true return php code w. function definition instead fo function name * bool encode_php_objs let php objects be sent to server using the 'improved' xmlrpc notation, so server can deserialize them as php objects * bool decode_php_objs --- WARNING !!! possible security hazard. only use it with trusted servers --- @@ -581,6 +570,7 @@ $encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false; $decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false; + // it seems like the meaning of 'simple_client_copy' here is swapped wrt client_copy_mode later on... $simple_client_copy = isset($extra_options['simple_client_copy']) ? (int)($extra_options['simple_client_copy']) : 0; $buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true; $prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc'; @@ -600,7 +590,7 @@ $valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; - $msg =& new $msgclass('system.methodSignature'); + $msg = new $msgclass('system.methodSignature'); $msg->addparam(new $valclass($methodname)); $client->setDebug($debug); $response =& $client->send($msg, $timeout, $protocol); @@ -646,7 +636,7 @@ // in online mode, favour speed of operation if(!$buildit) { - $msg =& new $msgclass('system.methodHelp'); + $msg = new $msgclass('system.methodHelp'); $msg->addparam(new $valclass($methodname)); $response =& $client->send($msg, $timeout, $protocol); if (!$response->faultCode()) @@ -715,7 +705,7 @@ //$valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; - $msg =& new $msgclass('system.listMethods'); + $msg = new $msgclass('system.listMethods'); $response =& $client->send($msg, $timeout, $protocol); if($response->faultCode()) { @@ -835,7 +825,7 @@ $innercode = ''; $this_ = 'this->'; } - $innercode .= "\$msg =& new {$prefix}msg('$methodname');\n"; + $innercode .= "\$msg = new {$prefix}msg('$methodname');\n"; if ($mdesc != '') { @@ -858,7 +848,7 @@ $ptype == 'string' || $ptype == 'dateTime.iso8601' || $ptype == 'base64' || $ptype == 'null') { // only build directly xmlrpcvals when type is known and scalar - $innercode .= "\$p$i =& new {$prefix}val(\$p$i, '$ptype');\n"; + $innercode .= "\$p$i = new {$prefix}val(\$p$i, '$ptype');\n"; } else { @@ -920,7 +910,7 @@ */ function build_client_wrapper_code($client, $verbatim_client_copy, $prefix='xmlrpc') { - $code = "\$client =& new {$prefix}_client('".str_replace("'", "\'", $client->path). + $code = "\$client = new {$prefix}_client('".str_replace("'", "\'", $client->path). "', '" . str_replace("'", "\'", $client->server) . "', $client->port);\n"; // copy all client fields to the client that will be generated runtime