class.soap_server.php 40 KB

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