class.soap_server.php 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. <?php
  2. /**
  3. *
  4. * nusoap_server allows the user to create a SOAP server
  5. * that is capable of receiving messages and returning responses
  6. *
  7. * @author Dietrich Ayala <dietrich@ganx4.com>
  8. * @author Scott Nichol <snichol@users.sourceforge.net>
  9. * @version $Id: class.soap_server.php,v 1.63 2010/04/26 20:15:08 snichol Exp $
  10. * @access public
  11. */
  12. class nusoap_server extends nusoap_base {
  13. /**
  14. * HTTP headers of request
  15. * @var array
  16. * @access private
  17. */
  18. var $headers = array();
  19. /**
  20. * HTTP request
  21. * @var string
  22. * @access private
  23. */
  24. var $request = '';
  25. /**
  26. * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
  27. * @var string
  28. * @access public
  29. */
  30. var $requestHeaders = '';
  31. /**
  32. * SOAP Headers from request (parsed)
  33. * @var mixed
  34. * @access public
  35. */
  36. var $requestHeader = NULL;
  37. /**
  38. * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
  39. * @var string
  40. * @access public
  41. */
  42. var $document = '';
  43. /**
  44. * SOAP payload for request (text)
  45. * @var string
  46. * @access public
  47. */
  48. var $requestSOAP = '';
  49. /**
  50. * requested method namespace URI
  51. * @var string
  52. * @access private
  53. */
  54. var $methodURI = '';
  55. /**
  56. * name of method requested
  57. * @var string
  58. * @access private
  59. */
  60. var $methodname = '';
  61. /**
  62. * method parameters from request
  63. * @var array
  64. * @access private
  65. */
  66. var $methodparams = array();
  67. /**
  68. * SOAP Action from request
  69. * @var string
  70. * @access private
  71. */
  72. var $SOAPAction = '';
  73. /**
  74. * character set encoding of incoming (request) messages
  75. * @var string
  76. * @access public
  77. */
  78. var $xml_encoding = '';
  79. /**
  80. * toggles whether the parser decodes element content w/ utf8_decode()
  81. * @var boolean
  82. * @access public
  83. */
  84. var $decode_utf8 = true;
  85. /**
  86. * HTTP headers of response
  87. * @var array
  88. * @access public
  89. */
  90. var $outgoing_headers = array();
  91. /**
  92. * HTTP response
  93. * @var string
  94. * @access private
  95. */
  96. var $response = '';
  97. /**
  98. * SOAP headers for response (text or array of soapval or associative array)
  99. * @var mixed
  100. * @access public
  101. */
  102. var $responseHeaders = '';
  103. /**
  104. * SOAP payload for response (text)
  105. * @var string
  106. * @access private
  107. */
  108. var $responseSOAP = '';
  109. /**
  110. * method return value to place in response
  111. * @var mixed
  112. * @access private
  113. */
  114. var $methodreturn = false;
  115. /**
  116. * whether $methodreturn is a string of literal XML
  117. * @var boolean
  118. * @access public
  119. */
  120. var $methodreturnisliteralxml = false;
  121. /**
  122. * SOAP fault for response (or false)
  123. * @var mixed
  124. * @access private
  125. */
  126. var $fault = false;
  127. /**
  128. * text indication of result (for debugging)
  129. * @var string
  130. * @access private
  131. */
  132. var $result = 'successful';
  133. /**
  134. * assoc array of operations => opData; operations are added by the register()
  135. * method or by parsing an external WSDL definition
  136. * @var array
  137. * @access private
  138. */
  139. var $operations = array();
  140. /**
  141. * wsdl instance (if one)
  142. * @var mixed
  143. * @access private
  144. */
  145. var $wsdl = false;
  146. /**
  147. * URL for WSDL (if one)
  148. * @var mixed
  149. * @access private
  150. */
  151. var $externalWSDLURL = false;
  152. /**
  153. * whether to append debug to response as XML comment
  154. * @var boolean
  155. * @access public
  156. */
  157. var $debug_flag = false;
  158. /**
  159. * constructor
  160. * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
  161. *
  162. * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
  163. * @access public
  164. */
  165. function nusoap_server($wsdl=false){
  166. parent::nusoap_base();
  167. // turn on debugging?
  168. global $debug;
  169. global $HTTP_SERVER_VARS;
  170. if (isset($_SERVER)) {
  171. $this->debug("_SERVER is defined:");
  172. $this->appendDebug($this->varDump($_SERVER));
  173. } elseif (isset($HTTP_SERVER_VARS)) {
  174. $this->debug("HTTP_SERVER_VARS is defined:");
  175. $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
  176. } else {
  177. $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
  178. }
  179. if (isset($debug)) {
  180. $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
  181. $this->debug_flag = $debug;
  182. } elseif (isset($_SERVER['QUERY_STRING'])) {
  183. $qs = explode('&', $_SERVER['QUERY_STRING']);
  184. foreach ($qs as $v) {
  185. if (substr($v, 0, 6) == 'debug=') {
  186. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
  187. $this->debug_flag = substr($v, 6);
  188. }
  189. }
  190. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
  191. $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
  192. foreach ($qs as $v) {
  193. if (substr($v, 0, 6) == 'debug=') {
  194. $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
  195. $this->debug_flag = substr($v, 6);
  196. }
  197. }
  198. }
  199. // wsdl
  200. if($wsdl){
  201. $this->debug("In nusoap_server, WSDL is specified");
  202. if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
  203. $this->wsdl = $wsdl;
  204. $this->externalWSDLURL = $this->wsdl->wsdl;
  205. $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
  206. } else {
  207. $this->debug('Create wsdl from ' . $wsdl);
  208. $this->wsdl = new wsdl($wsdl);
  209. $this->externalWSDLURL = $wsdl;
  210. }
  211. $this->appendDebug($this->wsdl->getDebug());
  212. $this->wsdl->clearDebug();
  213. if($err = $this->wsdl->getError()){
  214. die('WSDL ERROR: '.$err);
  215. }
  216. }
  217. }
  218. /**
  219. * processes request and returns response
  220. *
  221. * @param string $data usually is the value of $HTTP_RAW_POST_DATA
  222. * @access public
  223. */
  224. function service($data){
  225. global $HTTP_SERVER_VARS;
  226. if (isset($_SERVER['REQUEST_METHOD'])) {
  227. $rm = $_SERVER['REQUEST_METHOD'];
  228. } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
  229. $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
  230. } else {
  231. $rm = '';
  232. }
  233. if (isset($_SERVER['QUERY_STRING'])) {
  234. $qs = $_SERVER['QUERY_STRING'];
  235. } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
  236. $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
  237. } else {
  238. $qs = '';
  239. }
  240. $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
  241. if ($rm == 'POST') {
  242. $this->debug("In service, invoke the request");
  243. $this->parse_request($data);
  244. if (! $this->fault) {
  245. $this->invoke_method();
  246. }
  247. if (! $this->fault) {
  248. $this->serialize_return();
  249. }
  250. $this->send_response();
  251. } elseif (preg_match('/wsdl/', $qs) ){
  252. $this->debug("In service, this is a request for WSDL");
  253. if ($this->externalWSDLURL){
  254. if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
  255. $this->debug("In service, re-direct for WSDL");
  256. header('Location: '.$this->externalWSDLURL);
  257. } else { // assume file
  258. $this->debug("In service, use file passthru for WSDL");
  259. header("Content-Type: text/xml\r\n");
  260. $pos = strpos($this->externalWSDLURL, "file://");
  261. if ($pos === false) {
  262. $filename = $this->externalWSDLURL;
  263. } else {
  264. $filename = substr($this->externalWSDLURL, $pos + 7);
  265. }
  266. $fp = fopen($this->externalWSDLURL, 'r');
  267. fpassthru($fp);
  268. }
  269. } elseif ($this->wsdl) {
  270. $this->debug("In service, serialize WSDL");
  271. header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
  272. print $this->wsdl->serialize($this->debug_flag);
  273. if ($this->debug_flag) {
  274. $this->debug('wsdl:');
  275. $this->appendDebug($this->varDump($this->wsdl));
  276. print $this->getDebugAsXMLComment();
  277. }
  278. } else {
  279. $this->debug("In service, there is no WSDL");
  280. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
  281. print "This service does not provide WSDL";
  282. }
  283. } elseif ($this->wsdl) {
  284. $this->debug("In service, return Web description");
  285. print $this->wsdl->webDescription();
  286. } else {
  287. $this->debug("In service, no Web description");
  288. header("Content-Type: text/html; charset=ISO-8859-1\r\n");
  289. print "This service does not provide a Web description";
  290. }
  291. }
  292. /**
  293. * parses HTTP request headers.
  294. *
  295. * The following fields are set by this function (when successful)
  296. *
  297. * headers
  298. * request
  299. * xml_encoding
  300. * SOAPAction
  301. *
  302. * @access private
  303. */
  304. function parse_http_headers() {
  305. global $HTTP_SERVER_VARS;
  306. $this->request = '';
  307. $this->SOAPAction = '';
  308. if(function_exists('getallheaders')){
  309. $this->debug("In parse_http_headers, use getallheaders");
  310. $headers = getallheaders();
  311. foreach($headers as $k=>$v){
  312. $k = strtolower($k);
  313. $this->headers[$k] = $v;
  314. $this->request .= "$k: $v\r\n";
  315. $this->debug("$k: $v");
  316. }
  317. // get SOAPAction header
  318. if(isset($this->headers['soapaction'])){
  319. $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
  320. }
  321. // get the character encoding of the incoming request
  322. if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
  323. $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
  324. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
  325. $this->xml_encoding = strtoupper($enc);
  326. } else {
  327. $this->xml_encoding = 'US-ASCII';
  328. }
  329. } else {
  330. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  331. $this->xml_encoding = 'ISO-8859-1';
  332. }
  333. } elseif(isset($_SERVER) && is_array($_SERVER)){
  334. $this->debug("In parse_http_headers, use _SERVER");
  335. foreach ($_SERVER as $k => $v) {
  336. if (substr($k, 0, 5) == 'HTTP_') {
  337. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
  338. } else {
  339. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
  340. }
  341. if ($k == 'soapaction') {
  342. // get SOAPAction header
  343. $k = 'SOAPAction';
  344. $v = str_replace('"', '', $v);
  345. $v = str_replace('\\', '', $v);
  346. $this->SOAPAction = $v;
  347. } else if ($k == 'content-type') {
  348. // get the character encoding of the incoming request
  349. if (strpos($v, '=')) {
  350. $enc = substr(strstr($v, '='), 1);
  351. $enc = str_replace('"', '', $enc);
  352. $enc = str_replace('\\', '', $enc);
  353. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
  354. $this->xml_encoding = strtoupper($enc);
  355. } else {
  356. $this->xml_encoding = 'US-ASCII';
  357. }
  358. } else {
  359. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  360. $this->xml_encoding = 'ISO-8859-1';
  361. }
  362. }
  363. $this->headers[$k] = $v;
  364. $this->request .= "$k: $v\r\n";
  365. $this->debug("$k: $v");
  366. }
  367. } elseif (is_array($HTTP_SERVER_VARS)) {
  368. $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
  369. foreach ($HTTP_SERVER_VARS as $k => $v) {
  370. if (substr($k, 0, 5) == 'HTTP_') {
  371. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
  372. } else {
  373. $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
  374. }
  375. if ($k == 'soapaction') {
  376. // get SOAPAction header
  377. $k = 'SOAPAction';
  378. $v = str_replace('"', '', $v);
  379. $v = str_replace('\\', '', $v);
  380. $this->SOAPAction = $v;
  381. } else if ($k == 'content-type') {
  382. // get the character encoding of the incoming request
  383. if (strpos($v, '=')) {
  384. $enc = substr(strstr($v, '='), 1);
  385. $enc = str_replace('"', '', $enc);
  386. $enc = str_replace('\\', '', $enc);
  387. if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)) {
  388. $this->xml_encoding = strtoupper($enc);
  389. } else {
  390. $this->xml_encoding = 'US-ASCII';
  391. }
  392. } else {
  393. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  394. $this->xml_encoding = 'ISO-8859-1';
  395. }
  396. }
  397. $this->headers[$k] = $v;
  398. $this->request .= "$k: $v\r\n";
  399. $this->debug("$k: $v");
  400. }
  401. } else {
  402. $this->debug("In parse_http_headers, HTTP headers not accessible");
  403. $this->setError("HTTP headers not accessible");
  404. }
  405. }
  406. /**
  407. * parses a request
  408. *
  409. * The following fields are set by this function (when successful)
  410. *
  411. * headers
  412. * request
  413. * xml_encoding
  414. * SOAPAction
  415. * request
  416. * requestSOAP
  417. * methodURI
  418. * methodname
  419. * methodparams
  420. * requestHeaders
  421. * document
  422. *
  423. * This sets the fault field on error
  424. *
  425. * @param string $data XML string
  426. * @access private
  427. */
  428. function parse_request($data='') {
  429. $this->debug('entering parse_request()');
  430. $this->parse_http_headers();
  431. $this->debug('got character encoding: '.$this->xml_encoding);
  432. // uncompress if necessary
  433. if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
  434. $this->debug('got content encoding: ' . $this->headers['content-encoding']);
  435. if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
  436. // if decoding works, use it. else assume data wasn't gzencoded
  437. if (function_exists('gzuncompress')) {
  438. if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
  439. $data = $degzdata;
  440. } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
  441. $data = $degzdata;
  442. } else {
  443. $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
  444. return;
  445. }
  446. } else {
  447. $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
  448. return;
  449. }
  450. }
  451. }
  452. $this->request .= "\r\n".$data;
  453. $data = $this->parseRequest($this->headers, $data);
  454. $this->requestSOAP = $data;
  455. $this->debug('leaving parse_request');
  456. }
  457. /**
  458. * invokes a PHP function for the requested SOAP method
  459. *
  460. * The following fields are set by this function (when successful)
  461. *
  462. * methodreturn
  463. *
  464. * Note that the PHP function that is called may also set the following
  465. * fields to affect the response sent to the client
  466. *
  467. * responseHeaders
  468. * outgoing_headers
  469. *
  470. * This sets the fault field on error
  471. *
  472. * @access private
  473. */
  474. function invoke_method() {
  475. $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
  476. //
  477. // if you are debugging in this area of the code, your service uses a class to implement methods,
  478. // you use SOAP RPC, and the client is .NET, please be aware of the following...
  479. // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
  480. // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
  481. // the XML request and reading the XML response. you need to add the RequestElementName and
  482. // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
  483. // generates for the method. these parameters are used to specify the correct XML element names
  484. // for .NET to use, i.e. the names with the '.' in them.
  485. //
  486. $orig_methodname = $this->methodname;
  487. if ($this->wsdl) {
  488. if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
  489. $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
  490. $this->appendDebug('opData=' . $this->varDump($this->opData));
  491. } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
  492. // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
  493. $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
  494. $this->appendDebug('opData=' . $this->varDump($this->opData));
  495. $this->methodname = $this->opData['name'];
  496. } else {
  497. $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
  498. $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
  499. return;
  500. }
  501. } else {
  502. $this->debug('in invoke_method, no WSDL to validate method');
  503. }
  504. // if a . is present in $this->methodname, we see if there is a class in scope,
  505. // which could be referred to. We will also distinguish between two deliminators,
  506. // to allow methods to be called a the class or an instance
  507. if (strpos($this->methodname, '..') > 0) {
  508. $delim = '..';
  509. } else if (strpos($this->methodname, '.') > 0) {
  510. $delim = '.';
  511. } else {
  512. $delim = '';
  513. }
  514. $this->debug("in invoke_method, delim=$delim");
  515. $class = '';
  516. $method = '';
  517. if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
  518. $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
  519. if (class_exists($try_class)) {
  520. // get the class and method name
  521. $class = $try_class;
  522. $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
  523. $this->debug("in invoke_method, class=$class method=$method delim=$delim");
  524. } else {
  525. $this->debug("in invoke_method, class=$try_class not found");
  526. }
  527. } else {
  528. $try_class = '';
  529. $this->debug("in invoke_method, no class to try");
  530. }
  531. // does method exist?
  532. if ($class == '') {
  533. if (!function_exists($this->methodname)) {
  534. $this->debug("in invoke_method, function '$this->methodname' not found!");
  535. $this->result = 'fault: method not found';
  536. $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
  537. return;
  538. }
  539. } else {
  540. $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
  541. if (!in_array($method_to_compare, get_class_methods($class))) {
  542. $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
  543. $this->result = 'fault: method not found';
  544. $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
  545. return;
  546. }
  547. }
  548. // evaluate message, getting back parameters
  549. // verify that request parameters match the method's signature
  550. if(! $this->verify_method($this->methodname,$this->methodparams)){
  551. // debug
  552. $this->debug('ERROR: request not verified against method signature');
  553. $this->result = 'fault: request failed validation against method signature';
  554. // return fault
  555. $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
  556. return;
  557. }
  558. // if there are parameters to pass
  559. $this->debug('in invoke_method, params:');
  560. $this->appendDebug($this->varDump($this->methodparams));
  561. $this->debug("in invoke_method, calling '$this->methodname'");
  562. if (!function_exists('call_user_func_array')) {
  563. if ($class == '') {
  564. $this->debug('in invoke_method, calling function using eval()');
  565. $funcCall = "\$this->methodreturn = $this->methodname(";
  566. } else {
  567. if ($delim == '..') {
  568. $this->debug('in invoke_method, calling class method using eval()');
  569. $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
  570. } else {
  571. $this->debug('in invoke_method, calling instance method using eval()');
  572. // generate unique instance name
  573. $instname = "\$inst_".time();
  574. $funcCall = $instname." = new ".$class."(); ";
  575. $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
  576. }
  577. }
  578. if ($this->methodparams) {
  579. foreach ($this->methodparams as $param) {
  580. if (is_array($param) || is_object($param)) {
  581. $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
  582. return;
  583. }
  584. $funcCall .= "\"$param\",";
  585. }
  586. $funcCall = substr($funcCall, 0, -1);
  587. }
  588. $funcCall .= ');';
  589. $this->debug('in invoke_method, function call: '.$funcCall);
  590. @eval($funcCall);
  591. } else {
  592. if ($class == '') {
  593. $this->debug('in invoke_method, calling function using call_user_func_array()');
  594. $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
  595. } elseif ($delim == '..') {
  596. $this->debug('in invoke_method, calling class method using call_user_func_array()');
  597. $call_arg = array ($class, $method);
  598. } else {
  599. $this->debug('in invoke_method, calling instance method using call_user_func_array()');
  600. $instance = new $class ();
  601. $call_arg = array(&$instance, $method);
  602. }
  603. if (is_array($this->methodparams)) {
  604. $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
  605. } else {
  606. $this->methodreturn = call_user_func_array($call_arg, array());
  607. }
  608. }
  609. $this->debug('in invoke_method, methodreturn:');
  610. $this->appendDebug($this->varDump($this->methodreturn));
  611. $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
  612. }
  613. /**
  614. * serializes the return value from a PHP function into a full SOAP Envelope
  615. *
  616. * The following fields are set by this function (when successful)
  617. *
  618. * responseSOAP
  619. *
  620. * This sets the fault field on error
  621. *
  622. * @access private
  623. */
  624. function serialize_return() {
  625. $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
  626. // if fault
  627. if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
  628. $this->debug('got a fault object from method');
  629. $this->fault = $this->methodreturn;
  630. return;
  631. } elseif ($this->methodreturnisliteralxml) {
  632. $return_val = $this->methodreturn;
  633. // returned value(s)
  634. } else {
  635. $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
  636. $this->debug('serializing return value');
  637. if($this->wsdl){
  638. if (sizeof($this->opData['output']['parts']) > 1) {
  639. $this->debug('more than one output part, so use the method return unchanged');
  640. $opParams = $this->methodreturn;
  641. } elseif (sizeof($this->opData['output']['parts']) == 1) {
  642. $this->debug('exactly one output part, so wrap the method return in a simple array');
  643. // TODO: verify that it is not already wrapped!
  644. //foreach ($this->opData['output']['parts'] as $name => $type) {
  645. // $this->debug('wrap in element named ' . $name);
  646. //}
  647. $opParams = array($this->methodreturn);
  648. }
  649. $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
  650. $this->appendDebug($this->wsdl->getDebug());
  651. $this->wsdl->clearDebug();
  652. if($errstr = $this->wsdl->getError()){
  653. $this->debug('got wsdl error: '.$errstr);
  654. $this->fault('SOAP-ENV:Server', 'unable to serialize result');
  655. return;
  656. }
  657. } else {
  658. if (isset($this->methodreturn)) {
  659. $return_val = $this->serialize_val($this->methodreturn, 'return');
  660. } else {
  661. $return_val = '';
  662. $this->debug('in absence of WSDL, assume void return for backward compatibility');
  663. }
  664. }
  665. }
  666. $this->debug('return value:');
  667. $this->appendDebug($this->varDump($return_val));
  668. $this->debug('serializing response');
  669. if ($this->wsdl) {
  670. $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
  671. if ($this->opData['style'] == 'rpc') {
  672. $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
  673. if ($this->opData['output']['use'] == 'literal') {
  674. // 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
  675. if ($this->methodURI) {
  676. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  677. } else {
  678. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
  679. }
  680. } else {
  681. if ($this->methodURI) {
  682. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  683. } else {
  684. $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
  685. }
  686. }
  687. } else {
  688. $this->debug('style is not rpc for serialization: assume document');
  689. $payload = $return_val;
  690. }
  691. } else {
  692. $this->debug('do not have WSDL for serialization: assume rpc/encoded');
  693. $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
  694. }
  695. $this->result = 'successful';
  696. if($this->wsdl){
  697. //if($this->debug_flag){
  698. $this->appendDebug($this->wsdl->getDebug());
  699. // }
  700. if (isset($this->opData['output']['encodingStyle'])) {
  701. $encodingStyle = $this->opData['output']['encodingStyle'];
  702. } else {
  703. $encodingStyle = '';
  704. }
  705. // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
  706. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
  707. } else {
  708. $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
  709. }
  710. $this->debug("Leaving serialize_return");
  711. }
  712. /**
  713. * sends an HTTP response
  714. *
  715. * The following fields are set by this function (when successful)
  716. *
  717. * outgoing_headers
  718. * response
  719. *
  720. * @access private
  721. */
  722. function send_response() {
  723. $this->debug('Enter send_response');
  724. if ($this->fault) {
  725. $payload = $this->fault->serialize();
  726. $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
  727. $this->outgoing_headers[] = "Status: 500 Internal Server Error";
  728. } else {
  729. $payload = $this->responseSOAP;
  730. // Some combinations of PHP+Web server allow the Status
  731. // to come through as a header. Since OK is the default
  732. // just do nothing.
  733. // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
  734. // $this->outgoing_headers[] = "Status: 200 OK";
  735. }
  736. // add debug data if in debug mode
  737. if(isset($this->debug_flag) && $this->debug_flag){
  738. $payload .= $this->getDebugAsXMLComment();
  739. }
  740. $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
  741. preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
  742. $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
  743. // Let the Web server decide about this
  744. //$this->outgoing_headers[] = "Connection: Close\r\n";
  745. $payload = $this->getHTTPBody($payload);
  746. $type = $this->getHTTPContentType();
  747. $charset = $this->getHTTPContentTypeCharset();
  748. $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
  749. //begin code to compress payload - by John
  750. // NOTE: there is no way to know whether the Web server will also compress
  751. // this data.
  752. if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
  753. if (strstr($this->headers['accept-encoding'], 'gzip')) {
  754. if (function_exists('gzencode')) {
  755. if (isset($this->debug_flag) && $this->debug_flag) {
  756. $payload .= "<!-- Content being gzipped -->";
  757. }
  758. $this->outgoing_headers[] = "Content-Encoding: gzip";
  759. $payload = gzencode($payload);
  760. } else {
  761. if (isset($this->debug_flag) && $this->debug_flag) {
  762. $payload .= "<!-- Content will not be gzipped: no gzencode -->";
  763. }
  764. }
  765. } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
  766. // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
  767. // instead of gzcompress output,
  768. // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
  769. if (function_exists('gzdeflate')) {
  770. if (isset($this->debug_flag) && $this->debug_flag) {
  771. $payload .= "<!-- Content being deflated -->";
  772. }
  773. $this->outgoing_headers[] = "Content-Encoding: deflate";
  774. $payload = gzdeflate($payload);
  775. } else {
  776. if (isset($this->debug_flag) && $this->debug_flag) {
  777. $payload .= "<!-- Content will not be deflated: no gzcompress -->";
  778. }
  779. }
  780. }
  781. }
  782. //end code
  783. $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
  784. reset($this->outgoing_headers);
  785. foreach($this->outgoing_headers as $hdr){
  786. header($hdr, false);
  787. }
  788. print $payload;
  789. $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
  790. }
  791. /**
  792. * takes the value that was created by parsing the request
  793. * and compares to the method's signature, if available.
  794. *
  795. * @param string $operation The operation to be invoked
  796. * @param array $request The array of parameter values
  797. * @return boolean Whether the operation was found
  798. * @access private
  799. */
  800. function verify_method($operation,$request){
  801. if(isset($this->wsdl) && is_object($this->wsdl)){
  802. if($this->wsdl->getOperationData($operation)){
  803. return true;
  804. }
  805. } elseif(isset($this->operations[$operation])){
  806. return true;
  807. }
  808. return false;
  809. }
  810. /**
  811. * processes SOAP message received from client
  812. *
  813. * @param array $headers The HTTP headers
  814. * @param string $data unprocessed request data from client
  815. * @return mixed value of the message, decoded into a PHP type
  816. * @access private
  817. */
  818. function parseRequest($headers, $data) {
  819. $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
  820. $this->appendDebug($this->varDump($headers));
  821. if (!isset($headers['content-type'])) {
  822. $this->setError('Request not of type text/xml (no content-type header)');
  823. return false;
  824. }
  825. if (!strstr($headers['content-type'], 'text/xml')) {
  826. $this->setError('Request not of type text/xml');
  827. return false;
  828. }
  829. if (strpos($headers['content-type'], '=')) {
  830. $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
  831. $this->debug('Got response encoding: ' . $enc);
  832. if(preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i',$enc)){
  833. $this->xml_encoding = strtoupper($enc);
  834. } else {
  835. $this->xml_encoding = 'US-ASCII';
  836. }
  837. } else {
  838. // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
  839. $this->xml_encoding = 'ISO-8859-1';
  840. }
  841. $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
  842. // parse response, get soap parser obj
  843. $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
  844. // parser debug
  845. $this->debug("parser debug: \n".$parser->getDebug());
  846. // if fault occurred during message parsing
  847. if($err = $parser->getError()){
  848. $this->result = 'fault: error in msg parsing: '.$err;
  849. $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
  850. // else successfully parsed request into soapval object
  851. } else {
  852. // get/set methodname
  853. $this->methodURI = $parser->root_struct_namespace;
  854. $this->methodname = $parser->root_struct_name;
  855. $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
  856. $this->debug('calling parser->get_soapbody()');
  857. $this->methodparams = $parser->get_soapbody();
  858. // get SOAP headers
  859. $this->requestHeaders = $parser->getHeaders();
  860. // get SOAP Header
  861. $this->requestHeader = $parser->get_soapheader();
  862. // add document for doclit support
  863. $this->document = $parser->document;
  864. }
  865. }
  866. /**
  867. * gets the HTTP body for the current response.
  868. *
  869. * @param string $soapmsg The SOAP payload
  870. * @return string The HTTP body, which includes the SOAP payload
  871. * @access private
  872. */
  873. function getHTTPBody($soapmsg) {
  874. return $soapmsg;
  875. }
  876. /**
  877. * gets the HTTP content type for the current response.
  878. *
  879. * Note: getHTTPBody must be called before this.
  880. *
  881. * @return string the HTTP content type for the current response.
  882. * @access private
  883. */
  884. function getHTTPContentType() {
  885. return 'text/xml';
  886. }
  887. /**
  888. * gets the HTTP content type charset for the current response.
  889. * returns false for non-text content types.
  890. *
  891. * Note: getHTTPBody must be called before this.
  892. *
  893. * @return string the HTTP content type charset for the current response.
  894. * @access private
  895. */
  896. function getHTTPContentTypeCharset() {
  897. return $this->soap_defencoding;
  898. }
  899. /**
  900. * add a method to the dispatch map (this has been replaced by the register method)
  901. *
  902. * @param string $methodname
  903. * @param string $in array of input values
  904. * @param string $out array of output values
  905. * @access public
  906. * @deprecated
  907. */
  908. function add_to_map($methodname,$in,$out){
  909. $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
  910. }
  911. /**
  912. * register a service function with the server
  913. *
  914. * @param string $name the name of the PHP function, class.method or class..method
  915. * @param array $in assoc array of input values: key = param name, value = param type
  916. * @param array $out assoc array of output values: key = param name, value = param type
  917. * @param mixed $namespace the element namespace for the method or false
  918. * @param mixed $soapaction the soapaction for the method or false
  919. * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
  920. * @param mixed $use optional (encoded|literal) or false
  921. * @param string $documentation optional Description to include in WSDL
  922. * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
  923. * @access public
  924. */
  925. function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
  926. global $HTTP_SERVER_VARS;
  927. if($this->externalWSDLURL){
  928. die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
  929. }
  930. if (! $name) {
  931. die('You must specify a name when you register an operation');
  932. }
  933. if (!is_array($in)) {
  934. die('You must provide an array for operation inputs');
  935. }
  936. if (!is_array($out)) {
  937. die('You must provide an array for operation outputs');
  938. }
  939. if(false == $namespace) {
  940. }
  941. if(false == $soapaction) {
  942. if (isset($_SERVER)) {
  943. $SERVER_NAME = $_SERVER['SERVER_NAME'];
  944. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
  945. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
  946. } elseif (isset($HTTP_SERVER_VARS)) {
  947. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
  948. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
  949. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
  950. } else {
  951. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
  952. }
  953. if ($HTTPS == '1' || $HTTPS == 'on') {
  954. $SCHEME = 'https';
  955. } else {
  956. $SCHEME = 'http';
  957. }
  958. $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
  959. }
  960. if(false == $style) {
  961. $style = "rpc";
  962. }
  963. if(false == $use) {
  964. $use = "encoded";
  965. }
  966. if ($use == 'encoded' && $encodingStyle == '') {
  967. $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
  968. }
  969. $this->operations[$name] = array(
  970. 'name' => $name,
  971. 'in' => $in,
  972. 'out' => $out,
  973. 'namespace' => $namespace,
  974. 'soapaction' => $soapaction,
  975. 'style' => $style);
  976. if($this->wsdl){
  977. $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
  978. }
  979. return true;
  980. }
  981. /**
  982. * Specify a fault to be returned to the client.
  983. * This also acts as a flag to the server that a fault has occured.
  984. *
  985. * @param string $faultcode
  986. * @param string $faultstring
  987. * @param string $faultactor
  988. * @param string $faultdetail
  989. * @access public
  990. */
  991. function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
  992. if ($faultdetail == '' && $this->debug_flag) {
  993. $faultdetail = $this->getDebug();
  994. }
  995. $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
  996. $this->fault->soap_defencoding = $this->soap_defencoding;
  997. }
  998. /**
  999. * Sets up wsdl object.
  1000. * Acts as a flag to enable internal WSDL generation
  1001. *
  1002. * @param string $serviceName, name of the service
  1003. * @param mixed $namespace optional 'tns' service namespace or false
  1004. * @param mixed $endpoint optional URL of service endpoint or false
  1005. * @param string $style optional (rpc|document) WSDL style (also specified by operation)
  1006. * @param string $transport optional SOAP transport
  1007. * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
  1008. */
  1009. function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
  1010. {
  1011. global $HTTP_SERVER_VARS;
  1012. if (isset($_SERVER)) {
  1013. $SERVER_NAME = $_SERVER['SERVER_NAME'];
  1014. $SERVER_PORT = $_SERVER['SERVER_PORT'];
  1015. $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
  1016. $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
  1017. } elseif (isset($HTTP_SERVER_VARS)) {
  1018. $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
  1019. $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
  1020. $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
  1021. $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
  1022. } else {
  1023. $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
  1024. }
  1025. // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
  1026. $colon = strpos($SERVER_NAME,":");
  1027. if ($colon) {
  1028. $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
  1029. }
  1030. if ($SERVER_PORT == 80) {
  1031. $SERVER_PORT = '';
  1032. } else {
  1033. $SERVER_PORT = ':' . $SERVER_PORT;
  1034. }
  1035. if(false == $namespace) {
  1036. $namespace = "http://$SERVER_NAME/soap/$serviceName";
  1037. }
  1038. if(false == $endpoint) {
  1039. if ($HTTPS == '1' || $HTTPS == 'on') {
  1040. $SCHEME = 'https';
  1041. } else {
  1042. $SCHEME = 'http';
  1043. }
  1044. $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
  1045. }
  1046. if(false == $schemaTargetNamespace) {
  1047. $schemaTargetNamespace = $namespace;
  1048. }
  1049. $this->wsdl = new wsdl;
  1050. $this->wsdl->serviceName = $serviceName;
  1051. $this->wsdl->endpoint = $endpoint;
  1052. $this->wsdl->namespaces['tns'] = $namespace;
  1053. $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
  1054. $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
  1055. if ($schemaTargetNamespace != $namespace) {
  1056. $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
  1057. }
  1058. $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
  1059. if ($style == 'document') {
  1060. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
  1061. }
  1062. $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
  1063. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
  1064. $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
  1065. $this->wsdl->bindings[$serviceName.'Binding'] = array(
  1066. 'name'=>$serviceName.'Binding',
  1067. 'style'=>$style,
  1068. 'transport'=>$transport,
  1069. 'portType'=>$serviceName.'PortType');
  1070. $this->wsdl->ports[$serviceName.'Port'] = array(
  1071. 'binding'=>$serviceName.'Binding',
  1072. 'location'=>$endpoint,
  1073. 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
  1074. }
  1075. }
  1076. /**
  1077. * Backward compatibility
  1078. */
  1079. class soap_server extends nusoap_server {
  1080. }
  1081. ?>