File indexing completed on 2024-12-22 05:37:14
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_XmlRpc 0017 * @subpackage Client 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 0024 /** 0025 * For handling the HTTP connection to the XML-RPC service 0026 * @see Zend_Http_Client 0027 */ 0028 // require_once 'Zend/Http/Client.php'; 0029 0030 /** 0031 * Enables object chaining for calling namespaced XML-RPC methods. 0032 * @see Zend_XmlRpc_Client_ServerProxy 0033 */ 0034 // require_once 'Zend/XmlRpc/Client/ServerProxy.php'; 0035 0036 /** 0037 * Introspects remote servers using the XML-RPC de facto system.* methods 0038 * @see Zend_XmlRpc_Client_ServerIntrospection 0039 */ 0040 // require_once 'Zend/XmlRpc/Client/ServerIntrospection.php'; 0041 0042 /** 0043 * Represent a native XML-RPC value, used both in sending parameters 0044 * to methods and as the parameters retrieve from method calls 0045 * @see Zend_XmlRpc_Value 0046 */ 0047 // require_once 'Zend/XmlRpc/Value.php'; 0048 0049 /** 0050 * XML-RPC Request 0051 * @see Zend_XmlRpc_Request 0052 */ 0053 // require_once 'Zend/XmlRpc/Request.php'; 0054 0055 /** 0056 * XML-RPC Response 0057 * @see Zend_XmlRpc_Response 0058 */ 0059 // require_once 'Zend/XmlRpc/Response.php'; 0060 0061 /** 0062 * XML-RPC Fault 0063 * @see Zend_XmlRpc_Fault 0064 */ 0065 // require_once 'Zend/XmlRpc/Fault.php'; 0066 0067 0068 /** 0069 * An XML-RPC client implementation 0070 * 0071 * @category Zend 0072 * @package Zend_XmlRpc 0073 * @subpackage Client 0074 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0075 * @license http://framework.zend.com/license/new-bsd New BSD License 0076 */ 0077 class Zend_XmlRpc_Client 0078 { 0079 /** 0080 * Full address of the XML-RPC service 0081 * @var string 0082 * @example http://time.xmlrpc.com/RPC2 0083 */ 0084 protected $_serverAddress; 0085 0086 /** 0087 * HTTP Client to use for requests 0088 * @var Zend_Http_Client 0089 */ 0090 protected $_httpClient = null; 0091 0092 /** 0093 * Introspection object 0094 * @var Zend_Http_Client_Introspector 0095 */ 0096 protected $_introspector = null; 0097 0098 /** 0099 * Request of the last method call 0100 * @var Zend_XmlRpc_Request 0101 */ 0102 protected $_lastRequest = null; 0103 0104 /** 0105 * Response received from the last method call 0106 * @var Zend_XmlRpc_Response 0107 */ 0108 protected $_lastResponse = null; 0109 0110 /** 0111 * Proxy object for more convenient method calls 0112 * @var array of Zend_XmlRpc_Client_ServerProxy 0113 */ 0114 protected $_proxyCache = array(); 0115 0116 /** 0117 * Flag for skipping system lookup 0118 * @var bool 0119 */ 0120 protected $_skipSystemLookup = false; 0121 0122 /** 0123 * Create a new XML-RPC client to a remote server 0124 * 0125 * @param string $server Full address of the XML-RPC service 0126 * (e.g. http://time.xmlrpc.com/RPC2) 0127 * @param Zend_Http_Client $httpClient HTTP Client to use for requests 0128 * @return void 0129 */ 0130 public function __construct($server, Zend_Http_Client $httpClient = null) 0131 { 0132 if ($httpClient === null) { 0133 $this->_httpClient = new Zend_Http_Client(); 0134 } else { 0135 $this->_httpClient = $httpClient; 0136 } 0137 0138 $this->_introspector = new Zend_XmlRpc_Client_ServerIntrospection($this); 0139 $this->_serverAddress = $server; 0140 } 0141 0142 0143 /** 0144 * Sets the HTTP client object to use for connecting the XML-RPC server. 0145 * 0146 * @param Zend_Http_Client $httpClient 0147 * @return Zend_Http_Client 0148 */ 0149 public function setHttpClient(Zend_Http_Client $httpClient) 0150 { 0151 return $this->_httpClient = $httpClient; 0152 } 0153 0154 0155 /** 0156 * Gets the HTTP client object. 0157 * 0158 * @return Zend_Http_Client 0159 */ 0160 public function getHttpClient() 0161 { 0162 return $this->_httpClient; 0163 } 0164 0165 0166 /** 0167 * Sets the object used to introspect remote servers 0168 * 0169 * @param Zend_XmlRpc_Client_ServerIntrospection 0170 * @return Zend_XmlRpc_Client_ServerIntrospection 0171 */ 0172 public function setIntrospector(Zend_XmlRpc_Client_ServerIntrospection $introspector) 0173 { 0174 return $this->_introspector = $introspector; 0175 } 0176 0177 0178 /** 0179 * Gets the introspection object. 0180 * 0181 * @return Zend_XmlRpc_Client_ServerIntrospection 0182 */ 0183 public function getIntrospector() 0184 { 0185 return $this->_introspector; 0186 } 0187 0188 0189 /** 0190 * The request of the last method call 0191 * 0192 * @return Zend_XmlRpc_Request 0193 */ 0194 public function getLastRequest() 0195 { 0196 return $this->_lastRequest; 0197 } 0198 0199 0200 /** 0201 * The response received from the last method call 0202 * 0203 * @return Zend_XmlRpc_Response 0204 */ 0205 public function getLastResponse() 0206 { 0207 return $this->_lastResponse; 0208 } 0209 0210 0211 /** 0212 * Returns a proxy object for more convenient method calls 0213 * 0214 * @param string $namespace Namespace to proxy or empty string for none 0215 * @return Zend_XmlRpc_Client_ServerProxy 0216 */ 0217 public function getProxy($namespace = '') 0218 { 0219 if (empty($this->_proxyCache[$namespace])) { 0220 $proxy = new Zend_XmlRpc_Client_ServerProxy($this, $namespace); 0221 $this->_proxyCache[$namespace] = $proxy; 0222 } 0223 return $this->_proxyCache[$namespace]; 0224 } 0225 0226 /** 0227 * Set skip system lookup flag 0228 * 0229 * @param bool $flag 0230 * @return Zend_XmlRpc_Client 0231 */ 0232 public function setSkipSystemLookup($flag = true) 0233 { 0234 $this->_skipSystemLookup = (bool) $flag; 0235 return $this; 0236 } 0237 0238 /** 0239 * Skip system lookup when determining if parameter should be array or struct? 0240 * 0241 * @return bool 0242 */ 0243 public function skipSystemLookup() 0244 { 0245 return $this->_skipSystemLookup; 0246 } 0247 0248 /** 0249 * Perform an XML-RPC request and return a response. 0250 * 0251 * @param Zend_XmlRpc_Request $request 0252 * @param null|Zend_XmlRpc_Response $response 0253 * @return void 0254 * @throws Zend_XmlRpc_Client_HttpException 0255 */ 0256 public function doRequest($request, $response = null) 0257 { 0258 $this->_lastRequest = $request; 0259 0260 if (PHP_VERSION_ID < 50600) { 0261 iconv_set_encoding('input_encoding', 'UTF-8'); 0262 iconv_set_encoding('output_encoding', 'UTF-8'); 0263 iconv_set_encoding('internal_encoding', 'UTF-8'); 0264 } else { 0265 ini_set('input_encoding', 'UTF-8'); 0266 ini_set('output_encoding', 'UTF-8'); 0267 ini_set('default_charset', 'UTF-8'); 0268 } 0269 0270 $http = $this->getHttpClient(); 0271 if($http->getUri() === null) { 0272 $http->setUri($this->_serverAddress); 0273 } 0274 0275 $http->setHeaders(array( 0276 'Content-Type: text/xml; charset=utf-8', 0277 'Accept: text/xml', 0278 )); 0279 0280 if ($http->getHeader('user-agent') === null) { 0281 $http->setHeaders(array('User-Agent: Zend_XmlRpc_Client')); 0282 } 0283 0284 $xml = $this->_lastRequest->__toString(); 0285 $http->setRawData($xml); 0286 $httpResponse = $http->request(Zend_Http_Client::POST); 0287 0288 if (! $httpResponse->isSuccessful()) { 0289 /** 0290 * Exception thrown when an HTTP error occurs 0291 * @see Zend_XmlRpc_Client_HttpException 0292 */ 0293 // require_once 'Zend/XmlRpc/Client/HttpException.php'; 0294 throw new Zend_XmlRpc_Client_HttpException( 0295 $httpResponse->getMessage(), 0296 $httpResponse->getStatus()); 0297 } 0298 0299 if ($response === null) { 0300 $response = new Zend_XmlRpc_Response(); 0301 } 0302 $this->_lastResponse = $response; 0303 $this->_lastResponse->loadXml(trim($httpResponse->getBody())); 0304 } 0305 0306 /** 0307 * Send an XML-RPC request to the service (for a specific method) 0308 * 0309 * @param string $method Name of the method we want to call 0310 * @param array $params Array of parameters for the method 0311 * @return mixed 0312 * @throws Zend_XmlRpc_Client_FaultException 0313 */ 0314 public function call($method, $params=array()) 0315 { 0316 if (!$this->skipSystemLookup() && ('system.' != substr($method, 0, 7))) { 0317 // Ensure empty array/struct params are cast correctly 0318 // If system.* methods are not available, bypass. (ZF-2978) 0319 $success = true; 0320 try { 0321 $signatures = $this->getIntrospector()->getMethodSignature($method); 0322 } catch (Zend_XmlRpc_Exception $e) { 0323 $success = false; 0324 } 0325 if ($success) { 0326 $validTypes = array( 0327 Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY, 0328 Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64, 0329 Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN, 0330 Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME, 0331 Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE, 0332 Zend_XmlRpc_Value::XMLRPC_TYPE_I4, 0333 Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER, 0334 Zend_XmlRpc_Value::XMLRPC_TYPE_NIL, 0335 Zend_XmlRpc_Value::XMLRPC_TYPE_STRING, 0336 Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT, 0337 ); 0338 0339 if (!is_array($params)) { 0340 $params = array($params); 0341 } 0342 0343 foreach ($params as $key => $param) 0344 { 0345 if ($param instanceof Zend_XmlRpc_Value) { 0346 continue; 0347 } 0348 0349 if (count($signatures) > 1) { 0350 $type = Zend_XmlRpc_Value::getXmlRpcTypeByValue($param); 0351 foreach ($signatures as $signature) { 0352 if (!is_array($signature)) { 0353 continue; 0354 } 0355 if (isset($signature['parameters'][$key])) { 0356 if ($signature['parameters'][$key] == $type) { 0357 break; 0358 } 0359 } 0360 } 0361 } elseif (isset($signatures[0]['parameters'][$key])) { 0362 $type = $signatures[0]['parameters'][$key]; 0363 } else { 0364 $type = null; 0365 } 0366 0367 if (empty($type) || !in_array($type, $validTypes)) { 0368 $type = Zend_XmlRpc_Value::AUTO_DETECT_TYPE; 0369 } 0370 0371 $params[$key] = Zend_XmlRpc_Value::getXmlRpcValue($param, $type); 0372 } 0373 } 0374 } 0375 0376 $request = $this->_createRequest($method, $params); 0377 0378 $this->doRequest($request); 0379 0380 if ($this->_lastResponse->isFault()) { 0381 $fault = $this->_lastResponse->getFault(); 0382 /** 0383 * Exception thrown when an XML-RPC fault is returned 0384 * @see Zend_XmlRpc_Client_FaultException 0385 */ 0386 // require_once 'Zend/XmlRpc/Client/FaultException.php'; 0387 throw new Zend_XmlRpc_Client_FaultException($fault->getMessage(), 0388 $fault->getCode()); 0389 } 0390 0391 return $this->_lastResponse->getReturnValue(); 0392 } 0393 0394 /** 0395 * Create request object 0396 * 0397 * @return Zend_XmlRpc_Request 0398 */ 0399 protected function _createRequest($method, $params) 0400 { 0401 return new Zend_XmlRpc_Request($method, $params); 0402 } 0403 }