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_Controller
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  */
0020 
0021 /**
0022  * Zend_XmlRpc_Value
0023  */
0024 // require_once 'Zend/XmlRpc/Value.php';
0025 
0026 /**
0027  * Zend_XmlRpc_Fault
0028  */
0029 // require_once 'Zend/XmlRpc/Fault.php';
0030 
0031 /** @see Zend_Xml_Security */
0032 // require_once 'Zend/Xml/Security.php';
0033 
0034 /** @see Zend_Xml_Exception */
0035 // require_once 'Zend/Xml/Exception.php';
0036 
0037 /**
0038  * XmlRpc Request object
0039  *
0040  * Encapsulates an XmlRpc request, holding the method call and all parameters.
0041  * Provides accessors for these, as well as the ability to load from XML and to
0042  * create the XML request string.
0043  *
0044  * Additionally, if errors occur setting the method or parsing XML, a fault is
0045  * generated and stored in {@link $_fault}; developers may check for it using
0046  * {@link isFault()} and {@link getFault()}.
0047  *
0048  * @category Zend
0049  * @package  Zend_XmlRpc
0050  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0051  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0052  * @version $Id$
0053  */
0054 class Zend_XmlRpc_Request
0055 {
0056     /**
0057      * Request character encoding
0058      * @var string
0059      */
0060     protected $_encoding = 'UTF-8';
0061 
0062     /**
0063      * Method to call
0064      * @var string
0065      */
0066     protected $_method;
0067 
0068     /**
0069      * XML request
0070      * @var string
0071      */
0072     protected $_xml;
0073 
0074     /**
0075      * Method parameters
0076      * @var array
0077      */
0078     protected $_params = array();
0079 
0080     /**
0081      * Fault object, if any
0082      * @var Zend_XmlRpc_Fault
0083      */
0084     protected $_fault = null;
0085 
0086     /**
0087      * XML-RPC type for each param
0088      * @var array
0089      */
0090     protected $_types = array();
0091 
0092     /**
0093      * XML-RPC request params
0094      * @var array
0095      */
0096     protected $_xmlRpcParams = array();
0097 
0098     /**
0099      * Create a new XML-RPC request
0100      *
0101      * @param string $method (optional)
0102      * @param array $params  (optional)
0103      */
0104     public function __construct($method = null, $params = null)
0105     {
0106         if ($method !== null) {
0107             $this->setMethod($method);
0108         }
0109 
0110         if ($params !== null) {
0111             $this->setParams($params);
0112         }
0113     }
0114 
0115 
0116     /**
0117      * Set encoding to use in request
0118      *
0119      * @param string $encoding
0120      * @return Zend_XmlRpc_Request
0121      */
0122     public function setEncoding($encoding)
0123     {
0124         $this->_encoding = $encoding;
0125         Zend_XmlRpc_Value::setEncoding($encoding);
0126         return $this;
0127     }
0128 
0129     /**
0130      * Retrieve current request encoding
0131      *
0132      * @return string
0133      */
0134     public function getEncoding()
0135     {
0136         return $this->_encoding;
0137     }
0138 
0139     /**
0140      * Set method to call
0141      *
0142      * @param string $method
0143      * @return boolean Returns true on success, false if method name is invalid
0144      */
0145     public function setMethod($method)
0146     {
0147         if (!is_string($method) || !preg_match('/^[a-z0-9_.:\/]+$/i', $method)) {
0148             $this->_fault = new Zend_XmlRpc_Fault(634, 'Invalid method name ("' . $method . '")');
0149             $this->_fault->setEncoding($this->getEncoding());
0150             return false;
0151         }
0152 
0153         $this->_method = $method;
0154         return true;
0155     }
0156 
0157     /**
0158      * Retrieve call method
0159      *
0160      * @return string
0161      */
0162     public function getMethod()
0163     {
0164         return $this->_method;
0165     }
0166 
0167     /**
0168      * Add a parameter to the parameter stack
0169      *
0170      * Adds a parameter to the parameter stack, associating it with the type
0171      * $type if provided
0172      *
0173      * @param mixed $value
0174      * @param string $type Optional; type hinting
0175      * @return void
0176      */
0177     public function addParam($value, $type = null)
0178     {
0179         $this->_params[] = $value;
0180         if (null === $type) {
0181             // Detect type if not provided explicitly
0182             if ($value instanceof Zend_XmlRpc_Value) {
0183                 $type = $value->getType();
0184             } else {
0185                 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($value);
0186                 $type        = $xmlRpcValue->getType();
0187             }
0188         }
0189         $this->_types[]  = $type;
0190         $this->_xmlRpcParams[] = array('value' => $value, 'type' => $type);
0191     }
0192 
0193     /**
0194      * Set the parameters array
0195      *
0196      * If called with a single, array value, that array is used to set the
0197      * parameters stack. If called with multiple values or a single non-array
0198      * value, the arguments are used to set the parameters stack.
0199      *
0200      * Best is to call with array of the format, in order to allow type hinting
0201      * when creating the XMLRPC values for each parameter:
0202      * <code>
0203      * $array = array(
0204      *     array(
0205      *         'value' => $value,
0206      *         'type'  => $type
0207      *     )[, ... ]
0208      * );
0209      * </code>
0210      *
0211      * @access public
0212      * @return void
0213      */
0214     public function setParams()
0215     {
0216         $argc = func_num_args();
0217         $argv = func_get_args();
0218         if (0 == $argc) {
0219             return;
0220         }
0221 
0222         if ((1 == $argc) && is_array($argv[0])) {
0223             $params     = array();
0224             $types      = array();
0225             $wellFormed = true;
0226             foreach ($argv[0] as $arg) {
0227                 if (!is_array($arg) || !isset($arg['value'])) {
0228                     $wellFormed = false;
0229                     break;
0230                 }
0231                 $params[] = $arg['value'];
0232 
0233                 if (!isset($arg['type'])) {
0234                     $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg['value']);
0235                     $arg['type'] = $xmlRpcValue->getType();
0236                 }
0237                 $types[] = $arg['type'];
0238             }
0239             if ($wellFormed) {
0240                 $this->_xmlRpcParams = $argv[0];
0241                 $this->_params = $params;
0242                 $this->_types  = $types;
0243             } else {
0244                 $this->_params = $argv[0];
0245                 $this->_types  = array();
0246                 $xmlRpcParams  = array();
0247                 foreach ($argv[0] as $arg) {
0248                     if ($arg instanceof Zend_XmlRpc_Value) {
0249                         $type = $arg->getType();
0250                     } else {
0251                         $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg);
0252                         $type        = $xmlRpcValue->getType();
0253                     }
0254                     $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
0255                     $this->_types[] = $type;
0256                 }
0257                 $this->_xmlRpcParams = $xmlRpcParams;
0258             }
0259             return;
0260         }
0261 
0262         $this->_params = $argv;
0263         $this->_types  = array();
0264         $xmlRpcParams  = array();
0265         foreach ($argv as $arg) {
0266             if ($arg instanceof Zend_XmlRpc_Value) {
0267                 $type = $arg->getType();
0268             } else {
0269                 $xmlRpcValue = Zend_XmlRpc_Value::getXmlRpcValue($arg);
0270                 $type        = $xmlRpcValue->getType();
0271             }
0272             $xmlRpcParams[] = array('value' => $arg, 'type' => $type);
0273             $this->_types[] = $type;
0274         }
0275         $this->_xmlRpcParams = $xmlRpcParams;
0276     }
0277 
0278     /**
0279      * Retrieve the array of parameters
0280      *
0281      * @return array
0282      */
0283     public function getParams()
0284     {
0285         return $this->_params;
0286     }
0287 
0288     /**
0289      * Return parameter types
0290      *
0291      * @return array
0292      */
0293     public function getTypes()
0294     {
0295         return $this->_types;
0296     }
0297 
0298     /**
0299      * Load XML and parse into request components
0300      *
0301      * @param string $request
0302      * @return boolean True on success, false if an error occurred.
0303      */
0304     public function loadXml($request)
0305     {
0306         if (!is_string($request)) {
0307             $this->_fault = new Zend_XmlRpc_Fault(635);
0308             $this->_fault->setEncoding($this->getEncoding());
0309             return false;
0310         }
0311 
0312         try {
0313             $xml = Zend_Xml_Security::scan($request);
0314         } catch (Zend_Xml_Exception $e) {
0315             // Not valid XML
0316             $this->_fault = new Zend_XmlRpc_Fault(631);
0317             $this->_fault->setEncoding($this->getEncoding());
0318             return false;
0319         }
0320 
0321         // Check for method name
0322         if (empty($xml->methodName)) {
0323             // Missing method name
0324             $this->_fault = new Zend_XmlRpc_Fault(632);
0325             $this->_fault->setEncoding($this->getEncoding());
0326             return false;
0327         }
0328 
0329         $this->_method = (string) $xml->methodName;
0330 
0331         // Check for parameters
0332         if (!empty($xml->params)) {
0333             $types = array();
0334             $argv  = array();
0335             foreach ($xml->params->children() as $param) {
0336                 if (!isset($param->value)) {
0337                     $this->_fault = new Zend_XmlRpc_Fault(633);
0338                     $this->_fault->setEncoding($this->getEncoding());
0339                     return false;
0340                 }
0341 
0342                 try {
0343                     $param   = Zend_XmlRpc_Value::getXmlRpcValue($param->value, Zend_XmlRpc_Value::XML_STRING);
0344                     $types[] = $param->getType();
0345                     $argv[]  = $param->getValue();
0346                 } catch (Exception $e) {
0347                     $this->_fault = new Zend_XmlRpc_Fault(636);
0348                     $this->_fault->setEncoding($this->getEncoding());
0349                     return false;
0350                 }
0351             }
0352 
0353             $this->_types  = $types;
0354             $this->_params = $argv;
0355         }
0356 
0357         $this->_xml = $request;
0358 
0359         return true;
0360     }
0361 
0362     /**
0363      * Does the current request contain errors and should it return a fault
0364      * response?
0365      *
0366      * @return boolean
0367      */
0368     public function isFault()
0369     {
0370         return $this->_fault instanceof Zend_XmlRpc_Fault;
0371     }
0372 
0373     /**
0374      * Retrieve the fault response, if any
0375      *
0376      * @return null|Zend_XmlRpc_Fault
0377      */
0378     public function getFault()
0379     {
0380         return $this->_fault;
0381     }
0382 
0383     /**
0384      * Retrieve method parameters as XMLRPC values
0385      *
0386      * @return array
0387      */
0388     protected function _getXmlRpcParams()
0389     {
0390         $params = array();
0391         if (is_array($this->_xmlRpcParams)) {
0392             foreach ($this->_xmlRpcParams as $param) {
0393                 $value = $param['value'];
0394                 $type  = isset($param['type']) ? $param['type'] : Zend_XmlRpc_Value::AUTO_DETECT_TYPE;
0395 
0396                 if (!$value instanceof Zend_XmlRpc_Value) {
0397                     $value = Zend_XmlRpc_Value::getXmlRpcValue($value, $type);
0398                 }
0399                 $params[] = $value;
0400             }
0401         }
0402 
0403         return $params;
0404     }
0405 
0406     /**
0407      * Create XML request
0408      *
0409      * @return string
0410      */
0411     public function saveXml()
0412     {
0413         $args   = $this->_getXmlRpcParams();
0414         $method = $this->getMethod();
0415 
0416         $generator = Zend_XmlRpc_Value::getGenerator();
0417         $generator->openElement('methodCall')
0418                   ->openElement('methodName', $method)
0419                   ->closeElement('methodName');
0420 
0421         if (is_array($args) && count($args)) {
0422             $generator->openElement('params');
0423 
0424             foreach ($args as $arg) {
0425                 $generator->openElement('param');
0426                 $arg->generateXml();
0427                 $generator->closeElement('param');
0428             }
0429             $generator->closeElement('params');
0430         }
0431         $generator->closeElement('methodCall');
0432 
0433         return $generator->flush();
0434     }
0435 
0436     /**
0437      * Return XML request
0438      *
0439      * @return string
0440      */
0441     public function __toString()
0442     {
0443         return $this->saveXML();
0444     }
0445 }