shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

class.soapclient.php (32661B)


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