Commit | Line | Data |
---|---|---|
696f20d5 MS |
1 | <?php |
2 | ||
3 | ||
4 | ||
5 | ||
6 | /** | |
7 | * | |
8 | * nusoap_server allows the user to create a SOAP server | |
9 | * that is capable of receiving messages and returning responses | |
10 | * | |
11 | * @author Dietrich Ayala <dietrich@ganx4.com> | |
12 | * @author Scott Nichol <snichol@users.sourceforge.net> | |
13 | * @version $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $ | |
14 | * @access public | |
15 | */ | |
16 | class nusoap_server extends nusoap_base { | |
17 | /** | |
18 | * HTTP headers of request | |
19 | * @var array | |
20 | * @access private | |
21 | */ | |
22 | var $headers = array(); | |
23 | /** | |
24 | * HTTP request | |
25 | * @var string | |
26 | * @access private | |
27 | */ | |
28 | var $request = ''; | |
29 | /** | |
30 | * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) | |
31 | * @var string | |
32 | * @access public | |
33 | */ | |
34 | var $requestHeaders = ''; | |
35 | /** | |
36 | * SOAP Headers from request (parsed) | |
37 | * @var mixed | |
38 | * @access public | |
39 | */ | |
40 | var $requestHeader = NULL; | |
41 | /** | |
42 | * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) | |
43 | * @var string | |
44 | * @access public | |
45 | */ | |
46 | var $document = ''; | |
47 | /** | |
48 | * SOAP payload for request (text) | |
49 | * @var string | |
50 | * @access public | |
51 | */ | |
52 | var $requestSOAP = ''; | |
53 | /** | |
54 | * requested method namespace URI | |
55 | * @var string | |
56 | * @access private | |
57 | */ | |
58 | var $methodURI = ''; | |
59 | /** | |
60 | * name of method requested | |
61 | * @var string | |
62 | * @access private | |
63 | */ | |
64 | var $methodname = ''; | |
65 | /** | |
66 | * method parameters from request | |
67 | * @var array | |
68 | * @access private | |
69 | */ | |
70 | var $methodparams = array(); | |
71 | /** | |
72 | * SOAP Action from request | |
73 | * @var string | |
74 | * @access private | |
75 | */ | |
76 | var $SOAPAction = ''; | |
77 | /** | |
78 | * character set encoding of incoming (request) messages | |
79 | * @var string | |
80 | * @access public | |
81 | */ | |
82 | var $xml_encoding = ''; | |
83 | /** | |
84 | * toggles whether the parser decodes element content w/ utf8_decode() | |
85 | * @var boolean | |
86 | * @access public | |
87 | */ | |
88 | var $decode_utf8 = true; | |
89 | ||
90 | /** | |
91 | * HTTP headers of response | |
92 | * @var array | |
93 | * @access public | |
94 | */ | |
95 | var $outgoing_headers = array(); | |
96 | /** | |
97 | * HTTP response | |
98 | * @var string | |
99 | * @access private | |
100 | */ | |
101 | var $response = ''; | |
102 | /** | |
103 | * SOAP headers for response (text or array of soapval or associative array) | |
104 | * @var mixed | |
105 | * @access public | |
106 | */ | |
107 | var $responseHeaders = ''; | |
108 | /** | |
109 | * SOAP payload for response (text) | |
110 | * @var string | |
111 | * @access private | |
112 | */ | |
113 | var $responseSOAP = ''; | |
114 | /** | |
115 | * method return value to place in response | |
116 | * @var mixed | |
117 | * @access private | |
118 | */ | |
119 | var $methodreturn = false; | |
120 | /** | |
121 | * whether $methodreturn is a string of literal XML | |
122 | * @var boolean | |
123 | * @access public | |
124 | */ | |
125 | var $methodreturnisliteralxml = false; | |
126 | /** | |
127 | * SOAP fault for response (or false) | |
128 | * @var mixed | |
129 | * @access private | |
130 | */ | |
131 | var $fault = false; | |
132 | /** | |
133 | * text indication of result (for debugging) | |
134 | * @var string | |
135 | * @access private | |
136 | */ | |
137 | var $result = 'successful'; | |
138 | ||
139 | /** | |
140 | * assoc array of operations => opData; operations are added by the register() | |
141 | * method or by parsing an external WSDL definition | |
142 | * @var array | |
143 | * @access private | |
144 | */ | |
145 | var $operations = array(); | |
146 | /** | |
147 | * wsdl instance (if one) | |
148 | * @var mixed | |
149 | * @access private | |
150 | */ | |
151 | var $wsdl = false; | |
152 | /** | |
153 | * URL for WSDL (if one) | |
154 | * @var mixed | |
155 | * @access private | |
156 | */ | |
157 | var $externalWSDLURL = false; | |
158 | /** | |
159 | * whether to append debug to response as XML comment | |
160 | * @var boolean | |
161 | * @access public | |
162 | */ | |
163 | var $debug_flag = false; | |
164 | ||
165 | ||
166 | /** | |
167 | * constructor | |
168 | * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. | |
169 | * | |
170 | * @param mixed $wsdl file path or URL (string), or wsdl instance (object) | |
171 | * @access public | |
172 | */ | |
173 | function nusoap_server($wsdl=false){ | |
174 | parent::nusoap_base(); | |
175 | // turn on debugging? | |
176 | global $debug; | |
177 | global $HTTP_SERVER_VARS; | |
178 | ||
179 | if (isset($_SERVER)) { | |
180 | $this->debug("_SERVER is defined:"); | |
181 | $this->appendDebug($this->varDump($_SERVER)); | |
182 | } elseif (isset($HTTP_SERVER_VARS)) { | |
183 | $this->debug("HTTP_SERVER_VARS is defined:"); | |
184 | $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); | |
185 | } else { | |
186 | $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined."); | |
187 | } | |
188 | ||
189 | if (isset($debug)) { | |
190 | $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); | |
191 | $this->debug_flag = $debug; | |
192 | } elseif (isset($_SERVER['QUERY_STRING'])) { | |
193 | $qs = explode('&', $_SERVER['QUERY_STRING']); | |
194 | foreach ($qs as $v) { | |
195 | if (substr($v, 0, 6) == 'debug=') { | |
196 | $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1"); | |
197 | $this->debug_flag = substr($v, 6); | |
198 | } | |
199 | } | |
200 | } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { | |
201 | $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); | |
202 | foreach ($qs as $v) { | |
203 | if (substr($v, 0, 6) == 'debug=') { | |
204 | $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2"); | |
205 | $this->debug_flag = substr($v, 6); | |
206 | } | |
207 | } | |
208 | } | |
209 | ||
210 | // wsdl | |
211 | if($wsdl){ | |
212 | $this->debug("In nusoap_server, WSDL is specified"); | |
213 | if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { | |
214 | $this->wsdl = $wsdl; | |
215 | $this->externalWSDLURL = $this->wsdl->wsdl; | |
216 | $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL); | |
217 | } else { | |
218 | $this->debug('Create wsdl from ' . $wsdl); | |
219 | $this->wsdl = new wsdl($wsdl); | |
220 | $this->externalWSDLURL = $wsdl; | |
221 | } | |
222 | $this->appendDebug($this->wsdl->getDebug()); | |
223 | $this->wsdl->clearDebug(); | |
224 | if($err = $this->wsdl->getError()){ | |
225 | die('WSDL ERROR: '.$err); | |
226 | } | |
227 | } | |
228 | } | |
229 | ||
230 | /** | |
231 | * processes request and returns response | |
232 | * | |
233 | * @param string $data usually is the value of $HTTP_RAW_POST_DATA | |
234 | * @access public | |
235 | */ | |
236 | function service($data){ | |
237 | global $HTTP_SERVER_VARS; | |
238 | ||
239 | if (isset($_SERVER['REQUEST_METHOD'])) { | |
240 | $rm = $_SERVER['REQUEST_METHOD']; | |
241 | } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) { | |
242 | $rm = $HTTP_SERVER_VARS['REQUEST_METHOD']; | |
243 | } else { | |
244 | $rm = ''; | |
245 | } | |
246 | ||
247 | if (isset($_SERVER['QUERY_STRING'])) { | |
248 | $qs = $_SERVER['QUERY_STRING']; | |
249 | } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { | |
250 | $qs = $HTTP_SERVER_VARS['QUERY_STRING']; | |
251 | } else { | |
252 | $qs = ''; | |
253 | } | |
254 | $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data)); | |
255 | ||
256 | if ($rm == 'POST') { | |
257 | $this->debug("In service, invoke the request"); | |
258 | $this->parse_request($data); | |
259 | if (! $this->fault) { | |
260 | $this->invoke_method(); | |
261 | } | |
262 | if (! $this->fault) { | |
263 | $this->serialize_return(); | |
264 | } | |
265 | $this->send_response(); | |
266 | } elseif (preg_match('/wsdl/', $qs) ){ | |
267 | $this->debug("In service, this is a request for WSDL"); | |
268 | if ($this->externalWSDLURL){ | |
269 | if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL | |
270 | $this->debug("In service, re-direct for WSDL"); | |
271 | header('Location: '.$this->externalWSDLURL); | |
272 | } else { // assume file | |
273 | $this->debug("In service, use file passthru for WSDL"); | |
274 | header("Content-Type: text/xml\r\n"); | |
275 | $pos = strpos($this->externalWSDLURL, "file://"); | |
276 | if ($pos === false) { | |
277 | $filename = $this->externalWSDLURL; | |
278 | } else { | |
279 | $filename = substr($this->externalWSDLURL, $pos + 7); | |
280 | } | |
281 | $fp = fopen($this->externalWSDLURL, 'r'); | |
282 | fpassthru($fp); | |
283 | } | |
284 | } elseif ($this->wsdl) { | |
285 | $this->debug("In service, serialize WSDL"); | |
286 | header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); | |
287 | print $this->wsdl->serialize($this->debug_flag); | |
288 | if ($this->debug_flag) { | |
289 | $this->debug('wsdl:'); | |
290 | $this->appendDebug($this->varDump($this->wsdl)); | |
291 | print $this->getDebugAsXMLComment(); | |
292 | } | |
293 | } else { | |
294 | $this->debug("In service, there is no WSDL"); | |
295 | header("Content-Type: text/html; charset=ISO-8859-1\r\n"); | |
296 | print "This service does not provide WSDL"; | |
297 | } | |
298 | } elseif ($this->wsdl) { | |
299 | $this->debug("In service, return Web description"); | |
300 | print $this->wsdl->webDescription(); | |
301 | } else { | |
302 | $this->debug("In service, no Web description"); | |
303 | header("Content-Type: text/html; charset=ISO-8859-1\r\n"); | |
304 | print "This service does not provide a Web description"; | |
305 | } | |
306 | } | |
307 | ||
308 | /** | |
309 | * parses HTTP request headers. | |
310 | * | |
311 | * The following fields are set by this function (when successful) | |
312 | * | |
313 | * headers | |
314 | * request | |
315 | * xml_encoding | |
316 | * SOAPAction | |
317 | * | |
318 | * @access private | |
319 | */ | |
320 | function parse_http_headers() { | |
321 | global $HTTP_SERVER_VARS; | |
322 | ||
323 | $this->request = ''; | |
324 | $this->SOAPAction = ''; | |
325 | if(function_exists('getallheaders')){ | |
326 | $this->debug("In parse_http_headers, use getallheaders"); | |
327 | $headers = getallheaders(); | |
328 | foreach($headers as $k=>$v){ | |
329 | $k = strtolower($k); | |
330 | $this->headers[$k] = $v; | |
331 | $this->request .= "$k: $v\r\n"; | |
332 | $this->debug("$k: $v"); | |
333 | } | |
334 | // get SOAPAction header | |
335 | if(isset($this->headers['soapaction'])){ | |
336 | $this->SOAPAction = str_replace('"','',$this->headers['soapaction']); | |
337 | } | |
338 | // get the character encoding of the incoming request | |
339 | if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){ | |
340 | $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1)); | |
341 | if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ | |
342 | $this->xml_encoding = strtoupper($enc); | |
343 | } else { | |
344 | $this->xml_encoding = 'US-ASCII'; | |
345 | } | |
346 | } else { | |
347 | // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 | |
348 | $this->xml_encoding = 'ISO-8859-1'; | |
349 | } | |
350 | } elseif(isset($_SERVER) && is_array($_SERVER)){ | |
351 | $this->debug("In parse_http_headers, use _SERVER"); | |
352 | foreach ($_SERVER as $k => $v) { | |
353 | if (substr($k, 0, 5) == 'HTTP_') { | |
354 | $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); | |
355 | } else { | |
356 | $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); | |
357 | } | |
358 | if ($k == 'soapaction') { | |
359 | // get SOAPAction header | |
360 | $k = 'SOAPAction'; | |
361 | $v = str_replace('"', '', $v); | |
362 | $v = str_replace('\\', '', $v); | |
363 | $this->SOAPAction = $v; | |
364 | } else if ($k == 'content-type') { | |
365 | // get the character encoding of the incoming request | |
366 | if (strpos($v, '=')) { | |
367 | $enc = substr(strstr($v, '='), 1); | |
368 | $enc = str_replace('"', '', $enc); | |
369 | $enc = str_replace('\\', '', $enc); | |
370 | if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { | |
371 | $this->xml_encoding = strtoupper($enc); | |
372 | } else { | |
373 | $this->xml_encoding = 'US-ASCII'; | |
374 | } | |
375 | } else { | |
376 | // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 | |
377 | $this->xml_encoding = 'ISO-8859-1'; | |
378 | } | |
379 | } | |
380 | $this->headers[$k] = $v; | |
381 | $this->request .= "$k: $v\r\n"; | |
382 | $this->debug("$k: $v"); | |
383 | } | |
384 | } elseif (is_array($HTTP_SERVER_VARS)) { | |
385 | $this->debug("In parse_http_headers, use HTTP_SERVER_VARS"); | |
386 | foreach ($HTTP_SERVER_VARS as $k => $v) { | |
387 | if (substr($k, 0, 5) == 'HTTP_') { | |
388 | $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5)); | |
389 | } else { | |
390 | $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); | |
391 | } | |
392 | if ($k == 'soapaction') { | |
393 | // get SOAPAction header | |
394 | $k = 'SOAPAction'; | |
395 | $v = str_replace('"', '', $v); | |
396 | $v = str_replace('\\', '', $v); | |
397 | $this->SOAPAction = $v; | |
398 | } else if ($k == 'content-type') { | |
399 | // get the character encoding of the incoming request | |
400 | if (strpos($v, '=')) { | |
401 | $enc = substr(strstr($v, '='), 1); | |
402 | $enc = str_replace('"', '', $enc); | |
403 | $enc = str_replace('\\', '', $enc); | |
404 | if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) { | |
405 | $this->xml_encoding = strtoupper($enc); | |
406 | } else { | |
407 | $this->xml_encoding = 'US-ASCII'; | |
408 | } | |
409 | } else { | |
410 | // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 | |
411 | $this->xml_encoding = 'ISO-8859-1'; | |
412 | } | |
413 | } | |
414 | $this->headers[$k] = $v; | |
415 | $this->request .= "$k: $v\r\n"; | |
416 | $this->debug("$k: $v"); | |
417 | } | |
418 | } else { | |
419 | $this->debug("In parse_http_headers, HTTP headers not accessible"); | |
420 | $this->setError("HTTP headers not accessible"); | |
421 | } | |
422 | } | |
423 | ||
424 | /** | |
425 | * parses a request | |
426 | * | |
427 | * The following fields are set by this function (when successful) | |
428 | * | |
429 | * headers | |
430 | * request | |
431 | * xml_encoding | |
432 | * SOAPAction | |
433 | * request | |
434 | * requestSOAP | |
435 | * methodURI | |
436 | * methodname | |
437 | * methodparams | |
438 | * requestHeaders | |
439 | * document | |
440 | * | |
441 | * This sets the fault field on error | |
442 | * | |
443 | * @param string $data XML string | |
444 | * @access private | |
445 | */ | |
446 | function parse_request($data='') { | |
447 | $this->debug('entering parse_request()'); | |
448 | $this->parse_http_headers(); | |
449 | $this->debug('got character encoding: '.$this->xml_encoding); | |
450 | // uncompress if necessary | |
451 | if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { | |
452 | $this->debug('got content encoding: ' . $this->headers['content-encoding']); | |
453 | if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { | |
454 | // if decoding works, use it. else assume data wasn't gzencoded | |
455 | if (function_exists('gzuncompress')) { | |
456 | if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { | |
457 | $data = $degzdata; | |
458 | } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { | |
459 | $data = $degzdata; | |
460 | } else { | |
461 | $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); | |
462 | return; | |
463 | } | |
464 | } else { | |
465 | $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); | |
466 | return; | |
467 | } | |
468 | } | |
469 | } | |
470 | $this->request .= "\r\n".$data; | |
471 | $data = $this->parseRequest($this->headers, $data); | |
472 | $this->requestSOAP = $data; | |
473 | $this->debug('leaving parse_request'); | |
474 | } | |
475 | ||
476 | /** | |
477 | * invokes a PHP function for the requested SOAP method | |
478 | * | |
479 | * The following fields are set by this function (when successful) | |
480 | * | |
481 | * methodreturn | |
482 | * | |
483 | * Note that the PHP function that is called may also set the following | |
484 | * fields to affect the response sent to the client | |
485 | * | |
486 | * responseHeaders | |
487 | * outgoing_headers | |
488 | * | |
489 | * This sets the fault field on error | |
490 | * | |
491 | * @access private | |
492 | */ | |
493 | function invoke_method() { | |
494 | $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction); | |
495 | ||
496 | // | |
497 | // if you are debugging in this area of the code, your service uses a class to implement methods, | |
498 | // you use SOAP RPC, and the client is .NET, please be aware of the following... | |
499 | // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the | |
500 | // method name. that is fine for naming the .NET methods. it is not fine for properly constructing | |
501 | // the XML request and reading the XML response. you need to add the RequestElementName and | |
502 | // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe | |
503 | // generates for the method. these parameters are used to specify the correct XML element names | |
504 | // for .NET to use, i.e. the names with the '.' in them. | |
505 | // | |
506 | $orig_methodname = $this->methodname; | |
507 | if ($this->wsdl) { | |
508 | if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { | |
509 | $this->debug('in invoke_method, found WSDL operation=' . $this->methodname); | |
510 | $this->appendDebug('opData=' . $this->varDump($this->opData)); | |
511 | } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { | |
512 | // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element | |
513 | $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']); | |
514 | $this->appendDebug('opData=' . $this->varDump($this->opData)); | |
515 | $this->methodname = $this->opData['name']; | |
516 | } else { | |
517 | $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); | |
518 | $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service"); | |
519 | return; | |
520 | } | |
521 | } else { | |
522 | $this->debug('in invoke_method, no WSDL to validate method'); | |
523 | } | |
524 | ||
525 | // if a . is present in $this->methodname, we see if there is a class in scope, | |
526 | // which could be referred to. We will also distinguish between two deliminators, | |
527 | // to allow methods to be called a the class or an instance | |
528 | if (strpos($this->methodname, '..') > 0) { | |
529 | $delim = '..'; | |
530 | } else if (strpos($this->methodname, '.') > 0) { | |
531 | $delim = '.'; | |
532 | } else { | |
533 | $delim = ''; | |
534 | } | |
535 | $this->debug("in invoke_method, delim=$delim"); | |
536 | ||
537 | $class = ''; | |
538 | $method = ''; | |
539 | if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) { | |
540 | $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim)); | |
541 | if (class_exists($try_class)) { | |
542 | // get the class and method name | |
543 | $class = $try_class; | |
544 | $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); | |
545 | $this->debug("in invoke_method, class=$class method=$method delim=$delim"); | |
546 | } else { | |
547 | $this->debug("in invoke_method, class=$try_class not found"); | |
548 | } | |
549 | } else { | |
550 | $try_class = ''; | |
551 | $this->debug("in invoke_method, no class to try"); | |
552 | } | |
553 | ||
554 | // does method exist? | |
555 | if ($class == '') { | |
556 | if (!function_exists($this->methodname)) { | |
557 | $this->debug("in invoke_method, function '$this->methodname' not found!"); | |
558 | $this->result = 'fault: method not found'; | |
559 | $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')"); | |
560 | return; | |
561 | } | |
562 | } else { | |
563 | $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; | |
564 | if (!in_array($method_to_compare, get_class_methods($class))) { | |
565 | $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); | |
566 | $this->result = 'fault: method not found'; | |
567 | $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')"); | |
568 | return; | |
569 | } | |
570 | } | |
571 | ||
572 | // evaluate message, getting back parameters | |
573 | // verify that request parameters match the method's signature | |
574 | if(! $this->verify_method($this->methodname,$this->methodparams)){ | |
575 | // debug | |
576 | $this->debug('ERROR: request not verified against method signature'); | |
577 | $this->result = 'fault: request failed validation against method signature'; | |
578 | // return fault | |
579 | $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service."); | |
580 | return; | |
581 | } | |
582 | ||
583 | // if there are parameters to pass | |
584 | $this->debug('in invoke_method, params:'); | |
585 | $this->appendDebug($this->varDump($this->methodparams)); | |
586 | $this->debug("in invoke_method, calling '$this->methodname'"); | |
587 | if (!function_exists('call_user_func_array')) { | |
588 | if ($class == '') { | |
589 | $this->debug('in invoke_method, calling function using eval()'); | |
590 | $funcCall = "\$this->methodreturn = $this->methodname("; | |
591 | } else { | |
592 | if ($delim == '..') { | |
593 | $this->debug('in invoke_method, calling class method using eval()'); | |
594 | $funcCall = "\$this->methodreturn = ".$class."::".$method."("; | |
595 | } else { | |
596 | $this->debug('in invoke_method, calling instance method using eval()'); | |
597 | // generate unique instance name | |
598 | $instname = "\$inst_".time(); | |
599 | $funcCall = $instname." = new ".$class."(); "; | |
600 | $funcCall .= "\$this->methodreturn = ".$instname."->".$method."("; | |
601 | } | |
602 | } | |
603 | if ($this->methodparams) { | |
604 | foreach ($this->methodparams as $param) { | |
605 | if (is_array($param) || is_object($param)) { | |
606 | $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); | |
607 | return; | |
608 | } | |
609 | $funcCall .= "\"$param\","; | |
610 | } | |
611 | $funcCall = substr($funcCall, 0, -1); | |
612 | } | |
613 | $funcCall .= ');'; | |
614 | $this->debug('in invoke_method, function call: '.$funcCall); | |
615 | @eval($funcCall); | |
616 | } else { | |
617 | if ($class == '') { | |
618 | $this->debug('in invoke_method, calling function using call_user_func_array()'); | |
619 | $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() | |
620 | } elseif ($delim == '..') { | |
621 | $this->debug('in invoke_method, calling class method using call_user_func_array()'); | |
622 | $call_arg = array ($class, $method); | |
623 | } else { | |
624 | $this->debug('in invoke_method, calling instance method using call_user_func_array()'); | |
625 | $instance = new $class (); | |
626 | $call_arg = array(&$instance, $method); | |
627 | } | |
628 | if (is_array($this->methodparams)) { | |
629 | $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); | |
630 | } else { | |
631 | $this->methodreturn = call_user_func_array($call_arg, array()); | |
632 | } | |
633 | } | |
634 | $this->debug('in invoke_method, methodreturn:'); | |
635 | $this->appendDebug($this->varDump($this->methodreturn)); | |
636 | $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); | |
637 | } | |
638 | ||
639 | /** | |
640 | * serializes the return value from a PHP function into a full SOAP Envelope | |
641 | * | |
642 | * The following fields are set by this function (when successful) | |
643 | * | |
644 | * responseSOAP | |
645 | * | |
646 | * This sets the fault field on error | |
647 | * | |
648 | * @access private | |
649 | */ | |
650 | function serialize_return() { | |
651 | $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); | |
652 | // if fault | |
653 | if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { | |
654 | $this->debug('got a fault object from method'); | |
655 | $this->fault = $this->methodreturn; | |
656 | return; | |
657 | } elseif ($this->methodreturnisliteralxml) { | |
658 | $return_val = $this->methodreturn; | |
659 | // returned value(s) | |
660 | } else { | |
661 | $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); | |
662 | $this->debug('serializing return value'); | |
663 | if($this->wsdl){ | |
664 | if (sizeof($this->opData['output']['parts']) > 1) { | |
665 | $this->debug('more than one output part, so use the method return unchanged'); | |
666 | $opParams = $this->methodreturn; | |
667 | } elseif (sizeof($this->opData['output']['parts']) == 1) { | |
668 | $this->debug('exactly one output part, so wrap the method return in a simple array'); | |
669 | // TODO: verify that it is not already wrapped! | |
670 | //foreach ($this->opData['output']['parts'] as $name => $type) { | |
671 | // $this->debug('wrap in element named ' . $name); | |
672 | //} | |
673 | $opParams = array($this->methodreturn); | |
674 | } | |
675 | $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); | |
676 | $this->appendDebug($this->wsdl->getDebug()); | |
677 | $this->wsdl->clearDebug(); | |
678 | if($errstr = $this->wsdl->getError()){ | |
679 | $this->debug('got wsdl error: '.$errstr); | |
680 | $this->fault('SOAP-ENV:Server', 'unable to serialize result'); | |
681 | return; | |
682 | } | |
683 | } else { | |
684 | if (isset($this->methodreturn)) { | |
685 | $return_val = $this->serialize_val($this->methodreturn, 'return'); | |
686 | } else { | |
687 | $return_val = ''; | |
688 | $this->debug('in absence of WSDL, assume void return for backward compatibility'); | |
689 | } | |
690 | } | |
691 | } | |
692 | $this->debug('return value:'); | |
693 | $this->appendDebug($this->varDump($return_val)); | |
694 | ||
695 | $this->debug('serializing response'); | |
696 | if ($this->wsdl) { | |
697 | $this->debug('have WSDL for serialization: style is ' . $this->opData['style']); | |
698 | if ($this->opData['style'] == 'rpc') { | |
699 | $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); | |
700 | if ($this->opData['output']['use'] == 'literal') { | |
701 | // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace | |
702 | if ($this->methodURI) { | |
703 | $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; | |
704 | } else { | |
705 | $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>'; | |
706 | } | |
707 | } else { | |
708 | if ($this->methodURI) { | |
709 | $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; | |
710 | } else { | |
711 | $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>'; | |
712 | } | |
713 | } | |
714 | } else { | |
715 | $this->debug('style is not rpc for serialization: assume document'); | |
716 | $payload = $return_val; | |
717 | } | |
718 | } else { | |
719 | $this->debug('do not have WSDL for serialization: assume rpc/encoded'); | |
720 | $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; | |
721 | } | |
722 | $this->result = 'successful'; | |
723 | if($this->wsdl){ | |
724 | //if($this->debug_flag){ | |
725 | $this->appendDebug($this->wsdl->getDebug()); | |
726 | // } | |
727 | if (isset($this->opData['output']['encodingStyle'])) { | |
728 | $encodingStyle = $this->opData['output']['encodingStyle']; | |
729 | } else { | |
730 | $encodingStyle = ''; | |
731 | } | |
732 | // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. | |
733 | $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle); | |
734 | } else { | |
735 | $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); | |
736 | } | |
737 | $this->debug("Leaving serialize_return"); | |
738 | } | |
739 | ||
740 | /** | |
741 | * sends an HTTP response | |
742 | * | |
743 | * The following fields are set by this function (when successful) | |
744 | * | |
745 | * outgoing_headers | |
746 | * response | |
747 | * | |
748 | * @access private | |
749 | */ | |
750 | function send_response() { | |
751 | $this->debug('Enter send_response'); | |
752 | if ($this->fault) { | |
753 | $payload = $this->fault->serialize(); | |
754 | $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error"; | |
755 | $this->outgoing_headers[] = "Status: 500 Internal Server Error"; | |
756 | } else { | |
757 | $payload = $this->responseSOAP; | |
758 | // Some combinations of PHP+Web server allow the Status | |
759 | // to come through as a header. Since OK is the default | |
760 | // just do nothing. | |
761 | // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; | |
762 | // $this->outgoing_headers[] = "Status: 200 OK"; | |
763 | } | |
764 | // add debug data if in debug mode | |
765 | if(isset($this->debug_flag) && $this->debug_flag){ | |
766 | $payload .= $this->getDebugAsXMLComment(); | |
767 | } | |
768 | $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; | |
769 | preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev); | |
770 | $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; | |
771 | // Let the Web server decide about this | |
772 | //$this->outgoing_headers[] = "Connection: Close\r\n"; | |
773 | $payload = $this->getHTTPBody($payload); | |
774 | $type = $this->getHTTPContentType(); | |
775 | $charset = $this->getHTTPContentTypeCharset(); | |
776 | $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : ''); | |
777 | //begin code to compress payload - by John | |
778 | // NOTE: there is no way to know whether the Web server will also compress | |
779 | // this data. | |
780 | if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { | |
781 | if (strstr($this->headers['accept-encoding'], 'gzip')) { | |
782 | if (function_exists('gzencode')) { | |
783 | if (isset($this->debug_flag) && $this->debug_flag) { | |
784 | $payload .= "<!-- Content being gzipped -->"; | |
785 | } | |
786 | $this->outgoing_headers[] = "Content-Encoding: gzip"; | |
787 | $payload = gzencode($payload); | |
788 | } else { | |
789 | if (isset($this->debug_flag) && $this->debug_flag) { | |
790 | $payload .= "<!-- Content will not be gzipped: no gzencode -->"; | |
791 | } | |
792 | } | |
793 | } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { | |
794 | // Note: MSIE requires gzdeflate output (no Zlib header and checksum), | |
795 | // instead of gzcompress output, | |
796 | // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) | |
797 | if (function_exists('gzdeflate')) { | |
798 | if (isset($this->debug_flag) && $this->debug_flag) { | |
799 | $payload .= "<!-- Content being deflated -->"; | |
800 | } | |
801 | $this->outgoing_headers[] = "Content-Encoding: deflate"; | |
802 | $payload = gzdeflate($payload); | |
803 | } else { | |
804 | if (isset($this->debug_flag) && $this->debug_flag) { | |
805 | $payload .= "<!-- Content will not be deflated: no gzcompress -->"; | |
806 | } | |
807 | } | |
808 | } | |
809 | } | |
810 | //end code | |
811 | $this->outgoing_headers[] = "Content-Length: ".strlen($payload); | |
812 | reset($this->outgoing_headers); | |
813 | foreach($this->outgoing_headers as $hdr){ | |
814 | header($hdr, false); | |
815 | } | |
816 | print $payload; | |
817 | $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload; | |
818 | } | |
819 | ||
820 | /** | |
821 | * takes the value that was created by parsing the request | |
822 | * and compares to the method's signature, if available. | |
823 | * | |
824 | * @param string $operation The operation to be invoked | |
825 | * @param array $request The array of parameter values | |
826 | * @return boolean Whether the operation was found | |
827 | * @access private | |
828 | */ | |
829 | function verify_method($operation,$request){ | |
830 | if(isset($this->wsdl) && is_object($this->wsdl)){ | |
831 | if($this->wsdl->getOperationData($operation)){ | |
832 | return true; | |
833 | } | |
834 | } elseif(isset($this->operations[$operation])){ | |
835 | return true; | |
836 | } | |
837 | return false; | |
838 | } | |
839 | ||
840 | /** | |
841 | * processes SOAP message received from client | |
842 | * | |
843 | * @param array $headers The HTTP headers | |
844 | * @param string $data unprocessed request data from client | |
845 | * @return mixed value of the message, decoded into a PHP type | |
846 | * @access private | |
847 | */ | |
848 | function parseRequest($headers, $data) { | |
849 | $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:'); | |
850 | $this->appendDebug($this->varDump($headers)); | |
851 | if (!isset($headers['content-type'])) { | |
852 | $this->setError('Request not of type text/xml (no content-type header)'); | |
853 | return false; | |
854 | } | |
855 | if (!strstr($headers['content-type'], 'text/xml')) { | |
856 | $this->setError('Request not of type text/xml'); | |
857 | return false; | |
858 | } | |
859 | if (strpos($headers['content-type'], '=')) { | |
860 | $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); | |
861 | $this->debug('Got response encoding: ' . $enc); | |
862 | if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){ | |
863 | $this->xml_encoding = strtoupper($enc); | |
864 | } else { | |
865 | $this->xml_encoding = 'US-ASCII'; | |
866 | } | |
867 | } else { | |
868 | // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 | |
869 | $this->xml_encoding = 'ISO-8859-1'; | |
870 | } | |
871 | $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); | |
872 | // parse response, get soap parser obj | |
873 | $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8); | |
874 | // parser debug | |
875 | $this->debug("parser debug: \n".$parser->getDebug()); | |
876 | // if fault occurred during message parsing | |
877 | if($err = $parser->getError()){ | |
878 | $this->result = 'fault: error in msg parsing: '.$err; | |
879 | $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err); | |
880 | // else successfully parsed request into soapval object | |
881 | } else { | |
882 | // get/set methodname | |
883 | $this->methodURI = $parser->root_struct_namespace; | |
884 | $this->methodname = $parser->root_struct_name; | |
885 | $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); | |
886 | $this->debug('calling parser->get_soapbody()'); | |
887 | $this->methodparams = $parser->get_soapbody(); | |
888 | // get SOAP headers | |
889 | $this->requestHeaders = $parser->getHeaders(); | |
890 | // get SOAP Header | |
891 | $this->requestHeader = $parser->get_soapheader(); | |
892 | // add document for doclit support | |
893 | $this->document = $parser->document; | |
894 | } | |
895 | } | |
896 | ||
897 | /** | |
898 | * gets the HTTP body for the current response. | |
899 | * | |
900 | * @param string $soapmsg The SOAP payload | |
901 | * @return string The HTTP body, which includes the SOAP payload | |
902 | * @access private | |
903 | */ | |
904 | function getHTTPBody($soapmsg) { | |
905 | return $soapmsg; | |
906 | } | |
907 | ||
908 | /** | |
909 | * gets the HTTP content type for the current response. | |
910 | * | |
911 | * Note: getHTTPBody must be called before this. | |
912 | * | |
913 | * @return string the HTTP content type for the current response. | |
914 | * @access private | |
915 | */ | |
916 | function getHTTPContentType() { | |
917 | return 'text/xml'; | |
918 | } | |
919 | ||
920 | /** | |
921 | * gets the HTTP content type charset for the current response. | |
922 | * returns false for non-text content types. | |
923 | * | |
924 | * Note: getHTTPBody must be called before this. | |
925 | * | |
926 | * @return string the HTTP content type charset for the current response. | |
927 | * @access private | |
928 | */ | |
929 | function getHTTPContentTypeCharset() { | |
930 | return $this->soap_defencoding; | |
931 | } | |
932 | ||
933 | /** | |
934 | * add a method to the dispatch map (this has been replaced by the register method) | |
935 | * | |
936 | * @param string $methodname | |
937 | * @param string $in array of input values | |
938 | * @param string $out array of output values | |
939 | * @access public | |
940 | * @deprecated | |
941 | */ | |
942 | function add_to_map($methodname,$in,$out){ | |
943 | $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out); | |
944 | } | |
945 | ||
946 | /** | |
947 | * register a service function with the server | |
948 | * | |
949 | * @param string $name the name of the PHP function, class.method or class..method | |
950 | * @param array $in assoc array of input values: key = param name, value = param type | |
951 | * @param array $out assoc array of output values: key = param name, value = param type | |
952 | * @param mixed $namespace the element namespace for the method or false | |
953 | * @param mixed $soapaction the soapaction for the method or false | |
954 | * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically | |
955 | * @param mixed $use optional (encoded|literal) or false | |
956 | * @param string $documentation optional Description to include in WSDL | |
957 | * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) | |
958 | * @access public | |
959 | */ | |
960 | function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){ | |
961 | global $HTTP_SERVER_VARS; | |
962 | ||
963 | if($this->externalWSDLURL){ | |
964 | die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); | |
965 | } | |
966 | if (! $name) { | |
967 | die('You must specify a name when you register an operation'); | |
968 | } | |
969 | if (!is_array($in)) { | |
970 | die('You must provide an array for operation inputs'); | |
971 | } | |
972 | if (!is_array($out)) { | |
973 | die('You must provide an array for operation outputs'); | |
974 | } | |
975 | if(false == $namespace) { | |
976 | } | |
977 | if(false == $soapaction) { | |
978 | if (isset($_SERVER)) { | |
979 | $SERVER_NAME = $_SERVER['SERVER_NAME']; | |
980 | $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; | |
981 | $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); | |
982 | } elseif (isset($HTTP_SERVER_VARS)) { | |
983 | $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; | |
984 | $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; | |
985 | $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; | |
986 | } else { | |
987 | $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); | |
988 | } | |
989 | if ($HTTPS == '1' || $HTTPS == 'on') { | |
990 | $SCHEME = 'https'; | |
991 | } else { | |
992 | $SCHEME = 'http'; | |
993 | } | |
994 | $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; | |
995 | } | |
996 | if(false == $style) { | |
997 | $style = "rpc"; | |
998 | } | |
999 | if(false == $use) { | |
1000 | $use = "encoded"; | |
1001 | } | |
1002 | if ($use == 'encoded' && $encodingStyle == '') { | |
1003 | $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; | |
1004 | } | |
1005 | ||
1006 | $this->operations[$name] = array( | |
1007 | 'name' => $name, | |
1008 | 'in' => $in, | |
1009 | 'out' => $out, | |
1010 | 'namespace' => $namespace, | |
1011 | 'soapaction' => $soapaction, | |
1012 | 'style' => $style); | |
1013 | if($this->wsdl){ | |
1014 | $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle); | |
1015 | } | |
1016 | return true; | |
1017 | } | |
1018 | ||
1019 | /** | |
1020 | * Specify a fault to be returned to the client. | |
1021 | * This also acts as a flag to the server that a fault has occured. | |
1022 | * | |
1023 | * @param string $faultcode | |
1024 | * @param string $faultstring | |
1025 | * @param string $faultactor | |
1026 | * @param string $faultdetail | |
1027 | * @access public | |
1028 | */ | |
1029 | function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){ | |
1030 | if ($faultdetail == '' && $this->debug_flag) { | |
1031 | $faultdetail = $this->getDebug(); | |
1032 | } | |
1033 | $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail); | |
1034 | $this->fault->soap_defencoding = $this->soap_defencoding; | |
1035 | } | |
1036 | ||
1037 | /** | |
1038 | * Sets up wsdl object. | |
1039 | * Acts as a flag to enable internal WSDL generation | |
1040 | * | |
1041 | * @param string $serviceName, name of the service | |
1042 | * @param mixed $namespace optional 'tns' service namespace or false | |
1043 | * @param mixed $endpoint optional URL of service endpoint or false | |
1044 | * @param string $style optional (rpc|document) WSDL style (also specified by operation) | |
1045 | * @param string $transport optional SOAP transport | |
1046 | * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false | |
1047 | */ | |
1048 | function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) | |
1049 | { | |
1050 | global $HTTP_SERVER_VARS; | |
1051 | ||
1052 | if (isset($_SERVER)) { | |
1053 | $SERVER_NAME = $_SERVER['SERVER_NAME']; | |
1054 | $SERVER_PORT = $_SERVER['SERVER_PORT']; | |
1055 | $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; | |
1056 | $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); | |
1057 | } elseif (isset($HTTP_SERVER_VARS)) { | |
1058 | $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; | |
1059 | $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; | |
1060 | $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; | |
1061 | $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; | |
1062 | } else { | |
1063 | $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); | |
1064 | } | |
1065 | // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) | |
1066 | $colon = strpos($SERVER_NAME,":"); | |
1067 | if ($colon) { | |
1068 | $SERVER_NAME = substr($SERVER_NAME, 0, $colon); | |
1069 | } | |
1070 | if ($SERVER_PORT == 80) { | |
1071 | $SERVER_PORT = ''; | |
1072 | } else { | |
1073 | $SERVER_PORT = ':' . $SERVER_PORT; | |
1074 | } | |
1075 | if(false == $namespace) { | |
1076 | $namespace = "http://$SERVER_NAME/soap/$serviceName"; | |
1077 | } | |
1078 | ||
1079 | if(false == $endpoint) { | |
1080 | if ($HTTPS == '1' || $HTTPS == 'on') { | |
1081 | $SCHEME = 'https'; | |
1082 | } else { | |
1083 | $SCHEME = 'http'; | |
1084 | } | |
1085 | $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; | |
1086 | } | |
1087 | ||
1088 | if(false == $schemaTargetNamespace) { | |
1089 | $schemaTargetNamespace = $namespace; | |
1090 | } | |
1091 | ||
1092 | $this->wsdl = new wsdl; | |
1093 | $this->wsdl->serviceName = $serviceName; | |
1094 | $this->wsdl->endpoint = $endpoint; | |
1095 | $this->wsdl->namespaces['tns'] = $namespace; | |
1096 | $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; | |
1097 | $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; | |
1098 | if ($schemaTargetNamespace != $namespace) { | |
1099 | $this->wsdl->namespaces['types'] = $schemaTargetNamespace; | |
1100 | } | |
1101 | $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); | |
1102 | if ($style == 'document') { | |
1103 | $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; | |
1104 | } | |
1105 | $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; | |
1106 | $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true); | |
1107 | $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); | |
1108 | $this->wsdl->bindings[$serviceName.'Binding'] = array( | |
1109 | 'name'=>$serviceName.'Binding', | |
1110 | 'style'=>$style, | |
1111 | 'transport'=>$transport, | |
1112 | 'portType'=>$serviceName.'PortType'); | |
1113 | $this->wsdl->ports[$serviceName.'Port'] = array( | |
1114 | 'binding'=>$serviceName.'Binding', | |
1115 | 'location'=>$endpoint, | |
1116 | 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'); | |
1117 | } | |
1118 | } | |
1119 | ||
1120 | /** | |
1121 | * Backward compatibility | |
1122 | */ | |
1123 | class soap_server extends nusoap_server { | |
1124 | } | |
1125 | ||
1126 | ||
1127 | ?> |