1<?php 2/** 3 * The Horde_Rpc_Soap class provides a PHP 5 Soap implementation 4 * of the Horde RPC system. 5 * 6 * Copyright 2003-2017 Horde LLC (http://www.horde.org/) 7 * 8 * See the enclosed file COPYING for license information (LGPL). If you 9 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 10 * 11 * @author Chuck Hagenbuch <chuck@horde.org> 12 * @package Rpc 13 */ 14class Horde_Rpc_Soap extends Horde_Rpc 15{ 16 /** 17 * Resource handler for the SOAP server. 18 * 19 * @var object 20 */ 21 var $_server; 22 23 /** 24 * List of types to emit in the WSDL. 25 * 26 * @var array 27 */ 28 var $_allowedTypes = array(); 29 30 /** 31 * List of method names to allow. 32 * 33 * @var array 34 */ 35 var $_allowedMethods = array(); 36 37 /** 38 * Name of the SOAP service to use in the WSDL. 39 * 40 * @var string 41 */ 42 var $_serviceName = null; 43 44 /** 45 * SOAP server constructor 46 * 47 * @access private 48 */ 49 public function __construct($request, $params = array()) 50 { 51 parent::__construct($request, $params); 52 53 if (!empty($params['allowedTypes'])) { 54 $this->_allowedTypes = $params['allowedTypes']; 55 } 56 if (!empty($params['allowedMethods'])) { 57 $this->_allowedMethods = $params['allowedMethods']; 58 } 59 if (!empty($params['serviceName'])) { 60 $this->_serviceName = $params['serviceName']; 61 } 62 63 $this->_server = new SoapServer(null, array('uri' => (string)Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/rpc.php', true, -1))); 64 $this->_server->addFunction(SOAP_FUNCTIONS_ALL); 65 $this->_server->setClass('Horde_Rpc_Soap_Caller', $params); 66 } 67 68 /** 69 * Takes a SOAP request and returns the result. 70 * 71 * @param string The raw request string. 72 * 73 * @return string The XML encoded response from the server. 74 */ 75 function getResponse($request) 76 { 77 if ($request == 'disco' || $request == 'wsdl') { 78 /*@TODO Replace with subcalls for disco and wsdl generation from the old SOAP driver. */ 79 //$handler = new Horde_Rpc_Soap($this->_params); 80 //return $handler->getResponse($request); 81 } 82 83 /* We can't use Horde_Util::bufferOutput() here for some reason. */ 84 $beginTime = time(); 85 ob_start(); 86 $this->_server->handle($request); 87 Horde::log( 88 sprintf('SOAP call: %s(%s) by %s serviced in %d seconds, sent %d bytes in response', 89 $GLOBALS['__horde_rpc_PhpSoap']['lastMethodCalled'], 90 implode(', ', array_map(function ($a) { return is_array($a) ? 'Array' : $a; }, 91 $GLOBALS['__horde_rpc_PhpSoap']['lastMethodParams'])), 92 $GLOBALS['registry']->getAuth(), 93 time() - $beginTime, 94 ob_get_length()), 95 'INFO'); 96 return ob_get_clean(); 97 } 98 99 /** 100 * Builds a SOAP request and sends it to the SOAP server. 101 * 102 * This statically called method is actually the SOAP client. 103 * 104 * @param string|Horde_Url $url Ignored. 105 * @param string $method The method to call. 106 * @param array $params A hash containing any necessary parameters 107 * for the method call. 108 * @param SoapClient $soap A configured SoapClient object. 109 * 110 * @return mixed The returned result from the method 111 * @throws Horde_Rpc_Exception 112 */ 113 public static function request($url, $method, $params, $soap) 114 { 115 try { 116 return $soap->__soapCall($method, $params); 117 } catch (Exception $e) { 118 throw new Horde_Rpc_Exception($e); 119 } 120 } 121 122} 123 124class Horde_Rpc_Soap_Caller { 125 126 /** 127 * List of method names to allow. 128 * 129 * @var array 130 */ 131 protected $_allowedMethods = array(); 132 133 /** 134 */ 135 public function __construct($params = array()) 136 { 137 if (!empty($params['allowedMethods'])) { 138 $this->_allowedMethods = $params['allowedMethods']; 139 } 140 } 141 142 /** 143 * Will be registered as the handler for all methods called in the 144 * SOAP server and will call the appropriate function through the registry. 145 * 146 * @todo PEAR SOAP operates on a copy of this object at some unknown 147 * point and therefore doesn't have access to instance 148 * variables if they're set here. Instead, globals are used 149 * to track the method name and args for the logging code. 150 * Once this is PHP 5-only, the globals can go in favor of 151 * instance variables. 152 * 153 * @access private 154 * 155 * @param string $method The name of the method called by the RPC request. 156 * @param array $params The passed parameters. 157 * @param mixed $data Unknown. 158 * 159 * @return mixed The result of the called registry method. 160 */ 161 public function __call($method, $params) 162 { 163 $method = str_replace('.', '/', $method); 164 165 if (!empty($this->_params['allowedMethods']) && 166 !in_array($method, $this->_params['allowedMethods'])) { 167 return sprintf(Horde_Rpc_Translation::t("Method \"%s\" is not defined"), $method); 168 } 169 170 $GLOBALS['__horde_rpc_PhpSoap']['lastMethodCalled'] = $method; 171 $GLOBALS['__horde_rpc_PhpSoap']['lastMethodParams'] = 172 !empty($params) ? $params : array(); 173 174 if (!$GLOBALS['registry']->hasMethod($method)) { 175 return sprintf(Horde_Rpc_Translation::t("Method \"%s\" is not defined"), $method); 176 } 177 178 return $GLOBALS['registry']->call($method, $params); 179 } 180 181} 182