/** * Handle an xmlrpc call (actual work) * * @param Polycast_XmlRpc_Request $request * @return Polycast_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(Polycast_XmlRpc_Request $request) { $method = $request->getMethod(); // Check for valid method if (!$this->_table->hasMethod($method)) { require_once 'Polycast/XmlRpc/Server/Exception.php'; throw new Polycast_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 = Polycast_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 'Polycast/XmlRpc/Server/Exception.php'; throw new Polycast_XmlRpc_Server_Exception('Calling parameters do not match signature', 623); } $return = $this->_dispatch($info, $params); $responseClass = $this->getResponseClass(); return new $responseClass($return); }
/** * 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->_server->fault('system.multicall expects each method to be a struct', 601); } elseif (!isset($method['methodName'])) { $fault = $this->_server->fault('Missing methodName: ' . var_export($methods, 1), 602); } elseif (!isset($method['params'])) { $fault = $this->_server->fault('Missing params', 603); } elseif (!is_array($method['params'])) { $fault = $this->_server->fault('Params must be an array', 604); } else { if ('system.multicall' == $method['methodName']) { // don't allow recursive calls to multicall $fault = $this->_server->fault('Recursive system.multicall forbidden', 605); } } if (!$fault) { try { $request = new Polycast_XmlRpc_Request(); $request->setMethod($method['methodName']); $request->setParams($method['params']); $response = $this->_server->handle($request); if ($response instanceof Polycast_XmlRpc_Fault || $response->isFault()) { $fault = $response; } else { $responses[] = $response->getReturnValue(); } } catch (Exception $e) { $fault = $this->_server->fault($e); } } if ($fault) { $responses[] = array('faultCode' => $fault->getCode(), 'faultString' => $fault->getMessage()); } } return $responses; }
/** * Perform an XML-RPC request and return a response. * * @param Polycast_XmlRpc_Request $request * @param null|Polycast_XmlRpc_Response $response * @return void * @throws Polycast_XmlRpc_Client_HttpException */ public function doRequest($request, $response = null) { $this->_lastRequest = $request; iconv_set_encoding('input_encoding', 'UTF-8'); iconv_set_encoding('output_encoding', 'UTF-8'); iconv_set_encoding('internal_encoding', 'UTF-8'); $http = $this->getHttpClient(); if ($http->getUri() === null) { $http->setUri($this->_serverAddress); } $http->setHeaders(array('Content-Type: text/xml; charset=utf-8', 'Accept: text/xml')); if ($http->getHeader('user-agent') === null) { $http->setHeaders(array('User-Agent: Polycast_XmlRpc_Client')); } $xml = $this->_lastRequest->__toString(); $http->setRawData($xml); $httpResponse = $http->request(Zend_Http_Client::POST); if (!$httpResponse->isSuccessful()) { /** * Exception thrown when an HTTP error occurs * @see Polycast_XmlRpc_Client_HttpException */ require_once 'Polycast/XmlRpc/Client/HttpException.php'; throw new Polycast_XmlRpc_Client_HttpException($httpResponse->getMessage(), $httpResponse->getStatus()); } if ($response === null) { $response = new Polycast_XmlRpc_Response(); } $this->_lastResponse = $response; $this->_lastResponse->loadXml($httpResponse->getBody()); }