[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/api/soap/nusoap/ -> class.soap_server.php (source)

   1  <?php
   2  
   3  
   4  
   5  
   6  /**

   7  *

   8  * nusoap_server allows the user to create a SOAP server

   9  * that is capable of receiving messages and returning responses

  10  *

  11  * @author   Dietrich Ayala <dietrich@ganx4.com>

  12  * @author   Scott Nichol <snichol@users.sourceforge.net>

  13  * @version  $Id: class.soap_server.php,v 1.58 2007/10/30 18:50:30 snichol Exp $

  14  * @access   public

  15  */
  16  class nusoap_server extends nusoap_base {
  17      /**

  18       * HTTP headers of request

  19       * @var array

  20       * @access private

  21       */
  22      var $headers = array();
  23      /**

  24       * HTTP request

  25       * @var string

  26       * @access private

  27       */
  28      var $request = '';
  29      /**

  30       * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)

  31       * @var string

  32       * @access public

  33       */
  34      var $requestHeaders = '';
  35      /**

  36       * SOAP Headers from request (parsed)

  37       * @var mixed

  38       * @access public

  39       */
  40      var $requestHeader = NULL;
  41      /**

  42       * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)

  43       * @var string

  44       * @access public

  45       */
  46      var $document = '';
  47      /**

  48       * SOAP payload for request (text)

  49       * @var string

  50       * @access public

  51       */
  52      var $requestSOAP = '';
  53      /**

  54       * requested method namespace URI

  55       * @var string

  56       * @access private

  57       */
  58      var $methodURI = '';
  59      /**

  60       * name of method requested

  61       * @var string

  62       * @access private

  63       */
  64      var $methodname = '';
  65      /**

  66       * method parameters from request

  67       * @var array

  68       * @access private

  69       */
  70      var $methodparams = array();
  71      /**

  72       * SOAP Action from request

  73       * @var string

  74       * @access private

  75       */
  76      var $SOAPAction = '';
  77      /**

  78       * character set encoding of incoming (request) messages

  79       * @var string

  80       * @access public

  81       */
  82      var $xml_encoding = '';
  83      /**

  84       * toggles whether the parser decodes element content w/ utf8_decode()

  85       * @var boolean

  86       * @access public

  87       */
  88      var $decode_utf8 = true;
  89  
  90      /**

  91       * HTTP headers of response

  92       * @var array

  93       * @access public

  94       */
  95      var $outgoing_headers = array();
  96      /**

  97       * HTTP response

  98       * @var string

  99       * @access private

 100       */
 101      var $response = '';
 102      /**

 103       * SOAP headers for response (text or array of soapval or associative array)

 104       * @var mixed

 105       * @access public

 106       */
 107      var $responseHeaders = '';
 108      /**

 109       * SOAP payload for response (text)

 110       * @var string

 111       * @access private

 112       */
 113      var $responseSOAP = '';
 114      /**

 115       * method return value to place in response

 116       * @var mixed

 117       * @access private

 118       */
 119      var $methodreturn = false;
 120      /**

 121       * whether $methodreturn is a string of literal XML

 122       * @var boolean

 123       * @access public

 124       */
 125      var $methodreturnisliteralxml = false;
 126      /**

 127       * SOAP fault for response (or false)

 128       * @var mixed

 129       * @access private

 130       */
 131      var $fault = false;
 132      /**

 133       * text indication of result (for debugging)

 134       * @var string

 135       * @access private

 136       */
 137      var $result = 'successful';
 138  
 139      /**

 140       * assoc array of operations => opData; operations are added by the register()

 141       * method or by parsing an external WSDL definition

 142       * @var array

 143       * @access private

 144       */
 145      var $operations = array();
 146      /**

 147       * wsdl instance (if one)

 148       * @var mixed

 149       * @access private

 150       */
 151      var $wsdl = false;
 152      /**

 153       * URL for WSDL (if one)

 154       * @var mixed

 155       * @access private

 156       */
 157      var $externalWSDLURL = false;
 158      /**

 159       * whether to append debug to response as XML comment

 160       * @var boolean

 161       * @access public

 162       */
 163      var $debug_flag = false;
 164  
 165  
 166      /**

 167      * constructor

 168      * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.

 169      *

 170      * @param mixed $wsdl file path or URL (string), or wsdl instance (object)

 171      * @access   public

 172      */
 173  	function nusoap_server($wsdl=false){
 174          parent::nusoap_base();
 175          // turn on debugging?

 176          global $debug;
 177          global $HTTP_SERVER_VARS;
 178  
 179          if (isset($_SERVER)) {
 180              $this->debug("_SERVER is defined:");
 181              $this->appendDebug($this->varDump($_SERVER));
 182          } elseif (isset($HTTP_SERVER_VARS)) {
 183              $this->debug("HTTP_SERVER_VARS is defined:");
 184              $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
 185          } else {
 186              $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
 187          }
 188  
 189          if (isset($debug)) {
 190              $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
 191              $this->debug_flag = $debug;
 192          } elseif (isset($_SERVER['QUERY_STRING'])) {
 193              $qs = explode('&', $_SERVER['QUERY_STRING']);
 194              foreach ($qs as $v) {
 195                  if (substr($v, 0, 6) == 'debug=') {
 196                      $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
 197                      $this->debug_flag = substr($v, 6);
 198                  }
 199              }
 200          } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
 201              $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
 202              foreach ($qs as $v) {
 203                  if (substr($v, 0, 6) == 'debug=') {
 204                      $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
 205                      $this->debug_flag = substr($v, 6);
 206                  }
 207              }
 208          }
 209  
 210          // wsdl

 211          if($wsdl){
 212              $this->debug("In nusoap_server, WSDL is specified");
 213              if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
 214                  $this->wsdl = $wsdl;
 215                  $this->externalWSDLURL = $this->wsdl->wsdl;
 216                  $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
 217              } else {
 218                  $this->debug('Create wsdl from ' . $wsdl);
 219                  $this->wsdl = new wsdl($wsdl);
 220                  $this->externalWSDLURL = $wsdl;
 221              }
 222              $this->appendDebug($this->wsdl->getDebug());
 223              $this->wsdl->clearDebug();
 224              if($err = $this->wsdl->getError()){
 225                  die('WSDL ERROR: '.$err);
 226              }
 227          }
 228      }
 229  
 230      /**

 231      * processes request and returns response

 232      *

 233      * @param    string $data usually is the value of $HTTP_RAW_POST_DATA

 234      * @access   public

 235      */
 236  	function service($data){
 237          global $HTTP_SERVER_VARS;
 238  
 239          if (isset($_SERVER['QUERY_STRING'])) {
 240              $qs = $_SERVER['QUERY_STRING'];
 241          } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
 242              $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
 243          } else {
 244              $qs = '';
 245          }
 246          $this->debug("In service, query string=$qs");
 247  
 248          if (ereg('wsdl', $qs) ){
 249              $this->debug("In service, this is a request for WSDL");
 250              if($this->externalWSDLURL){
 251                if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
 252                  header('Location: '.$this->externalWSDLURL);
 253                } else { // assume file
 254                  header("Content-Type: text/xml\r\n");
 255                  $fp = fopen($this->externalWSDLURL, 'r');
 256                  fpassthru($fp);
 257                }
 258              } elseif ($this->wsdl) {
 259                  header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
 260                  print $this->wsdl->serialize($this->debug_flag);
 261                  if ($this->debug_flag) {
 262                      $this->debug('wsdl:');
 263                      $this->appendDebug($this->varDump($this->wsdl));
 264                      print $this->getDebugAsXMLComment();
 265                  }
 266              } else {
 267                  header("Content-Type: text/html; charset=ISO-8859-1\r\n");
 268                  print "This service does not provide WSDL";
 269              }
 270          } elseif ($data == '' && $this->wsdl) {
 271              $this->debug("In service, there is no data, so return Web description");
 272              print $this->wsdl->webDescription();
 273          } else {
 274              $this->debug("In service, invoke the request");
 275              $this->parse_request($data);
 276              if (! $this->fault) {
 277                  $this->invoke_method();
 278              }
 279              if (! $this->fault) {
 280                  $this->serialize_return();
 281              }
 282              $this->send_response();
 283          }
 284      }
 285  
 286      /**

 287      * parses HTTP request headers.

 288      *

 289      * The following fields are set by this function (when successful)

 290      *

 291      * headers

 292      * request

 293      * xml_encoding

 294      * SOAPAction

 295      *

 296      * @access   private

 297      */
 298  	function parse_http_headers() {
 299          global $HTTP_SERVER_VARS;
 300  
 301          $this->request = '';
 302          $this->SOAPAction = '';
 303          if(function_exists('getallheaders')){
 304              $this->debug("In parse_http_headers, use getallheaders");
 305              $headers = getallheaders();
 306              foreach($headers as $k=>$v){
 307                  $k = strtolower($k);
 308                  $this->headers[$k] = $v;
 309                  $this->request .= "$k: $v\r\n";
 310                  $this->debug("$k: $v");
 311              }
 312              // get SOAPAction header

 313              if(isset($this->headers['soapaction'])){
 314                  $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
 315              }
 316              // get the character encoding of the incoming request

 317              if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
 318                  $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
 319                  if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
 320                      $this->xml_encoding = strtoupper($enc);
 321                  } else {
 322                      $this->xml_encoding = 'US-ASCII';
 323                  }
 324              } else {
 325                  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

 326                  $this->xml_encoding = 'ISO-8859-1';
 327              }
 328          } elseif(isset($_SERVER) && is_array($_SERVER)){
 329              $this->debug("In parse_http_headers, use _SERVER");
 330              foreach ($_SERVER as $k => $v) {
 331                  if (substr($k, 0, 5) == 'HTTP_') {
 332                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
 333                  } else {
 334                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
 335                  }
 336                  if ($k == 'soapaction') {
 337                      // get SOAPAction header

 338                      $k = 'SOAPAction';
 339                      $v = str_replace('"', '', $v);
 340                      $v = str_replace('\\', '', $v);
 341                      $this->SOAPAction = $v;
 342                  } else if ($k == 'content-type') {
 343                      // get the character encoding of the incoming request

 344                      if (strpos($v, '=')) {
 345                          $enc = substr(strstr($v, '='), 1);
 346                          $enc = str_replace('"', '', $enc);
 347                          $enc = str_replace('\\', '', $enc);
 348                          if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
 349                              $this->xml_encoding = strtoupper($enc);
 350                          } else {
 351                              $this->xml_encoding = 'US-ASCII';
 352                          }
 353                      } else {
 354                          // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

 355                          $this->xml_encoding = 'ISO-8859-1';
 356                      }
 357                  }
 358                  $this->headers[$k] = $v;
 359                  $this->request .= "$k: $v\r\n";
 360                  $this->debug("$k: $v");
 361              }
 362          } elseif (is_array($HTTP_SERVER_VARS)) {
 363              $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
 364              foreach ($HTTP_SERVER_VARS as $k => $v) {
 365                  if (substr($k, 0, 5) == 'HTTP_') {
 366                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));                                              $k = strtolower(substr($k, 5));
 367                  } else {
 368                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));                                              $k = strtolower($k);
 369                  }
 370                  if ($k == 'soapaction') {
 371                      // get SOAPAction header

 372                      $k = 'SOAPAction';
 373                      $v = str_replace('"', '', $v);
 374                      $v = str_replace('\\', '', $v);
 375                      $this->SOAPAction = $v;
 376                  } else if ($k == 'content-type') {
 377                      // get the character encoding of the incoming request

 378                      if (strpos($v, '=')) {
 379                          $enc = substr(strstr($v, '='), 1);
 380                          $enc = str_replace('"', '', $enc);
 381                          $enc = str_replace('\\', '', $enc);
 382                          if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
 383                              $this->xml_encoding = strtoupper($enc);
 384                          } else {
 385                              $this->xml_encoding = 'US-ASCII';
 386                          }
 387                      } else {
 388                          // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

 389                          $this->xml_encoding = 'ISO-8859-1';
 390                      }
 391                  }
 392                  $this->headers[$k] = $v;
 393                  $this->request .= "$k: $v\r\n";
 394                  $this->debug("$k: $v");
 395              }
 396          } else {
 397              $this->debug("In parse_http_headers, HTTP headers not accessible");
 398              $this->setError("HTTP headers not accessible");
 399          }
 400      }
 401  
 402      /**

 403      * parses a request

 404      *

 405      * The following fields are set by this function (when successful)

 406      *

 407      * headers

 408      * request

 409      * xml_encoding

 410      * SOAPAction

 411      * request

 412      * requestSOAP

 413      * methodURI

 414      * methodname

 415      * methodparams

 416      * requestHeaders

 417      * document

 418      *

 419      * This sets the fault field on error

 420      *

 421      * @param    string $data XML string

 422      * @access   private

 423      */
 424  	function parse_request($data='') {
 425          $this->debug('entering parse_request()');
 426          $this->parse_http_headers();
 427          $this->debug('got character encoding: '.$this->xml_encoding);
 428          // uncompress if necessary

 429          if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
 430              $this->debug('got content encoding: ' . $this->headers['content-encoding']);
 431              if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
 432                  // if decoding works, use it. else assume data wasn't gzencoded

 433                  if (function_exists('gzuncompress')) {
 434                      if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
 435                          $data = $degzdata;
 436                      } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
 437                          $data = $degzdata;
 438                      } else {
 439                          $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
 440                          return;
 441                      }
 442                  } else {
 443                      $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
 444                      return;
 445                  }
 446              }
 447          }
 448          $this->request .= "\r\n".$data;
 449          $data = $this->parseRequest($this->headers, $data);
 450          $this->requestSOAP = $data;
 451          $this->debug('leaving parse_request');
 452      }
 453  
 454      /**

 455      * invokes a PHP function for the requested SOAP method

 456      *

 457      * The following fields are set by this function (when successful)

 458      *

 459      * methodreturn

 460      *

 461      * Note that the PHP function that is called may also set the following

 462      * fields to affect the response sent to the client

 463      *

 464      * responseHeaders

 465      * outgoing_headers

 466      *

 467      * This sets the fault field on error

 468      *

 469      * @access   private

 470      */
 471  	function invoke_method() {
 472          $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
 473  
 474          if ($this->wsdl) {
 475              if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
 476                  $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
 477                  $this->appendDebug('opData=' . $this->varDump($this->opData));
 478              } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
 479                  // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element

 480                  $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
 481                  $this->appendDebug('opData=' . $this->varDump($this->opData));
 482                  $this->methodname = $this->opData['name'];
 483              } else {
 484                  $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
 485                  $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
 486                  return;
 487              }
 488          } else {
 489              $this->debug('in invoke_method, no WSDL to validate method');
 490          }
 491  
 492          // if a . is present in $this->methodname, we see if there is a class in scope,

 493          // which could be referred to. We will also distinguish between two deliminators,

 494          // to allow methods to be called a the class or an instance

 495          $class = '';
 496          $method = '';
 497          if (strpos($this->methodname, '..') > 0) {
 498              $delim = '..';
 499          } else if (strpos($this->methodname, '.') > 0) {
 500              $delim = '.';
 501          } else {
 502              $delim = '';
 503          }
 504  
 505          if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
 506              class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
 507              // get the class and method name

 508              $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
 509              $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
 510              $this->debug("in invoke_method, class=$class method=$method delim=$delim");
 511          }
 512  
 513          // does method exist?

 514          if ($class == '') {
 515              if (!function_exists($this->methodname)) {
 516                  $this->debug("in invoke_method, function '$this->methodname' not found!");
 517                  $this->result = 'fault: method not found';
 518                  $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
 519                  return;
 520              }
 521          } else {
 522              $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
 523              if (!in_array($method_to_compare, get_class_methods($class))) {
 524                  $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
 525                  $this->result = 'fault: method not found';
 526                  $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
 527                  return;
 528              }
 529          }
 530  
 531          // evaluate message, getting back parameters

 532          // verify that request parameters match the method's signature

 533          if(! $this->verify_method($this->methodname,$this->methodparams)){
 534              // debug

 535              $this->debug('ERROR: request not verified against method signature');
 536              $this->result = 'fault: request failed validation against method signature';
 537              // return fault

 538              $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
 539              return;
 540          }
 541  
 542          // if there are parameters to pass

 543          $this->debug('in invoke_method, params:');
 544          $this->appendDebug($this->varDump($this->methodparams));
 545          $this->debug("in invoke_method, calling '$this->methodname'");
 546          if (!function_exists('call_user_func_array')) {
 547              if ($class == '') {
 548                  $this->debug('in invoke_method, calling function using eval()');
 549                  $funcCall = "\$this->methodreturn = $this->methodname(";
 550              } else {
 551                  if ($delim == '..') {
 552                      $this->debug('in invoke_method, calling class method using eval()');
 553                      $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
 554                  } else {
 555                      $this->debug('in invoke_method, calling instance method using eval()');
 556                      // generate unique instance name

 557                      $instname = "\$inst_".time();
 558                      $funcCall = $instname." = new ".$class."(); ";
 559                      $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
 560                  }
 561              }
 562              if ($this->methodparams) {
 563                  foreach ($this->methodparams as $param) {
 564                      if (is_array($param) || is_object($param)) {
 565                          $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
 566                          return;
 567                      }
 568                      $funcCall .= "\"$param\",";
 569                  }
 570                  $funcCall = substr($funcCall, 0, -1);
 571              }
 572              $funcCall .= ');';
 573              $this->debug('in invoke_method, function call: '.$funcCall);
 574              @eval($funcCall);
 575          } else {
 576              if ($class == '') {
 577                  $this->debug('in invoke_method, calling function using call_user_func_array()');
 578                  $call_arg = "$this->methodname";    // straight assignment changes $this->methodname to lower case after call_user_func_array()

 579              } elseif ($delim == '..') {
 580                  $this->debug('in invoke_method, calling class method using call_user_func_array()');
 581                  $call_arg = array ($class, $method);
 582              } else {
 583                  $this->debug('in invoke_method, calling instance method using call_user_func_array()');
 584                  $instance = new $class ();
 585                  $call_arg = array(&$instance, $method);
 586              }
 587              if (is_array($this->methodparams)) {
 588                  $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
 589              } else {
 590                  $this->methodreturn = call_user_func_array($call_arg, array());
 591              }
 592          }
 593          $this->debug('in invoke_method, methodreturn:');
 594          $this->appendDebug($this->varDump($this->methodreturn));
 595          $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
 596      }
 597  
 598      /**

 599      * serializes the return value from a PHP function into a full SOAP Envelope

 600      *

 601      * The following fields are set by this function (when successful)

 602      *

 603      * responseSOAP

 604      *

 605      * This sets the fault field on error

 606      *

 607      * @access   private

 608      */
 609  	function serialize_return() {
 610          $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
 611          // if fault

 612          if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
 613              $this->debug('got a fault object from method');
 614              $this->fault = $this->methodreturn;
 615              return;
 616          } elseif ($this->methodreturnisliteralxml) {
 617              $return_val = $this->methodreturn;
 618          // returned value(s)

 619          } else {
 620              $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
 621              $this->debug('serializing return value');
 622              if($this->wsdl){
 623                  if (sizeof($this->opData['output']['parts']) > 1) {
 624                      $this->debug('more than one output part, so use the method return unchanged');
 625                      $opParams = $this->methodreturn;
 626                  } elseif (sizeof($this->opData['output']['parts']) == 1) {
 627                      $this->debug('exactly one output part, so wrap the method return in a simple array');
 628                      // TODO: verify that it is not already wrapped!

 629                      //foreach ($this->opData['output']['parts'] as $name => $type) {

 630                      //    $this->debug('wrap in element named ' . $name);

 631                      //}

 632                      $opParams = array($this->methodreturn);
 633                  }
 634                  $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
 635                  $this->appendDebug($this->wsdl->getDebug());
 636                  $this->wsdl->clearDebug();
 637                  if($errstr = $this->wsdl->getError()){
 638                      $this->debug('got wsdl error: '.$errstr);
 639                      $this->fault('SOAP-ENV:Server', 'unable to serialize result');
 640                      return;
 641                  }
 642              } else {
 643                  if (isset($this->methodreturn)) {
 644                      $return_val = $this->serialize_val($this->methodreturn, 'return');
 645                  } else {
 646                      $return_val = '';
 647                      $this->debug('in absence of WSDL, assume void return for backward compatibility');
 648                  }
 649              }
 650          }
 651          $this->debug('return value:');
 652          $this->appendDebug($this->varDump($return_val));
 653  
 654          $this->debug('serializing response');
 655          if ($this->wsdl) {
 656              $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
 657              if ($this->opData['style'] == 'rpc') {
 658                  $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
 659                  if ($this->opData['output']['use'] == 'literal') {
 660                      // 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

 661                      $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
 662                  } else {
 663                      $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
 664                  }
 665              } else {
 666                  $this->debug('style is not rpc for serialization: assume document');
 667                  $payload = $return_val;
 668              }
 669          } else {
 670              $this->debug('do not have WSDL for serialization: assume rpc/encoded');
 671              $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
 672          }
 673          $this->result = 'successful';
 674          if($this->wsdl){
 675              //if($this->debug_flag){

 676                  $this->appendDebug($this->wsdl->getDebug());
 677              //    }

 678              if (isset($opData['output']['encodingStyle'])) {
 679                  $encodingStyle = $opData['output']['encodingStyle'];
 680              } else {
 681                  $encodingStyle = '';
 682              }
 683              // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.

 684              $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
 685          } else {
 686              $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
 687          }
 688          $this->debug("Leaving serialize_return");
 689      }
 690  
 691      /**

 692      * sends an HTTP response

 693      *

 694      * The following fields are set by this function (when successful)

 695      *

 696      * outgoing_headers

 697      * response

 698      *

 699      * @access   private

 700      */
 701  	function send_response() {
 702          $this->debug('Enter send_response');
 703          if ($this->fault) {
 704              $payload = $this->fault->serialize();
 705              $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
 706              $this->outgoing_headers[] = "Status: 500 Internal Server Error";
 707          } else {
 708              $payload = $this->responseSOAP;
 709              // Some combinations of PHP+Web server allow the Status

 710              // to come through as a header.  Since OK is the default

 711              // just do nothing.

 712              // $this->outgoing_headers[] = "HTTP/1.0 200 OK";

 713              // $this->outgoing_headers[] = "Status: 200 OK";

 714          }
 715          // add debug data if in debug mode

 716          if(isset($this->debug_flag) && $this->debug_flag){
 717              $payload .= $this->getDebugAsXMLComment();
 718          }
 719          $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
 720          ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
 721          $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
 722          // Let the Web server decide about this

 723          //$this->outgoing_headers[] = "Connection: Close\r\n";

 724          $payload = $this->getHTTPBody($payload);
 725          $type = $this->getHTTPContentType();
 726          $charset = $this->getHTTPContentTypeCharset();
 727          $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
 728          //begin code to compress payload - by John

 729          // NOTE: there is no way to know whether the Web server will also compress

 730          // this data.

 731          if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {    
 732              if (strstr($this->headers['accept-encoding'], 'gzip')) {
 733                  if (function_exists('gzencode')) {
 734                      if (isset($this->debug_flag) && $this->debug_flag) {
 735                          $payload .= "<!-- Content being gzipped -->";
 736                      }
 737                      $this->outgoing_headers[] = "Content-Encoding: gzip";
 738                      $payload = gzencode($payload);
 739                  } else {
 740                      if (isset($this->debug_flag) && $this->debug_flag) {
 741                          $payload .= "<!-- Content will not be gzipped: no gzencode -->";
 742                      }
 743                  }
 744              } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
 745                  // Note: MSIE requires gzdeflate output (no Zlib header and checksum),

 746                  // instead of gzcompress output,

 747                  // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)

 748                  if (function_exists('gzdeflate')) {
 749                      if (isset($this->debug_flag) && $this->debug_flag) {
 750                          $payload .= "<!-- Content being deflated -->";
 751                      }
 752                      $this->outgoing_headers[] = "Content-Encoding: deflate";
 753                      $payload = gzdeflate($payload);
 754                  } else {
 755                      if (isset($this->debug_flag) && $this->debug_flag) {
 756                          $payload .= "<!-- Content will not be deflated: no gzcompress -->";
 757                      }
 758                  }
 759              }
 760          }
 761          //end code

 762          $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
 763          reset($this->outgoing_headers);
 764          foreach($this->outgoing_headers as $hdr){
 765              header($hdr, false);
 766          }
 767          print $payload;
 768          $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
 769      }
 770  
 771      /**

 772      * takes the value that was created by parsing the request

 773      * and compares to the method's signature, if available.

 774      *

 775      * @param    string    $operation    The operation to be invoked

 776      * @param    array    $request    The array of parameter values

 777      * @return    boolean    Whether the operation was found

 778      * @access   private

 779      */
 780  	function verify_method($operation,$request){
 781          if(isset($this->wsdl) && is_object($this->wsdl)){
 782              if($this->wsdl->getOperationData($operation)){
 783                  return true;
 784              }
 785          } elseif(isset($this->operations[$operation])){
 786              return true;
 787          }
 788          return false;
 789      }
 790  
 791      /**

 792      * processes SOAP message received from client

 793      *

 794      * @param    array    $headers    The HTTP headers

 795      * @param    string    $data        unprocessed request data from client

 796      * @return    mixed    value of the message, decoded into a PHP type

 797      * @access   private

 798      */
 799      function parseRequest($headers, $data) {
 800          $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
 801          if (!strstr($headers['content-type'], 'text/xml')) {
 802              $this->setError('Request not of type text/xml');
 803              return false;
 804          }
 805          if (strpos($headers['content-type'], '=')) {
 806              $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
 807              $this->debug('Got response encoding: ' . $enc);
 808              if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
 809                  $this->xml_encoding = strtoupper($enc);
 810              } else {
 811                  $this->xml_encoding = 'US-ASCII';
 812              }
 813          } else {
 814              // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

 815              $this->xml_encoding = 'ISO-8859-1';
 816          }
 817          $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
 818          // parse response, get soap parser obj

 819          $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
 820          // parser debug

 821          $this->debug("parser debug: \n".$parser->getDebug());
 822          // if fault occurred during message parsing

 823          if($err = $parser->getError()){
 824              $this->result = 'fault: error in msg parsing: '.$err;
 825              $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
 826          // else successfully parsed request into soapval object

 827          } else {
 828              // get/set methodname

 829              $this->methodURI = $parser->root_struct_namespace;
 830              $this->methodname = $parser->root_struct_name;
 831              $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
 832              $this->debug('calling parser->get_soapbody()');
 833              $this->methodparams = $parser->get_soapbody();
 834              // get SOAP headers

 835              $this->requestHeaders = $parser->getHeaders();
 836              // get SOAP Header

 837              $this->requestHeader = $parser->get_soapheader();
 838              // add document for doclit support

 839              $this->document = $parser->document;
 840          }
 841       }
 842  
 843      /**

 844      * gets the HTTP body for the current response.

 845      *

 846      * @param string $soapmsg The SOAP payload

 847      * @return string The HTTP body, which includes the SOAP payload

 848      * @access private

 849      */
 850  	function getHTTPBody($soapmsg) {
 851          return $soapmsg;
 852      }
 853      
 854      /**

 855      * gets the HTTP content type for the current response.

 856      *

 857      * Note: getHTTPBody must be called before this.

 858      *

 859      * @return string the HTTP content type for the current response.

 860      * @access private

 861      */
 862  	function getHTTPContentType() {
 863          return 'text/xml';
 864      }
 865      
 866      /**

 867      * gets the HTTP content type charset for the current response.

 868      * returns false for non-text content types.

 869      *

 870      * Note: getHTTPBody must be called before this.

 871      *

 872      * @return string the HTTP content type charset for the current response.

 873      * @access private

 874      */
 875  	function getHTTPContentTypeCharset() {
 876          return $this->soap_defencoding;
 877      }
 878  
 879      /**

 880      * add a method to the dispatch map (this has been replaced by the register method)

 881      *

 882      * @param    string $methodname

 883      * @param    string $in array of input values

 884      * @param    string $out array of output values

 885      * @access   public

 886      * @deprecated

 887      */
 888  	function add_to_map($methodname,$in,$out){
 889              $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
 890      }
 891  
 892      /**

 893      * register a service function with the server

 894      *

 895      * @param    string $name the name of the PHP function, class.method or class..method

 896      * @param    array $in assoc array of input values: key = param name, value = param type

 897      * @param    array $out assoc array of output values: key = param name, value = param type

 898      * @param    mixed $namespace the element namespace for the method or false

 899      * @param    mixed $soapaction the soapaction for the method or false

 900      * @param    mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically

 901      * @param    mixed $use optional (encoded|literal) or false

 902      * @param    string $documentation optional Description to include in WSDL

 903      * @param    string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)

 904      * @access   public

 905      */
 906  	function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
 907          global $HTTP_SERVER_VARS;
 908  
 909          if($this->externalWSDLURL){
 910              die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
 911          }
 912          if (! $name) {
 913              die('You must specify a name when you register an operation');
 914          }
 915          if (!is_array($in)) {
 916              die('You must provide an array for operation inputs');
 917          }
 918          if (!is_array($out)) {
 919              die('You must provide an array for operation outputs');
 920          }
 921          if(false == $namespace) {
 922          }
 923          if(false == $soapaction) {
 924              if (isset($_SERVER)) {
 925                  $SERVER_NAME = $_SERVER['SERVER_NAME'];
 926                  $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
 927                  $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
 928              } elseif (isset($HTTP_SERVER_VARS)) {
 929                  $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
 930                  $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
 931                  $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
 932              } else {
 933                  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
 934              }
 935              if ($HTTPS == '1' || $HTTPS == 'on') {
 936                  $SCHEME = 'https';
 937              } else {
 938                  $SCHEME = 'http';
 939              }
 940              $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
 941          }
 942          if(false == $style) {
 943              $style = "rpc";
 944          }
 945          if(false == $use) {
 946              $use = "encoded";
 947          }
 948          if ($use == 'encoded' && $encodingStyle = '') {
 949              $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
 950          }
 951  
 952          $this->operations[$name] = array(
 953          'name' => $name,
 954          'in' => $in,
 955          'out' => $out,
 956          'namespace' => $namespace,
 957          'soapaction' => $soapaction,
 958          'style' => $style);
 959          if($this->wsdl){
 960              $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
 961          }
 962          return true;
 963      }
 964  
 965      /**

 966      * Specify a fault to be returned to the client.

 967      * This also acts as a flag to the server that a fault has occured.

 968      *

 969      * @param    string $faultcode

 970      * @param    string $faultstring

 971      * @param    string $faultactor

 972      * @param    string $faultdetail

 973      * @access   public

 974      */
 975  	function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
 976          if ($faultdetail == '' && $this->debug_flag) {
 977              $faultdetail = $this->getDebug();
 978          }
 979          $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
 980          $this->fault->soap_defencoding = $this->soap_defencoding;
 981      }
 982  
 983      /**

 984      * Sets up wsdl object.

 985      * Acts as a flag to enable internal WSDL generation

 986      *

 987      * @param string $serviceName, name of the service

 988      * @param mixed $namespace optional 'tns' service namespace or false

 989      * @param mixed $endpoint optional URL of service endpoint or false

 990      * @param string $style optional (rpc|document) WSDL style (also specified by operation)

 991      * @param string $transport optional SOAP transport

 992      * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false

 993      */
 994      function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
 995      {
 996          global $HTTP_SERVER_VARS;
 997  
 998          if (isset($_SERVER)) {
 999              $SERVER_NAME = $_SERVER['SERVER_NAME'];
1000              $SERVER_PORT = $_SERVER['SERVER_PORT'];
1001              $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
1002              $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
1003          } elseif (isset($HTTP_SERVER_VARS)) {
1004              $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
1005              $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
1006              $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
1007              $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
1008          } else {
1009              $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
1010          }
1011          // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)

1012          $colon = strpos($SERVER_NAME,":");
1013          if ($colon) {
1014              $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
1015          }
1016          if ($SERVER_PORT == 80) {
1017              $SERVER_PORT = '';
1018          } else {
1019              $SERVER_PORT = ':' . $SERVER_PORT;
1020          }
1021          if(false == $namespace) {
1022              $namespace = "http://$SERVER_NAME/soap/$serviceName";
1023          }
1024          
1025          if(false == $endpoint) {
1026              if ($HTTPS == '1' || $HTTPS == 'on') {
1027                  $SCHEME = 'https';
1028              } else {
1029                  $SCHEME = 'http';
1030              }
1031              $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
1032          }
1033          
1034          if(false == $schemaTargetNamespace) {
1035              $schemaTargetNamespace = $namespace;
1036          }
1037          
1038          $this->wsdl = new wsdl;
1039          $this->wsdl->serviceName = $serviceName;
1040          $this->wsdl->endpoint = $endpoint;
1041          $this->wsdl->namespaces['tns'] = $namespace;
1042          $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
1043          $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
1044          if ($schemaTargetNamespace != $namespace) {
1045              $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
1046          }
1047          $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
1048          if ($style == 'document') {
1049              $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
1050          }
1051          $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
1052          $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
1053          $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
1054          $this->wsdl->bindings[$serviceName.'Binding'] = array(
1055              'name'=>$serviceName.'Binding',
1056              'style'=>$style,
1057              'transport'=>$transport,
1058              'portType'=>$serviceName.'PortType');
1059          $this->wsdl->ports[$serviceName.'Port'] = array(
1060              'binding'=>$serviceName.'Binding',
1061              'location'=>$endpoint,
1062              'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
1063      }
1064  }
1065  
1066  /**

1067   * Backward compatibility

1068   */
1069  class soap_server extends nusoap_server {
1070  }
1071  
1072  
1073  ?>


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics