| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615 |
- <?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-2015 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
- */
- /**
- * Extends Zend_Server_Abstract
- */
- require_once 'Zend/Server/Abstract.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';
- /**
- * XMLRPC server system methods class
- */
- require_once 'Zend/XmlRpc/Server/System.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-2015 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
- class Zend_XmlRpc_Server extends Zend_Server_Abstract
- {
- /**
- * Character encoding
- * @var string
- */
- protected $_encoding = 'UTF-8';
- /**
- * 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 Zend_Server_Definition
- */
- protected $_table;
- /**
- * PHP types => XML-RPC types
- * @var array
- */
- protected $_typeMap = array(
- 'i4' => 'i4',
- 'int' => 'int',
- 'integer' => 'int',
- 'Zend_Crypt_Math_BigInteger' => 'i8',
- 'i8' => 'i8',
- 'ex:i8' => 'i8',
- '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',
- 'Zend_Date' => 'dateTime.iso8601',
- 'DateTime' => 'dateTime.iso8601',
- 'array' => 'array',
- 'struct' => 'struct',
- 'null' => 'nil',
- 'nil' => 'nil',
- 'ex:nil' => 'nil',
- 'void' => 'void',
- 'mixed' => 'struct',
- );
- /**
- * Send arguments to all methods or just constructor?
- *
- * @var bool
- */
- protected $_sendArgumentsToAllMethods = true;
- /**
- * Constructor
- *
- * Creates system.* methods.
- *
- * @return void
- */
- public function __construct()
- {
- $this->_table = new Zend_Server_Definition();
- $this->_registerSystemMethods();
- }
- /**
- * Proxy calls to system object
- *
- * @param string $method
- * @param array $params
- * @return mixed
- * @throws Zend_XmlRpc_Server_Exception
- */
- public function __call($method, $params)
- {
- $system = $this->getSystem();
- if (!method_exists($system, $method)) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Unknown instance method called on server: ' . $method);
- }
- return call_user_func_array(array($system, $method), $params);
- }
- /**
- * 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)) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- 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)) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Unable to attach function; invalid', 611);
- }
- $reflection = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
- $this->_buildSignature($reflection);
- }
- }
- /**
- * 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)) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
- }
- $args = null;
- if (2 < func_num_args()) {
- $args = func_get_args();
- $args = array_slice($args, 2);
- }
- $dispatchable = Zend_Server_Reflection::reflectClass($class, $args, $namespace);
- foreach ($dispatchable->getMethods() as $reflection) {
- $this->_buildSignature($reflection, $class);
- }
- }
- /**
- * Raise an xmlrpc server fault
- *
- * @param string|Exception $fault
- * @param int $code
- * @return Zend_XmlRpc_Server_Fault
- */
- public function fault($fault = null, $code = 404)
- {
- if (!$fault instanceof Exception) {
- $fault = (string) $fault;
- if (empty($fault)) {
- $fault = 'Unknown Error';
- }
- require_once 'Zend/XmlRpc/Server/Exception.php';
- $fault = new Zend_XmlRpc_Server_Exception($fault, $code);
- }
- return Zend_XmlRpc_Server_Fault::getInstance($fault);
- }
- /**
- * Handle an xmlrpc call
- *
- * @param Zend_XmlRpc_Request $request Optional
- * @return Zend_XmlRpc_Response|Zend_XmlRpc_Fault
- */
- public function handle($request = false)
- {
- // Get request
- if ((!$request || !$request instanceof Zend_XmlRpc_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;
- }
- /**
- * 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|Zend_Server_Definition $definition
- * @return void
- * @throws Zend_XmlRpc_Server_Exception on invalid input
- */
- public function loadFunctions($definition)
- {
- if (!is_array($definition) && (!$definition instanceof Zend_Server_Definition)) {
- if (is_object($definition)) {
- $type = get_class($definition);
- } else {
- $type = gettype($definition);
- }
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Unable to load server definition; must be an array or Zend_Server_Definition, received ' . $type, 612);
- }
- $this->_table->clearMethods();
- $this->_registerSystemMethods();
- if ($definition instanceof Zend_Server_Definition) {
- $definition = $definition->getMethods();
- }
- foreach ($definition as $key => $method) {
- if ('system.' == substr($key, 0, 7)) {
- continue;
- }
- $this->_table->addMethod($method, $key);
- }
- }
- /**
- * Set encoding
- *
- * @param string $encoding
- * @return Zend_XmlRpc_Server
- */
- public function setEncoding($encoding)
- {
- $this->_encoding = $encoding;
- Zend_XmlRpc_Value::setEncoding($encoding);
- return $this;
- }
- /**
- * Retrieve current encoding
- *
- * @return string
- */
- public function getEncoding()
- {
- return $this->_encoding;
- }
- /**
- * Do nothing; persistence is handled via {@link Zend_XmlRpc_Server_Cache}
- *
- * @param mixed $mode
- * @return void
- */
- public function setPersistence($mode)
- {
- }
- /**
- * 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) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Invalid request class');
- }
- $request->setEncoding($this->getEncoding());
- } elseif (!$request instanceof Zend_XmlRpc_Request) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- 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;
- }
- /**
- * 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) or
- ($c = new ReflectionClass($class) and !$c->isSubclassOf('Zend_XmlRpc_Response'))) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Invalid response class');
- }
- $this->_responseClass = $class;
- return true;
- }
- /**
- * Retrieve current response class
- *
- * @return string
- */
- public function getResponseClass()
- {
- return $this->_responseClass;
- }
- /**
- * Retrieve dispatch table
- *
- * @return array
- */
- public function getDispatchTable()
- {
- return $this->_table;
- }
- /**
- * 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 $this->_table->toArray();
- }
- /**
- * Retrieve system object
- *
- * @return Zend_XmlRpc_Server_System
- */
- public function getSystem()
- {
- return $this->_system;
- }
- /**
- * Send arguments to all methods?
- *
- * If setClass() is used to add classes to the server, this flag defined
- * how to handle arguments. If set to true, all methods including constructor
- * will receive the arguments. If set to false, only constructor will receive the
- * arguments
- */
- public function sendArgumentsToAllMethods($flag = null)
- {
- if ($flag === null) {
- return $this->_sendArgumentsToAllMethods;
- }
- $this->_sendArgumentsToAllMethods = (bool)$flag;
- return $this;
- }
- /**
- * Map PHP type to XML-RPC type
- *
- * @param string $type
- * @return string
- */
- protected function _fixType($type)
- {
- if (isset($this->_typeMap[$type])) {
- return $this->_typeMap[$type];
- }
- return 'void';
- }
- /**
- * 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 (!$this->_table->hasMethod($method)) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Method "' . $method . '" does not exist', 620);
- }
- $info = $this->_table->getMethod($method);
- $params = $request->getParams();
- $argv = $info->getInvokeArguments();
- if (0 < count($argv) and $this->sendArgumentsToAllMethods()) {
- $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();
- if ($sigCalled === $sigParams) {
- $matched = true;
- break;
- }
- }
- if (!$matched) {
- require_once 'Zend/XmlRpc/Server/Exception.php';
- throw new Zend_XmlRpc_Server_Exception('Calling parameters do not match signature', 623);
- }
- $return = $this->_dispatch($info, $params);
- $responseClass = $this->getResponseClass();
- return new $responseClass($return);
- }
- /**
- * Register system methods with the server
- *
- * @return void
- */
- protected function _registerSystemMethods()
- {
- $system = new Zend_XmlRpc_Server_System($this);
- $this->_system = $system;
- $this->setClass($system, 'system');
- }
- }
|