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 ?>