30 switch(strtolower($phptype))
48 return strtolower($phptype);
52 if(class_exists($phptype))
71 switch(strtolower($xmlrpctype))
74 case 'datetime.iso8601':
91 return strtolower($xmlrpctype);
144 $buildit = isset($extra_options[
'return_source']) ? !($extra_options[
'return_source']) :
true;
145 $prefix = isset($extra_options[
'prefix']) ? $extra_options[
'prefix'] :
'xmlrpc';
146 $encode_php_objects = isset($extra_options[
'encode_php_objs']) ? (bool)$extra_options[
'encode_php_objs'] :
false;
147 $decode_php_objects = isset($extra_options[
'decode_php_objs']) ? (bool)$extra_options[
'decode_php_objs'] :
false;
148 $catch_warnings = isset($extra_options[
'suppress_warnings']) && $extra_options[
'suppress_warnings'] ?
'@' :
'';
150 if(version_compare(phpversion(),
'5.0.3') == -1)
153 error_log(
'XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3');
156 if((is_array($funcname) && !method_exists($funcname[0], $funcname[1])) || !function_exists($funcname))
158 error_log(
'XML-RPC: function to be wrapped is not defined: '.$funcname);
164 if($newfuncname ==
'')
166 if(is_array($funcname))
168 $xmlrpcfuncname =
"{$prefix}_".implode(
'_', $funcname);
172 $xmlrpcfuncname =
"{$prefix}_$funcname";
177 $xmlrpcfuncname = $newfuncname;
179 while($buildit && function_exists($xmlrpcfuncname))
181 $xmlrpcfuncname .=
'x';
185 $func =
new ReflectionFunction($funcname);
186 if($func->isInternal())
190 error_log(
'XML-RPC: function to be wrapped is internal: '.$funcname);
203 $paramDocs = array();
205 $docs = $func->getDocComment();
208 $docs = explode(
"\n", $docs);
210 foreach($docs
as $doc)
212 $doc = trim($doc,
" \r\t/*");
213 if(strlen($doc) && strpos($doc,
'@') !== 0 && !$i)
221 elseif(strpos($doc,
'@param') === 0)
224 if(preg_match(
'/@param\s+(\S+)(\s+\$\S+)?\s+(.+)/', $doc, $matches))
226 if(strpos($matches[1],
'|'))
229 $paramDocs[$i][
'type'] =
'mixed';
233 $paramDocs[$i][
'type'] = $matches[1];
235 $paramDocs[$i][
'name'] = trim($matches[2]);
236 $paramDocs[$i][
'doc'] = $matches[3];
240 elseif(strpos($doc,
'@return') === 0)
244 if(preg_match(
'/@return\s+(\S+)\s+(.+)/', $doc, $matches))
247 if(isset($matches[2]))
249 $returnsDocs = $matches[2];
259 foreach($func->getParameters()
as $paramobj)
261 $params[$i] = array();
262 $params[$i][
'name'] =
'$'.$paramobj->getName();
263 $params[$i][
'isoptional'] = $paramobj->isOptional();
271 $parsvariations = array();
273 $pnum = count($params);
274 foreach($params
as $param)
276 if (isset($paramDocs[$i][
'name']) && $paramDocs[$i][
'name'] && strtolower($paramDocs[$i][
'name']) != strtolower($param[
'name']))
279 $paramDocs[$i][
'type'] =
'mixed';
282 if($param[
'isoptional'])
285 $innercode .=
"if (\$paramcount > $i) {\n";
286 $parsvariations[] = $pars;
288 $innercode .=
"\$p$i = \$msg->getParam($i);\n";
289 if ($decode_php_objects)
291 $innercode .=
"if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i, array('decode_php_objs'));\n";
295 $innercode .=
"if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i);\n";
300 if($param[
'isoptional'])
307 $parsvariations[] = $pars;
313 if(count($parsvariations) == 0)
316 $parsvariations[] = array();
321 $minpars = count($parsvariations[0]);
328 $innercode =
"\$paramcount = \$msg->getNumParams();\n" .
329 "if (\$paramcount < $minpars) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}');\n" . $innercode;
333 $innercode =
"\$paramcount = \$msg->getNumParams();\n" . $innercode;
336 $innercode .=
"\$np = false;\n";
337 foreach($parsvariations
as $pars)
339 $innercode .=
"if (\$paramcount == " . count($pars) .
") \$retval = {$catch_warnings}$funcname(" . implode(
',', $pars) .
"); else\n";
341 $sig = array($returns);
342 $psig = array($returnsDocs);
343 for($i=0; $i < count($pars); $i++)
345 if (isset($paramDocs[$i][
'type']))
353 $psig[] = isset($paramDocs[$i][
'doc']) ? $paramDocs[$i][
'doc'] :
'';
358 $innercode .=
"\$np = true;\n";
359 $innercode .=
"if (\$np) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}'); else {\n";
361 $innercode .=
"if (is_a(\$retval, '{$prefix}resp')) return \$retval; else\n";
362 if($returns ==
$GLOBALS[
'xmlrpcDateTime'] || $returns ==
$GLOBALS[
'xmlrpcBase64'])
364 $innercode .=
"return new {$prefix}resp(new {$prefix}val(\$retval, '$returns'));";
368 if ($encode_php_objects)
369 $innercode .=
"return new {$prefix}resp(php_{$prefix}_encode(\$retval, array('encode_php_objs')));\n";
371 $innercode .=
"return new {$prefix}resp(php_{$prefix}_encode(\$retval));\n";
376 $code =
"function $xmlrpcfuncname(\$msg) {\n" . $innercode .
"}\n}";
381 eval($code.
'$allOK=1;');
387 error_log(
'XML-RPC: could not create function '.$xmlrpcfuncname.
' to wrap php function '.$funcname);
395 $ret = array(
'function' => $xmlrpcfuncname,
'signature' => $sigs,
'docstring' => $desc,
'signature_docs' => $psigs,
'source' => $code);
437 function wrap_xmlrpc_method($client, $methodname, $extra_options=0, $timeout=0, $protocol=
'', $newfuncname=
'')
441 if (!is_array($extra_options))
443 $signum = $extra_options;
444 $extra_options = array();
448 $signum = isset($extra_options[
'signum']) ? (int)$extra_options[
'signum'] : 0;
449 $timeout = isset($extra_options[
'timeout']) ? (int)$extra_options[
'timeout'] : 0;
450 $protocol = isset($extra_options[
'protocol']) ? $extra_options[
'protocol'] :
'';
451 $newfuncname = isset($extra_options[
'new_function_name']) ? $extra_options[
'new_function_name'] :
'';
457 $encode_php_objects = isset($extra_options[
'encode_php_objs']) ? (bool)$extra_options[
'encode_php_objs'] :
false;
458 $decode_php_objects = isset($extra_options[
'decode_php_objs']) ? (bool)$extra_options[
'decode_php_objs'] :
false;
459 $simple_client_copy = isset($extra_options[
'simple_client_copy']) ? (int)($extra_options[
'simple_client_copy']) : 0;
460 $buildit = isset($extra_options[
'return_source']) ? !($extra_options[
'return_source']) :
true;
461 $prefix = isset($extra_options[
'prefix']) ? $extra_options[
'prefix'] :
'xmlrpc';
462 if (isset($extra_options[
'return_on_fault']))
464 $decode_fault =
true;
465 $fault_response = $extra_options[
'return_on_fault'];
469 $decode_fault =
false;
470 $fault_response =
'';
472 $debug = isset($extra_options[
'debug']) ? ($extra_options[
'debug']) : 0;
474 $msgclass = $prefix.
'msg';
475 $valclass = $prefix.
'val';
476 $decodefunc =
'php_'.$prefix.
'_decode';
478 $msg =
new $msgclass(
'system.methodSignature');
479 $msg->addparam(
new $valclass($methodname));
480 $client->setDebug($debug);
481 $response =& $client->send($msg, $timeout, $protocol);
482 if($response->faultCode())
484 error_log(
'XML-RPC: could not retrieve method signature from remote server for method '.$methodname);
489 $msig = $response->value();
490 if ($client->return_type !=
'phpvals')
492 $msig = $decodefunc($msig);
494 if(!is_array($msig) || count($msig) <= $signum)
496 error_log(
'XML-RPC: could not retrieve method signature nr.'.$signum.
' from remote server for method '.$methodname);
502 if($newfuncname !=
'')
504 $xmlrpcfuncname = $newfuncname;
510 $xmlrpcfuncname = $prefix.
'_'.preg_replace(array(
'/\./',
'/[^a-zA-Z0-9_\x7f-\xff]/'),
511 array(
'_',
''), $methodname);
513 while($buildit && function_exists($xmlrpcfuncname))
515 $xmlrpcfuncname .=
'x';
518 $msig = $msig[$signum];
524 $msg =
new $msgclass(
'system.methodHelp');
525 $msg->addparam(
new $valclass($methodname));
526 $response =& $client->send($msg, $timeout, $protocol);
527 if (!$response->faultCode())
529 $mdesc = $response->value();
530 if ($client->return_type !=
'phpvals')
532 $mdesc = $mdesc->scalarval();
538 $xmlrpcfuncname, $msig, $mdesc, $timeout, $protocol, $simple_client_copy,
539 $prefix, $decode_php_objects, $encode_php_objects, $decode_fault,
546 eval($results[
'source'].
'$allOK=1;');
551 return $xmlrpcfuncname;
555 error_log(
'XML-RPC: could not create function '.$xmlrpcfuncname.
' to wrap remote method '.$methodname);
561 $results[
'function'] = $xmlrpcfuncname;
578 $methodfilter = isset($extra_options[
'method_filter']) ? $extra_options[
'method_filter'] :
'';
579 $signum = isset($extra_options[
'signum']) ? (int)$extra_options[
'signum'] : 0;
580 $timeout = isset($extra_options[
'timeout']) ? (int)$extra_options[
'timeout'] : 0;
581 $protocol = isset($extra_options[
'protocol']) ? $extra_options[
'protocol'] :
'';
582 $newclassname = isset($extra_options[
'new_class_name']) ? $extra_options[
'new_class_name'] :
'';
583 $encode_php_objects = isset($extra_options[
'encode_php_objs']) ? (bool)$extra_options[
'encode_php_objs'] :
false;
584 $decode_php_objects = isset($extra_options[
'decode_php_objs']) ? (bool)$extra_options[
'decode_php_objs'] :
false;
585 $verbatim_client_copy = isset($extra_options[
'simple_client_copy']) ? !($extra_options[
'simple_client_copy']) :
true;
586 $buildit = isset($extra_options[
'return_source']) ? !($extra_options[
'return_source']) :
true;
587 $prefix = isset($extra_options[
'prefix']) ? $extra_options[
'prefix'] :
'xmlrpc';
589 $msgclass = $prefix.
'msg';
591 $decodefunc =
'php_'.$prefix.
'_decode';
593 $msg =
new $msgclass(
'system.listMethods');
594 $response = $client->send($msg, $timeout, $protocol);
595 if($response->faultCode())
597 error_log(
'XML-RPC: could not retrieve method list from remote server');
602 $mlist = $response->value();
603 if ($client->return_type !=
'phpvals')
605 $mlist = $decodefunc($mlist);
607 if(!is_array($mlist) || !count($mlist))
609 error_log(
'XML-RPC: could not retrieve meaningful method list from remote server');
615 if($newclassname !=
'')
617 $xmlrpcclassname = $newclassname;
621 $xmlrpcclassname = $prefix.
'_'.preg_replace(array(
'/\./',
'/[^a-zA-Z0-9_\x7f-\xff]/'),
622 array(
'_',
''), $client->server).
'_client';
624 while($buildit && class_exists($xmlrpcclassname))
626 $xmlrpcclassname .=
'x';
630 $source =
"class $xmlrpcclassname\n{\nvar \$client;\n\n";
631 $source .=
"function $xmlrpcclassname()\n{\n";
633 $source .=
"\$this->client =& \$client;\n}\n\n";
634 $opts = array(
'simple_client_copy' => 2,
'return_source' =>
true,
635 'timeout' => $timeout,
'protocol' => $protocol,
636 'encode_php_objs' => $encode_php_objects,
'prefix' => $prefix,
637 'decode_php_objs' => $decode_php_objects
640 foreach($mlist
as $mname)
642 if ($methodfilter ==
'' || preg_match($methodfilter, $mname))
644 $opts[
'new_function_name'] = preg_replace(array(
'/\./',
'/[^a-zA-Z0-9_\x7f-\xff]/'),
645 array(
'_',
''), $mname);
651 $source .= $methodwrap[
'docstring'];
653 $source .= $methodwrap[
'source'].
"\n";
657 error_log(
'XML-RPC: will not create class method to wrap remote method '.$mname);
665 eval($source.
'$allOK=1;');
670 return $xmlrpcclassname;
674 error_log(
'XML-RPC: could not create class '.$xmlrpcclassname.
' to wrap remote server '.$client->server);
680 return array(
'class' => $xmlrpcclassname,
'code' => $source,
'docstring' =>
'');
695 $msig, $mdesc=
'', $timeout=0, $protocol=
'', $client_copy_mode=0, $prefix=
'xmlrpc',
696 $decode_php_objects=
false, $encode_php_objects=
false, $decode_fault=
false,
699 $code =
"function $xmlrpcfuncname (";
700 if ($client_copy_mode < 2)
704 $innercode .=
"\$client->setDebug(\$debug);\n";
713 $innercode .=
"\$msg = new {$prefix}msg('$methodname');\n";
718 $mdesc =
"/**\n* ".str_replace(
'*/',
'* /', $mdesc).
"\n";
722 $mdesc =
"/**\nFunction $xmlrpcfuncname\n";
727 $pcount = count($msig);
728 for($i = 1; $i < $pcount; $i++)
732 if($ptype ==
'i4' || $ptype ==
'int' || $ptype ==
'boolean' || $ptype ==
'double' ||
733 $ptype ==
'string' || $ptype ==
'dateTime.iso8601' || $ptype ==
'base64' || $ptype ==
'null')
736 $innercode .=
"\$p$i = new {$prefix}val(\$p$i, '$ptype');\n";
740 if ($encode_php_objects)
742 $innercode .=
"\$p$i =& php_{$prefix}_encode(\$p$i, array('encode_php_objs'));\n";
746 $innercode .=
"\$p$i =& php_{$prefix}_encode(\$p$i);\n";
749 $innercode .=
"\$msg->addparam(\$p$i);\n";
750 $mdesc .=
'* @param '.xmlrpc_2_php_type($ptype).
" \$p$i\n";
752 if ($client_copy_mode < 2)
754 $plist[] =
'$debug=0';
755 $mdesc .=
"* @param int \$debug when 1 (or 2) will enable debugging of the underlying {$prefix} call (defaults to 0)\n";
757 $plist = implode(
', ', $plist);
758 $mdesc .=
'* @return '.xmlrpc_2_php_type($msig[0]).
" (or an {$prefix}resp obj instance if call fails)\n*/\n";
760 $innercode .=
"\$res =& \${$this_}client->send(\$msg, $timeout, '$protocol');\n";
763 if (is_string($fault_response) && ((strpos($fault_response,
'%faultCode%') !==
false) || (strpos($fault_response,
'%faultString%') !==
false)))
765 $respcode =
"str_replace(array('%faultCode%', '%faultString%'), array(\$res->faultCode(), \$res->faultString()), '".str_replace(
"'",
"''", $fault_response).
"')";
769 $respcode = var_export($fault_response,
true);
776 if ($decode_php_objects)
778 $innercode .=
"if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value(), array('decode_php_objs'));";
782 $innercode .=
"if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value());";
785 $code = $code . $plist.
") {\n" . $innercode .
"\n}\n";
787 return array(
'source' => $code,
'docstring' => $mdesc);
798 $code =
"\$client = new {$prefix}_client('".str_replace(
"'",
"\'", $client->path).
799 "', '" . str_replace(
"'",
"\'", $client->server) .
"', $client->port);\n";
803 if ($verbatim_client_copy)
805 foreach($client
as $fld => $val)
807 if($fld !=
'debug' && $fld !=
'return_type')
809 $val = var_export($val,
true);
810 $code .=
"\$client->$fld = $val;\n";
815 $code .=
"\$client->return_type = '{$prefix}vals';\n";