nusoap_client

[nu]soapclient higher level class for easy usage.

Defined (2)

The class is defined in the following location(s).

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