class.soapclient.php 32 KB

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