]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/nusoap/class.soapclient.php
Release 6.5.0
[Github/sugarcrm.git] / include / nusoap / class.soapclient.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 r39619 - 2008-09-09 13:41:34 -0700 (Tue, 09 Sep 2008) - jmertic - Bug 24827 - Remove all instances where we return a new object and assign it by reference, since this is deprecated in PHP 5 and emits E_DEPRECATED errors in PHP 5.3.
30 Touched:
31 - data/SugarBean.php
32 - include/domit/php_http_client_generic.php
33 - include/domit/php_http_connector.php
34 - include/domit/testing_domit.php
35 - include/domit/xml_domit_getelementsbypath.php
36 - include/domit/xml_domit_lite_parser.php
37 - include/domit/xml_domit_nodemaps.php
38 - include/domit/xml_domit_parser.php
39 - include/domit/xml_domit_shared.php
40 - include/generic/SugarWidgets/SugarWidgetField.php
41 - include/generic/SugarWidgets/SugarWidgetReportField.php
42 - include/ListView/ProcessView.php
43 - include/nusoap/class.soapclient.php
44 - include/nusoap/nusoap.php
45 - include/nusoap/nusoapmime.php
46 - include/Pear/HTML_Safe/Safe.php
47 - include/Pear/XML_HTMLSax3/HTMLSax3.php
48 - modules/Administration/RebuildWorkFlow.php
49 - modules/Expressions/RelateSelector.php
50 - modules/Reports/templates/templates_reports.php
51 - modules/WorkFlow/Delete.php
52 - modules/WorkFlow/Save.php
53 - modules/WorkFlow/SaveSequence.php
54 - modules/WorkFlow/WorkFlow.php
55 - modules/WorkFlowActionShells/CreateStep1.php
56 - modules/WorkFlowActionShells/CreateStep2.php
57 - modules/WorkFlowActionShells/Save.php
58 - modules/WorkFlowActionShells/WorkFlowActionShell.php
59 - modules/WorkFlowAlerts/Save.php
60 - modules/WorkFlowAlerts/WorkFlowAlert.php
61 - modules/WorkFlowAlertShells/DetailView.php
62 - modules/WorkFlowAlertShells/WorkFlowAlertShell.php
63 - modules/WorkFlowTriggerShells/CreateStep1.php
64 - modules/WorkFlowTriggerShells/CreateStepFilter.php
65 - modules/WorkFlowTriggerShells/SaveFilter.php
66 - modules/WorkFlowTriggerShells/WorkFlowTriggerShell.php
67 - soap/SoapHelperFunctions.php
68 - test/modules/DynamicFields/DynamicFields_Bug24095_test.php
69 - test/simpletest/browser.php
70 - test/simpletest/default_reporter.php
71 - test/simpletest/detached.php
72 - test/simpletest/eclipse.php
73 - test/simpletest/expectation.php
74 - test/simpletest/extensions/pear_test_case.php
75 - test/simpletest/form.php
76 - test/simpletest/http.php
77 - test/simpletest/mock_objects.php
78 - test/simpletest/page.php
79 - test/simpletest/parser.php
80 - test/simpletest/remote.php
81 - test/simpletest/shell_tester.php
82 - test/simpletest/simple_test.php
83 - test/simpletest/simpletest.php
84 - test/simpletest/test/acceptance_test.php
85 - test/simpletest/test/adapter_test.php
86 - test/simpletest/test/authentication_test.php
87 - test/simpletest/test/browser_test.php
88 - test/simpletest/test/collector_test.php
89 - test/simpletest/test/compatibility_test.php
90 - test/simpletest/test/detached_test.php
91 - test/simpletest/test/eclipse_test.php
92 - test/simpletest/test/encoding_test.php
93 - test/simpletest/test/errors_test.php
94 - test/simpletest/test/expectation_test.php
95 - test/simpletest/test/form_test.php
96 - test/simpletest/test/frames_test.php
97 - test/simpletest/test/http_test.php
98 - test/simpletest/test/live_test.php
99 - test/simpletest/test/mock_objects_test.php
100 - test/simpletest/test/page_test.php
101 - test/simpletest/test/parse_error_test.php
102 - test/simpletest/test/parser_test.php
103 - test/simpletest/test/remote_test.php
104 - test/simpletest/test/shell_test.php
105 - test/simpletest/test/shell_tester_test.php
106 - test/simpletest/test/simpletest_test.php
107 - test/simpletest/test/site/page_request.php
108 - test/simpletest/test/tag_test.php
109 - test/simpletest/test/unit_tester_test.php
110 - test/simpletest/test/user_agent_test.php
111 - test/simpletest/test/visual_test.php
112 - test/simpletest/test/xml_test.php
113 - test/simpletest/test_case.php
114 - test/simpletest/ui/array_reporter/test.php
115 - test/simpletest/ui/recorder/test.php
116 - test/simpletest/unit_tester.php
117 - test/simpletest/url.php
118 - test/simpletest/user_agent.php
119 - test/simpletest/web_tester.php
120 - test/spikephpcoverage/src/PEAR.php
121 - test/spikephpcoverage/src/util/Utility.php
122 - test/spikephpcoverage/src/XML/Parser.php
123 - test/spikephpcoverage/src/XML/Parser/Simple.php
124 - test/test_utilities/SugarTest_SimpleBrowser.php
125
126 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
127
128 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
129
130 r8991 - 2005-11-03 19:07:25 -0800 (Thu, 03 Nov 2005) - majed - fixes nusoap issue
131
132 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
133
134 r7905 - 2005-09-21 19:12:57 -0700 (Wed, 21 Sep 2005) - majed - restores old nusoap pre & with a few fixes
135
136 r7861 - 2005-09-20 15:40:25 -0700 (Tue, 20 Sep 2005) - majed - & fix for 3.5.1
137
138 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
139
140 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly.  --clint
141
142 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
143
144 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
145
146
147 */
148
149
150 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
151
152
153
154
155 /**
156 *
157 * [nu]soapclient higher level class for easy usage.
158 *
159 * usage:
160 *
161 * // instantiate client with server info
162 * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
163 *
164 * // call method, get results
165 * echo $soapclient->call( string methodname [ ,array parameters] );
166 *
167 * // bye bye client
168 * unset($soapclient);
169 *
170 * @author   Dietrich Ayala <dietrich@ganx4.com>
171 * @author   Scott Nichol <snichol@users.sourceforge.net>
172
173 * @access   public
174 */
175 class nusoap_client extends nusoap_base  {
176
177         var $username = '';                             // Username for HTTP authentication
178         var $password = '';                             // Password for HTTP authentication
179         var $authtype = '';                             // Type of HTTP authentication
180         var $certRequest = array();             // Certificate for HTTP SSL authentication
181         var $requestHeaders = false;    // SOAP headers in request (text)
182         var $responseHeaders = '';              // SOAP headers from response (incomplete namespace resolution) (text)
183         var $responseHeader = NULL;             // SOAP Header from response (parsed)
184         var $document = '';                             // SOAP body response portion (incomplete namespace resolution) (text)
185         var $endpoint;
186         var $forceEndpoint = '';                // overrides WSDL endpoint
187     var $proxyhost = '';
188     var $proxyport = '';
189         var $proxyusername = '';
190         var $proxypassword = '';
191         var $portName = '';                             // port name to use in WSDL
192     var $xml_encoding = '';                     // character set encoding of incoming (response) messages
193         var $http_encoding = false;
194         var $timeout = 0;                               // HTTP connection timeout
195         var $response_timeout = 30;             // HTTP response timeout
196         var $endpointType = '';                 // soap|wsdl, empty for WSDL initialization error
197         var $persistentConnection = false;
198         var $defaultRpcParams = false;  // This is no longer used
199         var $request = '';                              // HTTP request
200         var $response = '';                             // HTTP response
201         var $responseData = '';                 // SOAP payload of response
202         var $cookies = array();                 // Cookies from response or for request
203     var $decode_utf8 = true;            // toggles whether the parser decodes element content w/ utf8_decode()
204         var $operations = array();              // WSDL operations, empty for WSDL initialization error
205         var $curl_options = array();    // User-specified cURL options
206         var $bindingType = '';                  // WSDL operation binding type
207         var $use_curl = false;                  // whether to always try to use cURL
208
209         /*
210          * fault related variables
211          */
212         /**
213          * @var      fault
214          * @access   public
215          */
216         var $fault;
217         /**
218          * @var      faultcode
219          * @access   public
220          */
221         var $faultcode;
222         /**
223          * @var      faultstring
224          * @access   public
225          */
226         var $faultstring;
227         /**
228          * @var      faultdetail
229          * @access   public
230          */
231         var $faultdetail;
232
233         /**
234         * constructor
235         *
236         * @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
237         * @param    mixed $wsdl optional, set to 'wsdl' or true if using WSDL
238         * @param    string $proxyhost optional
239         * @param    string $proxyport optional
240         * @param        string $proxyusername optional
241         * @param        string $proxypassword optional
242         * @param        integer $timeout set the connection timeout
243         * @param        integer $response_timeout set the response timeout
244         * @param        string $portName optional portName in WSDL document
245         * @access   public
246         */
247         function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = ''){
248                 parent::nusoap_base();
249                 $this->endpoint = $endpoint;
250                 $this->proxyhost = $proxyhost;
251                 $this->proxyport = $proxyport;
252                 $this->proxyusername = $proxyusername;
253                 $this->proxypassword = $proxypassword;
254                 $this->timeout = $timeout;
255                 $this->response_timeout = $response_timeout;
256                 $this->portName = $portName;
257
258                 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
259                 $this->appendDebug('endpoint=' . $this->varDump($endpoint));
260
261                 // make values
262                 if($wsdl){
263                         if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
264                                 $this->wsdl = $endpoint;
265                                 $this->endpoint = $this->wsdl->wsdl;
266                                 $this->wsdlFile = $this->endpoint;
267                                 $this->debug('existing wsdl instance created from ' . $this->endpoint);
268                                 $this->checkWSDL();
269                         } else {
270                                 $this->wsdlFile = $this->endpoint;
271                                 $this->wsdl = null;
272                                 $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
273                         }
274                         $this->endpointType = 'wsdl';
275                 } else {
276                         $this->debug("instantiate SOAP with endpoint at $endpoint");
277                         $this->endpointType = 'soap';
278                 }
279         }
280
281         /**
282         * calls method, returns PHP native type
283         *
284         * @param    string $operation SOAP server URL or path
285         * @param    mixed $params An array, associative or simple, of the parameters
286         *                                     for the method call, or a string that is the XML
287         *                                     for the call.  For rpc style, this call will
288         *                                     wrap the XML in a tag named after the method, as
289         *                                     well as the SOAP Envelope and Body.  For document
290         *                                     style, this will only wrap with the Envelope and Body.
291         *                                     IMPORTANT: when using an array with document style,
292         *                                     in which case there
293         *                         is really one parameter, the root of the fragment
294         *                         used in the call, which encloses what programmers
295         *                         normally think of parameters.  A parameter array
296         *                         *must* include the wrapper.
297         * @param        string $namespace optional method namespace (WSDL can override)
298         * @param        string $soapAction optional SOAPAction value (WSDL can override)
299         * @param        mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
300         * @param        boolean $rpcParams optional (no longer used)
301         * @param        string  $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
302         * @param        string  $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
303         * @return       mixed   response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
304         * @access   public
305         */
306         function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
307                 $this->operation = $operation;
308                 $this->fault = false;
309                 $this->setError('');
310                 $this->request = '';
311                 $this->response = '';
312                 $this->responseData = '';
313                 $this->faultstring = '';
314                 $this->faultcode = '';
315                 $this->opData = array();
316                 
317                 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
318                 $this->appendDebug('params=' . $this->varDump($params));
319                 $this->appendDebug('headers=' . $this->varDump($headers));
320                 if ($headers) {
321                         $this->requestHeaders = $headers;
322                 }
323                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
324                         $this->loadWSDL();
325                         if ($this->getError())
326                                 return false;
327                 }
328                 // serialize parameters
329                 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
330                         // use WSDL for operation
331                         $this->opData = $opData;
332                         $this->debug("found operation");
333                         $this->appendDebug('opData=' . $this->varDump($opData));
334                         if (isset($opData['soapAction'])) {
335                                 $soapAction = $opData['soapAction'];
336                         }
337                         if (! $this->forceEndpoint) {
338                                 $this->endpoint = $opData['endpoint'];
339                         } else {
340                                 $this->endpoint = $this->forceEndpoint;
341                         }
342                         $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :     $namespace;
343                         $style = $opData['style'];
344                         $use = $opData['input']['use'];
345                         // add ns to ns array
346                         if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
347                                 $nsPrefix = 'ns' . rand(1000, 9999);
348                                 $this->wsdl->namespaces[$nsPrefix] = $namespace;
349                         }
350             $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
351                         // serialize payload
352                         if (is_string($params)) {
353                                 $this->debug("serializing param string for WSDL operation $operation");
354                                 $payload = $params;
355                         } elseif (is_array($params)) {
356                                 $this->debug("serializing param array for WSDL operation $operation");
357                                 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
358                         } else {
359                                 $this->debug('params must be array or string');
360                                 $this->setError('params must be array or string');
361                                 return false;
362                         }
363             $usedNamespaces = $this->wsdl->usedNamespaces;
364                         if (isset($opData['input']['encodingStyle'])) {
365                                 $encodingStyle = $opData['input']['encodingStyle'];
366                         } else {
367                                 $encodingStyle = '';
368                         }
369                         $this->appendDebug($this->wsdl->getDebug());
370                         $this->wsdl->clearDebug();
371                         if ($errstr = $this->wsdl->getError()) {
372                                 $this->debug('got wsdl error: '.$errstr);
373                                 $this->setError('wsdl error: '.$errstr);
374                                 return false;
375                         }
376                 } elseif($this->endpointType == 'wsdl') {
377                         // operation not in WSDL
378                         $this->appendDebug($this->wsdl->getDebug());
379                         $this->wsdl->clearDebug();
380                         $this->setError('operation '.$operation.' not present in WSDL.');
381                         $this->debug("operation '$operation' not present in WSDL.");
382                         return false;
383                 } else {
384                         // no WSDL
385                         //$this->namespaces['ns1'] = $namespace;
386                         $nsPrefix = 'ns' . rand(1000, 9999);
387                         // serialize 
388                         $payload = '';
389                         if (is_string($params)) {
390                                 $this->debug("serializing param string for operation $operation");
391                                 $payload = $params;
392                         } elseif (is_array($params)) {
393                                 $this->debug("serializing param array for operation $operation");
394                                 foreach($params as $k => $v){
395                                         $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
396                                 }
397                         } else {
398                                 $this->debug('params must be array or string');
399                                 $this->setError('params must be array or string');
400                                 return false;
401                         }
402                         $usedNamespaces = array();
403                         if ($use == 'encoded') {
404                                 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
405                         } else {
406                                 $encodingStyle = '';
407                         }
408                 }
409                 // wrap RPC calls with method element
410                 if ($style == 'rpc') {
411                         if ($use == 'literal') {
412                                 $this->debug("wrapping RPC request with literal method element");
413                                 if ($namespace) {
414                                         // 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
415                                         $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
416                                                                 $payload .
417                                                                 "</$nsPrefix:$operation>";
418                                 } else {
419                                         $payload = "<$operation>" . $payload . "</$operation>";
420                                 }
421                         } else {
422                                 $this->debug("wrapping RPC request with encoded method element");
423                                 if ($namespace) {
424                                         $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
425                                                                 $payload .
426                                                                 "</$nsPrefix:$operation>";
427                                 } else {
428                                         $payload = "<$operation>" .
429                                                                 $payload .
430                                                                 "</$operation>";
431                                 }
432                         }
433                 }
434                 // serialize envelope
435                 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
436                 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
437                 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
438                 // send
439                 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
440                 if($errstr = $this->getError()){
441                         $this->debug('Error: '.$errstr);
442                         return false;
443                 } else {
444                         $this->return = $return;
445                         $this->debug('sent message successfully and got a(n) '.gettype($return));
446                 $this->appendDebug('return=' . $this->varDump($return));
447                         
448                         // fault?
449                         if(is_array($return) && isset($return['faultcode'])){
450                                 $this->debug('got fault');
451                                 $this->setError($return['faultcode'].': '.$return['faultstring']);
452                                 $this->fault = true;
453                                 foreach($return as $k => $v){
454                                         $this->$k = $v;
455                                         $this->debug("$k = $v<br>");
456                                 }
457                                 return $return;
458                         } elseif ($style == 'document') {
459                                 // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
460                                 // we are only going to return the first part here...sorry about that
461                                 return $return;
462                         } else {
463                                 // array of return values
464                                 if(is_array($return)){
465                                         // multiple 'out' parameters, which we return wrapped up
466                                         // in the array
467                                         if(sizeof($return) > 1){
468                                                 return $return;
469                                         }
470                                         // single 'out' parameter (normally the return value)
471                                         $return = array_shift($return);
472                                         $this->debug('return shifted value: ');
473                                         $this->appendDebug($this->varDump($return));
474                                 return $return;
475                                 // nothing returned (ie, echoVoid)
476                                 } else {
477                                         return "";
478                                 }
479                         }
480                 }
481         }
482
483         /**
484         * check WSDL passed as an instance or pulled from an endpoint
485         *
486         * @access   private
487         */
488         function checkWSDL() {
489                 $this->appendDebug($this->wsdl->getDebug());
490                 $this->wsdl->clearDebug();
491                 $this->debug('checkWSDL');
492                 // catch errors
493                 if ($errstr = $this->wsdl->getError()) {
494                         $this->appendDebug($this->wsdl->getDebug());
495                         $this->wsdl->clearDebug();
496                         $this->debug('got wsdl error: '.$errstr);
497                         $this->setError('wsdl error: '.$errstr);
498                 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
499                         $this->appendDebug($this->wsdl->getDebug());
500                         $this->wsdl->clearDebug();
501                         $this->bindingType = 'soap';
502                         $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
503                 } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
504                         $this->appendDebug($this->wsdl->getDebug());
505                         $this->wsdl->clearDebug();
506                         $this->bindingType = 'soap12';
507                         $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
508                         $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
509                 } else {
510                         $this->appendDebug($this->wsdl->getDebug());
511                         $this->wsdl->clearDebug();
512                         $this->debug('getOperations returned false');
513                         $this->setError('no operations defined in the WSDL document!');
514                 }
515         }
516
517         /**
518          * instantiate wsdl object and parse wsdl file
519          *
520          * @access      public
521          */
522         function loadWSDL() {
523                 $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
524                 $this->wsdl = new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
525                 $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
526                 $this->wsdl->fetchWSDL($this->wsdlFile);
527                 $this->checkWSDL();
528         }
529
530         /**
531         * get available data pertaining to an operation
532         *
533         * @param    string $operation operation name
534         * @return       array array of data pertaining to the operation
535         * @access   public
536         */
537         function getOperationData($operation){
538                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
539                         $this->loadWSDL();
540                         if ($this->getError())
541                                 return false;
542                 }
543                 if(isset($this->operations[$operation])){
544                         return $this->operations[$operation];
545                 }
546                 $this->debug("No data for operation: $operation");
547         }
548
549     /**
550     * send the SOAP message
551     *
552     * Note: if the operation has multiple return values
553     * the return value of this method will be an array
554     * of those values.
555     *
556         * @param    string $msg a SOAPx4 soapmsg object
557         * @param    string $soapaction SOAPAction value
558         * @param    integer $timeout set connection timeout in seconds
559         * @param        integer $response_timeout set response timeout in seconds
560         * @return       mixed native PHP types.
561         * @access   private
562         */
563         function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
564                 $this->checkCookies();
565                 // detect transport
566                 switch(true){
567                         // http(s)
568                         case preg_match('/^http/',$this->endpoint):
569                                 $this->debug('transporting via HTTP');
570                                 if($this->persistentConnection == true && is_object($this->persistentConnection)){
571                                         $http =& $this->persistentConnection;
572                                 } else {
573                                         $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
574                                         if ($this->persistentConnection) {
575                                                 $http->usePersistentConnection();
576                                         }
577                                 }
578                                 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
579                                 $http->setSOAPAction($soapaction);
580                                 if($this->proxyhost && $this->proxyport){
581                                         $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
582                                 }
583                 if($this->authtype != '') {
584                                         $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
585                                 }
586                                 if($this->http_encoding != ''){
587                                         $http->setEncoding($this->http_encoding);
588                                 }
589                                 $this->debug('sending message, length='.strlen($msg));
590                                 if(preg_match('/^http:/',$this->endpoint)){
591                                 //if(strpos($this->endpoint,'http:')){
592                                         $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
593                                 } elseif(preg_match('/^https/',$this->endpoint)){
594                                 //} elseif(strpos($this->endpoint,'https:')){
595                                         //if(phpversion() == '4.3.0-dev'){
596                                                 //$response = $http->send($msg,$timeout,$response_timeout);
597                                 //$this->request = $http->outgoing_payload;
598                                                 //$this->response = $http->incoming_payload;
599                                         //} else
600                                         $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
601                                 } else {
602                                         $this->setError('no http/s in endpoint url');
603                                 }
604                                 $this->request = $http->outgoing_payload;
605                                 $this->response = $http->incoming_payload;
606                                 $this->appendDebug($http->getDebug());
607                                 $this->UpdateCookies($http->incoming_cookies);
608
609                                 // save transport object if using persistent connections
610                                 if ($this->persistentConnection) {
611                                         $http->clearDebug();
612                                         if (!is_object($this->persistentConnection)) {
613                                                 $this->persistentConnection = $http;
614                                         }
615                                 }
616                                 
617                                 if($err = $http->getError()){
618                                         $this->setError('HTTP Error: '.$err);
619                                         return false;
620                                 } elseif($this->getError()){
621                                         return false;
622                                 } else {
623                                         $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
624                                         return $this->parseResponse($http->incoming_headers, $this->responseData);
625                                 }
626                         break;
627                         default:
628                                 $this->setError('no transport found, or selected transport is not yet supported!');
629                         return false;
630                         break;
631                 }
632         }
633
634         /**
635         * processes SOAP message returned from server
636         *
637         * @param        array   $headers        The HTTP headers
638         * @param        string  $data           unprocessed response data from server
639         * @return       mixed   value of the message, decoded into a PHP type
640         * @access   private
641         */
642     function parseResponse($headers, $data) {
643                 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
644                 $this->appendDebug($this->varDump($headers));
645         if (!isset($headers['content-type'])) {
646                         $this->setError('Response not of type text/xml (no content-type header)');
647                         return false;
648         }
649                 if (!strstr($headers['content-type'], 'text/xml')) {
650                         $this->setError('Response not of type text/xml: ' . $headers['content-type']);
651                         return false;
652                 }
653                 if (strpos($headers['content-type'], '=')) {
654                         $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
655                         $this->debug('Got response encoding: ' . $enc);
656                         if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
657                                 $this->xml_encoding = strtoupper($enc);
658                         } else {
659                                 $this->xml_encoding = 'US-ASCII';
660                         }
661                 } else {
662                         // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
663                         $this->xml_encoding = 'ISO-8859-1';
664                 }
665                 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
666                 $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
667                 // add parser debug data to our debug
668                 $this->appendDebug($parser->getDebug());
669                 // if parse errors
670                 if($errstr = $parser->getError()){
671                         $this->setError( $errstr);
672                         // destroy the parser object
673                         unset($parser);
674                         return false;
675                 } else {
676                         // get SOAP headers
677                         $this->responseHeaders = $parser->getHeaders();
678                         // get SOAP headers
679                         $this->responseHeader = $parser->get_soapheader();
680                         // get decoded message
681                         $return = $parser->get_soapbody();
682             // add document for doclit support
683             $this->document = $parser->document;
684                         // destroy the parser object
685                         unset($parser);
686                         // return decode message
687                         return $return;
688                 }
689          }
690
691         /**
692         * sets user-specified cURL options
693         *
694         * @param        mixed $option The cURL option (always integer?)
695         * @param        mixed $value The cURL option value
696         * @access   public
697         */
698         function setCurlOption($option, $value) {
699                 $this->debug("setCurlOption option=$option, value=");
700                 $this->appendDebug($this->varDump($value));
701                 $this->curl_options[$option] = $value;
702         }
703
704         /**
705         * sets the SOAP endpoint, which can override WSDL
706         *
707         * @param        string $endpoint The endpoint URL to use, or empty string or false to prevent override
708         * @access   public
709         */
710         function setEndpoint($endpoint) {
711                 $this->debug("setEndpoint(\"$endpoint\")");
712                 $this->forceEndpoint = $endpoint;
713         }
714
715         /**
716         * set the SOAP headers
717         *
718         * @param        mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
719         * @access   public
720         */
721         function setHeaders($headers){
722                 $this->debug("setHeaders headers=");
723                 $this->appendDebug($this->varDump($headers));
724                 $this->requestHeaders = $headers;
725         }
726
727         /**
728         * get the SOAP response headers (namespace resolution incomplete)
729         *
730         * @return       string
731         * @access   public
732         */
733         function getHeaders(){
734                 return $this->responseHeaders;
735         }
736
737         /**
738         * get the SOAP response Header (parsed)
739         *
740         * @return       mixed
741         * @access   public
742         */
743         function getHeader(){
744                 return $this->responseHeader;
745         }
746
747         /**
748         * set proxy info here
749         *
750         * @param    string $proxyhost
751         * @param    string $proxyport
752         * @param        string $proxyusername
753         * @param        string $proxypassword
754         * @access   public
755         */
756         function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
757                 $this->proxyhost = $proxyhost;
758                 $this->proxyport = $proxyport;
759                 $this->proxyusername = $proxyusername;
760                 $this->proxypassword = $proxypassword;
761         }
762
763         /**
764         * if authenticating, set user credentials here
765         *
766         * @param    string $username
767         * @param    string $password
768         * @param        string $authtype (basic|digest|certificate|ntlm)
769         * @param        array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
770         * @access   public
771         */
772         function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
773                 $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
774                 $this->appendDebug($this->varDump($certRequest));
775                 $this->username = $username;
776                 $this->password = $password;
777                 $this->authtype = $authtype;
778                 $this->certRequest = $certRequest;
779         }
780         
781         /**
782         * use HTTP encoding
783         *
784         * @param    string $enc HTTP encoding
785         * @access   public
786         */
787         function setHTTPEncoding($enc='gzip, deflate'){
788                 $this->debug("setHTTPEncoding(\"$enc\")");
789                 $this->http_encoding = $enc;
790         }
791         
792         /**
793         * Set whether to try to use cURL connections if possible
794         *
795         * @param        boolean $use Whether to try to use cURL
796         * @access   public
797         */
798         function setUseCURL($use) {
799                 $this->debug("setUseCURL($use)");
800                 $this->use_curl = $use;
801         }
802
803         /**
804         * use HTTP persistent connections if possible
805         *
806         * @access   public
807         */
808         function useHTTPPersistentConnection(){
809                 $this->debug("useHTTPPersistentConnection");
810                 $this->persistentConnection = true;
811         }
812         
813         /**
814         * gets the default RPC parameter setting.
815         * If true, default is that call params are like RPC even for document style.
816         * Each call() can override this value.
817         *
818         * This is no longer used.
819         *
820         * @return boolean
821         * @access public
822         * @deprecated
823         */
824         function getDefaultRpcParams() {
825                 return $this->defaultRpcParams;
826         }
827
828         /**
829         * sets the default RPC parameter setting.
830         * If true, default is that call params are like RPC even for document style
831         * Each call() can override this value.
832         *
833         * This is no longer used.
834         *
835         * @param    boolean $rpcParams
836         * @access public
837         * @deprecated
838         */
839         function setDefaultRpcParams($rpcParams) {
840                 $this->defaultRpcParams = $rpcParams;
841         }
842         
843         /**
844         * dynamically creates an instance of a proxy class,
845         * allowing user to directly call methods from wsdl
846         *
847         * @return   object soap_proxy object
848         * @access   public
849         */
850         function getProxy() {
851                 $r = rand();
852                 $evalStr = $this->_getProxyClassCode($r);
853                 //$this->debug("proxy class: $evalStr");
854                 if ($this->getError()) {
855                         $this->debug("Error from _getProxyClassCode, so return NULL");
856                         return null;
857                 }
858                 // eval the class
859                 eval($evalStr);
860                 // instantiate proxy object
861                 eval("\$proxy = new nusoap_proxy_$r('');");
862                 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
863                 $proxy->endpointType = 'wsdl';
864                 $proxy->wsdlFile = $this->wsdlFile;
865                 $proxy->wsdl = $this->wsdl;
866                 $proxy->operations = $this->operations;
867                 $proxy->defaultRpcParams = $this->defaultRpcParams;
868                 // transfer other state
869                 $proxy->soap_defencoding = $this->soap_defencoding;
870                 $proxy->username = $this->username;
871                 $proxy->password = $this->password;
872                 $proxy->authtype = $this->authtype;
873                 $proxy->certRequest = $this->certRequest;
874                 $proxy->requestHeaders = $this->requestHeaders;
875                 $proxy->endpoint = $this->endpoint;
876                 $proxy->forceEndpoint = $this->forceEndpoint;
877                 $proxy->proxyhost = $this->proxyhost;
878                 $proxy->proxyport = $this->proxyport;
879                 $proxy->proxyusername = $this->proxyusername;
880                 $proxy->proxypassword = $this->proxypassword;
881                 $proxy->http_encoding = $this->http_encoding;
882                 $proxy->timeout = $this->timeout;
883                 $proxy->response_timeout = $this->response_timeout;
884                 $proxy->persistentConnection = &$this->persistentConnection;
885                 $proxy->decode_utf8 = $this->decode_utf8;
886                 $proxy->curl_options = $this->curl_options;
887                 $proxy->bindingType = $this->bindingType;
888                 $proxy->use_curl = $this->use_curl;
889                 return $proxy;
890         }
891
892         /**
893         * dynamically creates proxy class code
894         *
895         * @return   string PHP/NuSOAP code for the proxy class
896         * @access   private
897         */
898         function _getProxyClassCode($r) {
899                 $this->debug("in getProxy endpointType=$this->endpointType");
900                 $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
901                 if ($this->endpointType != 'wsdl') {
902                         $evalStr = 'A proxy can only be created for a WSDL client';
903                         $this->setError($evalStr);
904                         $evalStr = "echo \"$evalStr\";";
905                         return $evalStr;
906                 }
907                 if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
908                         $this->loadWSDL();
909                         if ($this->getError()) {
910                                 return "echo \"" . $this->getError() . "\";";
911                         }
912                 }
913                 $evalStr = '';
914                 foreach ($this->operations as $operation => $opData) {
915                         if ($operation != '') {
916                                 // create param string and param comment string
917                                 if (sizeof($opData['input']['parts']) > 0) {
918                                         $paramStr = '';
919                                         $paramArrayStr = '';
920                                         $paramCommentStr = '';
921                                         foreach ($opData['input']['parts'] as $name => $type) {
922                                                 $paramStr .= "\$$name, ";
923                                                 $paramArrayStr .= "'$name' => \$$name, ";
924                                                 $paramCommentStr .= "$type \$$name, ";
925                                         }
926                                         $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
927                                         $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
928                                         $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
929                                 } else {
930                                         $paramStr = '';
931                                         $paramArrayStr = '';
932                                         $paramCommentStr = 'void';
933                                 }
934                                 $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
935                                 $evalStr .= "// $paramCommentStr
936         function " . str_replace('.', '__', $operation) . "($paramStr) {
937                 \$params = array($paramArrayStr);
938                 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
939         }
940         ";
941                                 unset($paramStr);
942                                 unset($paramCommentStr);
943                         }
944                 }
945                 $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
946         '.$evalStr.'
947 }';
948                 return $evalStr;
949         }
950
951         /**
952         * dynamically creates proxy class code
953         *
954         * @return   string PHP/NuSOAP code for the proxy class
955         * @access   public
956         */
957         function getProxyClassCode() {
958                 $r = rand();
959                 return $this->_getProxyClassCode($r);
960         }
961
962         /**
963         * gets the HTTP body for the current request.
964         *
965         * @param string $soapmsg The SOAP payload
966         * @return string The HTTP body, which includes the SOAP payload
967         * @access private
968         */
969         function getHTTPBody($soapmsg) {
970                 return $soapmsg;
971         }
972         
973         /**
974         * gets the HTTP content type for the current request.
975         *
976         * Note: getHTTPBody must be called before this.
977         *
978         * @return string the HTTP content type for the current request.
979         * @access private
980         */
981         function getHTTPContentType() {
982                 return 'text/xml';
983         }
984         
985         /**
986         * gets the HTTP content type charset for the current request.
987         * returns false for non-text content types.
988         *
989         * Note: getHTTPBody must be called before this.
990         *
991         * @return string the HTTP content type charset for the current request.
992         * @access private
993         */
994         function getHTTPContentTypeCharset() {
995                 return $this->soap_defencoding;
996         }
997
998         /*
999         * whether or not parser should decode utf8 element content
1000     *
1001     * @return   always returns true
1002     * @access   public
1003     */
1004     function decodeUTF8($bool){
1005                 $this->decode_utf8 = $bool;
1006                 return true;
1007     }
1008
1009         /**
1010          * adds a new Cookie into $this->cookies array
1011          *
1012          * @param       string $name Cookie Name
1013          * @param       string $value Cookie Value
1014          * @return      boolean if cookie-set was successful returns true, else false
1015          * @access      public
1016          */
1017         function setCookie($name, $value) {
1018                 if (strlen($name) == 0) {
1019                         return false;
1020                 }
1021                 $this->cookies[] = array('name' => $name, 'value' => $value);
1022                 return true;
1023         }
1024
1025         /**
1026          * gets all Cookies
1027          *
1028          * @return   array with all internal cookies
1029          * @access   public
1030          */
1031         function getCookies() {
1032                 return $this->cookies;
1033         }
1034
1035         /**
1036          * checks all Cookies and delete those which are expired
1037          *
1038          * @return   boolean always return true
1039          * @access   private
1040          */
1041         function checkCookies() {
1042                 if (sizeof($this->cookies) == 0) {
1043                         return true;
1044                 }
1045                 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
1046                 $curr_cookies = $this->cookies;
1047                 $this->cookies = array();
1048                 foreach ($curr_cookies as $cookie) {
1049                         if (! is_array($cookie)) {
1050                                 $this->debug('Remove cookie that is not an array');
1051                                 continue;
1052                         }
1053                         if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
1054                                 if (strtotime($cookie['expires']) > time()) {
1055                                         $this->cookies[] = $cookie;
1056                                 } else {
1057                                         $this->debug('Remove expired cookie ' . $cookie['name']);
1058                                 }
1059                         } else {
1060                                 $this->cookies[] = $cookie;
1061                         }
1062                 }
1063                 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
1064                 return true;
1065         }
1066
1067         /**
1068          * updates the current cookies with a new set
1069          *
1070          * @param       array $cookies new cookies with which to update current ones
1071          * @return      boolean always return true
1072          * @access      private
1073          */
1074         function UpdateCookies($cookies) {
1075                 if (sizeof($this->cookies) == 0) {
1076                         // no existing cookies: take whatever is new
1077                         if (sizeof($cookies) > 0) {
1078                                 $this->debug('Setting new cookie(s)');
1079                                 $this->cookies = $cookies;
1080                         }
1081                         return true;
1082                 }
1083                 if (sizeof($cookies) == 0) {
1084                         // no new cookies: keep what we've got
1085                         return true;
1086                 }
1087                 // merge
1088                 foreach ($cookies as $newCookie) {
1089                         if (!is_array($newCookie)) {
1090                                 continue;
1091                         }
1092                         if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
1093                                 continue;
1094                         }
1095                         $newName = $newCookie['name'];
1096
1097                         $found = false;
1098                         for ($i = 0; $i < count($this->cookies); $i++) {
1099                                 $cookie = $this->cookies[$i];
1100                                 if (!is_array($cookie)) {
1101                                         continue;
1102                                 }
1103                                 if (!isset($cookie['name'])) {
1104                                         continue;
1105                                 }
1106                                 if ($newName != $cookie['name']) {
1107                                         continue;
1108                                 }
1109                                 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
1110                                 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
1111                                 if ($newDomain != $domain) {
1112                                         continue;
1113                                 }
1114                                 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
1115                                 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
1116                                 if ($newPath != $path) {
1117                                         continue;
1118                                 }
1119                                 $this->cookies[$i] = $newCookie;
1120                                 $found = true;
1121                                 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
1122                                 break;
1123                         }
1124                         if (! $found) {
1125                                 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
1126                                 $this->cookies[] = $newCookie;
1127                         }
1128                 }
1129                 return true;
1130         }
1131 }
1132
1133 if (!extension_loaded('soap')) {
1134         /**
1135          *      For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
1136          */
1137         class soapclient extends nusoap_client {
1138         }
1139 }
1140
1141 /**
1142  *      For backwards compatiblity, define nusoapclient unless the PHP SOAP extension is loaded.
1143  */
1144 class nusoapclient extends nusoap_client {
1145 }
1146 ?>