Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 18 /** 19 * SOAP web service implementation classes and methods. 20 * 21 * @package webservice_soap 22 * @copyright 2009 Petr Skodak 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 global $CFG; 26 require_once($CFG->dirroot . '/webservice/lib.php'); 27 use webservice_soap\wsdl; 28 29 /** 30 * SOAP service server implementation. 31 * 32 * @package webservice_soap 33 * @copyright 2009 Petr Skodak 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 * @since Moodle 2.0 36 */ 37 class webservice_soap_server extends webservice_base_server { 38 39 /** @var moodle_url The server URL. */ 40 protected $serverurl; 41 42 /** @var SoapServer The Soap */ 43 protected $soapserver; 44 45 /** @var string The response. */ 46 protected $response; 47 48 /** @var string The class name of the virtual class generated for this web service. */ 49 protected $serviceclass; 50 51 /** @var bool WSDL mode flag. */ 52 protected $wsdlmode; 53 54 /** @var \webservice_soap\wsdl The object for WSDL generation. */ 55 protected $wsdl; 56 57 /** 58 * Contructor. 59 * 60 * @param string $authmethod authentication method of the web service (WEBSERVICE_AUTHMETHOD_PERMANENT_TOKEN, ...) 61 */ 62 public function __construct($authmethod) { 63 parent::__construct($authmethod); 64 // Must not cache wsdl - the list of functions is created on the fly. 65 ini_set('soap.wsdl_cache_enabled', '0'); 66 $this->wsname = 'soap'; 67 $this->wsdlmode = false; 68 } 69 70 /** 71 * This method parses the $_POST and $_GET superglobals and looks for the following information: 72 * - User authentication parameters: 73 * - Username + password (wsusername and wspassword), or 74 * - Token (wstoken) 75 */ 76 protected function parse_request() { 77 // Retrieve and clean the POST/GET parameters from the parameters specific to the server. 78 parent::set_web_service_call_settings(); 79 80 if ($this->authmethod == WEBSERVICE_AUTHMETHOD_USERNAME) { 81 $this->username = optional_param('wsusername', null, PARAM_RAW); 82 $this->password = optional_param('wspassword', null, PARAM_RAW); 83 84 if (!$this->username or !$this->password) { 85 // Workaround for the trouble with & in soap urls. 86 $authdata = get_file_argument(); 87 $authdata = explode('/', trim($authdata, '/')); 88 if (count($authdata) == 2) { 89 list($this->username, $this->password) = $authdata; 90 } 91 } 92 $this->serverurl = new moodle_url('/webservice/soap/simpleserver.php/' . $this->username . '/' . $this->password); 93 } else { 94 $this->token = optional_param('wstoken', null, PARAM_RAW); 95 96 $this->serverurl = new moodle_url('/webservice/soap/server.php'); 97 $this->serverurl->param('wstoken', $this->token); 98 } 99 100 if ($wsdl = optional_param('wsdl', 0, PARAM_INT)) { 101 $this->wsdlmode = true; 102 } 103 } 104 105 /** 106 * Runs the SOAP web service. 107 * 108 * @throws coding_exception 109 * @throws moodle_exception 110 * @throws webservice_access_exception 111 */ 112 public function run() { 113 // We will probably need a lot of memory in some functions. 114 raise_memory_limit(MEMORY_EXTRA); 115 116 // Set some longer timeout since operations may need longer time to finish. 117 \core_external\external_api::set_timeout(); 118 119 // Set up exception handler. 120 set_exception_handler(array($this, 'exception_handler')); 121 122 // Init all properties from the request data. 123 $this->parse_request(); 124 125 // Authenticate user, this has to be done after the request parsing. This also sets up $USER and $SESSION. 126 $this->authenticate_user(); 127 128 // Make a list of all functions user is allowed to execute. 129 $this->init_service_class(); 130 131 if ($this->wsdlmode) { 132 // Generate the WSDL. 133 $this->generate_wsdl(); 134 } 135 136 // Log the web service request. 137 $params = array( 138 'other' => array( 139 'function' => 'unknown' 140 ) 141 ); 142 /** @var \core\event\webservice_function_called $event */ 143 $event = \core\event\webservice_function_called::create($params); 144 $event->trigger(); 145 146 // Handle the SOAP request. 147 $this->handle(); 148 149 // Session cleanup. 150 $this->session_cleanup(); 151 die; 152 } 153 154 /** 155 * Generates the WSDL. 156 */ 157 protected function generate_wsdl() { 158 // Initialise WSDL. 159 $this->wsdl = new wsdl($this->serviceclass, $this->serverurl); 160 // Register service struct classes as complex types. 161 foreach ($this->servicestructs as $structinfo) { 162 $this->wsdl->add_complex_type($structinfo->classname, $structinfo->properties); 163 } 164 // Register the method for the WSDL generation. 165 foreach ($this->servicemethods as $methodinfo) { 166 $this->wsdl->register($methodinfo->name, $methodinfo->inputparams, $methodinfo->outputparams, $methodinfo->description); 167 } 168 } 169 170 /** 171 * Handles the web service function call. 172 */ 173 protected function handle() { 174 if ($this->wsdlmode) { 175 // Prepare the response. 176 $this->response = $this->wsdl->to_xml(); 177 178 // Send the results back in correct format. 179 $this->send_response(); 180 } else { 181 $wsdlurl = clone($this->serverurl); 182 $wsdlurl->param('wsdl', 1); 183 184 $options = array( 185 'uri' => $this->serverurl->out(false) 186 ); 187 // Initialise the SOAP server. 188 $this->soapserver = new SoapServer($wsdlurl->out(false), $options); 189 if (!empty($this->serviceclass)) { 190 $this->soapserver->setClass($this->serviceclass); 191 // Get all the methods for the generated service class then register to the SOAP server. 192 $functions = get_class_methods($this->serviceclass); 193 $this->soapserver->addFunction($functions); 194 } 195 196 // Get soap request from raw POST data. 197 $soaprequest = file_get_contents('php://input'); 198 // Handle the request. 199 try { 200 $this->soapserver->handle($soaprequest); 201 } catch (Exception $e) { 202 $this->fault($e); 203 } 204 } 205 } 206 207 /** 208 * Send the error information to the WS client formatted as an XML document. 209 * 210 * @param Exception $ex the exception to send back 211 */ 212 protected function send_error($ex = null) { 213 if ($ex) { 214 $info = $ex->getMessage(); 215 if (debugging() and isset($ex->debuginfo)) { 216 $info .= ' - '.$ex->debuginfo; 217 } 218 } else { 219 $info = 'Unknown error'; 220 } 221 222 // Initialise new DOM document object. 223 $dom = new DOMDocument('1.0', 'UTF-8'); 224 225 // Fault node. 226 $fault = $dom->createElement('SOAP-ENV:Fault'); 227 // Faultcode node. 228 $fault->appendChild($dom->createElement('faultcode', 'MOODLE:error')); 229 // Faultstring node. 230 $fault->appendChild($dom->createElement('faultstring', $info)); 231 232 // Body node. 233 $body = $dom->createElement('SOAP-ENV:Body'); 234 $body->appendChild($fault); 235 236 // Envelope node. 237 $envelope = $dom->createElement('SOAP-ENV:Envelope'); 238 $envelope->setAttribute('xmlns:SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/'); 239 $envelope->appendChild($body); 240 $dom->appendChild($envelope); 241 242 $this->response = $dom->saveXML(); 243 $this->send_response(); 244 } 245 246 /** 247 * Send the result of function call to the WS client. 248 */ 249 protected function send_response() { 250 $this->send_headers(); 251 echo $this->response; 252 } 253 254 /** 255 * Internal implementation - sending of page headers. 256 */ 257 protected function send_headers() { 258 header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); 259 header('Expires: ' . gmdate('D, d M Y H:i:s', 0) . ' GMT'); 260 header('Pragma: no-cache'); 261 header('Accept-Ranges: none'); 262 header('Content-Length: ' . strlen($this->response)); 263 header('Content-Type: application/xml; charset=utf-8'); 264 header('Content-Disposition: inline; filename="response.xml"'); 265 } 266 267 /** 268 * Generate a server fault. 269 * 270 * Note that the parameter order is the reverse of SoapFault's constructor parameters. 271 * 272 * Moodle note: basically we return the faultactor (errorcode) and faultdetails (debuginfo). 273 * 274 * If an exception is passed as the first argument, its message and code 275 * will be used to create the fault object. 276 * 277 * @link http://www.w3.org/TR/soap12-part1/#faultcodes 278 * @param string|Exception $fault 279 * @param string $code SOAP Fault Codes 280 */ 281 public function fault($fault = null, $code = 'Receiver') { 282 $allowedfaultmodes = array( 283 'VersionMismatch', 'MustUnderstand', 'DataEncodingUnknown', 284 'Sender', 'Receiver', 'Server' 285 ); 286 if (!in_array($code, $allowedfaultmodes)) { 287 $code = 'Receiver'; 288 } 289 290 // Intercept any exceptions and add the errorcode and debuginfo (optional). 291 $actor = null; 292 $details = null; 293 $errorcode = 'unknownerror'; 294 $message = get_string($errorcode); 295 if ($fault instanceof Exception) { 296 // Add the debuginfo to the exception message if debuginfo must be returned. 297 $actor = isset($fault->errorcode) ? $fault->errorcode : null; 298 $errorcode = $actor; 299 if (debugging()) { 300 $message = $fault->getMessage(); 301 $details = isset($fault->debuginfo) ? $fault->debuginfo : null; 302 } 303 } else if (is_string($fault)) { 304 $message = $fault; 305 } 306 307 $this->soapserver->fault($code, $message . ' | ERRORCODE: ' . $errorcode, $actor, $details); 308 } 309 } 310 311 /** 312 * SOAP test client class 313 * 314 * @package webservice_soap 315 * @copyright 2009 Petr Skodak 316 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 317 * @since Moodle 2.0 318 */ 319 class webservice_soap_test_client implements webservice_test_client_interface { 320 321 /** 322 * Execute test client WS request 323 * 324 * @param string $serverurl server url (including token parameter or username/password parameters) 325 * @param string $function function name 326 * @param array $params parameters of the called function 327 * @return mixed 328 */ 329 public function simpletest($serverurl, $function, $params) { 330 global $CFG; 331 332 require_once($CFG->dirroot . '/webservice/soap/lib.php'); 333 $client = new webservice_soap_client($serverurl); 334 return $client->call($function, $params); 335 } 336 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body