PageRenderTime 25ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/XmlRpc/Request.php

https://github.com/shevron/zf2
PHP | 422 lines | 222 code | 43 blank | 157 comment | 29 complexity | 437953a7b148bdeb045f69ae61affe96 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_XmlRpc
  9. */
  10. namespace Zend\XmlRpc;
  11. /**
  12. * XmlRpc Request object
  13. *
  14. * Encapsulates an XmlRpc request, holding the method call and all parameters.
  15. * Provides accessors for these, as well as the ability to load from XML and to
  16. * create the XML request string.
  17. *
  18. * Additionally, if errors occur setting the method or parsing XML, a fault is
  19. * generated and stored in {@link $_fault}; developers may check for it using
  20. * {@link isFault()} and {@link getFault()}.
  21. *
  22. * @category Zend
  23. * @package Zend_XmlRpc
  24. */
  25. class Request
  26. {
  27. /**
  28. * Request character encoding
  29. * @var string
  30. */
  31. protected $_encoding = 'UTF-8';
  32. /**
  33. * Method to call
  34. * @var string
  35. */
  36. protected $_method;
  37. /**
  38. * XML request
  39. * @var string
  40. */
  41. protected $_xml;
  42. /**
  43. * Method parameters
  44. * @var array
  45. */
  46. protected $_params = array();
  47. /**
  48. * Fault object, if any
  49. * @var Zend\XmlRpc\Fault
  50. */
  51. protected $_fault = null;
  52. /**
  53. * XML-RPC type for each param
  54. * @var array
  55. */
  56. protected $_types = array();
  57. /**
  58. * XML-RPC request params
  59. * @var array
  60. */
  61. protected $_xmlRpcParams = array();
  62. /**
  63. * Create a new XML-RPC request
  64. *
  65. * @param string $method (optional)
  66. * @param array $params (optional)
  67. */
  68. public function __construct($method = null, $params = null)
  69. {
  70. if ($method !== null) {
  71. $this->setMethod($method);
  72. }
  73. if ($params !== null) {
  74. $this->setParams($params);
  75. }
  76. }
  77. /**
  78. * Set encoding to use in request
  79. *
  80. * @param string $encoding
  81. * @return Zend\XmlRpc\Request
  82. */
  83. public function setEncoding($encoding)
  84. {
  85. $this->_encoding = $encoding;
  86. AbstractValue::setEncoding($encoding);
  87. return $this;
  88. }
  89. /**
  90. * Retrieve current request encoding
  91. *
  92. * @return string
  93. */
  94. public function getEncoding()
  95. {
  96. return $this->_encoding;
  97. }
  98. /**
  99. * Set method to call
  100. *
  101. * @param string $method
  102. * @return boolean Returns true on success, false if method name is invalid
  103. */
  104. public function setMethod($method)
  105. {
  106. if (!is_string($method) || !preg_match('/^[a-z0-9_.:\\\\\/]+$/i', $method)) {
  107. $this->_fault = new Fault(634, 'Invalid method name ("' . $method . '")');
  108. $this->_fault->setEncoding($this->getEncoding());
  109. return false;
  110. }
  111. $this->_method = $method;
  112. return true;
  113. }
  114. /**
  115. * Retrieve call method
  116. *
  117. * @return string
  118. */
  119. public function getMethod()
  120. {
  121. return $this->_method;
  122. }
  123. /**
  124. * Add a parameter to the parameter stack
  125. *
  126. * Adds a parameter to the parameter stack, associating it with the type
  127. * $type if provided
  128. *
  129. * @param mixed $value
  130. * @param string $type Optional; type hinting
  131. * @return void
  132. */
  133. public function addParam($value, $type = null)
  134. {
  135. $this->_params[] = $value;
  136. if (null === $type) {
  137. // Detect type if not provided explicitly
  138. if ($value instanceof AbstractValue) {
  139. $type = $value->getType();
  140. } else {
  141. $xmlRpcValue = AbstractValue::getXmlRpcValue($value);
  142. $type = $xmlRpcValue->getType();
  143. }
  144. }
  145. $this->_types[] = $type;
  146. $this->_xmlRpcParams[] = array('value' => $value, 'type' => $type);
  147. }
  148. /**
  149. * Set the parameters array
  150. *
  151. * If called with a single, array value, that array is used to set the
  152. * parameters stack. If called with multiple values or a single non-array
  153. * value, the arguments are used to set the parameters stack.
  154. *
  155. * Best is to call with array of the format, in order to allow type hinting
  156. * when creating the XMLRPC values for each parameter:
  157. * <code>
  158. * $array = array(
  159. * array(
  160. * 'value' => $value,
  161. * 'type' => $type
  162. * )[, ... ]
  163. * );
  164. * </code>
  165. *
  166. * @access public
  167. * @return void
  168. */
  169. public function setParams()
  170. {
  171. $argc = func_num_args();
  172. $argv = func_get_args();
  173. if (0 == $argc) {
  174. return;
  175. }
  176. if ((1 == $argc) && is_array($argv[0])) {
  177. $params = array();
  178. $types = array();
  179. $wellFormed = true;
  180. foreach ($argv[0] as $arg) {
  181. if (!is_array($arg) || !isset($arg['value'])) {
  182. $wellFormed = false;
  183. break;
  184. }
  185. $params[] = $arg['value'];
  186. if (!isset($arg['type'])) {
  187. $xmlRpcValue = AbstractValue::getXmlRpcValue($arg['value']);
  188. $arg['type'] = $xmlRpcValue->getType();
  189. }
  190. $types[] = $arg['type'];
  191. }
  192. if ($wellFormed) {
  193. $this->_xmlRpcParams = $argv[0];
  194. $this->_params = $params;
  195. $this->_types = $types;
  196. } else {
  197. $this->_params = $argv[0];
  198. $this->_types = array();
  199. $xmlRpcParams = array();
  200. foreach ($argv[0] as $arg) {
  201. if ($arg instanceof AbstractValue) {
  202. $type = $arg->getType();
  203. } else {
  204. $xmlRpcValue = AbstractValue::getXmlRpcValue($arg);
  205. $type = $xmlRpcValue->getType();
  206. }
  207. $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
  208. $this->_types[] = $type;
  209. }
  210. $this->_xmlRpcParams = $xmlRpcParams;
  211. }
  212. return;
  213. }
  214. $this->_params = $argv;
  215. $this->_types = array();
  216. $xmlRpcParams = array();
  217. foreach ($argv as $arg) {
  218. if ($arg instanceof AbstractValue) {
  219. $type = $arg->getType();
  220. } else {
  221. $xmlRpcValue = AbstractValue::getXmlRpcValue($arg);
  222. $type = $xmlRpcValue->getType();
  223. }
  224. $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
  225. $this->_types[] = $type;
  226. }
  227. $this->_xmlRpcParams = $xmlRpcParams;
  228. }
  229. /**
  230. * Retrieve the array of parameters
  231. *
  232. * @return array
  233. */
  234. public function getParams()
  235. {
  236. return $this->_params;
  237. }
  238. /**
  239. * Return parameter types
  240. *
  241. * @return array
  242. */
  243. public function getTypes()
  244. {
  245. return $this->_types;
  246. }
  247. /**
  248. * Load XML and parse into request components
  249. *
  250. * @param string $request
  251. * @return boolean True on success, false if an error occurred.
  252. */
  253. public function loadXml($request)
  254. {
  255. if (!is_string($request)) {
  256. $this->_fault = new Fault(635);
  257. $this->_fault->setEncoding($this->getEncoding());
  258. return false;
  259. }
  260. // @see ZF-12293 - disable external entities for security purposes
  261. $loadEntities = libxml_disable_entity_loader(true);
  262. try {
  263. $xml = new \SimpleXMLElement($request);
  264. libxml_disable_entity_loader($loadEntities);
  265. } catch (\Exception $e) {
  266. // Not valid XML
  267. $this->_fault = new Fault(631);
  268. $this->_fault->setEncoding($this->getEncoding());
  269. libxml_disable_entity_loader($loadEntities);
  270. return false;
  271. }
  272. // Check for method name
  273. if (empty($xml->methodName)) {
  274. // Missing method name
  275. $this->_fault = new Fault(632);
  276. $this->_fault->setEncoding($this->getEncoding());
  277. return false;
  278. }
  279. $this->_method = (string) $xml->methodName;
  280. // Check for parameters
  281. if (!empty($xml->params)) {
  282. $types = array();
  283. $argv = array();
  284. foreach ($xml->params->children() as $param) {
  285. if (!isset($param->value)) {
  286. $this->_fault = new Fault(633);
  287. $this->_fault->setEncoding($this->getEncoding());
  288. return false;
  289. }
  290. try {
  291. $param = AbstractValue::getXmlRpcValue($param->value, AbstractValue::XML_STRING);
  292. $types[] = $param->getType();
  293. $argv[] = $param->getValue();
  294. } catch (\Exception $e) {
  295. $this->_fault = new Fault(636);
  296. $this->_fault->setEncoding($this->getEncoding());
  297. return false;
  298. }
  299. }
  300. $this->_types = $types;
  301. $this->_params = $argv;
  302. }
  303. $this->_xml = $request;
  304. return true;
  305. }
  306. /**
  307. * Does the current request contain errors and should it return a fault
  308. * response?
  309. *
  310. * @return boolean
  311. */
  312. public function isFault()
  313. {
  314. return $this->_fault instanceof Fault;
  315. }
  316. /**
  317. * Retrieve the fault response, if any
  318. *
  319. * @return null|Zend\XmlRpc\Fault
  320. */
  321. public function getFault()
  322. {
  323. return $this->_fault;
  324. }
  325. /**
  326. * Retrieve method parameters as XMLRPC values
  327. *
  328. * @return array
  329. */
  330. protected function _getXmlRpcParams()
  331. {
  332. $params = array();
  333. if (is_array($this->_xmlRpcParams)) {
  334. foreach ($this->_xmlRpcParams as $param) {
  335. $value = $param['value'];
  336. $type = $param['type'] ?: AbstractValue::AUTO_DETECT_TYPE;
  337. if (!$value instanceof AbstractValue) {
  338. $value = AbstractValue::getXmlRpcValue($value, $type);
  339. }
  340. $params[] = $value;
  341. }
  342. }
  343. return $params;
  344. }
  345. /**
  346. * Create XML request
  347. *
  348. * @return string
  349. */
  350. public function saveXml()
  351. {
  352. $args = $this->_getXmlRpcParams();
  353. $method = $this->getMethod();
  354. $generator = AbstractValue::getGenerator();
  355. $generator->openElement('methodCall')
  356. ->openElement('methodName', $method)
  357. ->closeElement('methodName');
  358. if (is_array($args) && count($args)) {
  359. $generator->openElement('params');
  360. foreach ($args as $arg) {
  361. $generator->openElement('param');
  362. $arg->generateXml();
  363. $generator->closeElement('param');
  364. }
  365. $generator->closeElement('params');
  366. }
  367. $generator->closeElement('methodCall');
  368. return $generator->flush();
  369. }
  370. /**
  371. * Return XML request
  372. *
  373. * @return string
  374. */
  375. public function __toString()
  376. {
  377. return $this->saveXML();
  378. }
  379. }