File indexing completed on 2024-05-12 06:03:17

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  * @package    Zend_XmlRpc
0016  * @subpackage Server
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  * @version    $Id$
0020  */
0021 
0022 /**
0023  * Zend_XmlRpc_Value
0024  */
0025 // require_once 'Zend/XmlRpc/Value.php';
0026 
0027 /**
0028  * XMLRPC Faults
0029  *
0030  * Container for XMLRPC faults, containing both a code and a message;
0031  * additionally, has methods for determining if an XML response is an XMLRPC
0032  * fault, as well as generating the XML for an XMLRPC fault response.
0033  *
0034  * To allow method chaining, you may only use the {@link getInstance()} factory
0035  * to instantiate a Zend_XmlRpc_Server_Fault.
0036  *
0037  * @category   Zend
0038  * @package    Zend_XmlRpc
0039  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0040  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0041  */
0042 class Zend_XmlRpc_Fault
0043 {
0044     /**
0045      * Fault code
0046      * @var int
0047      */
0048     protected $_code;
0049 
0050     /**
0051      * Fault character encoding
0052      * @var string
0053      */
0054     protected $_encoding = 'UTF-8';
0055 
0056     /**
0057      * Fault message
0058      * @var string
0059      */
0060     protected $_message;
0061 
0062     /**
0063      * Internal fault codes => messages
0064      * @var array
0065      */
0066     protected $_internal = array(
0067         404 => 'Unknown Error',
0068 
0069         // 610 - 619 reflection errors
0070         610 => 'Invalid method class',
0071         611 => 'Unable to attach function or callback; not callable',
0072         612 => 'Unable to load array; not an array',
0073         613 => 'One or more method records are corrupt or otherwise unusable',
0074 
0075         // 620 - 629 dispatch errors
0076         620 => 'Method does not exist',
0077         621 => 'Error instantiating class to invoke method',
0078         622 => 'Method missing implementation',
0079         623 => 'Calling parameters do not match signature',
0080 
0081         // 630 - 639 request errors
0082         630 => 'Unable to read request',
0083         631 => 'Failed to parse request',
0084         632 => 'Invalid request, no method passed; request must contain a \'methodName\' tag',
0085         633 => 'Param must contain a value',
0086         634 => 'Invalid method name',
0087         635 => 'Invalid XML provided to request',
0088         636 => 'Error creating xmlrpc value',
0089 
0090         // 640 - 649 system.* errors
0091         640 => 'Method does not exist',
0092 
0093         // 650 - 659 response errors
0094         650 => 'Invalid XML provided for response',
0095         651 => 'Failed to parse response',
0096         652 => 'Invalid response',
0097         653 => 'Invalid XMLRPC value in response',
0098     );
0099 
0100     /**
0101      * Constructor
0102      *
0103      * @return Zend_XmlRpc_Fault
0104      */
0105     public function __construct($code = 404, $message = '')
0106     {
0107         $this->setCode($code);
0108         $code = $this->getCode();
0109 
0110         if (empty($message) && isset($this->_internal[$code])) {
0111             $message = $this->_internal[$code];
0112         } elseif (empty($message)) {
0113             $message = 'Unknown error';
0114         }
0115         $this->setMessage($message);
0116     }
0117 
0118     /**
0119      * Set the fault code
0120      *
0121      * @param int $code
0122      * @return Zend_XmlRpc_Fault
0123      */
0124     public function setCode($code)
0125     {
0126         $this->_code = (int) $code;
0127         return $this;
0128     }
0129 
0130     /**
0131      * Return fault code
0132      *
0133      * @return int
0134      */
0135     public function getCode()
0136     {
0137         return $this->_code;
0138     }
0139 
0140     /**
0141      * Retrieve fault message
0142      *
0143      * @param string
0144      * @return Zend_XmlRpc_Fault
0145      */
0146     public function setMessage($message)
0147     {
0148         $this->_message = (string) $message;
0149         return $this;
0150     }
0151 
0152     /**
0153      * Retrieve fault message
0154      *
0155      * @return string
0156      */
0157     public function getMessage()
0158     {
0159         return $this->_message;
0160     }
0161 
0162     /**
0163      * Set encoding to use in fault response
0164      *
0165      * @param string $encoding
0166      * @return Zend_XmlRpc_Fault
0167      */
0168     public function setEncoding($encoding)
0169     {
0170         $this->_encoding = $encoding;
0171         Zend_XmlRpc_Value::setEncoding($encoding);
0172         return $this;
0173     }
0174 
0175     /**
0176      * Retrieve current fault encoding
0177      *
0178      * @return string
0179      */
0180     public function getEncoding()
0181     {
0182         return $this->_encoding;
0183     }
0184 
0185     /**
0186      * Load an XMLRPC fault from XML
0187      *
0188      * @param string $fault
0189      * @return boolean Returns true if successfully loaded fault response, false
0190      * if response was not a fault response
0191      * @throws Zend_XmlRpc_Exception if no or faulty XML provided, or if fault
0192      * response does not contain either code or message
0193      */
0194     public function loadXml($fault)
0195     {
0196         if (!is_string($fault)) {
0197             // require_once 'Zend/XmlRpc/Exception.php';
0198             throw new Zend_XmlRpc_Exception('Invalid XML provided to fault');
0199         }
0200 
0201         try {
0202             $xml = @new SimpleXMLElement($fault);
0203         } catch (Exception $e) {
0204             // Not valid XML
0205             // require_once 'Zend/XmlRpc/Exception.php';
0206             throw new Zend_XmlRpc_Exception('Failed to parse XML fault: ' .  $e->getMessage(), 500, $e);
0207         }
0208 
0209         // Check for fault
0210         if (!$xml->fault) {
0211             // Not a fault
0212             return false;
0213         }
0214 
0215         if (!$xml->fault->value->struct) {
0216             // not a proper fault
0217             // require_once 'Zend/XmlRpc/Exception.php';
0218             throw new Zend_XmlRpc_Exception('Invalid fault structure', 500);
0219         }
0220 
0221         $structXml = $xml->fault->value->asXML();
0222         $struct    = Zend_XmlRpc_Value::getXmlRpcValue($structXml, Zend_XmlRpc_Value::XML_STRING);
0223         $struct    = $struct->getValue();
0224 
0225         if (isset($struct['faultCode'])) {
0226             $code = $struct['faultCode'];
0227         }
0228         if (isset($struct['faultString'])) {
0229             $message = $struct['faultString'];
0230         }
0231 
0232         if (empty($code) && empty($message)) {
0233             // require_once 'Zend/XmlRpc/Exception.php';
0234             throw new Zend_XmlRpc_Exception('Fault code and string required');
0235         }
0236 
0237         if (empty($code)) {
0238             $code = '404';
0239         }
0240 
0241         if (empty($message)) {
0242             if (isset($this->_internal[$code])) {
0243                 $message = $this->_internal[$code];
0244             } else {
0245                 $message = 'Unknown Error';
0246             }
0247         }
0248 
0249         $this->setCode($code);
0250         $this->setMessage($message);
0251 
0252         return true;
0253     }
0254 
0255     /**
0256      * Determine if an XML response is an XMLRPC fault
0257      *
0258      * @param string $xml
0259      * @return boolean
0260      */
0261     public static function isFault($xml)
0262     {
0263         $fault = new self();
0264         // require_once 'Zend/XmlRpc/Exception.php';
0265         try {
0266             $isFault = $fault->loadXml($xml);
0267         } catch (Zend_XmlRpc_Exception $e) {
0268             $isFault = false;
0269         }
0270 
0271         return $isFault;
0272     }
0273 
0274     /**
0275      * Serialize fault to XML
0276      *
0277      * @return string
0278      */
0279     public function saveXml()
0280     {
0281         // Create fault value
0282         $faultStruct = array(
0283             'faultCode'   => $this->getCode(),
0284             'faultString' => $this->getMessage()
0285         );
0286         $value = Zend_XmlRpc_Value::getXmlRpcValue($faultStruct);
0287 
0288         $generator = Zend_XmlRpc_Value::getGenerator();
0289         $generator->openElement('methodResponse')
0290                   ->openElement('fault');
0291         $value->generateXml();
0292         $generator->closeElement('fault')
0293                   ->closeElement('methodResponse');
0294 
0295         return $generator->flush();
0296     }
0297 
0298     /**
0299      * Return XML fault response
0300      *
0301      * @return string
0302      */
0303     public function __toString()
0304     {
0305         return $this->saveXML();
0306     }
0307 }