Completed
Push — master ( dca322...47e653 )
by Julito
08:54
created

nusoap_client   F

Complexity

Total Complexity 126

Size/Duplication

Total Lines 955
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 474
dl 0
loc 955
rs 2
c 0
b 0
f 0
wmc 126

How to fix   Complexity   

Complex Class

Complex classes like nusoap_client often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use nusoap_client, and based on these observations, apply Extract Interface, too.

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