| Server IP : 213.186.33.2 / Your IP : 216.73.216.39 Web Server : Apache System : Linux webm005.cluster102.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64 User : symetry ( 21728) PHP Version : 8.2.31 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/symetry/www/ARCHIVES/library/Zend/XmlRpc/ |
Upload File : |
<?php
/**
* Zend Framework
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://framework.zend.com/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
* @package Zend_XmlRpc
* @subpackage Server
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id: Server.php 9132 2008-04-04 11:59:57Z thomas $
*/
/**
* Implement Zend_Server_Interface
*/
require_once 'Zend/Server/Interface.php';
/**
* Exception this class throws
*/
require_once 'Zend/XmlRpc/Server/Exception.php';
/**
* XMLRPC Request
*/
require_once 'Zend/XmlRpc/Request.php';
/**
* XMLRPC Response
*/
require_once 'Zend/XmlRpc/Response.php';
/**
* XMLRPC HTTP Response
*/
require_once 'Zend/XmlRpc/Response/Http.php';
/**
* XMLRPC server fault class
*/
require_once 'Zend/XmlRpc/Server/Fault.php';
/**
* Convert PHP to and from xmlrpc native types
*/
require_once 'Zend/XmlRpc/Value.php';
/**
* Reflection API for function/method introspection
*/
require_once 'Zend/Server/Reflection.php';
/**
* Zend_Server_Reflection_Function_Abstract
*/
require_once 'Zend/Server/Reflection/Function/Abstract.php';
/**
* Specifically grab the Zend_Server_Reflection_Method for manually setting up
* system.* methods and handling callbacks in {@link loadFunctions()}.
*/
require_once 'Zend/Server/Reflection/Method.php';
/**
* An XML-RPC server implementation
*
* Example:
* <code>
* require_once 'Zend/XmlRpc/Server.php';
* require_once 'Zend/XmlRpc/Server/Cache.php';
* require_once 'Zend/XmlRpc/Server/Fault.php';
* require_once 'My/Exception.php';
* require_once 'My/Fault/Observer.php';
*
* // Instantiate server
* $server = new Zend_XmlRpc_Server();
*
* // Allow some exceptions to report as fault responses:
* Zend_XmlRpc_Server_Fault::attachFaultException('My_Exception');
* Zend_XmlRpc_Server_Fault::attachObserver('My_Fault_Observer');
*
* // Get or build dispatch table:
* if (!Zend_XmlRpc_Server_Cache::get($filename, $server)) {
* require_once 'Some/Service/Class.php';
* require_once 'Another/Service/Class.php';
*
* // Attach Some_Service_Class in 'some' namespace
* $server->setClass('Some_Service_Class', 'some');
*
* // Attach Another_Service_Class in 'another' namespace
* $server->setClass('Another_Service_Class', 'another');
*
* // Create dispatch table cache file
* Zend_XmlRpc_Server_Cache::save($filename, $server);
* }
*
* $response = $server->handle();
* echo $response;
* </code>
*
* @category Zend
* @package Zend_XmlRpc
* @subpackage Server
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_XmlRpc_Server
{
/**
* Character encoding
* @var string
*/
protected $_encoding = 'UTF-8';
/**
* Array of dispatchables
* @var array
*/
protected $_methods = array();
/**
* Request processed
* @var null|Zend_XmlRpc_Request
*/
protected $_request = null;
/**
* Class to use for responses; defaults to {@link Zend_XmlRpc_Response_Http}
* @var string
*/
protected $_responseClass = 'Zend_XmlRpc_Response_Http';
/**
* Dispatch table of name => method pairs
* @var array
*/
protected $_table = array();
/**
* PHP types => XML-RPC types
* @var array
*/
protected $_typeMap = array(
'i4' => 'i4',
'int' => 'int',
'integer' => 'int',
'double' => 'double',
'float' => 'double',
'real' => 'double',
'boolean' => 'boolean',
'bool' => 'boolean',
'true' => 'boolean',
'false' => 'boolean',
'string' => 'string',
'str' => 'string',
'base64' => 'base64',
'dateTime.iso8601' => 'dateTime.iso8601',
'date' => 'dateTime.iso8601',
'time' => 'dateTime.iso8601',
'time' => 'dateTime.iso8601',
'array' => 'array',
'struct' => 'struct',
'null' => 'nil',
'nil' => 'nil',
'void' => 'void',
'mixed' => 'struct'
);
/**
* Constructor
*
* Creates system.* methods.
*
* @return void
*/
public function __construct()
{
// Setup system.* methods
$system = array(
'listMethods',
'methodHelp',
'methodSignature',
'multicall'
);
$class = Zend_Server_Reflection::reflectClass($this);
foreach ($system as $method) {
$reflection = new Zend_Server_Reflection_Method($class, new ReflectionMethod($this, $method), 'system');
$reflection->system = true;
$this->_methods[] = $reflection;
}
$this->_buildDispatchTable();
}
/**
* Map PHP parameter types to XML-RPC types
*
* @param Zend_Server_Reflection_Function_Abstract $method
* @return void
*/
protected function _fixTypes(Zend_Server_Reflection_Function_Abstract $method)
{
foreach ($method->getPrototypes() as $prototype) {
foreach ($prototype->getParameters() as $param) {
$pType = $param->getType();
if (isset($this->_typeMap[$pType])) {
$param->setType($this->_typeMap[$pType]);
} else {
$param->setType('void');
}
}
}
}
/**
* Re/Build the dispatch table
*
* The dispatch table consists of a an array of method name =>
* Zend_Server_Reflection_Function_Abstract pairs
*
* @return void
*/
protected function _buildDispatchTable()
{
$table = array();
foreach ($this->_methods as $dispatchable) {
if ($dispatchable instanceof Zend_Server_Reflection_Function_Abstract) {
// function/method call
$ns = $dispatchable->getNamespace();
$name = $dispatchable->getName();
$name = empty($ns) ? $name : $ns . '.' . $name;
if (isset($table[$name])) {
throw new Zend_XmlRpc_Server_Exception('Duplicate method registered: ' . $name);
}
$table[$name] = $dispatchable;
$this->_fixTypes($dispatchable);
continue;
}
if ($dispatchable instanceof Zend_Server_Reflection_Class) {
foreach ($dispatchable->getMethods() as $method) {
$ns = $method->getNamespace();
$name = $method->getName();
$name = empty($ns) ? $name : $ns . '.' . $name;
if (isset($table[$name])) {
throw new Zend_XmlRpc_Server_Exception('Duplicate method registered: ' . $name);
}
$table[$name] = $method;
$this->_fixTypes($method);
continue;
}
}
}
$this->_table = $table;
}
/**
* Set encoding
*
* @param string $encoding
* @return Zend_XmlRpc_Server
*/
public function setEncoding($encoding)
{
$this->_encoding = $encoding;
return $this;
}
/**
* Retrieve current encoding
*
* @return string
*/
public function getEncoding()
{
return $this->_encoding;
}
/**
* Attach a callback as an XMLRPC method
*
* Attaches a callback as an XMLRPC method, prefixing the XMLRPC method name
* with $namespace, if provided. Reflection is done on the callback's
* docblock to create the methodHelp for the XMLRPC method.
*
* Additional arguments to pass to the function at dispatch may be passed;
* any arguments following the namespace will be aggregated and passed at
* dispatch time.
*
* @param string|array $function Valid callback
* @param string $namespace Optional namespace prefix
* @return void
* @throws Zend_XmlRpc_Server_Exception
*/
public function addFunction($function, $namespace = '')
{
if (!is_string($function) && !is_array($function)) {
throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
}
$argv = null;
if (2 < func_num_args()) {
$argv = func_get_args();
$argv = array_slice($argv, 2);
}
$function = (array) $function;
foreach ($function as $func) {
if (!is_string($func) || !function_exists($func)) {
throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
}
$this->_methods[] = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
}
$this->_buildDispatchTable();
}
/**
* Load methods as returned from {@link getFunctions}
*
* Typically, you will not use this method; it will be called using the
* results pulled from {@link Zend_XmlRpc_Server_Cache::get()}.
*
* @param array $array
* @return void
* @throws Zend_XmlRpc_Server_Exception on invalid input
*/
public function loadFunctions($array)
{
if (!is_array($array)) {
throw new Zend_XmlRpc_Server_Exception('Unable to load array; not an array', 612);
}
foreach ($array as $key => $value) {
if (!$value instanceof Zend_Server_Reflection_Function_Abstract
&& !$value instanceof Zend_Server_Reflection_Class)
{
throw new Zend_XmlRpc_Server_Exception('One or more method records are corrupt or otherwise unusable', 613);
}
if ($value->system) {
unset($array[$key]);
}
}
foreach ($array as $dispatchable) {
$this->_methods[] = $dispatchable;
}
$this->_buildDispatchTable();
}
/**
* Do nothing; persistence is handled via {@link Zend_XmlRpc_Server_Cache}
*
* @param mixed $class
* @return void
*/
public function setPersistence($class = null)
{
}
/**
* Attach class methods as XMLRPC method handlers
*
* $class may be either a class name or an object. Reflection is done on the
* class or object to determine the available public methods, and each is
* attached to the server as an available method; if a $namespace has been
* provided, that namespace is used to prefix the XMLRPC method names.
*
* Any additional arguments beyond $namespace will be passed to a method at
* invocation.
*
* @param string|object $class
* @param string $namespace Optional
* @param mixed $argv Optional arguments to pass to methods
* @return void
* @throws Zend_XmlRpc_Server_Exception on invalid input
*/
public function setClass($class, $namespace = '', $argv = null)
{
if (is_string($class) && !class_exists($class)) {
if (!class_exists($class)) {
throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
}
}
$argv = null;
if (3 < func_num_args()) {
$argv = func_get_args();
$argv = array_slice($argv, 3);
}
$this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
$this->_buildDispatchTable();
}
/**
* Set the request object
*
* @param string|Zend_XmlRpc_Request $request
* @return Zend_XmlRpc_Server
* @throws Zend_XmlRpc_Server_Exception on invalid request class or object
*/
public function setRequest($request)
{
if (is_string($request) && class_exists($request)) {
$request = new $request();
if (!$request instanceof Zend_XmlRpc_Request) {
throw new Zend_XmlRpc_Server_Exception('Invalid request class');
}
$request->setEncoding($this->getEncoding());
} elseif (!$request instanceof Zend_XmlRpc_Request) {
throw new Zend_XmlRpc_Server_Exception('Invalid request object');
}
$this->_request = $request;
return $this;
}
/**
* Return currently registered request object
*
* @return null|Zend_XmlRpc_Request
*/
public function getRequest()
{
return $this->_request;
}
/**
* Raise an xmlrpc server fault
*
* @param string|Exception $fault
* @param int $code
* @return Zend_XmlRpc_Server_Fault
*/
public function fault($fault, $code = 404)
{
if (!$fault instanceof Exception) {
$fault = (string) $fault;
$fault = new Zend_XmlRpc_Server_Exception($fault, $code);
}
return Zend_XmlRpc_Server_Fault::getInstance($fault);
}
/**
* Handle an xmlrpc call (actual work)
*
* @param Zend_XmlRpc_Request $request
* @return Zend_XmlRpc_Response
* @throws Zend_XmlRpcServer_Exception|Exception
* Zend_XmlRpcServer_Exceptions are thrown for internal errors; otherwise,
* any other exception may be thrown by the callback
*/
protected function _handle(Zend_XmlRpc_Request $request)
{
$method = $request->getMethod();
// Check for valid method
if (!isset($this->_table[$method])) {
throw new Zend_XmlRpc_Server_Exception('Method "' . $method . '" does not exist', 620);
}
$info = $this->_table[$method];
$params = $request->getParams();
$argv = $info->getInvokeArguments();
if (0 < count($argv)) {
$params = array_merge($params, $argv);
}
// Check calling parameters against signatures
$matched = false;
$sigCalled = $request->getTypes();
$sigLength = count($sigCalled);
$paramsLen = count($params);
if ($sigLength < $paramsLen) {
for ($i = $sigLength; $i < $paramsLen; ++$i) {
$xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($params[$i]);
$sigCalled[] = $xmlRpcValue->getType();
}
}
$signatures = $info->getPrototypes();
foreach ($signatures as $signature) {
$sigParams = $signature->getParameters();
$tmpParams = array();
foreach ($sigParams as $param) {
$tmpParams[] = $param->getType();
}
if ($sigCalled === $tmpParams) {
$matched = true;
break;
}
}
if (!$matched) {
throw new Zend_XmlRpc_Server_Exception('Calling parameters do not match signature', 623);
}
if ($info instanceof Zend_Server_Reflection_Function) {
$func = $info->getName();
$return = call_user_func_array($func, $params);
} elseif (($info instanceof Zend_Server_Reflection_Method) && $info->system) {
// System methods
$return = $info->invokeArgs($this, $params);
} elseif ($info instanceof Zend_Server_Reflection_Method) {
// Get class
$class = $info->getDeclaringClass()->getName();
if ('static' == $info->isStatic()) {
// for some reason, invokeArgs() does not work the same as
// invoke(), and expects the first argument to be an object.
// So, using a callback if the method is static.
$return = call_user_func_array(array($class, $info->getName()), $params);
} else {
// Object methods
try {
$object = $info->getDeclaringClass()->newInstance();
} catch (Exception $e) {
throw new Zend_XmlRpc_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName(), 621);
}
$return = $info->invokeArgs($object, $params);
}
} else {
throw new Zend_XmlRpc_Server_Exception('Method missing implementation ' . get_class($info), 622);
}
$response = new ReflectionClass($this->_responseClass);
return $response->newInstance($return);
}
/**
* Handle an xmlrpc call
*
* @param Zend_XmlRpc_Request $request Optional
* @return Zend_XmlRpc_Response|Zend_XmlRpc_Fault
*/
public function handle(Zend_XmlRpc_Request $request = null)
{
// Get request
if ((null === $request) && (null === ($request = $this->getRequest()))) {
require_once 'Zend/XmlRpc/Request/Http.php';
$request = new Zend_XmlRpc_Request_Http();
$request->setEncoding($this->getEncoding());
}
$this->setRequest($request);
if ($request->isFault()) {
$response = $request->getFault();
} else {
try {
$response = $this->_handle($request);
} catch (Exception $e) {
$response = $this->fault($e);
}
}
// Set output encoding
$response->setEncoding($this->getEncoding());
return $response;
}
/**
* Set the class to use for the response
*
* @param string $class
* @return boolean True if class was set, false if not
*/
public function setResponseClass($class)
{
if (class_exists($class)) {
$reflection = new ReflectionClass($class);
if ($reflection->isSubclassOf(new ReflectionClass('Zend_XmlRpc_Response'))) {
$this->_responseClass = $class;
return true;
}
}
return false;
}
/**
* Returns a list of registered methods
*
* Returns an array of dispatchables (Zend_Server_Reflection_Function,
* _Method, and _Class items).
*
* @return array
*/
public function getFunctions()
{
$return = array();
foreach ($this->_methods as $method) {
if ($method instanceof Zend_Server_Reflection_Class
&& ($method->system))
{
continue;
}
$return[] = $method;
}
return $return;
}
/**
* List all available XMLRPC methods
*
* Returns an array of methods.
*
* @return array
*/
public function listMethods()
{
return array_keys($this->_table);
}
/**
* Display help message for an XMLRPC method
*
* @param string $method
* @return string
*/
public function methodHelp($method)
{
if (!isset($this->_table[$method])) {
throw new Zend_Server_Exception('Method "' . $method . '"does not exist', 640);
}
return $this->_table[$method]->getDescription();
}
/**
* Return a method signature
*
* @param string $method
* @return array
*/
public function methodSignature($method)
{
if (!isset($this->_table[$method])) {
throw new Zend_Server_Exception('Method "' . $method . '"does not exist', 640);
}
$prototypes = $this->_table[$method]->getPrototypes();
$signatures = array();
foreach ($prototypes as $prototype) {
$signature = array($prototype->getReturnType());
foreach ($prototype->getParameters() as $parameter) {
$signature[] = $parameter->getType();
}
$signatures[] = $signature;
}
return $signatures;
}
/**
* Multicall - boxcar feature of XML-RPC for calling multiple methods
* in a single request.
*
* Expects a an array of structs representing method calls, each element
* having the keys:
* - methodName
* - params
*
* Returns an array of responses, one for each method called, with the value
* returned by the method. If an error occurs for a given method, returns a
* struct with a fault response.
*
* @see http://www.xmlrpc.com/discuss/msgReader$1208
* @param array $methods
* @return array
*/
public function multicall($methods)
{
$responses = array();
foreach ($methods as $method) {
$fault = false;
if (!is_array($method)) {
$fault = $this->fault('system.multicall expects each method to be a struct', 601);
} elseif (!isset($method['methodName'])) {
$fault = $this->fault('Missing methodName', 602);
} elseif (!isset($method['params'])) {
$fault = $this->fault('Missing params', 603);
} elseif (!is_array($method['params'])) {
$fault = $this->fault('Params must be an array', 604);
} else {
if ('system.multicall' == $method['methodName']) {
// don't allow recursive calls to multicall
$fault = $this->fault('Recursive system.multicall forbidden', 605);
}
}
if (!$fault) {
try {
$request = new Zend_XmlRpc_Request();
$request->setMethod($method['methodName']);
$request->setParams($method['params']);
$response = $this->_handle($request);
$responses[] = $response->getReturnValue();
} catch (Exception $e) {
$fault = $this->fault($e);
}
}
if ($fault) {
$responses[] = array(
'faultCode' => $fault->getCode(),
'faultString' => $fault->getMessage()
);
}
}
return $responses;
}
}