PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Soap/Server.php

https://bitbucket.org/hjain/loudmusic
PHP | 1019 lines | 482 code | 103 blank | 434 comment | 64 complexity | 5cad00226d8c69dc361c5f1eb3e69a9d MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Soap
  17. * @subpackage Server
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @see Zend_Server_Interface
  23. */
  24. require_once 'Zend/Server/Interface.php';
  25. /**
  26. * Zend_Soap_Server
  27. *
  28. * @category Zend
  29. * @package Zend_Soap
  30. * @subpackage Server
  31. * @uses Zend_Server_Interface
  32. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. * @version $Id: Server.php 25033 2012-08-17 19:50:08Z matthew $
  35. */
  36. class Zend_Soap_Server implements Zend_Server_Interface
  37. {
  38. /**
  39. * Actor URI
  40. * @var string URI
  41. */
  42. protected $_actor;
  43. /**
  44. * Class registered with this server
  45. * @var string
  46. */
  47. protected $_class;
  48. /**
  49. * Arguments to pass to {@link $_class} constructor
  50. * @var array
  51. */
  52. protected $_classArgs = array();
  53. /**
  54. * Object registered with this server
  55. */
  56. protected $_object;
  57. /**
  58. * Array of SOAP type => PHP class pairings for handling return/incoming values
  59. * @var array
  60. */
  61. protected $_classmap;
  62. /**
  63. * Encoding
  64. * @var string
  65. */
  66. protected $_encoding;
  67. /**
  68. * SOAP Server Features
  69. *
  70. * @var int
  71. */
  72. protected $_features;
  73. /**
  74. * WSDL Caching Options of SOAP Server
  75. *
  76. * @var mixed
  77. */
  78. protected $_wsdlCache;
  79. /**
  80. * WS-I compliant
  81. *
  82. * @var boolean
  83. */
  84. protected $_wsiCompliant;
  85. /**
  86. * Registered fault exceptions
  87. * @var array
  88. */
  89. protected $_faultExceptions = array();
  90. /**
  91. * Functions registered with this server; may be either an array or the SOAP_FUNCTIONS_ALL
  92. * constant
  93. * @var array|int
  94. */
  95. protected $_functions = array();
  96. /**
  97. * Persistence mode; should be one of the SOAP persistence constants
  98. * @var int
  99. */
  100. protected $_persistence;
  101. /**
  102. * Request XML
  103. * @var string
  104. */
  105. protected $_request;
  106. /**
  107. * Response XML
  108. * @var string
  109. */
  110. protected $_response;
  111. /**
  112. * Flag: whether or not {@link handle()} should return a response instead
  113. * of automatically emitting it.
  114. * @var boolean
  115. */
  116. protected $_returnResponse = false;
  117. /**
  118. * SOAP version to use; SOAP_1_2 by default, to allow processing of headers
  119. * @var int
  120. */
  121. protected $_soapVersion = SOAP_1_2;
  122. /**
  123. * URI or path to WSDL
  124. * @var string
  125. */
  126. protected $_wsdl;
  127. /**
  128. * URI namespace for SOAP server
  129. * @var string URI
  130. */
  131. protected $_uri;
  132. /**
  133. * Constructor
  134. *
  135. * Sets display_errors INI setting to off (prevent client errors due to bad
  136. * XML in response). Registers {@link handlePhpErrors()} as error handler
  137. * for E_USER_ERROR.
  138. *
  139. * If $wsdl is provided, it is passed on to {@link setWsdl()}; if any
  140. * options are specified, they are passed on to {@link setOptions()}.
  141. *
  142. * @param string $wsdl
  143. * @param array $options
  144. * @return void
  145. */
  146. public function __construct($wsdl = null, array $options = null)
  147. {
  148. if (!extension_loaded('soap')) {
  149. require_once 'Zend/Soap/Server/Exception.php';
  150. throw new Zend_Soap_Server_Exception('SOAP extension is not loaded.');
  151. }
  152. if (null !== $wsdl) {
  153. $this->setWsdl($wsdl);
  154. }
  155. if (null !== $options) {
  156. $this->setOptions($options);
  157. }
  158. }
  159. /**
  160. * Set Options
  161. *
  162. * Allows setting options as an associative array of option => value pairs.
  163. *
  164. * @param array|Zend_Config $options
  165. * @return Zend_Soap_Server
  166. */
  167. public function setOptions($options)
  168. {
  169. if($options instanceof Zend_Config) {
  170. $options = $options->toArray();
  171. }
  172. foreach ($options as $key => $value) {
  173. switch ($key) {
  174. case 'actor':
  175. $this->setActor($value);
  176. break;
  177. case 'classmap':
  178. case 'classMap':
  179. $this->setClassmap($value);
  180. break;
  181. case 'encoding':
  182. $this->setEncoding($value);
  183. break;
  184. case 'soapVersion':
  185. case 'soap_version':
  186. $this->setSoapVersion($value);
  187. break;
  188. case 'uri':
  189. $this->setUri($value);
  190. break;
  191. case 'wsdl':
  192. $this->setWsdl($value);
  193. break;
  194. case 'featues':
  195. trigger_error(__METHOD__ . ': the option "featues" is deprecated as of 1.10.x and will be removed with 2.0.0; use "features" instead', E_USER_NOTICE);
  196. case 'features':
  197. $this->setSoapFeatures($value);
  198. break;
  199. case 'cache_wsdl':
  200. $this->setWsdlCache($value);
  201. break;
  202. case 'wsi_compliant':
  203. $this->setWsiCompliant($value);
  204. break;
  205. default:
  206. break;
  207. }
  208. }
  209. return $this;
  210. }
  211. /**
  212. * Return array of options suitable for using with SoapServer constructor
  213. *
  214. * @return array
  215. */
  216. public function getOptions()
  217. {
  218. $options = array();
  219. if (null !== $this->_actor) {
  220. $options['actor'] = $this->_actor;
  221. }
  222. if (null !== $this->_classmap) {
  223. $options['classmap'] = $this->_classmap;
  224. }
  225. if (null !== $this->_encoding) {
  226. $options['encoding'] = $this->_encoding;
  227. }
  228. if (null !== $this->_soapVersion) {
  229. $options['soap_version'] = $this->_soapVersion;
  230. }
  231. if (null !== $this->_uri) {
  232. $options['uri'] = $this->_uri;
  233. }
  234. if (null !== $this->_features) {
  235. $options['features'] = $this->_features;
  236. }
  237. if (null !== $this->_wsdlCache) {
  238. $options['cache_wsdl'] = $this->_wsdlCache;
  239. }
  240. if (null !== $this->_wsiCompliant) {
  241. $options['wsi_compliant'] = $this->_wsiCompliant;
  242. }
  243. return $options;
  244. }
  245. /**
  246. * Set WS-I compliant
  247. *
  248. * @param boolean $value
  249. * @return Zend_Soap_Server
  250. */
  251. public function setWsiCompliant($value)
  252. {
  253. if (is_bool($value)) {
  254. $this->_wsiCompliant = $value;
  255. }
  256. return $this;
  257. }
  258. /**
  259. * Gt WS-I compliant
  260. *
  261. * @return boolean
  262. */
  263. public function getWsiCompliant()
  264. {
  265. return $this->_wsiCompliant;
  266. }
  267. /**
  268. * Set encoding
  269. *
  270. * @param string $encoding
  271. * @return Zend_Soap_Server
  272. * @throws Zend_Soap_Server_Exception with invalid encoding argument
  273. */
  274. public function setEncoding($encoding)
  275. {
  276. if (!is_string($encoding)) {
  277. require_once 'Zend/Soap/Server/Exception.php';
  278. throw new Zend_Soap_Server_Exception('Invalid encoding specified');
  279. }
  280. $this->_encoding = $encoding;
  281. return $this;
  282. }
  283. /**
  284. * Get encoding
  285. *
  286. * @return string
  287. */
  288. public function getEncoding()
  289. {
  290. return $this->_encoding;
  291. }
  292. /**
  293. * Set SOAP version
  294. *
  295. * @param int $version One of the SOAP_1_1 or SOAP_1_2 constants
  296. * @return Zend_Soap_Server
  297. * @throws Zend_Soap_Server_Exception with invalid soap version argument
  298. */
  299. public function setSoapVersion($version)
  300. {
  301. if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) {
  302. require_once 'Zend/Soap/Server/Exception.php';
  303. throw new Zend_Soap_Server_Exception('Invalid soap version specified');
  304. }
  305. $this->_soapVersion = $version;
  306. return $this;
  307. }
  308. /**
  309. * Get SOAP version
  310. *
  311. * @return int
  312. */
  313. public function getSoapVersion()
  314. {
  315. return $this->_soapVersion;
  316. }
  317. /**
  318. * Check for valid URN
  319. *
  320. * @param string $urn
  321. * @return true
  322. * @throws Zend_Soap_Server_Exception on invalid URN
  323. */
  324. public function validateUrn($urn)
  325. {
  326. $scheme = parse_url($urn, PHP_URL_SCHEME);
  327. if ($scheme === false || $scheme === null) {
  328. require_once 'Zend/Soap/Server/Exception.php';
  329. throw new Zend_Soap_Server_Exception('Invalid URN');
  330. }
  331. return true;
  332. }
  333. /**
  334. * Set actor
  335. *
  336. * Actor is the actor URI for the server.
  337. *
  338. * @param string $actor
  339. * @return Zend_Soap_Server
  340. */
  341. public function setActor($actor)
  342. {
  343. $this->validateUrn($actor);
  344. $this->_actor = $actor;
  345. return $this;
  346. }
  347. /**
  348. * Retrieve actor
  349. *
  350. * @return string
  351. */
  352. public function getActor()
  353. {
  354. return $this->_actor;
  355. }
  356. /**
  357. * Set URI
  358. *
  359. * URI in SoapServer is actually the target namespace, not a URI; $uri must begin with 'urn:'.
  360. *
  361. * @param string $uri
  362. * @return Zend_Soap_Server
  363. * @throws Zend_Soap_Server_Exception with invalid uri argument
  364. */
  365. public function setUri($uri)
  366. {
  367. $this->validateUrn($uri);
  368. $this->_uri = $uri;
  369. return $this;
  370. }
  371. /**
  372. * Retrieve URI
  373. *
  374. * @return string
  375. */
  376. public function getUri()
  377. {
  378. return $this->_uri;
  379. }
  380. /**
  381. * Set classmap
  382. *
  383. * @param array $classmap
  384. * @return Zend_Soap_Server
  385. * @throws Zend_Soap_Server_Exception for any invalid class in the class map
  386. */
  387. public function setClassmap($classmap)
  388. {
  389. if (!is_array($classmap)) {
  390. /**
  391. * @see Zend_Soap_Server_Exception
  392. */
  393. require_once 'Zend/Soap/Server/Exception.php';
  394. throw new Zend_Soap_Server_Exception('Classmap must be an array');
  395. }
  396. foreach ($classmap as $type => $class) {
  397. if (!class_exists($class)) {
  398. /**
  399. * @see Zend_Soap_Server_Exception
  400. */
  401. require_once 'Zend/Soap/Server/Exception.php';
  402. throw new Zend_Soap_Server_Exception('Invalid class in class map');
  403. }
  404. }
  405. $this->_classmap = $classmap;
  406. return $this;
  407. }
  408. /**
  409. * Retrieve classmap
  410. *
  411. * @return mixed
  412. */
  413. public function getClassmap()
  414. {
  415. return $this->_classmap;
  416. }
  417. /**
  418. * Set wsdl
  419. *
  420. * @param string $wsdl URI or path to a WSDL
  421. * @return Zend_Soap_Server
  422. */
  423. public function setWsdl($wsdl)
  424. {
  425. $this->_wsdl = $wsdl;
  426. return $this;
  427. }
  428. /**
  429. * Retrieve wsdl
  430. *
  431. * @return string
  432. */
  433. public function getWsdl()
  434. {
  435. return $this->_wsdl;
  436. }
  437. /**
  438. * Set the SOAP Feature options.
  439. *
  440. * @param string|int $feature
  441. * @return Zend_Soap_Server
  442. */
  443. public function setSoapFeatures($feature)
  444. {
  445. $this->_features = $feature;
  446. return $this;
  447. }
  448. /**
  449. * Return current SOAP Features options
  450. *
  451. * @return int
  452. */
  453. public function getSoapFeatures()
  454. {
  455. return $this->_features;
  456. }
  457. /**
  458. * Set the SOAP Wsdl Caching Options
  459. *
  460. * @param string|int|boolean $caching
  461. * @return Zend_Soap_Server
  462. */
  463. public function setWsdlCache($options)
  464. {
  465. $this->_wsdlCache = $options;
  466. return $this;
  467. }
  468. /**
  469. * Get current SOAP Wsdl Caching option
  470. */
  471. public function getWsdlCache()
  472. {
  473. return $this->_wsdlCache;
  474. }
  475. /**
  476. * Attach a function as a server method
  477. *
  478. * @param array|string $function Function name, array of function names to attach,
  479. * or SOAP_FUNCTIONS_ALL to attach all functions
  480. * @param string $namespace Ignored
  481. * @return Zend_Soap_Server
  482. * @throws Zend_Soap_Server_Exception on invalid functions
  483. */
  484. public function addFunction($function, $namespace = '')
  485. {
  486. // Bail early if set to SOAP_FUNCTIONS_ALL
  487. if ($this->_functions == SOAP_FUNCTIONS_ALL) {
  488. return $this;
  489. }
  490. if (is_array($function)) {
  491. foreach ($function as $func) {
  492. if (is_string($func) && function_exists($func)) {
  493. $this->_functions[] = $func;
  494. } else {
  495. require_once 'Zend/Soap/Server/Exception.php';
  496. throw new Zend_Soap_Server_Exception('One or more invalid functions specified in array');
  497. }
  498. }
  499. $this->_functions = array_merge($this->_functions, $function);
  500. } elseif (is_string($function) && function_exists($function)) {
  501. $this->_functions[] = $function;
  502. } elseif ($function == SOAP_FUNCTIONS_ALL) {
  503. $this->_functions = SOAP_FUNCTIONS_ALL;
  504. } else {
  505. require_once 'Zend/Soap/Server/Exception.php';
  506. throw new Zend_Soap_Server_Exception('Invalid function specified');
  507. }
  508. if (is_array($this->_functions)) {
  509. $this->_functions = array_unique($this->_functions);
  510. }
  511. return $this;
  512. }
  513. /**
  514. * Attach a class to a server
  515. *
  516. * Accepts a class name to use when handling requests. Any additional
  517. * arguments will be passed to that class' constructor when instantiated.
  518. *
  519. * See {@link setObject()} to set preconfigured object instances as request handlers.
  520. *
  521. * @param string $class Class Name which executes SOAP Requests at endpoint.
  522. * @return Zend_Soap_Server
  523. * @throws Zend_Soap_Server_Exception if called more than once, or if class
  524. * does not exist
  525. */
  526. public function setClass($class, $namespace = '', $argv = null)
  527. {
  528. if (isset($this->_class)) {
  529. require_once 'Zend/Soap/Server/Exception.php';
  530. throw new Zend_Soap_Server_Exception('A class has already been registered with this soap server instance');
  531. }
  532. if (!is_string($class)) {
  533. require_once 'Zend/Soap/Server/Exception.php';
  534. throw new Zend_Soap_Server_Exception('Invalid class argument (' . gettype($class) . ')');
  535. }
  536. if (!class_exists($class)) {
  537. require_once 'Zend/Soap/Server/Exception.php';
  538. throw new Zend_Soap_Server_Exception('Class "' . $class . '" does not exist');
  539. }
  540. $this->_class = $class;
  541. if (1 < func_num_args()) {
  542. $argv = func_get_args();
  543. array_shift($argv);
  544. $this->_classArgs = $argv;
  545. }
  546. return $this;
  547. }
  548. /**
  549. * Attach an object to a server
  550. *
  551. * Accepts an instanciated object to use when handling requests.
  552. *
  553. * @param object $object
  554. * @return Zend_Soap_Server
  555. */
  556. public function setObject($object)
  557. {
  558. if(!is_object($object)) {
  559. require_once 'Zend/Soap/Server/Exception.php';
  560. throw new Zend_Soap_Server_Exception('Invalid object argument ('.gettype($object).')');
  561. }
  562. if(isset($this->_object)) {
  563. require_once 'Zend/Soap/Server/Exception.php';
  564. throw new Zend_Soap_Server_Exception('An object has already been registered with this soap server instance');
  565. }
  566. if ($this->_wsiCompliant) {
  567. require_once 'Zend/Soap/Server/Proxy.php';
  568. $this->_object = new Zend_Soap_Server_Proxy($object);
  569. } else {
  570. $this->_object = $object;
  571. }
  572. return $this;
  573. }
  574. /**
  575. * Return a server definition array
  576. *
  577. * Returns a list of all functions registered with {@link addFunction()},
  578. * merged with all public methods of the class set with {@link setClass()}
  579. * (if any).
  580. *
  581. * @access public
  582. * @return array
  583. */
  584. public function getFunctions()
  585. {
  586. $functions = array();
  587. if (null !== $this->_class) {
  588. $functions = get_class_methods($this->_class);
  589. } elseif (null !== $this->_object) {
  590. $functions = get_class_methods($this->_object);
  591. }
  592. return array_merge((array) $this->_functions, $functions);
  593. }
  594. /**
  595. * Unimplemented: Load server definition
  596. *
  597. * @param array $array
  598. * @return void
  599. * @throws Zend_Soap_Server_Exception Unimplemented
  600. */
  601. public function loadFunctions($definition)
  602. {
  603. require_once 'Zend/Soap/Server/Exception.php';
  604. throw new Zend_Soap_Server_Exception('Unimplemented');
  605. }
  606. /**
  607. * Set server persistence
  608. *
  609. * @param int $mode
  610. * @return Zend_Soap_Server
  611. */
  612. public function setPersistence($mode)
  613. {
  614. if (!in_array($mode, array(SOAP_PERSISTENCE_SESSION, SOAP_PERSISTENCE_REQUEST))) {
  615. require_once 'Zend/Soap/Server/Exception.php';
  616. throw new Zend_Soap_Server_Exception('Invalid persistence mode specified');
  617. }
  618. $this->_persistence = $mode;
  619. return $this;
  620. }
  621. /**
  622. * Get server persistence
  623. *
  624. * @return Zend_Soap_Server
  625. */
  626. public function getPersistence()
  627. {
  628. return $this->_persistence;
  629. }
  630. /**
  631. * Set request
  632. *
  633. * $request may be any of:
  634. * - DOMDocument; if so, then cast to XML
  635. * - DOMNode; if so, then grab owner document and cast to XML
  636. * - SimpleXMLElement; if so, then cast to XML
  637. * - stdClass; if so, calls __toString() and verifies XML
  638. * - string; if so, verifies XML
  639. *
  640. * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request
  641. * @return Zend_Soap_Server
  642. */
  643. protected function _setRequest($request)
  644. {
  645. if ($request instanceof DOMDocument) {
  646. $xml = $request->saveXML();
  647. } elseif ($request instanceof DOMNode) {
  648. $xml = $request->ownerDocument->saveXML();
  649. } elseif ($request instanceof SimpleXMLElement) {
  650. $xml = $request->asXML();
  651. } elseif (is_object($request) || is_string($request)) {
  652. if (is_object($request)) {
  653. $xml = $request->__toString();
  654. } else {
  655. $xml = $request;
  656. }
  657. libxml_disable_entity_loader(true);
  658. $dom = new DOMDocument();
  659. if(strlen($xml) == 0 || !$dom->loadXML($xml)) {
  660. require_once 'Zend/Soap/Server/Exception.php';
  661. throw new Zend_Soap_Server_Exception('Invalid XML');
  662. }
  663. foreach ($dom->childNodes as $child) {
  664. if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
  665. require_once 'Zend/Soap/Server/Exception.php';
  666. throw new Zend_Soap_Server_Exception(
  667. 'Invalid XML: Detected use of illegal DOCTYPE'
  668. );
  669. }
  670. }
  671. libxml_disable_entity_loader(false);
  672. }
  673. $this->_request = $xml;
  674. return $this;
  675. }
  676. /**
  677. * Retrieve request XML
  678. *
  679. * @return string
  680. */
  681. public function getLastRequest()
  682. {
  683. return $this->_request;
  684. }
  685. /**
  686. * Set return response flag
  687. *
  688. * If true, {@link handle()} will return the response instead of
  689. * automatically sending it back to the requesting client.
  690. *
  691. * The response is always available via {@link getResponse()}.
  692. *
  693. * @param boolean $flag
  694. * @return Zend_Soap_Server
  695. */
  696. public function setReturnResponse($flag)
  697. {
  698. $this->_returnResponse = ($flag) ? true : false;
  699. return $this;
  700. }
  701. /**
  702. * Retrieve return response flag
  703. *
  704. * @return boolean
  705. */
  706. public function getReturnResponse()
  707. {
  708. return $this->_returnResponse;
  709. }
  710. /**
  711. * Get response XML
  712. *
  713. * @return string
  714. */
  715. public function getLastResponse()
  716. {
  717. return $this->_response;
  718. }
  719. /**
  720. * Get SoapServer object
  721. *
  722. * Uses {@link $_wsdl} and return value of {@link getOptions()} to instantiate
  723. * SoapServer object, and then registers any functions or class with it, as
  724. * well as peristence.
  725. *
  726. * @return SoapServer
  727. */
  728. protected function _getSoap()
  729. {
  730. $options = $this->getOptions();
  731. $server = new SoapServer($this->_wsdl, $options);
  732. if (!empty($this->_functions)) {
  733. $server->addFunction($this->_functions);
  734. }
  735. if (!empty($this->_class)) {
  736. $args = $this->_classArgs;
  737. array_unshift($args, $this->_class);
  738. if ($this->_wsiCompliant) {
  739. require_once 'Zend/Soap/Server/Proxy.php';
  740. array_unshift($args, 'Zend_Soap_Server_Proxy');
  741. }
  742. call_user_func_array(array($server, 'setClass'), $args);
  743. }
  744. if (!empty($this->_object)) {
  745. $server->setObject($this->_object);
  746. }
  747. if (null !== $this->_persistence) {
  748. $server->setPersistence($this->_persistence);
  749. }
  750. return $server;
  751. }
  752. /**
  753. * Handle a request
  754. *
  755. * Instantiates SoapServer object with options set in object, and
  756. * dispatches its handle() method.
  757. *
  758. * $request may be any of:
  759. * - DOMDocument; if so, then cast to XML
  760. * - DOMNode; if so, then grab owner document and cast to XML
  761. * - SimpleXMLElement; if so, then cast to XML
  762. * - stdClass; if so, calls __toString() and verifies XML
  763. * - string; if so, verifies XML
  764. *
  765. * If no request is passed, pulls request using php:://input (for
  766. * cross-platform compatability purposes).
  767. *
  768. * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request Optional request
  769. * @return void|string
  770. */
  771. public function handle($request = null)
  772. {
  773. if (null === $request) {
  774. $request = file_get_contents('php://input');
  775. }
  776. // Set Zend_Soap_Server error handler
  777. $displayErrorsOriginalState = $this->_initializeSoapErrorContext();
  778. $setRequestException = null;
  779. /**
  780. * @see Zend_Soap_Server_Exception
  781. */
  782. require_once 'Zend/Soap/Server/Exception.php';
  783. try {
  784. $this->_setRequest($request);
  785. } catch (Zend_Soap_Server_Exception $e) {
  786. $setRequestException = $e;
  787. }
  788. $soap = $this->_getSoap();
  789. $fault = false;
  790. ob_start();
  791. if ($setRequestException instanceof Exception) {
  792. // Create SOAP fault message if we've caught a request exception
  793. $fault = $this->fault($setRequestException->getMessage(), 'Sender');
  794. } else {
  795. try {
  796. $soap->handle($this->_request);
  797. } catch (Exception $e) {
  798. $fault = $this->fault($e);
  799. }
  800. }
  801. $this->_response = ob_get_clean();
  802. // Restore original error handler
  803. restore_error_handler();
  804. ini_set('display_errors', $displayErrorsOriginalState);
  805. // Send a fault, if we have one
  806. if ($fault) {
  807. $this->_response = $fault;
  808. }
  809. if (!$this->_returnResponse) {
  810. echo $this->_response;
  811. return;
  812. }
  813. return $this->_response;
  814. }
  815. /**
  816. * Method initalizes the error context that the SOAPServer enviroment will run in.
  817. *
  818. * @return boolean display_errors original value
  819. */
  820. protected function _initializeSoapErrorContext()
  821. {
  822. $displayErrorsOriginalState = ini_get('display_errors');
  823. ini_set('display_errors', false);
  824. set_error_handler(array($this, 'handlePhpErrors'), E_USER_ERROR);
  825. return $displayErrorsOriginalState;
  826. }
  827. /**
  828. * Register a valid fault exception
  829. *
  830. * @param string|array $class Exception class or array of exception classes
  831. * @return Zend_Soap_Server
  832. */
  833. public function registerFaultException($class)
  834. {
  835. $this->_faultExceptions = array_merge($this->_faultExceptions, (array) $class);
  836. return $this;
  837. }
  838. /**
  839. * Deregister a fault exception from the fault exception stack
  840. *
  841. * @param string $class
  842. * @return boolean
  843. */
  844. public function deregisterFaultException($class)
  845. {
  846. if (in_array($class, $this->_faultExceptions, true)) {
  847. $index = array_search($class, $this->_faultExceptions);
  848. unset($this->_faultExceptions[$index]);
  849. return true;
  850. }
  851. return false;
  852. }
  853. /**
  854. * Return fault exceptions list
  855. *
  856. * @return array
  857. */
  858. public function getFaultExceptions()
  859. {
  860. return $this->_faultExceptions;
  861. }
  862. /**
  863. * Generate a server fault
  864. *
  865. * Note that the arguments are reverse to those of SoapFault.
  866. *
  867. * If an exception is passed as the first argument, its message and code
  868. * will be used to create the fault object if it has been registered via
  869. * {@Link registerFaultException()}.
  870. *
  871. * @link http://www.w3.org/TR/soap12-part1/#faultcodes
  872. * @param string|Exception $fault
  873. * @param string $code SOAP Fault Codes
  874. * @return SoapFault
  875. */
  876. public function fault($fault = null, $code = "Receiver")
  877. {
  878. if ($fault instanceof Exception) {
  879. $class = get_class($fault);
  880. if (in_array($class, $this->_faultExceptions)) {
  881. $message = $fault->getMessage();
  882. $eCode = $fault->getCode();
  883. $code = empty($eCode) ? $code : $eCode;
  884. } else {
  885. $message = 'Unknown error';
  886. }
  887. } elseif(is_string($fault)) {
  888. $message = $fault;
  889. } else {
  890. $message = 'Unknown error';
  891. }
  892. $allowedFaultModes = array(
  893. 'VersionMismatch', 'MustUnderstand', 'DataEncodingUnknown',
  894. 'Sender', 'Receiver', 'Server'
  895. );
  896. if(!in_array($code, $allowedFaultModes)) {
  897. $code = "Receiver";
  898. }
  899. return new SoapFault($code, $message);
  900. }
  901. /**
  902. * Throw PHP errors as SoapFaults
  903. *
  904. * @param int $errno
  905. * @param string $errstr
  906. * @param string $errfile
  907. * @param int $errline
  908. * @param array $errcontext
  909. * @return void
  910. * @throws SoapFault
  911. */
  912. public function handlePhpErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
  913. {
  914. throw $this->fault($errstr, "Receiver");
  915. }
  916. }