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