[ Index ]
 

Code source de CMS made simple 1.0.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/modules/nuSOAP/classes/ -> nusoap.php (source)

   1  <?php
   2  
   3  /*

   4  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

   5  

   6  NuSOAP - Web Services Toolkit for PHP

   7  

   8  Copyright (c) 2002 NuSphere Corporation

   9  

  10  This library is free software; you can redistribute it and/or

  11  modify it under the terms of the GNU Lesser General Public

  12  License as published by the Free Software Foundation; either

  13  version 2.1 of the License, or (at your option) any later version.

  14  

  15  This library is distributed in the hope that it will be useful,

  16  but WITHOUT ANY WARRANTY; without even the implied warranty of

  17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

  18  Lesser General Public License for more details.

  19  

  20  You should have received a copy of the GNU Lesser General Public

  21  License along with this library; if not, write to the Free Software

  22  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  23  

  24  If you have any questions or comments, please email:

  25  

  26  Dietrich Ayala

  27  dietrich@ganx4.com

  28  http://dietrich.ganx4.com/nusoap

  29  

  30  NuSphere Corporation

  31  http://www.nusphere.com

  32  

  33  */
  34  
  35  
  36  /* load classes

  37  

  38  // necessary classes

  39  require_once('class.nu_soapclient.php');

  40  

  41  require_once('class.soap_val.php');

  42  require_once('class.soap_parser.php');

  43  require_once('class.soap_fault.php');

  44  

  45  // transport classes

  46  require_once('class.soap_transport_http.php');

  47  

  48  // optional add-on classes

  49  require_once('class.xmlschema.php');

  50  require_once('class.wsdl.php');

  51  

  52  // server class

  53  require_once('class.soap_server.php');

  54  

  55  */
  56  
  57  // class variable emulation

  58  // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html

  59  
  60  $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
  61  
  62  /**

  63  *

  64  * nusoap_base

  65  *

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

  67  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

  68  * @access   public

  69  */
  70  class nusoap_base {
  71      /**

  72       * Identification for HTTP headers.

  73       *

  74       * @var string

  75       * @access private

  76       */
  77      var $title = 'NuSOAP';
  78      /**

  79       * Version for HTTP headers.

  80       *

  81       * @var string

  82       * @access private

  83       */
  84      var $version = '0.7.2';
  85      /**

  86       * CVS revision for HTTP headers.

  87       *

  88       * @var string

  89       * @access private

  90       */
  91      var $revision = '$Revision: 1.94 $';
  92      /**

  93       * Current error string (manipulated by getError/setError)

  94       *

  95       * @var string

  96       * @access private

  97       */
  98      var $error_str = '';
  99      /**

 100       * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)

 101       *

 102       * @var string

 103       * @access private

 104       */
 105      var $debug_str = '';
 106      /**

 107       * toggles automatic encoding of special characters as entities

 108       * (should always be true, I think)

 109       *

 110       * @var boolean

 111       * @access private

 112       */
 113      var $charencoding = true;
 114      /**

 115       * the debug level for this instance

 116       *

 117       * @var    integer

 118       * @access private

 119       */
 120      var $debugLevel;
 121  
 122      /**

 123      * set schema version

 124      *

 125      * @var      string

 126      * @access   public

 127      */
 128      var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
 129      
 130      /**

 131      * charset encoding for outgoing messages

 132      *

 133      * @var      string

 134      * @access   public

 135      */
 136      //var $soap_defencoding = 'ISO-8859-1';

 137      var $soap_defencoding = 'UTF-8';
 138  
 139      /**

 140      * namespaces in an array of prefix => uri

 141      *

 142      * this is "seeded" by a set of constants, but it may be altered by code

 143      *

 144      * @var      array

 145      * @access   public

 146      */
 147      var $namespaces = array(
 148          'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
 149          'xsd' => 'http://www.w3.org/2001/XMLSchema',
 150          'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
 151          'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
 152          );
 153  
 154      /**

 155      * namespaces used in the current context, e.g. during serialization

 156      *

 157      * @var      array

 158      * @access   private

 159      */
 160      var $usedNamespaces = array();
 161  
 162      /**

 163      * XML Schema types in an array of uri => (array of xml type => php type)

 164      * is this legacy yet?

 165      * no, this is used by the xmlschema class to verify type => namespace mappings.

 166      * @var      array

 167      * @access   public

 168      */
 169      var $typemap = array(
 170      'http://www.w3.org/2001/XMLSchema' => array(
 171          'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
 172          'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
 173          'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
 174          // abstract "any" types

 175          'anyType'=>'string','anySimpleType'=>'string',
 176          // derived datatypes

 177          'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
 178          'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
 179          'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
 180          'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
 181      'http://www.w3.org/2000/10/XMLSchema' => array(
 182          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 183          'float'=>'double','dateTime'=>'string',
 184          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 185      'http://www.w3.org/1999/XMLSchema' => array(
 186          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 187          'float'=>'double','dateTime'=>'string',
 188          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 189      'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
 190      'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
 191      'http://xml.apache.org/xml-soap' => array('Map')
 192      );
 193  
 194      /**

 195      * XML entities to convert

 196      *

 197      * @var      array

 198      * @access   public

 199      * @deprecated

 200      * @see    expandEntities

 201      */
 202      var $xmlEntities = array('quot' => '"','amp' => '&',
 203          'lt' => '<','gt' => '>','apos' => "'");
 204  
 205      /**

 206      * constructor

 207      *

 208      * @access    public

 209      */
 210  	function nusoap_base() {
 211          $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
 212      }
 213  
 214      /**

 215      * gets the global debug level, which applies to future instances

 216      *

 217      * @return    integer    Debug level 0-9, where 0 turns off

 218      * @access    public

 219      */
 220  	function getGlobalDebugLevel() {
 221          return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
 222      }
 223  
 224      /**

 225      * sets the global debug level, which applies to future instances

 226      *

 227      * @param    int    $level    Debug level 0-9, where 0 turns off

 228      * @access    public

 229      */
 230  	function setGlobalDebugLevel($level) {
 231          $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
 232      }
 233  
 234      /**

 235      * gets the debug level for this instance

 236      *

 237      * @return    int    Debug level 0-9, where 0 turns off

 238      * @access    public

 239      */
 240  	function getDebugLevel() {
 241          return $this->debugLevel;
 242      }
 243  
 244      /**

 245      * sets the debug level for this instance

 246      *

 247      * @param    int    $level    Debug level 0-9, where 0 turns off

 248      * @access    public

 249      */
 250  	function setDebugLevel($level) {
 251          $this->debugLevel = $level;
 252      }
 253  
 254      /**

 255      * adds debug data to the instance debug string with formatting

 256      *

 257      * @param    string $string debug data

 258      * @access   private

 259      */
 260  	function debug($string){
 261          if ($this->debugLevel > 0) {
 262              $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
 263          }
 264      }
 265  
 266      /**

 267      * adds debug data to the instance debug string without formatting

 268      *

 269      * @param    string $string debug data

 270      * @access   public

 271      */
 272  	function appendDebug($string){
 273          if ($this->debugLevel > 0) {
 274              // it would be nice to use a memory stream here to use

 275              // memory more efficiently

 276              $this->debug_str .= $string;
 277          }
 278      }
 279  
 280      /**

 281      * clears the current debug data for this instance

 282      *

 283      * @access   public

 284      */
 285  	function clearDebug() {
 286          // it would be nice to use a memory stream here to use

 287          // memory more efficiently

 288          $this->debug_str = '';
 289      }
 290  
 291      /**

 292      * gets the current debug data for this instance

 293      *

 294      * @return   debug data

 295      * @access   public

 296      */
 297      function &getDebug() {
 298          // it would be nice to use a memory stream here to use

 299          // memory more efficiently

 300          return $this->debug_str;
 301      }
 302  
 303      /**

 304      * gets the current debug data for this instance as an XML comment

 305      * this may change the contents of the debug data

 306      *

 307      * @return   debug data as an XML comment

 308      * @access   public

 309      */
 310      function &getDebugAsXMLComment() {
 311          // it would be nice to use a memory stream here to use

 312          // memory more efficiently

 313          while (strpos($this->debug_str, '--')) {
 314              $this->debug_str = str_replace('--', '- -', $this->debug_str);
 315          }
 316          return "<!--\n" . $this->debug_str . "\n-->";
 317      }
 318  
 319      /**

 320      * expands entities, e.g. changes '<' to '&lt;'.

 321      *

 322      * @param    string    $val    The string in which to expand entities.

 323      * @access    private

 324      */
 325  	function expandEntities($val) {
 326          if ($this->charencoding) {
 327              $val = str_replace('&', '&amp;', $val);
 328              $val = str_replace("'", '&apos;', $val);
 329              $val = str_replace('"', '&quot;', $val);
 330              $val = str_replace('<', '&lt;', $val);
 331              $val = str_replace('>', '&gt;', $val);
 332          }
 333          return $val;
 334      }
 335  
 336      /**

 337      * returns error string if present

 338      *

 339      * @return   mixed error string or false

 340      * @access   public

 341      */
 342  	function getError(){
 343          if($this->error_str != ''){
 344              return $this->error_str;
 345          }
 346          return false;
 347      }
 348  
 349      /**

 350      * sets error string

 351      *

 352      * @return   boolean $string error string

 353      * @access   private

 354      */
 355  	function setError($str){
 356          $this->error_str = $str;
 357      }
 358  
 359      /**

 360      * detect if array is a simple array or a struct (associative array)

 361      *

 362      * @param    mixed    $val    The PHP array

 363      * @return    string    (arraySimple|arrayStruct)

 364      * @access    private

 365      */
 366  	function isArraySimpleOrStruct($val) {
 367          $keyList = array_keys($val);
 368          foreach ($keyList as $keyListValue) {
 369              if (!is_int($keyListValue)) {
 370                  return 'arrayStruct';
 371              }
 372          }
 373          return 'arraySimple';
 374      }
 375  
 376      /**

 377      * serializes PHP values in accordance w/ section 5. Type information is

 378      * not serialized if $use == 'literal'.

 379      *

 380      * @param    mixed    $val    The value to serialize

 381      * @param    string    $name    The name (local part) of the XML element

 382      * @param    string    $type    The XML schema type (local part) for the element

 383      * @param    string    $name_ns    The namespace for the name of the XML element

 384      * @param    string    $type_ns    The namespace for the type of the element

 385      * @param    array    $attributes    The attributes to serialize as name=>value pairs

 386      * @param    string    $use    The WSDL "use" (encoded|literal)

 387      * @return    string    The serialized element, possibly with child elements

 388      * @access    public

 389      */
 390  	function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){
 391          $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use");
 392          $this->appendDebug('value=' . $this->varDump($val));
 393          $this->appendDebug('attributes=' . $this->varDump($attributes));
 394          
 395          if(is_object($val) && get_class($val) == 'soapval'){
 396              return $val->serialize($use);
 397          }
 398          // force valid name if necessary

 399          if (is_numeric($name)) {
 400              $name = '__numeric_' . $name;
 401          } elseif (! $name) {
 402              $name = 'noname';
 403          }
 404          // if name has ns, add ns prefix to name

 405          $xmlns = '';
 406          if($name_ns){
 407              $prefix = 'nu'.rand(1000,9999);
 408              $name = $prefix.':'.$name;
 409              $xmlns .= " xmlns:$prefix=\"$name_ns\"";
 410          }
 411          // if type is prefixed, create type prefix

 412          if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
 413              // need to fix this. shouldn't default to xsd if no ns specified

 414              // w/o checking against typemap

 415              $type_prefix = 'xsd';
 416          } elseif($type_ns){
 417              $type_prefix = 'ns'.rand(1000,9999);
 418              $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
 419          }
 420          // serialize attributes if present

 421          $atts = '';
 422          if($attributes){
 423              foreach($attributes as $k => $v){
 424                  $atts .= " $k=\"".$this->expandEntities($v).'"';
 425              }
 426          }
 427          // serialize null value

 428          if (is_null($val)) {
 429              if ($use == 'literal') {
 430                  // TODO: depends on minOccurs

 431                  return "<$name$xmlns $atts/>";
 432              } else {
 433                  if (isset($type) && isset($type_prefix)) {
 434                      $type_str = " xsi:type=\"$type_prefix:$type\"";
 435                  } else {
 436                      $type_str = '';
 437                  }
 438                  return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
 439              }
 440          }
 441          // serialize if an xsd built-in primitive type

 442          if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
 443              if (is_bool($val)) {
 444                  if ($type == 'boolean') {
 445                      $val = $val ? 'true' : 'false';
 446                  } elseif (! $val) {
 447                      $val = 0;
 448                  }
 449              } else if (is_string($val)) {
 450                  $val = $this->expandEntities($val);
 451              }
 452              if ($use == 'literal') {
 453                  return "<$name$xmlns $atts>$val</$name>";
 454              } else {
 455                  return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</$name>";
 456              }
 457          }
 458          // detect type and serialize

 459          $xml = '';
 460          switch(true) {
 461              case (is_bool($val) || $type == 'boolean'):
 462                  if ($type == 'boolean') {
 463                      $val = $val ? 'true' : 'false';
 464                  } elseif (! $val) {
 465                      $val = 0;
 466                  }
 467                  if ($use == 'literal') {
 468                      $xml .= "<$name$xmlns $atts>$val</$name>";
 469                  } else {
 470                      $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
 471                  }
 472                  break;
 473              case (is_int($val) || is_long($val) || $type == 'int'):
 474                  if ($use == 'literal') {
 475                      $xml .= "<$name$xmlns $atts>$val</$name>";
 476                  } else {
 477                      $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
 478                  }
 479                  break;
 480              case (is_float($val)|| is_double($val) || $type == 'float'):
 481                  if ($use == 'literal') {
 482                      $xml .= "<$name$xmlns $atts>$val</$name>";
 483                  } else {
 484                      $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
 485                  }
 486                  break;
 487              case (is_string($val) || $type == 'string'):
 488                  $val = $this->expandEntities($val);
 489                  if ($use == 'literal') {
 490                      $xml .= "<$name$xmlns $atts>$val</$name>";
 491                  } else {
 492                      $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
 493                  }
 494                  break;
 495              case is_object($val):
 496                  if (! $name) {
 497                      $name = get_class($val);
 498                      $this->debug("In serialize_val, used class name $name as element name");
 499                  } else {
 500                      $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
 501                  }
 502                  foreach(get_object_vars($val) as $k => $v){
 503                      $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
 504                  }
 505                  $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
 506                  break;
 507              break;
 508              case (is_array($val) || $type):
 509                  // detect if struct or array

 510                  $valueType = $this->isArraySimpleOrStruct($val);
 511                  if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
 512                      $i = 0;
 513                      if(is_array($val) && count($val)> 0){
 514                          foreach($val as $v){
 515                              if(is_object($v) && get_class($v) ==  'soapval'){
 516                                  $tt_ns = $v->type_ns;
 517                                  $tt = $v->type;
 518                              } elseif (is_array($v)) {
 519                                  $tt = $this->isArraySimpleOrStruct($v);
 520                              } else {
 521                                  $tt = gettype($v);
 522                              }
 523                              $array_types[$tt] = 1;
 524                              // TODO: for literal, the name should be $name

 525                              $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
 526                              ++$i;
 527                          }
 528                          if(count($array_types) > 1){
 529                              $array_typename = 'xsd:anyType';
 530                          } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
 531                              if ($tt == 'integer') {
 532                                  $tt = 'int';
 533                              }
 534                              $array_typename = 'xsd:'.$tt;
 535                          } elseif(isset($tt) && $tt == 'arraySimple'){
 536                              $array_typename = 'SOAP-ENC:Array';
 537                          } elseif(isset($tt) && $tt == 'arrayStruct'){
 538                              $array_typename = 'unnamed_struct_use_soapval';
 539                          } else {
 540                              // if type is prefixed, create type prefix

 541                              if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
 542                                   $array_typename = 'xsd:' . $tt;
 543                              } elseif ($tt_ns) {
 544                                  $tt_prefix = 'ns' . rand(1000, 9999);
 545                                  $array_typename = "$tt_prefix:$tt";
 546                                  $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
 547                              } else {
 548                                  $array_typename = $tt;
 549                              }
 550                          }
 551                          $array_type = $i;
 552                          if ($use == 'literal') {
 553                              $type_str = '';
 554                          } else if (isset($type) && isset($type_prefix)) {
 555                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 556                          } else {
 557                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
 558                          }
 559                      // empty array

 560                      } else {
 561                          if ($use == 'literal') {
 562                              $type_str = '';
 563                          } else if (isset($type) && isset($type_prefix)) {
 564                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 565                          } else {
 566                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
 567                          }
 568                      }
 569                      // TODO: for array in literal, there is no wrapper here

 570                      $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
 571                  } else {
 572                      // got a struct

 573                      if(isset($type) && isset($type_prefix)){
 574                          $type_str = " xsi:type=\"$type_prefix:$type\"";
 575                      } else {
 576                          $type_str = '';
 577                      }
 578                      if ($use == 'literal') {
 579                          $xml .= "<$name$xmlns $atts>";
 580                      } else {
 581                          $xml .= "<$name$xmlns$type_str$atts>";
 582                      }
 583                      foreach($val as $k => $v){
 584                          // Apache Map

 585                          if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
 586                              $xml .= '<item>';
 587                              $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
 588                              $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
 589                              $xml .= '</item>';
 590                          } else {
 591                              $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
 592                          }
 593                      }
 594                      $xml .= "</$name>";
 595                  }
 596                  break;
 597              default:
 598                  $xml .= 'not detected, got '.gettype($val).' for '.$val;
 599                  break;
 600          }
 601          return $xml;
 602      }
 603  
 604      /**

 605      * serializes a message

 606      *

 607      * @param string $body the XML of the SOAP body

 608      * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers

 609      * @param array $namespaces optional the namespaces used in generating the body and headers

 610      * @param string $style optional (rpc|document)

 611      * @param string $use optional (encoded|literal)

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

 613      * @return string the message

 614      * @access public

 615      */
 616      function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
 617      // TODO: add an option to automatically run utf8_encode on $body and $headers

 618      // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows

 619      // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1

 620  
 621      $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
 622      $this->debug("headers:");
 623      $this->appendDebug($this->varDump($headers));
 624      $this->debug("namespaces:");
 625      $this->appendDebug($this->varDump($namespaces));
 626  
 627      // serialize namespaces

 628      $ns_string = '';
 629      foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
 630          $ns_string .= " xmlns:$k=\"$v\"";
 631      }
 632      if($encodingStyle) {
 633          $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
 634      }
 635  
 636      // serialize headers

 637      if($headers){
 638          if (is_array($headers)) {
 639              $xml = '';
 640              foreach ($headers as $header) {
 641                  $xml .= $this->serialize_val($header, false, false, false, false, false, $use);
 642              }
 643              $headers = $xml;
 644              $this->debug("In serializeEnvelope, serialzied array of headers to $headers");
 645          }
 646          $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
 647      }
 648      // serialize envelope

 649      return
 650      '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
 651      '<SOAP-ENV:Envelope'.$ns_string.">".
 652      $headers.
 653      "<SOAP-ENV:Body>".
 654          $body.
 655      "</SOAP-ENV:Body>".
 656      "</SOAP-ENV:Envelope>";
 657      }
 658  
 659      /**

 660       * formats a string to be inserted into an HTML stream

 661       *

 662       * @param string $str The string to format

 663       * @return string The formatted string

 664       * @access public

 665       * @deprecated

 666       */
 667      function formatDump($str){
 668          $str = htmlspecialchars($str);
 669          return nl2br($str);
 670      }
 671  
 672      /**

 673      * contracts (changes namespace to prefix) a qualified name

 674      *

 675      * @param    string $qname qname

 676      * @return    string contracted qname

 677      * @access   private

 678      */
 679  	function contractQname($qname){
 680          // get element namespace

 681          //$this->xdebug("Contract $qname");

 682          if (strrpos($qname, ':')) {
 683              // get unqualified name

 684              $name = substr($qname, strrpos($qname, ':') + 1);
 685              // get ns

 686              $ns = substr($qname, 0, strrpos($qname, ':'));
 687              $p = $this->getPrefixFromNamespace($ns);
 688              if ($p) {
 689                  return $p . ':' . $name;
 690              }
 691              return $qname;
 692          } else {
 693              return $qname;
 694          }
 695      }
 696  
 697      /**

 698      * expands (changes prefix to namespace) a qualified name

 699      *

 700      * @param    string $string qname

 701      * @return    string expanded qname

 702      * @access   private

 703      */
 704  	function expandQname($qname){
 705          // get element prefix

 706          if(strpos($qname,':') && !ereg('^http://',$qname)){
 707              // get unqualified name

 708              $name = substr(strstr($qname,':'),1);
 709              // get ns prefix

 710              $prefix = substr($qname,0,strpos($qname,':'));
 711              if(isset($this->namespaces[$prefix])){
 712                  return $this->namespaces[$prefix].':'.$name;
 713              } else {
 714                  return $qname;
 715              }
 716          } else {
 717              return $qname;
 718          }
 719      }
 720  
 721      /**

 722      * returns the local part of a prefixed string

 723      * returns the original string, if not prefixed

 724      *

 725      * @param string $str The prefixed string

 726      * @return string The local part

 727      * @access public

 728      */
 729  	function getLocalPart($str){
 730          if($sstr = strrchr($str,':')){
 731              // get unqualified name

 732              return substr( $sstr, 1 );
 733          } else {
 734              return $str;
 735          }
 736      }
 737  
 738      /**

 739      * returns the prefix part of a prefixed string

 740      * returns false, if not prefixed

 741      *

 742      * @param string $str The prefixed string

 743      * @return mixed The prefix or false if there is no prefix

 744      * @access public

 745      */
 746  	function getPrefix($str){
 747          if($pos = strrpos($str,':')){
 748              // get prefix

 749              return substr($str,0,$pos);
 750          }
 751          return false;
 752      }
 753  
 754      /**

 755      * pass it a prefix, it returns a namespace

 756      *

 757      * @param string $prefix The prefix

 758      * @return mixed The namespace, false if no namespace has the specified prefix

 759      * @access public

 760      */
 761  	function getNamespaceFromPrefix($prefix){
 762          if (isset($this->namespaces[$prefix])) {
 763              return $this->namespaces[$prefix];
 764          }
 765          //$this->setError("No namespace registered for prefix '$prefix'");

 766          return false;
 767      }
 768  
 769      /**

 770      * returns the prefix for a given namespace (or prefix)

 771      * or false if no prefixes registered for the given namespace

 772      *

 773      * @param string $ns The namespace

 774      * @return mixed The prefix, false if the namespace has no prefixes

 775      * @access public

 776      */
 777  	function getPrefixFromNamespace($ns) {
 778          foreach ($this->namespaces as $p => $n) {
 779              if ($ns == $n || $ns == $p) {
 780                  $this->usedNamespaces[$p] = $n;
 781                  return $p;
 782              }
 783          }
 784          return false;
 785      }
 786  
 787      /**

 788      * returns the time in ODBC canonical form with microseconds

 789      *

 790      * @return string The time in ODBC canonical form with microseconds

 791      * @access public

 792      */
 793  	function getmicrotime() {
 794          if (function_exists('gettimeofday')) {
 795              $tod = gettimeofday();
 796              $sec = $tod['sec'];
 797              $usec = $tod['usec'];
 798          } else {
 799              $sec = time();
 800              $usec = 0;
 801          }
 802          return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
 803      }
 804  
 805      /**

 806       * Returns a string with the output of var_dump

 807       *

 808       * @param mixed $data The variable to var_dump

 809       * @return string The output of var_dump

 810       * @access public

 811       */
 812      function varDump($data) {
 813          ob_start();
 814          var_dump($data);
 815          $ret_val = ob_get_contents();
 816          ob_end_clean();
 817          return $ret_val;
 818      }
 819  }
 820  
 821  // XML Schema Datatype Helper Functions

 822  
 823  //xsd:dateTime helpers

 824  
 825  /**

 826  * convert unix timestamp to ISO 8601 compliant date string

 827  *

 828  * @param    string $timestamp Unix time stamp

 829  * @access   public

 830  */
 831  function timestamp_to_iso8601($timestamp,$utc=true){
 832      $datestr = date('Y-m-d\TH:i:sO',$timestamp);
 833      if($utc){
 834          $eregStr =
 835          '([0-9]{4})-'.    // centuries & years CCYY-
 836          '([0-9]{2})-'.    // months MM-
 837          '([0-9]{2})'.    // days DD
 838          'T'.            // separator T
 839          '([0-9]{2}):'.    // hours hh:
 840          '([0-9]{2}):'.    // minutes mm:
 841          '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
 842          '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's

 843  
 844          if(ereg($eregStr,$datestr,$regs)){
 845              return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
 846          }
 847          return false;
 848      } else {
 849          return $datestr;
 850      }
 851  }
 852  
 853  /**

 854  * convert ISO 8601 compliant date string to unix timestamp

 855  *

 856  * @param    string $datestr ISO 8601 compliant date string

 857  * @access   public

 858  */
 859  function iso8601_to_timestamp($datestr){
 860      $eregStr =
 861      '([0-9]{4})-'.    // centuries & years CCYY-
 862      '([0-9]{2})-'.    // months MM-
 863      '([0-9]{2})'.    // days DD
 864      'T'.            // separator T
 865      '([0-9]{2}):'.    // hours hh:
 866      '([0-9]{2}):'.    // minutes mm:
 867      '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
 868      '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's

 869      if(ereg($eregStr,$datestr,$regs)){
 870          // not utc

 871          if($regs[8] != 'Z'){
 872              $op = substr($regs[8],0,1);
 873              $h = substr($regs[8],1,2);
 874              $m = substr($regs[8],strlen($regs[8])-2,2);
 875              if($op == '-'){
 876                  $regs[4] = $regs[4] + $h;
 877                  $regs[5] = $regs[5] + $m;
 878              } elseif($op == '+'){
 879                  $regs[4] = $regs[4] - $h;
 880                  $regs[5] = $regs[5] - $m;
 881              }
 882          }
 883          return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
 884      } else {
 885          return false;
 886      }
 887  }
 888  
 889  /**

 890  * sleeps some number of microseconds

 891  *

 892  * @param    string $usec the number of microseconds to sleep

 893  * @access   public

 894  * @deprecated

 895  */
 896  function usleepWindows($usec)
 897  {
 898      $start = gettimeofday();
 899      
 900      do
 901      {
 902          $stop = gettimeofday();
 903          $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
 904          + $stop['usec'] - $start['usec'];
 905      }
 906      while ($timePassed < $usec);
 907  }
 908  
 909  ?><?php
 910  
 911  
 912  
 913  /**

 914  * Contains information for a SOAP fault.

 915  * Mainly used for returning faults from deployed functions

 916  * in a server instance.

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

 918  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

 919  * @access public

 920  */
 921  class soap_fault extends nusoap_base {
 922      /**

 923       * The fault code (client|server)

 924       * @var string

 925       * @access private

 926       */
 927      var $faultcode;
 928      /**

 929       * The fault actor

 930       * @var string

 931       * @access private

 932       */
 933      var $faultactor;
 934      /**

 935       * The fault string, a description of the fault

 936       * @var string

 937       * @access private

 938       */
 939      var $faultstring;
 940      /**

 941       * The fault detail, typically a string or array of string

 942       * @var mixed

 943       * @access private

 944       */
 945      var $faultdetail;
 946  
 947      /**

 948      * constructor

 949      *

 950      * @param string $faultcode (client | server)

 951      * @param string $faultactor only used when msg routed between multiple actors

 952      * @param string $faultstring human readable error message

 953      * @param mixed $faultdetail detail, typically a string or array of string

 954      */
 955  	function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
 956          parent::nusoap_base();
 957          $this->faultcode = $faultcode;
 958          $this->faultactor = $faultactor;
 959          $this->faultstring = $faultstring;
 960          $this->faultdetail = $faultdetail;
 961      }
 962  
 963      /**

 964      * serialize a fault

 965      *

 966      * @return    string    The serialization of the fault instance.

 967      * @access   public

 968      */
 969  	function serialize(){
 970          $ns_string = '';
 971          foreach($this->namespaces as $k => $v){
 972              $ns_string .= "\n  xmlns:$k=\"$v\"";
 973          }
 974          $return_msg =
 975              '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
 976              '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
 977                  '<SOAP-ENV:Body>'.
 978                  '<SOAP-ENV:Fault>'.
 979                      $this->serialize_val($this->faultcode, 'faultcode').
 980                      $this->serialize_val($this->faultactor, 'faultactor').
 981                      $this->serialize_val($this->faultstring, 'faultstring').
 982                      $this->serialize_val($this->faultdetail, 'detail').
 983                  '</SOAP-ENV:Fault>'.
 984                  '</SOAP-ENV:Body>'.
 985              '</SOAP-ENV:Envelope>';
 986          return $return_msg;
 987      }
 988  }
 989  
 990  
 991  
 992  ?><?php
 993  
 994  
 995  
 996  /**

 997  * parses an XML Schema, allows access to it's data, other utility methods

 998  * no validation... yet.

 999  * very experimental and limited. As is discussed on XML-DEV, I'm one of the people

1000  * that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty

1001  * tutorials I refer to :)

1002  *

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

1004  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

1005  * @access   public

1006  */
1007  class XMLSchema extends nusoap_base  {
1008      
1009      // files

1010      var $schema = '';
1011      var $xml = '';
1012      // namespaces

1013      var $enclosingNamespaces;
1014      // schema info

1015      var $schemaInfo = array();
1016      var $schemaTargetNamespace = '';
1017      // types, elements, attributes defined by the schema

1018      var $attributes = array();
1019      var $complexTypes = array();
1020      var $complexTypeStack = array();
1021      var $currentComplexType = null;
1022      var $elements = array();
1023      var $elementStack = array();
1024      var $currentElement = null;
1025      var $simpleTypes = array();
1026      var $simpleTypeStack = array();
1027      var $currentSimpleType = null;
1028      // imports

1029      var $imports = array();
1030      // parser vars

1031      var $parser;
1032      var $position = 0;
1033      var $depth = 0;
1034      var $depth_array = array();
1035      var $message = array();
1036      var $defaultNamespace = array();
1037      
1038      /**

1039      * constructor

1040      *

1041      * @param    string $schema schema document URI

1042      * @param    string $xml xml document URI

1043      * @param    string $namespaces namespaces defined in enclosing XML

1044      * @access   public

1045      */
1046  	function XMLSchema($schema='',$xml='',$namespaces=array()){
1047          parent::nusoap_base();
1048          $this->debug('xmlschema class instantiated, inside constructor');
1049          // files

1050          $this->schema = $schema;
1051          $this->xml = $xml;
1052  
1053          // namespaces

1054          $this->enclosingNamespaces = $namespaces;
1055          $this->namespaces = array_merge($this->namespaces, $namespaces);
1056  
1057          // parse schema file

1058          if($schema != ''){
1059              $this->debug('initial schema file: '.$schema);
1060              $this->parseFile($schema, 'schema');
1061          }
1062  
1063          // parse xml file

1064          if($xml != ''){
1065              $this->debug('initial xml file: '.$xml);
1066              $this->parseFile($xml, 'xml');
1067          }
1068  
1069      }
1070  
1071      /**

1072      * parse an XML file

1073      *

1074      * @param string $xml, path/URL to XML file

1075      * @param string $type, (schema | xml)

1076      * @return boolean

1077      * @access public

1078      */
1079  	function parseFile($xml,$type){
1080          // parse xml file

1081          if($xml != ""){
1082              $xmlStr = @join("",@file($xml));
1083              if($xmlStr == ""){
1084                  $msg = 'Error reading XML from '.$xml;
1085                  $this->setError($msg);
1086                  $this->debug($msg);
1087              return false;
1088              } else {
1089                  $this->debug("parsing $xml");
1090                  $this->parseString($xmlStr,$type);
1091                  $this->debug("done parsing $xml");
1092              return true;
1093              }
1094          }
1095          return false;
1096      }
1097  
1098      /**

1099      * parse an XML string

1100      *

1101      * @param    string $xml path or URL

1102      * @param string $type, (schema|xml)

1103      * @access   private

1104      */
1105  	function parseString($xml,$type){
1106          // parse xml string

1107          if($xml != ""){
1108  
1109              // Create an XML parser.

1110              $this->parser = xml_parser_create();
1111              // Set the options for parsing the XML data.

1112              xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1113  
1114              // Set the object for the parser.

1115              xml_set_object($this->parser, $this);
1116  
1117              // Set the element handlers for the parser.

1118              if($type == "schema"){
1119                  xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1120                  xml_set_character_data_handler($this->parser,'schemaCharacterData');
1121              } elseif($type == "xml"){
1122                  xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1123                  xml_set_character_data_handler($this->parser,'xmlCharacterData');
1124              }
1125  
1126              // Parse the XML file.

1127              if(!xml_parse($this->parser,$xml,true)){
1128              // Display an error message.

1129                  $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1130                  xml_get_current_line_number($this->parser),
1131                  xml_error_string(xml_get_error_code($this->parser))
1132                  );
1133                  $this->debug($errstr);
1134                  $this->debug("XML payload:\n" . $xml);
1135                  $this->setError($errstr);
1136              }
1137              
1138              xml_parser_free($this->parser);
1139          } else{
1140              $this->debug('no xml passed to parseString()!!');
1141              $this->setError('no xml passed to parseString()!!');
1142          }
1143      }
1144  
1145      /**

1146      * start-element handler

1147      *

1148      * @param    string $parser XML parser object

1149      * @param    string $name element name

1150      * @param    string $attrs associative array of attributes

1151      * @access   private

1152      */
1153  	function schemaStartElement($parser, $name, $attrs) {
1154          
1155          // position in the total number of elements, starting from 0

1156          $pos = $this->position++;
1157          $depth = $this->depth++;
1158          // set self as current value for this depth

1159          $this->depth_array[$depth] = $pos;
1160          $this->message[$pos] = array('cdata' => ''); 
1161          if ($depth > 0) {
1162              $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1163          } else {
1164              $this->defaultNamespace[$pos] = false;
1165          }
1166  
1167          // get element prefix

1168          if($prefix = $this->getPrefix($name)){
1169              // get unqualified name

1170              $name = $this->getLocalPart($name);
1171          } else {
1172              $prefix = '';
1173          }
1174          
1175          // loop thru attributes, expanding, and registering namespace declarations

1176          if(count($attrs) > 0){
1177              foreach($attrs as $k => $v){
1178                  // if ns declarations, add to class level array of valid namespaces

1179                  if(ereg("^xmlns",$k)){
1180                      //$this->xdebug("$k: $v");

1181                      //$this->xdebug('ns_prefix: '.$this->getPrefix($k));

1182                      if($ns_prefix = substr(strrchr($k,':'),1)){
1183                          //$this->xdebug("Add namespace[$ns_prefix] = $v");

1184                          $this->namespaces[$ns_prefix] = $v;
1185                      } else {
1186                          $this->defaultNamespace[$pos] = $v;
1187                          if (! $this->getPrefixFromNamespace($v)) {
1188                              $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1189                          }
1190                      }
1191                      if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1192                          $this->XMLSchemaVersion = $v;
1193                          $this->namespaces['xsi'] = $v.'-instance';
1194                      }
1195                  }
1196              }
1197              foreach($attrs as $k => $v){
1198                  // expand each attribute

1199                  $k = strpos($k,':') ? $this->expandQname($k) : $k;
1200                  $v = strpos($v,':') ? $this->expandQname($v) : $v;
1201                  $eAttrs[$k] = $v;
1202              }
1203              $attrs = $eAttrs;
1204          } else {
1205              $attrs = array();
1206          }
1207          // find status, register data

1208          switch($name){
1209              case 'all':            // (optional) compositor content for a complexType
1210              case 'choice':
1211              case 'group':
1212              case 'sequence':
1213                  //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");

1214                  $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1215                  //if($name == 'all' || $name == 'sequence'){

1216                  //    $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';

1217                  //}

1218              break;
1219              case 'attribute':    // complexType attribute
1220                  //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);

1221                  $this->xdebug("parsing attribute:");
1222                  $this->appendDebug($this->varDump($attrs));
1223                  if (!isset($attrs['form'])) {
1224                      $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1225                  }
1226                  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1227                      $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1228                      if (!strpos($v, ':')) {
1229                          // no namespace in arrayType attribute value...

1230                          if ($this->defaultNamespace[$pos]) {
1231                              // ...so use the default

1232                              $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1233                          }
1234                      }
1235                  }
1236                  if(isset($attrs['name'])){
1237                      $this->attributes[$attrs['name']] = $attrs;
1238                      $aname = $attrs['name'];
1239                  } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1240                      if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1241                          $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1242                      } else {
1243                          $aname = '';
1244                      }
1245                  } elseif(isset($attrs['ref'])){
1246                      $aname = $attrs['ref'];
1247                      $this->attributes[$attrs['ref']] = $attrs;
1248                  }
1249                  
1250                  if($this->currentComplexType){    // This should *always* be
1251                      $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1252                  }
1253                  // arrayType attribute

1254                  if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1255                      $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1256                      $prefix = $this->getPrefix($aname);
1257                      if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1258                          $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1259                      } else {
1260                          $v = '';
1261                      }
1262                      if(strpos($v,'[,]')){
1263                          $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1264                      }
1265                      $v = substr($v,0,strpos($v,'[')); // clip the []

1266                      if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1267                          $v = $this->XMLSchemaVersion.':'.$v;
1268                      }
1269                      $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1270                  }
1271              break;
1272              case 'complexContent':    // (optional) content for a complexType
1273              break;
1274              case 'complexType':
1275                  $this->complexTypeStack[] = $this->currentComplexType;
1276                  if(isset($attrs['name'])){
1277                      $this->xdebug('processing named complexType '.$attrs['name']);
1278                      //$this->currentElement = false;

1279                      $this->currentComplexType = $attrs['name'];
1280                      $this->complexTypes[$this->currentComplexType] = $attrs;
1281                      $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1282                      // This is for constructs like

1283                      //           <complexType name="ListOfString" base="soap:Array">

1284                      //                <sequence>

1285                      //                    <element name="string" type="xsd:string"

1286                      //                        minOccurs="0" maxOccurs="unbounded" />

1287                      //                </sequence>

1288                      //            </complexType>

1289                      if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1290                          $this->xdebug('complexType is unusual array');
1291                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1292                      } else {
1293                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1294                      }
1295                  }else{
1296                      $this->xdebug('processing unnamed complexType for element '.$this->currentElement);
1297                      $this->currentComplexType = $this->currentElement . '_ContainedType';
1298                      //$this->currentElement = false;

1299                      $this->complexTypes[$this->currentComplexType] = $attrs;
1300                      $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1301                      // This is for constructs like

1302                      //           <complexType name="ListOfString" base="soap:Array">

1303                      //                <sequence>

1304                      //                    <element name="string" type="xsd:string"

1305                      //                        minOccurs="0" maxOccurs="unbounded" />

1306                      //                </sequence>

1307                      //            </complexType>

1308                      if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1309                          $this->xdebug('complexType is unusual array');
1310                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1311                      } else {
1312                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1313                      }
1314                  }
1315              break;
1316              case 'element':
1317                  $this->elementStack[] = $this->currentElement;
1318                  // elements defined as part of a complex type should

1319                  // not really be added to $this->elements, but for some

1320                  // reason, they are

1321                  if (!isset($attrs['form'])) {
1322                      $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1323                  }
1324                  if(isset($attrs['type'])){
1325                      $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1326                      if (! $this->getPrefix($attrs['type'])) {
1327                          if ($this->defaultNamespace[$pos]) {
1328                              $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1329                              $this->xdebug('used default namespace to make type ' . $attrs['type']);
1330                          }
1331                      }
1332                      // This is for constructs like

1333                      //           <complexType name="ListOfString" base="soap:Array">

1334                      //                <sequence>

1335                      //                    <element name="string" type="xsd:string"

1336                      //                        minOccurs="0" maxOccurs="unbounded" />

1337                      //                </sequence>

1338                      //            </complexType>

1339                      if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1340                          $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1341                          $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1342                      }
1343                      $this->currentElement = $attrs['name'];
1344                      $this->elements[ $attrs['name'] ] = $attrs;
1345                      $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1346                      $ename = $attrs['name'];
1347                  } elseif(isset($attrs['ref'])){
1348                      $this->xdebug("processing element as ref to ".$attrs['ref']);
1349                      $this->currentElement = "ref to ".$attrs['ref'];
1350                      $ename = $this->getLocalPart($attrs['ref']);
1351                  } else {
1352                      $this->xdebug("processing untyped element ".$attrs['name']);
1353                      $this->currentElement = $attrs['name'];
1354                      $this->elements[ $attrs['name'] ] = $attrs;
1355                      $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1356                      $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
1357                      $this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
1358                      $ename = $attrs['name'];
1359                  }
1360                  if(isset($ename) && $this->currentComplexType){
1361                      $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1362                  }
1363              break;
1364              case 'enumeration':    //    restriction value list member
1365                  $this->xdebug('enumeration ' . $attrs['value']);
1366                  if ($this->currentSimpleType) {
1367                      $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1368                  } elseif ($this->currentComplexType) {
1369                      $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1370                  }
1371              break;
1372              case 'extension':    // simpleContent or complexContent type extension
1373                  $this->xdebug('extension ' . $attrs['base']);
1374                  if ($this->currentComplexType) {
1375                      $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1376                  }
1377              break;
1378              case 'import':
1379                  if (isset($attrs['schemaLocation'])) {
1380                      //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);

1381                      $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1382                  } else {
1383                      //$this->xdebug('import namespace ' . $attrs['namespace']);

1384                      $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1385                      if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1386                          $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1387                      }
1388                  }
1389              break;
1390              case 'list':    // simpleType value list
1391              break;
1392              case 'restriction':    // simpleType, simpleContent or complexContent value restriction
1393                  $this->xdebug('restriction ' . $attrs['base']);
1394                  if($this->currentSimpleType){
1395                      $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1396                  } elseif($this->currentComplexType){
1397                      $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1398                      if(strstr($attrs['base'],':') == ':Array'){
1399                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1400                      }
1401                  }
1402              break;
1403              case 'schema':
1404                  $this->schemaInfo = $attrs;
1405                  $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1406                  if (isset($attrs['targetNamespace'])) {
1407                      $this->schemaTargetNamespace = $attrs['targetNamespace'];
1408                  }
1409                  if (!isset($attrs['elementFormDefault'])) {
1410                      $this->schemaInfo['elementFormDefault'] = 'unqualified';
1411                  }
1412                  if (!isset($attrs['attributeFormDefault'])) {
1413                      $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1414                  }
1415              break;
1416              case 'simpleContent':    // (optional) content for a complexType
1417              break;
1418              case 'simpleType':
1419                  $this->simpleTypeStack[] = $this->currentSimpleType;
1420                  if(isset($attrs['name'])){
1421                      $this->xdebug("processing simpleType for name " . $attrs['name']);
1422                      $this->currentSimpleType = $attrs['name'];
1423                      $this->simpleTypes[ $attrs['name'] ] = $attrs;
1424                      $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1425                      $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1426                  } else {
1427                      $this->xdebug('processing unnamed simpleType for element '.$this->currentElement);
1428                      $this->currentSimpleType = $this->currentElement . '_ContainedType';
1429                      //$this->currentElement = false;

1430                      $this->simpleTypes[$this->currentSimpleType] = $attrs;
1431                      $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1432                  }
1433              break;
1434              case 'union':    // simpleType type list
1435              break;
1436              default:
1437                  //$this->xdebug("do not have anything to do for element $name");

1438          }
1439      }
1440  
1441      /**

1442      * end-element handler

1443      *

1444      * @param    string $parser XML parser object

1445      * @param    string $name element name

1446      * @access   private

1447      */
1448  	function schemaEndElement($parser, $name) {
1449          // bring depth down a notch

1450          $this->depth--;
1451          // position of current element is equal to the last value left in depth_array for my depth

1452          if(isset($this->depth_array[$this->depth])){
1453              $pos = $this->depth_array[$this->depth];
1454          }
1455          // get element prefix

1456          if ($prefix = $this->getPrefix($name)){
1457              // get unqualified name

1458              $name = $this->getLocalPart($name);
1459          } else {
1460              $prefix = '';
1461          }
1462          // move on...

1463          if($name == 'complexType'){
1464              $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1465              $this->currentComplexType = array_pop($this->complexTypeStack);
1466              //$this->currentElement = false;

1467          }
1468          if($name == 'element'){
1469              $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1470              $this->currentElement = array_pop($this->elementStack);
1471          }
1472          if($name == 'simpleType'){
1473              $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1474              $this->currentSimpleType = array_pop($this->simpleTypeStack);
1475          }
1476      }
1477  
1478      /**

1479      * element content handler

1480      *

1481      * @param    string $parser XML parser object

1482      * @param    string $data element content

1483      * @access   private

1484      */
1485  	function schemaCharacterData($parser, $data){
1486          $pos = $this->depth_array[$this->depth - 1];
1487          $this->message[$pos]['cdata'] .= $data;
1488      }
1489  
1490      /**

1491      * serialize the schema

1492      *

1493      * @access   public

1494      */
1495  	function serializeSchema(){
1496  
1497          $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1498          $xml = '';
1499          // imports

1500          if (sizeof($this->imports) > 0) {
1501              foreach($this->imports as $ns => $list) {
1502                  foreach ($list as $ii) {
1503                      if ($ii['location'] != '') {
1504                          $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1505                      } else {
1506                          $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1507                      }
1508                  }
1509              } 
1510          } 
1511          // complex types

1512          foreach($this->complexTypes as $typeName => $attrs){
1513              $contentStr = '';
1514              // serialize child elements

1515              if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1516                  foreach($attrs['elements'] as $element => $eParts){
1517                      if(isset($eParts['ref'])){
1518                          $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
1519                      } else {
1520                          $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1521                          foreach ($eParts as $aName => $aValue) {
1522                              // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable

1523                              if ($aName != 'name' && $aName != 'type') {
1524                                  $contentStr .= " $aName=\"$aValue\"";
1525                              }
1526                          }
1527                          $contentStr .= "/>\n";
1528                      }
1529                  }
1530                  // compositor wraps elements

1531                  if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1532                      $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
1533                  }
1534              }
1535              // attributes

1536              if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1537                  foreach($attrs['attrs'] as $attr => $aParts){
1538                      $contentStr .= "    <$schemaPrefix:attribute";
1539                      foreach ($aParts as $a => $v) {
1540                          if ($a == 'ref' || $a == 'type') {
1541                              $contentStr .= " $a=\"".$this->contractQName($v).'"';
1542                          } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1543                              $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1544                              $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1545                          } else {
1546                              $contentStr .= " $a=\"$v\"";
1547                          }
1548                      }
1549                      $contentStr .= "/>\n";
1550                  }
1551              }
1552              // if restriction

1553              if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1554                  $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
1555                  // complex or simple content

1556                  if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1557                      $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
1558                  }
1559              }
1560              // finalize complex type

1561              if($contentStr != ''){
1562                  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1563              } else {
1564                  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1565              }
1566              $xml .= $contentStr;
1567          }
1568          // simple types

1569          if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1570              foreach($this->simpleTypes as $typeName => $eParts){
1571                  $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\"/>\n";
1572                  if (isset($eParts['enumeration'])) {
1573                      foreach ($eParts['enumeration'] as $e) {
1574                          $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
1575                      }
1576                  }
1577                  $xml .= " </$schemaPrefix:simpleType>";
1578              }
1579          }
1580          // elements

1581          if(isset($this->elements) && count($this->elements) > 0){
1582              foreach($this->elements as $element => $eParts){
1583                  $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1584              }
1585          }
1586          // attributes

1587          if(isset($this->attributes) && count($this->attributes) > 0){
1588              foreach($this->attributes as $attr => $aParts){
1589                  $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1590              }
1591          }
1592          // finish 'er up

1593          $el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
1594          foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1595              $el .= " xmlns:$nsp=\"$ns\"\n";
1596          }
1597          $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1598          return $xml;
1599      }
1600  
1601      /**

1602      * adds debug data to the clas level debug string

1603      *

1604      * @param    string $string debug data

1605      * @access   private

1606      */
1607  	function xdebug($string){
1608          $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1609      }
1610  
1611      /**

1612      * get the PHP type of a user defined type in the schema

1613      * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays

1614      * returns false if no type exists, or not w/ the given namespace

1615      * else returns a string that is either a native php type, or 'struct'

1616      *

1617      * @param string $type, name of defined type

1618      * @param string $ns, namespace of type

1619      * @return mixed

1620      * @access public

1621      * @deprecated

1622      */
1623  	function getPHPType($type,$ns){
1624          if(isset($this->typemap[$ns][$type])){
1625              //print "found type '$type' and ns $ns in typemap<br>";

1626              return $this->typemap[$ns][$type];
1627          } elseif(isset($this->complexTypes[$type])){
1628              //print "getting type '$type' and ns $ns from complexTypes array<br>";

1629              return $this->complexTypes[$type]['phpType'];
1630          }
1631          return false;
1632      }
1633  
1634      /**

1635      * returns an associative array of information about a given type

1636      * returns false if no type exists by the given name

1637      *

1638      *    For a complexType typeDef = array(

1639      *    'restrictionBase' => '',

1640      *    'phpType' => '',

1641      *    'compositor' => '(sequence|all)',

1642      *    'elements' => array(), // refs to elements array

1643      *    'attrs' => array() // refs to attributes array

1644      *    ... and so on (see addComplexType)

1645      *    )

1646      *

1647      *   For simpleType or element, the array has different keys.

1648      *

1649      * @param string

1650      * @return mixed

1651      * @access public

1652      * @see addComplexType

1653      * @see addSimpleType

1654      * @see addElement

1655      */
1656  	function getTypeDef($type){
1657          //$this->debug("in getTypeDef for type $type");

1658          if(isset($this->complexTypes[$type])){
1659              $this->xdebug("in getTypeDef, found complexType $type");
1660              return $this->complexTypes[$type];
1661          } elseif(isset($this->simpleTypes[$type])){
1662              $this->xdebug("in getTypeDef, found simpleType $type");
1663              if (!isset($this->simpleTypes[$type]['phpType'])) {
1664                  // get info for type to tack onto the simple type

1665                  // TODO: can this ever really apply (i.e. what is a simpleType really?)

1666                  $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1667                  $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1668                  $etype = $this->getTypeDef($uqType);
1669                  if ($etype) {
1670                      $this->xdebug("in getTypeDef, found type for simpleType $type:");
1671                      $this->xdebug($this->varDump($etype));
1672                      if (isset($etype['phpType'])) {
1673                          $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1674                      }
1675                      if (isset($etype['elements'])) {
1676                          $this->simpleTypes[$type]['elements'] = $etype['elements'];
1677                      }
1678                  }
1679              }
1680              return $this->simpleTypes[$type];
1681          } elseif(isset($this->elements[$type])){
1682              $this->xdebug("in getTypeDef, found element $type");
1683              if (!isset($this->elements[$type]['phpType'])) {
1684                  // get info for type to tack onto the element

1685                  $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1686                  $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1687                  $etype = $this->getTypeDef($uqType);
1688                  if ($etype) {
1689                      $this->xdebug("in getTypeDef, found type for element $type:");
1690                      $this->xdebug($this->varDump($etype));
1691                      if (isset($etype['phpType'])) {
1692                          $this->elements[$type]['phpType'] = $etype['phpType'];
1693                      }
1694                      if (isset($etype['elements'])) {
1695                          $this->elements[$type]['elements'] = $etype['elements'];
1696                      }
1697                  } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1698                      $this->xdebug("in getTypeDef, element $type is an XSD type");
1699                      $this->elements[$type]['phpType'] = 'scalar';
1700                  }
1701              }
1702              return $this->elements[$type];
1703          } elseif(isset($this->attributes[$type])){
1704              $this->xdebug("in getTypeDef, found attribute $type");
1705              return $this->attributes[$type];
1706          } elseif (ereg('_ContainedType$', $type)) {
1707              $this->xdebug("in getTypeDef, have an untyped element $type");
1708              $typeDef['typeClass'] = 'simpleType';
1709              $typeDef['phpType'] = 'scalar';
1710              $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1711              return $typeDef;
1712          }
1713          $this->xdebug("in getTypeDef, did not find $type");
1714          return false;
1715      }
1716  
1717      /**

1718      * returns a sample serialization of a given type, or false if no type by the given name

1719      *

1720      * @param string $type, name of type

1721      * @return mixed

1722      * @access public

1723      * @deprecated

1724      */
1725      function serializeTypeDef($type){
1726          //print "in sTD() for type $type<br>";

1727      if($typeDef = $this->getTypeDef($type)){
1728          $str .= '<'.$type;
1729          if(is_array($typeDef['attrs'])){
1730          foreach($attrs as $attName => $data){
1731              $str .= " $attName=\"{type = ".$data['type']."}\"";
1732          }
1733          }
1734          $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1735          if(count($typeDef['elements']) > 0){
1736          $str .= ">";
1737          foreach($typeDef['elements'] as $element => $eData){
1738              $str .= $this->serializeTypeDef($element);
1739          }
1740          $str .= "</$type>";
1741          } elseif($typeDef['typeClass'] == 'element') {
1742          $str .= "></$type>";
1743          } else {
1744          $str .= "/>";
1745          }
1746              return $str;
1747      }
1748          return false;
1749      }
1750  
1751      /**

1752      * returns HTML form elements that allow a user

1753      * to enter values for creating an instance of the given type.

1754      *

1755      * @param string $name, name for type instance

1756      * @param string $type, name of type

1757      * @return string

1758      * @access public

1759      * @deprecated

1760      */
1761  	function typeToForm($name,$type){
1762          // get typedef

1763          if($typeDef = $this->getTypeDef($type)){
1764              // if struct

1765              if($typeDef['phpType'] == 'struct'){
1766                  $buffer .= '<table>';
1767                  foreach($typeDef['elements'] as $child => $childDef){
1768                      $buffer .= "
1769                      <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1770                      <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1771                  }
1772                  $buffer .= '</table>';
1773              // if array

1774              } elseif($typeDef['phpType'] == 'array'){
1775                  $buffer .= '<table>';
1776                  for($i=0;$i < 3; $i++){
1777                      $buffer .= "
1778                      <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1779                      <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1780                  }
1781                  $buffer .= '</table>';
1782              // if scalar

1783              } else {
1784                  $buffer .= "<input type='text' name='parameters[$name]'>";
1785              }
1786          } else {
1787              $buffer .= "<input type='text' name='parameters[$name]'>";
1788          }
1789          return $buffer;
1790      }
1791      
1792      /**

1793      * adds a complex type to the schema

1794      * 

1795      * example: array

1796      * 

1797      * addType(

1798      *     'ArrayOfstring',

1799      *     'complexType',

1800      *     'array',

1801      *     '',

1802      *     'SOAP-ENC:Array',

1803      *     array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),

1804      *     'xsd:string'

1805      * );

1806      * 

1807      * example: PHP associative array ( SOAP Struct )

1808      * 

1809      * addType(

1810      *     'SOAPStruct',

1811      *     'complexType',

1812      *     'struct',

1813      *     'all',

1814      *     array('myVar'=> array('name'=>'myVar','type'=>'string')

1815      * );

1816      * 

1817      * @param name

1818      * @param typeClass (complexType|simpleType|attribute)

1819      * @param phpType: currently supported are array and struct (php assoc array)

1820      * @param compositor (all|sequence|choice)

1821      * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)

1822      * @param elements = array ( name = array(name=>'',type=>'') )

1823      * @param attrs = array(

1824      *     array(

1825      *        'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",

1826      *        "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"

1827      *     )

1828      * )

1829      * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)

1830      * @access public

1831      * @see getTypeDef

1832      */
1833  	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1834          $this->complexTypes[$name] = array(
1835          'name'        => $name,
1836          'typeClass'    => $typeClass,
1837          'phpType'    => $phpType,
1838          'compositor'=> $compositor,
1839          'restrictionBase' => $restrictionBase,
1840          'elements'    => $elements,
1841          'attrs'        => $attrs,
1842          'arrayType'    => $arrayType
1843          );
1844          
1845          $this->xdebug("addComplexType $name:");
1846          $this->appendDebug($this->varDump($this->complexTypes[$name]));
1847      }
1848      
1849      /**

1850      * adds a simple type to the schema

1851      *

1852      * @param string $name

1853      * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)

1854      * @param string $typeClass (should always be simpleType)

1855      * @param string $phpType (should always be scalar)

1856      * @param array $enumeration array of values

1857      * @access public

1858      * @see xmlschema

1859      * @see getTypeDef

1860      */
1861  	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1862          $this->simpleTypes[$name] = array(
1863          'name'            => $name,
1864          'typeClass'        => $typeClass,
1865          'phpType'        => $phpType,
1866          'type'            => $restrictionBase,
1867          'enumeration'    => $enumeration
1868          );
1869          
1870          $this->xdebug("addSimpleType $name:");
1871          $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1872      }
1873  
1874      /**

1875      * adds an element to the schema

1876      *

1877      * @param array $attrs attributes that must include name and type

1878      * @see xmlschema

1879      * @access public

1880      */
1881  	function addElement($attrs) {
1882          if (! $this->getPrefix($attrs['type'])) {
1883              $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1884          }
1885          $this->elements[ $attrs['name'] ] = $attrs;
1886          $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1887          
1888          $this->xdebug("addElement " . $attrs['name']);
1889          $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
1890      }
1891  }
1892  
1893  
1894  
1895  ?><?php
1896  
1897  
1898  
1899  /**

1900  * For creating serializable abstractions of native PHP types.  This class

1901  * allows element name/namespace, XSD type, and XML attributes to be

1902  * associated with a value.  This is extremely useful when WSDL is not

1903  * used, but is also useful when WSDL is used with polymorphic types, including

1904  * xsd:anyType and user-defined types.

1905  *

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

1907  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

1908  * @access   public

1909  */
1910  class soapval extends nusoap_base {
1911      /**

1912       * The XML element name

1913       *

1914       * @var string

1915       * @access private

1916       */
1917      var $name;
1918      /**

1919       * The XML type name (string or false)

1920       *

1921       * @var mixed

1922       * @access private

1923       */
1924      var $type;
1925      /**

1926       * The PHP value

1927       *

1928       * @var mixed

1929       * @access private

1930       */
1931      var $value;
1932      /**

1933       * The XML element namespace (string or false)

1934       *

1935       * @var mixed

1936       * @access private

1937       */
1938      var $element_ns;
1939      /**

1940       * The XML type namespace (string or false)

1941       *

1942       * @var mixed

1943       * @access private

1944       */
1945      var $type_ns;
1946      /**

1947       * The XML element attributes (array or false)

1948       *

1949       * @var mixed

1950       * @access private

1951       */
1952      var $attributes;
1953  
1954      /**

1955      * constructor

1956      *

1957      * @param    string $name optional name

1958      * @param    mixed $type optional type name

1959      * @param    mixed $value optional value

1960      * @param    mixed $element_ns optional namespace of value

1961      * @param    mixed $type_ns optional namespace of type

1962      * @param    mixed $attributes associative array of attributes to add to element serialization

1963      * @access   public

1964      */
1965    	function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
1966          parent::nusoap_base();
1967          $this->name = $name;
1968          $this->type = $type;
1969          $this->value = $value;
1970          $this->element_ns = $element_ns;
1971          $this->type_ns = $type_ns;
1972          $this->attributes = $attributes;
1973      }
1974  
1975      /**

1976      * return serialized value

1977      *

1978      * @param    string $use The WSDL use value (encoded|literal)

1979      * @return    string XML data

1980      * @access   public

1981      */
1982  	function serialize($use='encoded') {
1983          return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
1984      }
1985  
1986      /**

1987      * decodes a soapval object into a PHP native type

1988      *

1989      * @return    mixed

1990      * @access   public

1991      */
1992  	function decode(){
1993          return $this->value;
1994      }
1995  }
1996  
1997  
1998  
1999  ?><?php
2000  
2001  
2002  
2003  /**

2004  * transport class for sending/receiving data via HTTP and HTTPS

2005  * NOTE: PHP must be compiled with the CURL extension for HTTPS support

2006  *

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

2008  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

2009  * @access public

2010  */
2011  class soap_transport_http extends nusoap_base {
2012  
2013      var $url = '';
2014      var $uri = '';
2015      var $digest_uri = '';
2016      var $scheme = '';
2017      var $host = '';
2018      var $port = '';
2019      var $path = '';
2020      var $request_method = 'POST';
2021      var $protocol_version = '1.0';
2022      var $encoding = '';
2023      var $outgoing_headers = array();
2024      var $incoming_headers = array();
2025      var $incoming_cookies = array();
2026      var $outgoing_payload = '';
2027      var $incoming_payload = '';
2028      var $useSOAPAction = true;
2029      var $persistentConnection = false;
2030      var $ch = false;    // cURL handle

2031      var $username = '';
2032      var $password = '';
2033      var $authtype = '';
2034      var $digestRequest = array();
2035      var $certRequest = array();    // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional)

2036                                  // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'

2037                                  // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'

2038                                  // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'

2039                                  // passphrase: SSL key password/passphrase

2040                                  // verifypeer: default is 1

2041                                  // verifyhost: default is 1

2042  
2043      /**

2044      * constructor

2045      */
2046  	function soap_transport_http($url){
2047          parent::nusoap_base();
2048          $this->setURL($url);
2049          ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
2050          $this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')';
2051          $this->debug('set User-Agent: ' . $this->outgoing_headers['User-Agent']);
2052      }
2053  
2054  	function setURL($url) {
2055          $this->url = $url;
2056  
2057          $u = parse_url($url);
2058          foreach($u as $k => $v){
2059              $this->debug("$k = $v");
2060              $this->$k = $v;
2061          }
2062          
2063          // add any GET params to path

2064          if(isset($u['query']) && $u['query'] != ''){
2065              $this->path .= '?' . $u['query'];
2066          }
2067          
2068          // set default port

2069          if(!isset($u['port'])){
2070              if($u['scheme'] == 'https'){
2071                  $this->port = 443;
2072              } else {
2073                  $this->port = 80;
2074              }
2075          }
2076          
2077          $this->uri = $this->path;
2078          $this->digest_uri = $this->uri;
2079          
2080          // build headers

2081          if (!isset($u['port'])) {
2082              $this->outgoing_headers['Host'] = $this->host;
2083          } else {
2084              $this->outgoing_headers['Host'] = $this->host.':'.$this->port;
2085          }
2086          $this->debug('set Host: ' . $this->outgoing_headers['Host']);
2087  
2088          if (isset($u['user']) && $u['user'] != '') {
2089              $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2090          }
2091      }
2092      
2093  	function connect($connection_timeout=0,$response_timeout=30){
2094            // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like

2095            // "regular" socket.

2096            // TODO: disabled for now because OpenSSL must be *compiled* in (not just

2097            //       loaded), and until PHP5 stream_get_wrappers is not available.

2098  //          if ($this->scheme == 'https') {

2099  //              if (version_compare(phpversion(), '4.3.0') >= 0) {

2100  //                  if (extension_loaded('openssl')) {

2101  //                      $this->scheme = 'ssl';

2102  //                      $this->debug('Using SSL over OpenSSL');

2103  //                  }

2104  //              }

2105  //        }

2106          $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2107        if ($this->scheme == 'http' || $this->scheme == 'ssl') {
2108          // use persistent connection

2109          if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
2110              if (!feof($this->fp)) {
2111                  $this->debug('Re-use persistent connection');
2112                  return true;
2113              }
2114              fclose($this->fp);
2115              $this->debug('Closed persistent connection at EOF');
2116          }
2117  
2118          // munge host if using OpenSSL

2119          if ($this->scheme == 'ssl') {
2120              $host = 'ssl://' . $this->host;
2121          } else {
2122              $host = $this->host;
2123          }
2124          $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2125  
2126          // open socket

2127          if($connection_timeout > 0){
2128              $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2129          } else {
2130              $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
2131          }
2132          
2133          // test pointer

2134          if(!$this->fp) {
2135              $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2136              if ($this->errno) {
2137                  $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
2138              } else {
2139                  $msg .= ' prior to connect().  This is often a problem looking up the host name.';
2140              }
2141              $this->debug($msg);
2142              $this->setError($msg);
2143              return false;
2144          }
2145          
2146          // set response timeout

2147          $this->debug('set response timeout to ' . $response_timeout);
2148          socket_set_timeout( $this->fp, $response_timeout);
2149  
2150          $this->debug('socket connected');
2151          return true;
2152        } else if ($this->scheme == 'https') {
2153          if (!extension_loaded('curl')) {
2154              $this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2155              return false;
2156          }
2157          $this->debug('connect using https');
2158          // init CURL

2159          $this->ch = curl_init();
2160          // set url

2161          $hostURL = ($this->port != '') ? "https://$this->host:$this->port" : "https://$this->host";
2162          // add path

2163          $hostURL .= $this->path;
2164          curl_setopt($this->ch, CURLOPT_URL, $hostURL);
2165          // follow location headers (re-directs)

2166          curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
2167          // ask for headers in the response output

2168          curl_setopt($this->ch, CURLOPT_HEADER, 1);
2169          // ask for the response output as the return value

2170          curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
2171          // encode

2172          // We manage this ourselves through headers and encoding

2173  //        if(function_exists('gzuncompress')){

2174  //            curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate');

2175  //        }

2176          // persistent connection

2177          if ($this->persistentConnection) {
2178              // The way we send data, we cannot use persistent connections, since

2179              // there will be some "junk" at the end of our request.

2180              //curl_setopt($this->ch, CURL_HTTP_VERSION_1_1, true);

2181              $this->persistentConnection = false;
2182              $this->outgoing_headers['Connection'] = 'close';
2183              $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
2184          }
2185          // set timeout

2186          if ($connection_timeout != 0) {
2187              curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_timeout);
2188          }
2189          // TODO: cURL has added a connection timeout separate from the response timeout

2190          //if ($connection_timeout != 0) {

2191          //    curl_setopt($this->ch, CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);

2192          //}

2193          //if ($response_timeout != 0) {

2194          //    curl_setopt($this->ch, CURLOPT_TIMEOUT, $response_timeout);

2195          //}

2196  
2197          // recent versions of cURL turn on peer/host checking by default,

2198          // while PHP binaries are not compiled with a default location for the

2199          // CA cert bundle, so disable peer/host checking.

2200  //curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');        

2201          curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
2202          curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
2203  
2204          // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)

2205          if ($this->authtype == 'certificate') {
2206              if (isset($this->certRequest['cainfofile'])) {
2207                  curl_setopt($this->ch, CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2208              }
2209              if (isset($this->certRequest['verifypeer'])) {
2210                  curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2211              } else {
2212                  curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1);
2213              }
2214              if (isset($this->certRequest['verifyhost'])) {
2215                  curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2216              } else {
2217                  curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1);
2218              }
2219              if (isset($this->certRequest['sslcertfile'])) {
2220                  curl_setopt($this->ch, CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2221              }
2222              if (isset($this->certRequest['sslkeyfile'])) {
2223                  curl_setopt($this->ch, CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2224              }
2225              if (isset($this->certRequest['passphrase'])) {
2226                  curl_setopt($this->ch, CURLOPT_SSLKEYPASSWD , $this->certRequest['passphrase']);
2227              }
2228          }
2229          $this->debug('cURL connection set up');
2230          return true;
2231        } else {
2232          $this->setError('Unknown scheme ' . $this->scheme);
2233          $this->debug('Unknown scheme ' . $this->scheme);
2234          return false;
2235        }
2236      }
2237      
2238      /**

2239      * send the SOAP message via HTTP

2240      *

2241      * @param    string $data message data

2242      * @param    integer $timeout set connection timeout in seconds

2243      * @param    integer $response_timeout set response timeout in seconds

2244      * @param    array $cookies cookies to send

2245      * @return    string data

2246      * @access   public

2247      */
2248  	function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
2249          
2250          $this->debug('entered send() with data of length: '.strlen($data));
2251  
2252          $this->tryagain = true;
2253          $tries = 0;
2254          while ($this->tryagain) {
2255              $this->tryagain = false;
2256              if ($tries++ < 2) {
2257                  // make connnection

2258                  if (!$this->connect($timeout, $response_timeout)){
2259                      return false;
2260                  }
2261                  
2262                  // send request

2263                  if (!$this->sendRequest($data, $cookies)){
2264                      return false;
2265                  }
2266                  
2267                  // get response

2268                  $respdata = $this->getResponse();
2269              } else {
2270                  $this->setError('Too many tries to get an OK response');
2271              }
2272          }        
2273          $this->debug('end of send()');
2274          return $respdata;
2275      }
2276  
2277  
2278      /**

2279      * send the SOAP message via HTTPS 1.0 using CURL

2280      *

2281      * @param    string $msg message data

2282      * @param    integer $timeout set connection timeout in seconds

2283      * @param    integer $response_timeout set response timeout in seconds

2284      * @param    array $cookies cookies to send

2285      * @return    string data

2286      * @access   public

2287      */
2288  	function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
2289          return $this->send($data, $timeout, $response_timeout, $cookies);
2290      }
2291      
2292      /**

2293      * if authenticating, set user credentials here

2294      *

2295      * @param    string $username

2296      * @param    string $password

2297      * @param    string $authtype (basic, digest, certificate)

2298      * @param    array $digestRequest (keys must be nonce, nc, realm, qop)

2299      * @param    array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)

2300      * @access   public

2301      */
2302  	function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
2303          $this->debug("Set credentials for authtype $authtype");
2304          // cf. RFC 2617

2305          if ($authtype == 'basic') {
2306              $this->outgoing_headers['Authorization'] = 'Basic '.base64_encode(str_replace(':','',$username).':'.$password);
2307          } elseif ($authtype == 'digest') {
2308              if (isset($digestRequest['nonce'])) {
2309                  $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2310                  
2311                  // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)

2312      
2313                  // A1 = unq(username-value) ":" unq(realm-value) ":" passwd

2314                  $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2315      
2316                  // H(A1) = MD5(A1)

2317                  $HA1 = md5($A1);
2318      
2319                  // A2 = Method ":" digest-uri-value

2320                  $A2 = 'POST:' . $this->digest_uri;
2321      
2322                  // H(A2)

2323                  $HA2 =  md5($A2);
2324      
2325                  // KD(secret, data) = H(concat(secret, ":", data))

2326                  // if qop == auth:

2327                  // request-digest  = <"> < KD ( H(A1),     unq(nonce-value)

2328                  //                              ":" nc-value

2329                  //                              ":" unq(cnonce-value)

2330                  //                              ":" unq(qop-value)

2331                  //                              ":" H(A2)

2332                  //                            ) <">

2333                  // if qop is missing,

2334                  // request-digest  = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">

2335      
2336                  $unhashedDigest = '';
2337                  $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2338                  $cnonce = $nonce;
2339                  if ($digestRequest['qop'] != '') {
2340                      $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2341                  } else {
2342                      $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2343                  }
2344      
2345                  $hashedDigest = md5($unhashedDigest);
2346      
2347                  $this->outgoing_headers['Authorization'] = 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"';
2348              }
2349          } elseif ($authtype == 'certificate') {
2350              $this->certRequest = $certRequest;
2351          }
2352          $this->username = $username;
2353          $this->password = $password;
2354          $this->authtype = $authtype;
2355          $this->digestRequest = $digestRequest;
2356          
2357          if (isset($this->outgoing_headers['Authorization'])) {
2358              $this->debug('set Authorization: ' . substr($this->outgoing_headers['Authorization'], 0, 12) . '...');
2359          } else {
2360              $this->debug('Authorization header not set');
2361          }
2362      }
2363      
2364      /**

2365      * set the soapaction value

2366      *

2367      * @param    string $soapaction

2368      * @access   public

2369      */
2370  	function setSOAPAction($soapaction) {
2371          $this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"';
2372          $this->debug('set SOAPAction: ' . $this->outgoing_headers['SOAPAction']);
2373      }
2374      
2375      /**

2376      * use http encoding

2377      *

2378      * @param    string $enc encoding style. supported values: gzip, deflate, or both

2379      * @access   public

2380      */
2381  	function setEncoding($enc='gzip, deflate') {
2382          if (function_exists('gzdeflate')) {
2383              $this->protocol_version = '1.1';
2384              $this->outgoing_headers['Accept-Encoding'] = $enc;
2385              $this->debug('set Accept-Encoding: ' . $this->outgoing_headers['Accept-Encoding']);
2386              if (!isset($this->outgoing_headers['Connection'])) {
2387                  $this->outgoing_headers['Connection'] = 'close';
2388                  $this->persistentConnection = false;
2389                  $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
2390              }
2391              set_magic_quotes_runtime(0);
2392              // deprecated

2393              $this->encoding = $enc;
2394          }
2395      }
2396      
2397      /**

2398      * set proxy info here

2399      *

2400      * @param    string $proxyhost

2401      * @param    string $proxyport

2402      * @param    string $proxyusername

2403      * @param    string $proxypassword

2404      * @access   public

2405      */
2406  	function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
2407          $this->uri = $this->url;
2408          $this->host = $proxyhost;
2409          $this->port = $proxyport;
2410          if ($proxyusername != '' && $proxypassword != '') {
2411              $this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword);
2412              $this->debug('set Proxy-Authorization: ' . $this->outgoing_headers['Proxy-Authorization']);
2413          }
2414      }
2415      
2416      /**

2417      * decode a string that is encoded w/ "chunked' transfer encoding

2418       * as defined in RFC2068 19.4.6

2419      *

2420      * @param    string $buffer

2421      * @param    string $lb

2422      * @returns    string

2423      * @access   public

2424      * @deprecated

2425      */
2426  	function decodeChunked($buffer, $lb){
2427          // length := 0

2428          $length = 0;
2429          $new = '';
2430          
2431          // read chunk-size, chunk-extension (if any) and CRLF

2432          // get the position of the linebreak

2433          $chunkend = strpos($buffer, $lb);
2434          if ($chunkend == FALSE) {
2435              $this->debug('no linebreak found in decodeChunked');
2436              return $new;
2437          }
2438          $temp = substr($buffer,0,$chunkend);
2439          $chunk_size = hexdec( trim($temp) );
2440          $chunkstart = $chunkend + strlen($lb);
2441          // while (chunk-size > 0) {

2442          while ($chunk_size > 0) {
2443              $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2444              $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
2445                
2446              // Just in case we got a broken connection

2447                if ($chunkend == FALSE) {
2448                    $chunk = substr($buffer,$chunkstart);
2449                  // append chunk-data to entity-body

2450                  $new .= $chunk;
2451                    $length += strlen($chunk);
2452                    break;
2453              }
2454              
2455                // read chunk-data and CRLF

2456                $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2457                // append chunk-data to entity-body

2458                $new .= $chunk;
2459                // length := length + chunk-size

2460                $length += strlen($chunk);
2461                // read chunk-size and CRLF

2462                $chunkstart = $chunkend + strlen($lb);
2463              
2464                $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2465              if ($chunkend == FALSE) {
2466                  break; //Just in case we got a broken connection

2467              }
2468              $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2469              $chunk_size = hexdec( trim($temp) );
2470              $chunkstart = $chunkend;
2471          }
2472          return $new;
2473      }
2474      
2475      /*

2476       *    Writes payload, including HTTP headers, to $this->outgoing_payload.

2477       */
2478  	function buildPayload($data, $cookie_str = '') {
2479          // add content-length header

2480          $this->outgoing_headers['Content-Length'] = strlen($data);
2481          $this->debug('set Content-Length: ' . $this->outgoing_headers['Content-Length']);
2482  
2483          // start building outgoing payload:

2484          $req = "$this->request_method $this->uri HTTP/$this->protocol_version";
2485          $this->debug("HTTP request: $req");
2486          $this->outgoing_payload = "$req\r\n";
2487  
2488          // loop thru headers, serializing

2489          foreach($this->outgoing_headers as $k => $v){
2490              $hdr = $k.': '.$v;
2491              $this->debug("HTTP header: $hdr");
2492              $this->outgoing_payload .= "$hdr\r\n";
2493          }
2494  
2495          // add any cookies

2496          if ($cookie_str != '') {
2497              $hdr = 'Cookie: '.$cookie_str;
2498              $this->debug("HTTP header: $hdr");
2499              $this->outgoing_payload .= "$hdr\r\n";
2500          }
2501  
2502          // header/body separator

2503          $this->outgoing_payload .= "\r\n";
2504          
2505          // add data

2506          $this->outgoing_payload .= $data;
2507      }
2508  
2509  	function sendRequest($data, $cookies = NULL) {
2510          // build cookie string

2511          $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2512  
2513          // build payload

2514          $this->buildPayload($data, $cookie_str);
2515  
2516        if ($this->scheme == 'http' || $this->scheme == 'ssl') {
2517          // send payload

2518          if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2519              $this->setError('couldn\'t write message data to socket');
2520              $this->debug('couldn\'t write message data to socket');
2521              return false;
2522          }
2523          $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2524          return true;
2525        } else if ($this->scheme == 'https') {
2526          // set payload

2527          // TODO: cURL does say this should only be the verb, and in fact it

2528          // turns out that the URI and HTTP version are appended to this, which

2529          // some servers refuse to work with

2530          //curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);

2531          foreach($this->outgoing_headers as $k => $v){
2532              $curl_headers[] = "$k: $v";
2533          }
2534          if ($cookie_str != '') {
2535              $curl_headers[] = 'Cookie: ' . $cookie_str;
2536          }
2537          curl_setopt($this->ch, CURLOPT_HTTPHEADER, $curl_headers);
2538          if ($this->request_method == "POST") {
2539                curl_setopt($this->ch, CURLOPT_POST, 1);
2540                curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
2541            } else {
2542            }
2543          $this->debug('set cURL payload');
2544          return true;
2545        }
2546      }
2547  
2548  	function getResponse(){
2549          $this->incoming_payload = '';
2550          
2551        if ($this->scheme == 'http' || $this->scheme == 'ssl') {
2552          // loop until headers have been retrieved

2553          $data = '';
2554          while (!isset($lb)){
2555  
2556              // We might EOF during header read.

2557              if(feof($this->fp)) {
2558                  $this->incoming_payload = $data;
2559                  $this->debug('found no headers before EOF after length ' . strlen($data));
2560                  $this->debug("received before EOF:\n" . $data);
2561                  $this->setError('server failed to send headers');
2562                  return false;
2563              }
2564  
2565              $tmp = fgets($this->fp, 256);
2566              $tmplen = strlen($tmp);
2567              $this->debug("read line of $tmplen bytes: " . trim($tmp));
2568  
2569              if ($tmplen == 0) {
2570                  $this->incoming_payload = $data;
2571                  $this->debug('socket read of headers timed out after length ' . strlen($data));
2572                  $this->debug("read before timeout: " . $data);
2573                  $this->setError('socket read of headers timed out');
2574                  return false;
2575              }
2576  
2577              $data .= $tmp;
2578              $pos = strpos($data,"\r\n\r\n");
2579              if($pos > 1){
2580                  $lb = "\r\n";
2581              } else {
2582                  $pos = strpos($data,"\n\n");
2583                  if($pos > 1){
2584                      $lb = "\n";
2585                  }
2586              }
2587              // remove 100 header

2588              if(isset($lb) && ereg('^HTTP/1.1 100',$data)){
2589                  unset($lb);
2590                  $data = '';
2591              }//

2592          }
2593          // store header data

2594          $this->incoming_payload .= $data;
2595          $this->debug('found end of headers after length ' . strlen($data));
2596          // process headers

2597          $header_data = trim(substr($data,0,$pos));
2598          $header_array = explode($lb,$header_data);
2599          $this->incoming_headers = array();
2600          $this->incoming_cookies = array();
2601          foreach($header_array as $header_line){
2602              $arr = explode(':',$header_line, 2);
2603              if(count($arr) > 1){
2604                  $header_name = strtolower(trim($arr[0]));
2605                  $this->incoming_headers[$header_name] = trim($arr[1]);
2606                  if ($header_name == 'set-cookie') {
2607                      // TODO: allow multiple cookies from parseCookie

2608                      $cookie = $this->parseCookie(trim($arr[1]));
2609                      if ($cookie) {
2610                          $this->incoming_cookies[] = $cookie;
2611                          $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
2612                      } else {
2613                          $this->debug('did not find cookie in ' . trim($arr[1]));
2614                      }
2615                  }
2616              } else if (isset($header_name)) {
2617                  // append continuation line to previous header

2618                  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
2619              }
2620          }
2621          
2622          // loop until msg has been received

2623          if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
2624              $content_length =  2147483647;    // ignore any content-length header

2625              $chunked = true;
2626              $this->debug("want to read chunked content");
2627          } elseif (isset($this->incoming_headers['content-length'])) {
2628              $content_length = $this->incoming_headers['content-length'];
2629              $chunked = false;
2630              $this->debug("want to read content of length $content_length");
2631          } else {
2632              $content_length =  2147483647;
2633              $chunked = false;
2634              $this->debug("want to read content to EOF");
2635          }
2636          $data = '';
2637          do {
2638              if ($chunked) {
2639                  $tmp = fgets($this->fp, 256);
2640                  $tmplen = strlen($tmp);
2641                  $this->debug("read chunk line of $tmplen bytes");
2642                  if ($tmplen == 0) {
2643                      $this->incoming_payload = $data;
2644                      $this->debug('socket read of chunk length timed out after length ' . strlen($data));
2645                      $this->debug("read before timeout:\n" . $data);
2646                      $this->setError('socket read of chunk length timed out');
2647                      return false;
2648                  }
2649                  $content_length = hexdec(trim($tmp));
2650                  $this->debug("chunk length $content_length");
2651              }
2652              $strlen = 0;
2653              while (($strlen < $content_length) && (!feof($this->fp))) {
2654                  $readlen = min(8192, $content_length - $strlen);
2655                  $tmp = fread($this->fp, $readlen);
2656                  $tmplen = strlen($tmp);
2657                  $this->debug("read buffer of $tmplen bytes");
2658                  if (($tmplen == 0) && (!feof($this->fp))) {
2659                      $this->incoming_payload = $data;
2660                      $this->debug('socket read of body timed out after length ' . strlen($data));
2661                      $this->debug("read before timeout:\n" . $data);
2662                      $this->setError('socket read of body timed out');
2663                      return false;
2664                  }
2665                  $strlen += $tmplen;
2666                  $data .= $tmp;
2667              }
2668              if ($chunked && ($content_length > 0)) {
2669                  $tmp = fgets($this->fp, 256);
2670                  $tmplen = strlen($tmp);
2671                  $this->debug("read chunk terminator of $tmplen bytes");
2672                  if ($tmplen == 0) {
2673                      $this->incoming_payload = $data;
2674                      $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
2675                      $this->debug("read before timeout:\n" . $data);
2676                      $this->setError('socket read of chunk terminator timed out');
2677                      return false;
2678                  }
2679              }
2680          } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
2681          if (feof($this->fp)) {
2682              $this->debug('read to EOF');
2683          }
2684          $this->debug('read body of length ' . strlen($data));
2685          $this->incoming_payload .= $data;
2686          $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
2687          
2688          // close filepointer

2689          if(
2690              (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') || 
2691              (! $this->persistentConnection) || feof($this->fp)){
2692              fclose($this->fp);
2693              $this->fp = false;
2694              $this->debug('closed socket');
2695          }
2696          
2697          // connection was closed unexpectedly

2698          if($this->incoming_payload == ''){
2699              $this->setError('no response from server');
2700              return false;
2701          }
2702          
2703          // decode transfer-encoding

2704  //        if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){

2705  //            if(!$data = $this->decodeChunked($data, $lb)){

2706  //                $this->setError('Decoding of chunked data failed');

2707  //                return false;

2708  //            }

2709              //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";

2710              // set decoded payload

2711  //            $this->incoming_payload = $header_data.$lb.$lb.$data;

2712  //        }

2713      
2714        } else if ($this->scheme == 'https') {
2715          // send and receive

2716          $this->debug('send and receive with cURL');
2717          $this->incoming_payload = curl_exec($this->ch);
2718          $data = $this->incoming_payload;
2719  
2720          $cErr = curl_error($this->ch);
2721          if ($cErr != '') {
2722              $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
2723              // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE

2724              foreach(curl_getinfo($this->ch) as $k => $v){
2725                  $err .= "$k: $v<br>";
2726              }
2727              $this->debug($err);
2728              $this->setError($err);
2729              curl_close($this->ch);
2730              return false;
2731          } else {
2732              //echo '<pre>';

2733              //var_dump(curl_getinfo($this->ch));

2734              //echo '</pre>';

2735          }
2736          // close curl

2737          $this->debug('No cURL error, closing cURL');
2738          curl_close($this->ch);
2739          
2740          // remove 100 header(s)

2741          while (ereg('^HTTP/1.1 100',$data)) {
2742              if ($pos = strpos($data,"\r\n\r\n")) {
2743                  $data = ltrim(substr($data,$pos));
2744              } elseif($pos = strpos($data,"\n\n") ) {
2745                  $data = ltrim(substr($data,$pos));
2746              }
2747          }
2748          
2749          // separate content from HTTP headers

2750          if ($pos = strpos($data,"\r\n\r\n")) {
2751              $lb = "\r\n";
2752          } elseif( $pos = strpos($data,"\n\n")) {
2753              $lb = "\n";
2754          } else {
2755              $this->debug('no proper separation of headers and document');
2756              $this->setError('no proper separation of headers and document');
2757              return false;
2758          }
2759          $header_data = trim(substr($data,0,$pos));
2760          $header_array = explode($lb,$header_data);
2761          $data = ltrim(substr($data,$pos));
2762          $this->debug('found proper separation of headers and document');
2763          $this->debug('cleaned data, stringlen: '.strlen($data));
2764          // clean headers

2765          foreach ($header_array as $header_line) {
2766              $arr = explode(':',$header_line,2);
2767              if(count($arr) > 1){
2768                  $header_name = strtolower(trim($arr[0]));
2769                  $this->incoming_headers[$header_name] = trim($arr[1]);
2770                  if ($header_name == 'set-cookie') {
2771                      // TODO: allow multiple cookies from parseCookie

2772                      $cookie = $this->parseCookie(trim($arr[1]));
2773                      if ($cookie) {
2774                          $this->incoming_cookies[] = $cookie;
2775                          $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
2776                      } else {
2777                          $this->debug('did not find cookie in ' . trim($arr[1]));
2778                      }
2779                  }
2780              } else if (isset($header_name)) {
2781                  // append continuation line to previous header

2782                  $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
2783              }
2784          }
2785        }
2786  
2787          $arr = explode(' ', $header_array[0], 3);
2788          $http_version = $arr[0];
2789          $http_status = intval($arr[1]);
2790          $http_reason = count($arr) > 2 ? $arr[2] : '';
2791  
2792           // see if we need to resend the request with http digest authentication

2793           if (isset($this->incoming_headers['location']) && $http_status == 301) {
2794               $this->debug("Got 301 $http_reason with Location: " . $this->incoming_headers['location']);
2795               $this->setURL($this->incoming_headers['location']);
2796              $this->tryagain = true;
2797              return false;
2798          }
2799  
2800           // see if we need to resend the request with http digest authentication

2801           if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
2802               $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
2803               if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
2804                   $this->debug('Server wants digest authentication');
2805                   // remove "Digest " from our elements

2806                   $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
2807                   
2808                   // parse elements into array

2809                   $digestElements = explode(',', $digestString);
2810                   foreach ($digestElements as $val) {
2811                       $tempElement = explode('=', trim($val), 2);
2812                       $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
2813                   }
2814  
2815                  // should have (at least) qop, realm, nonce

2816                   if (isset($digestRequest['nonce'])) {
2817                       $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
2818                       $this->tryagain = true;
2819                       return false;
2820                   }
2821               }
2822              $this->debug('HTTP authentication failed');
2823              $this->setError('HTTP authentication failed');
2824              return false;
2825           }
2826          
2827          if (
2828              ($http_status >= 300 && $http_status <= 307) ||
2829              ($http_status >= 400 && $http_status <= 417) ||
2830              ($http_status >= 501 && $http_status <= 505)
2831             ) {
2832              $this->setError("Unsupported HTTP response status $http_status $http_reason (nu_soapclient->response has contents of the response)");
2833              return false;
2834          }
2835  
2836          // decode content-encoding

2837          if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
2838              if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
2839                  // if decoding works, use it. else assume data wasn't gzencoded

2840                  if(function_exists('gzinflate')){
2841                      //$timer->setMarker('starting decoding of gzip/deflated content');

2842                      // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)

2843                      // this means there are no Zlib headers, although there should be

2844                      $this->debug('The gzinflate function exists');
2845                      $datalen = strlen($data);
2846                      if ($this->incoming_headers['content-encoding'] == 'deflate') {
2847                          if ($degzdata = @gzinflate($data)) {
2848                              $data = $degzdata;
2849                              $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
2850                              if (strlen($data) < $datalen) {
2851                                  // test for the case that the payload has been compressed twice

2852                                  $this->debug('The inflated payload is smaller than the gzipped one; try again');
2853                                  if ($degzdata = @gzinflate($data)) {
2854                                      $data = $degzdata;
2855                                      $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
2856                                  }
2857                              }
2858                          } else {
2859                              $this->debug('Error using gzinflate to inflate the payload');
2860                              $this->setError('Error using gzinflate to inflate the payload');
2861                          }
2862                      } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
2863                          if ($degzdata = @gzinflate(substr($data, 10))) {    // do our best
2864                              $data = $degzdata;
2865                              $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
2866                              if (strlen($data) < $datalen) {
2867                                  // test for the case that the payload has been compressed twice

2868                                  $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
2869                                  if ($degzdata = @gzinflate(substr($data, 10))) {
2870                                      $data = $degzdata;
2871                                      $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
2872                                  }
2873                              }
2874                          } else {
2875                              $this->debug('Error using gzinflate to un-gzip the payload');
2876                              $this->setError('Error using gzinflate to un-gzip the payload');
2877                          }
2878                      }
2879                      //$timer->setMarker('finished decoding of gzip/deflated content');

2880                      //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";

2881                      // set decoded payload

2882                      $this->incoming_payload = $header_data.$lb.$lb.$data;
2883                  } else {
2884                      $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
2885                      $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
2886                  }
2887              } else {
2888                  $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
2889                  $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
2890              }
2891          } else {
2892              $this->debug('No Content-Encoding header');
2893          }
2894          
2895          if(strlen($data) == 0){
2896              $this->debug('no data after headers!');
2897              $this->setError('no data present after HTTP headers');
2898              return false;
2899          }
2900          
2901          return $data;
2902      }
2903  
2904  	function setContentType($type, $charset = false) {
2905          $this->outgoing_headers['Content-Type'] = $type . ($charset ? '; charset=' . $charset : '');
2906          $this->debug('set Content-Type: ' . $this->outgoing_headers['Content-Type']);
2907      }
2908  
2909  	function usePersistentConnection(){
2910          if (isset($this->outgoing_headers['Accept-Encoding'])) {
2911              return false;
2912          }
2913          $this->protocol_version = '1.1';
2914          $this->persistentConnection = true;
2915          $this->outgoing_headers['Connection'] = 'Keep-Alive';
2916          $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
2917          return true;
2918      }
2919  
2920      /**

2921       * parse an incoming Cookie into it's parts

2922       *

2923       * @param    string $cookie_str content of cookie

2924       * @return    array with data of that cookie

2925       * @access    private

2926       */
2927      /*

2928       * TODO: allow a Set-Cookie string to be parsed into multiple cookies

2929       */
2930  	function parseCookie($cookie_str) {
2931          $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
2932          $data = split(';', $cookie_str);
2933          $value_str = $data[0];
2934  
2935          $cookie_param = 'domain=';
2936          $start = strpos($cookie_str, $cookie_param);
2937          if ($start > 0) {
2938              $domain = substr($cookie_str, $start + strlen($cookie_param));
2939              $domain = substr($domain, 0, strpos($domain, ';'));
2940          } else {
2941              $domain = '';
2942          }
2943  
2944          $cookie_param = 'expires=';
2945          $start = strpos($cookie_str, $cookie_param);
2946          if ($start > 0) {
2947              $expires = substr($cookie_str, $start + strlen($cookie_param));
2948              $expires = substr($expires, 0, strpos($expires, ';'));
2949          } else {
2950              $expires = '';
2951          }
2952  
2953          $cookie_param = 'path=';
2954          $start = strpos($cookie_str, $cookie_param);
2955          if ( $start > 0 ) {
2956              $path = substr($cookie_str, $start + strlen($cookie_param));
2957              $path = substr($path, 0, strpos($path, ';'));
2958          } else {
2959              $path = '/';
2960          }
2961                          
2962          $cookie_param = ';secure;';
2963          if (strpos($cookie_str, $cookie_param) !== FALSE) {
2964              $secure = true;
2965          } else {
2966              $secure = false;
2967          }
2968  
2969          $sep_pos = strpos($value_str, '=');
2970  
2971          if ($sep_pos) {
2972              $name = substr($value_str, 0, $sep_pos);
2973              $value = substr($value_str, $sep_pos + 1);
2974              $cookie= array(    'name' => $name,
2975                              'value' => $value,
2976                              'domain' => $domain,
2977                              'path' => $path,
2978                              'expires' => $expires,
2979                              'secure' => $secure
2980                              );        
2981              return $cookie;
2982          }
2983          return false;
2984      }
2985    
2986      /**

2987       * sort out cookies for the current request

2988       *

2989       * @param    array $cookies array with all cookies

2990       * @param    boolean $secure is the send-content secure or not?

2991       * @return    string for Cookie-HTTP-Header

2992       * @access    private

2993       */
2994  	function getCookiesForRequest($cookies, $secure=false) {
2995          $cookie_str = '';
2996          if ((! is_null($cookies)) && (is_array($cookies))) {
2997              foreach ($cookies as $cookie) {
2998                  if (! is_array($cookie)) {
2999                      continue;
3000                  }
3001                  $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
3002                  if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3003                      if (strtotime($cookie['expires']) <= time()) {
3004                          $this->debug('cookie has expired');
3005                          continue;
3006                      }
3007                  }
3008                  if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3009                      $domain = preg_quote($cookie['domain']);
3010                      if (! preg_match("'.*$domain$'i", $this->host)) {
3011                          $this->debug('cookie has different domain');
3012                          continue;
3013                      }
3014                  }
3015                  if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3016                      $path = preg_quote($cookie['path']);
3017                      if (! preg_match("'^$path.*'i", $this->path)) {
3018                          $this->debug('cookie is for a different path');
3019                          continue;
3020                      }
3021                  }
3022                  if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3023                      $this->debug('cookie is secure, transport is not');
3024                      continue;
3025                  }
3026                  $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3027                  $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3028              }
3029          }
3030          return $cookie_str;
3031    }
3032  }
3033  
3034  ?><?php
3035  
3036  
3037  
3038  /**

3039  *

3040  * soap_server allows the user to create a SOAP server

3041  * that is capable of receiving messages and returning responses

3042  *

3043  * NOTE: WSDL functionality is experimental

3044  *

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

3046  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

3047  * @access   public

3048  */
3049  class soap_server extends nusoap_base {
3050      /**

3051       * HTTP headers of request

3052       * @var array

3053       * @access private

3054       */
3055      var $headers = array();
3056      /**

3057       * HTTP request

3058       * @var string

3059       * @access private

3060       */
3061      var $request = '';
3062      /**

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

3064       * @var string

3065       * @access public

3066       */
3067      var $requestHeaders = '';
3068      /**

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

3070       * @var string

3071       * @access public

3072       */
3073      var $document = '';
3074      /**

3075       * SOAP payload for request (text)

3076       * @var string

3077       * @access public

3078       */
3079      var $requestSOAP = '';
3080      /**

3081       * requested method namespace URI

3082       * @var string

3083       * @access private

3084       */
3085      var $methodURI = '';
3086      /**

3087       * name of method requested

3088       * @var string

3089       * @access private

3090       */
3091      var $methodname = '';
3092      /**

3093       * method parameters from request

3094       * @var array

3095       * @access private

3096       */
3097      var $methodparams = array();
3098      /**

3099       * SOAP Action from request

3100       * @var string

3101       * @access private

3102       */
3103      var $SOAPAction = '';
3104      /**

3105       * character set encoding of incoming (request) messages

3106       * @var string

3107       * @access public

3108       */
3109      var $xml_encoding = '';
3110      /**

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

3112       * @var boolean

3113       * @access public

3114       */
3115      var $decode_utf8 = true;
3116  
3117      /**

3118       * HTTP headers of response

3119       * @var array

3120       * @access public

3121       */
3122      var $outgoing_headers = array();
3123      /**

3124       * HTTP response

3125       * @var string

3126       * @access private

3127       */
3128      var $response = '';
3129      /**

3130       * SOAP headers for response (text)

3131       * @var string

3132       * @access public

3133       */
3134      var $responseHeaders = '';
3135      /**

3136       * SOAP payload for response (text)

3137       * @var string

3138       * @access private

3139       */
3140      var $responseSOAP = '';
3141      /**

3142       * method return value to place in response

3143       * @var mixed

3144       * @access private

3145       */
3146      var $methodreturn = false;
3147      /**

3148       * whether $methodreturn is a string of literal XML

3149       * @var boolean

3150       * @access public

3151       */
3152      var $methodreturnisliteralxml = false;
3153      /**

3154       * SOAP fault for response (or false)

3155       * @var mixed

3156       * @access private

3157       */
3158      var $fault = false;
3159      /**

3160       * text indication of result (for debugging)

3161       * @var string

3162       * @access private

3163       */
3164      var $result = 'successful';
3165  
3166      /**

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

3168       * method or by parsing an external WSDL definition

3169       * @var array

3170       * @access private

3171       */
3172      var $operations = array();
3173      /**

3174       * wsdl instance (if one)

3175       * @var mixed

3176       * @access private

3177       */
3178      var $wsdl = false;
3179      /**

3180       * URL for WSDL (if one)

3181       * @var mixed

3182       * @access private

3183       */
3184      var $externalWSDLURL = false;
3185      /**

3186       * whether to append debug to response as XML comment

3187       * @var boolean

3188       * @access public

3189       */
3190      var $debug_flag = false;
3191  
3192  
3193      /**

3194      * constructor

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

3196      *

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

3198      * @access   public

3199      */
3200  	function soap_server($wsdl=false){
3201          parent::nusoap_base();
3202          // turn on debugging?

3203          global $debug;
3204          global $HTTP_SERVER_VARS;
3205  
3206          if (isset($_SERVER)) {
3207              $this->debug("_SERVER is defined:");
3208              $this->appendDebug($this->varDump($_SERVER));
3209          } elseif (isset($HTTP_SERVER_VARS)) {
3210              $this->debug("HTTP_SERVER_VARS is defined:");
3211              $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3212          } else {
3213              $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3214          }
3215  
3216          if (isset($debug)) {
3217              $this->debug("In soap_server, set debug_flag=$debug based on global flag");
3218              $this->debug_flag = $debug;
3219          } elseif (isset($_SERVER['QUERY_STRING'])) {
3220              $qs = explode('&', $_SERVER['QUERY_STRING']);
3221              foreach ($qs as $v) {
3222                  if (substr($v, 0, 6) == 'debug=') {
3223                      $this->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3224                      $this->debug_flag = substr($v, 6);
3225                  }
3226              }
3227          } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3228              $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3229              foreach ($qs as $v) {
3230                  if (substr($v, 0, 6) == 'debug=') {
3231                      $this->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3232                      $this->debug_flag = substr($v, 6);
3233                  }
3234              }
3235          }
3236  
3237          // wsdl

3238          if($wsdl){
3239              $this->debug("In soap_server, WSDL is specified");
3240              if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3241                  $this->wsdl = $wsdl;
3242                  $this->externalWSDLURL = $this->wsdl->wsdl;
3243                  $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3244              } else {
3245                  $this->debug('Create wsdl from ' . $wsdl);
3246                  $this->wsdl = new wsdl($wsdl);
3247                  $this->externalWSDLURL = $wsdl;
3248              }
3249              $this->appendDebug($this->wsdl->getDebug());
3250              $this->wsdl->clearDebug();
3251              if($err = $this->wsdl->getError()){
3252                  die('WSDL ERROR: '.$err);
3253              }
3254          }
3255      }
3256  
3257      /**

3258      * processes request and returns response

3259      *

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

3261      * @access   public

3262      */
3263  	function service($data){
3264          global $HTTP_SERVER_VARS;
3265  
3266          if (isset($_SERVER['QUERY_STRING'])) {
3267              $qs = $_SERVER['QUERY_STRING'];
3268          } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3269              $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3270          } else {
3271              $qs = '';
3272          }
3273          $this->debug("In service, query string=$qs");
3274  
3275          if (ereg('wsdl', $qs) ){
3276              $this->debug("In service, this is a request for WSDL");
3277              if($this->externalWSDLURL){
3278                if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
3279                  header('Location: '.$this->externalWSDLURL);
3280                } else { // assume file
3281                  header("Content-Type: text/xml\r\n");
3282                  $fp = fopen($this->externalWSDLURL, 'r');
3283                  fpassthru($fp);
3284                }
3285              } elseif ($this->wsdl) {
3286                  header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3287                  print $this->wsdl->serialize($this->debug_flag);
3288                  if ($this->debug_flag) {
3289                      $this->debug('wsdl:');
3290                      $this->appendDebug($this->varDump($this->wsdl));
3291                      print $this->getDebugAsXMLComment();
3292                  }
3293              } else {
3294                  header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3295                  print "This service does not provide WSDL";
3296              }
3297          } elseif ($data == '' && $this->wsdl) {
3298              $this->debug("In service, there is no data, so return Web description");
3299              print $this->wsdl->webDescription();
3300          } else {
3301              $this->debug("In service, invoke the request");
3302              $this->parse_request($data);
3303              if (! $this->fault) {
3304                  $this->invoke_method();
3305              }
3306              if (! $this->fault) {
3307                  $this->serialize_return();
3308              }
3309              $this->send_response();
3310          }
3311      }
3312  
3313      /**

3314      * parses HTTP request headers.

3315      *

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

3317      *

3318      * headers

3319      * request

3320      * xml_encoding

3321      * SOAPAction

3322      *

3323      * @access   private

3324      */
3325  	function parse_http_headers() {
3326          global $HTTP_SERVER_VARS;
3327  
3328          $this->request = '';
3329          $this->SOAPAction = '';
3330          if(function_exists('getallheaders')){
3331              $this->debug("In parse_http_headers, use getallheaders");
3332              $headers = getallheaders();
3333              foreach($headers as $k=>$v){
3334                  $k = strtolower($k);
3335                  $this->headers[$k] = $v;
3336                  $this->request .= "$k: $v\r\n";
3337                  $this->debug("$k: $v");
3338              }
3339              // get SOAPAction header

3340              if(isset($this->headers['soapaction'])){
3341                  $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
3342              }
3343              // get the character encoding of the incoming request

3344              if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
3345                  $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
3346                  if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
3347                      $this->xml_encoding = strtoupper($enc);
3348                  } else {
3349                      $this->xml_encoding = 'US-ASCII';
3350                  }
3351              } else {
3352                  // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

3353                  $this->xml_encoding = 'ISO-8859-1';
3354              }
3355          } elseif(isset($_SERVER) && is_array($_SERVER)){
3356              $this->debug("In parse_http_headers, use _SERVER");
3357              foreach ($_SERVER as $k => $v) {
3358                  if (substr($k, 0, 5) == 'HTTP_') {
3359                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));                                              $k = strtolower(substr($k, 5));
3360                  } else {
3361                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));                                              $k = strtolower($k);
3362                  }
3363                  if ($k == 'soapaction') {
3364                      // get SOAPAction header

3365                      $k = 'SOAPAction';
3366                      $v = str_replace('"', '', $v);
3367                      $v = str_replace('\\', '', $v);
3368                      $this->SOAPAction = $v;
3369                  } else if ($k == 'content-type') {
3370                      // get the character encoding of the incoming request

3371                      if (strpos($v, '=')) {
3372                          $enc = substr(strstr($v, '='), 1);
3373                          $enc = str_replace('"', '', $enc);
3374                          $enc = str_replace('\\', '', $enc);
3375                          if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3376                              $this->xml_encoding = strtoupper($enc);
3377                          } else {
3378                              $this->xml_encoding = 'US-ASCII';
3379                          }
3380                      } else {
3381                          // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

3382                          $this->xml_encoding = 'ISO-8859-1';
3383                      }
3384                  }
3385                  $this->headers[$k] = $v;
3386                  $this->request .= "$k: $v\r\n";
3387                  $this->debug("$k: $v");
3388              }
3389          } elseif (is_array($HTTP_SERVER_VARS)) {
3390              $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3391              foreach ($HTTP_SERVER_VARS as $k => $v) {
3392                  if (substr($k, 0, 5) == 'HTTP_') {
3393                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));                                              $k = strtolower(substr($k, 5));
3394                  } else {
3395                      $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));                                              $k = strtolower($k);
3396                  }
3397                  if ($k == 'soapaction') {
3398                      // get SOAPAction header

3399                      $k = 'SOAPAction';
3400                      $v = str_replace('"', '', $v);
3401                      $v = str_replace('\\', '', $v);
3402                      $this->SOAPAction = $v;
3403                  } else if ($k == 'content-type') {
3404                      // get the character encoding of the incoming request

3405                      if (strpos($v, '=')) {
3406                          $enc = substr(strstr($v, '='), 1);
3407                          $enc = str_replace('"', '', $enc);
3408                          $enc = str_replace('\\', '', $enc);
3409                          if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3410                              $this->xml_encoding = strtoupper($enc);
3411                          } else {
3412                              $this->xml_encoding = 'US-ASCII';
3413                          }
3414                      } else {
3415                          // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

3416                          $this->xml_encoding = 'ISO-8859-1';
3417                      }
3418                  }
3419                  $this->headers[$k] = $v;
3420                  $this->request .= "$k: $v\r\n";
3421                  $this->debug("$k: $v");
3422              }
3423          } else {
3424              $this->debug("In parse_http_headers, HTTP headers not accessible");
3425              $this->setError("HTTP headers not accessible");
3426          }
3427      }
3428  
3429      /**

3430      * parses a request

3431      *

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

3433      *

3434      * headers

3435      * request

3436      * xml_encoding

3437      * SOAPAction

3438      * request

3439      * requestSOAP

3440      * methodURI

3441      * methodname

3442      * methodparams

3443      * requestHeaders

3444      * document

3445      *

3446      * This sets the fault field on error

3447      *

3448      * @param    string $data XML string

3449      * @access   private

3450      */
3451  	function parse_request($data='') {
3452          $this->debug('entering parse_request()');
3453          $this->parse_http_headers();
3454          $this->debug('got character encoding: '.$this->xml_encoding);
3455          // uncompress if necessary

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

3460                  if (function_exists('gzuncompress')) {
3461                      if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3462                          $data = $degzdata;
3463                      } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3464                          $data = $degzdata;
3465                      } else {
3466                          $this->fault('Client', 'Errors occurred when trying to decode the data');
3467                          return;
3468                      }
3469                  } else {
3470                      $this->fault('Client', 'This Server does not support compressed data');
3471                      return;
3472                  }
3473              }
3474          }
3475          $this->request .= "\r\n".$data;
3476          $data = $this->parseRequest($this->headers, $data);
3477          $this->requestSOAP = $data;
3478          $this->debug('leaving parse_request');
3479      }
3480  
3481      /**

3482      * invokes a PHP function for the requested SOAP method

3483      *

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

3485      *

3486      * methodreturn

3487      *

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

3489      * fields to affect the response sent to the client

3490      *

3491      * responseHeaders

3492      * outgoing_headers

3493      *

3494      * This sets the fault field on error

3495      *

3496      * @access   private

3497      */
3498  	function invoke_method() {
3499          $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3500  
3501          if ($this->wsdl) {
3502              if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3503                  $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3504                  $this->appendDebug('opData=' . $this->varDump($this->opData));
3505              } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3506                  // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element

3507                  $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3508                  $this->appendDebug('opData=' . $this->varDump($this->opData));
3509                  $this->methodname = $this->opData['name'];
3510              } else {
3511                  $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3512                  $this->fault('Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3513                  return;
3514              }
3515          } else {
3516              $this->debug('in invoke_method, no WSDL to validate method');
3517          }
3518  
3519          // if a . is present in $this->methodname, we see if there is a class in scope,

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

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

3522          $class = '';
3523          $method = '';
3524          if (strpos($this->methodname, '..') > 0) {
3525              $delim = '..';
3526          } else if (strpos($this->methodname, '.') > 0) {
3527              $delim = '.';
3528          } else {
3529              $delim = '';
3530          }
3531  
3532          if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3533              class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3534              // get the class and method name

3535              $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3536              $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3537              $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3538          }
3539  
3540          // does method exist?

3541          if ($class == '') {
3542              if (!function_exists($this->methodname)) {
3543                  $this->debug("in invoke_method, function '$this->methodname' not found!");
3544                  $this->result = 'fault: method not found';
3545                  $this->fault('Client',"method '$this->methodname' not defined in service");
3546                  return;
3547              }
3548          } else {
3549              $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
3550              if (!in_array($method_to_compare, get_class_methods($class))) {
3551                  $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
3552                  $this->result = 'fault: method not found';
3553                  $this->fault('Client',"method '$this->methodname' not defined in service");
3554                  return;
3555              }
3556          }
3557  
3558          // evaluate message, getting back parameters

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

3560          if(! $this->verify_method($this->methodname,$this->methodparams)){
3561              // debug

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

3565              $this->fault('Client',"Operation '$this->methodname' not defined in service.");
3566              return;
3567          }
3568  
3569          // if there are parameters to pass

3570          $this->debug('in invoke_method, params:');
3571          $this->appendDebug($this->varDump($this->methodparams));
3572          $this->debug("in invoke_method, calling '$this->methodname'");
3573          if (!function_exists('call_user_func_array')) {
3574              if ($class == '') {
3575                  $this->debug('in invoke_method, calling function using eval()');
3576                  $funcCall = "\$this->methodreturn = $this->methodname(";
3577              } else {
3578                  if ($delim == '..') {
3579                      $this->debug('in invoke_method, calling class method using eval()');
3580                      $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
3581                  } else {
3582                      $this->debug('in invoke_method, calling instance method using eval()');
3583                      // generate unique instance name

3584                      $instname = "\$inst_".time();
3585                      $funcCall = $instname." = new ".$class."(); ";
3586                      $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
3587                  }
3588              }
3589              if ($this->methodparams) {
3590                  foreach ($this->methodparams as $param) {
3591                      if (is_array($param)) {
3592                          $this->fault('Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
3593                          return;
3594                      }
3595                      $funcCall .= "\"$param\",";
3596                  }
3597                  $funcCall = substr($funcCall, 0, -1);
3598              }
3599              $funcCall .= ');';
3600              $this->debug('in invoke_method, function call: '.$funcCall);
3601              @eval($funcCall);
3602          } else {
3603              if ($class == '') {
3604                  $this->debug('in invoke_method, calling function using call_user_func_array()');
3605                  $call_arg = "$this->methodname";    // straight assignment changes $this->methodname to lower case after call_user_func_array()

3606              } elseif ($delim == '..') {
3607                  $this->debug('in invoke_method, calling class method using call_user_func_array()');
3608                  $call_arg = array ($class, $method);
3609              } else {
3610                  $this->debug('in invoke_method, calling instance method using call_user_func_array()');
3611                  $instance = new $class ();
3612                  $call_arg = array(&$instance, $method);
3613              }
3614              $this->methodreturn = call_user_func_array($call_arg, $this->methodparams);
3615          }
3616          $this->debug('in invoke_method, methodreturn:');
3617          $this->appendDebug($this->varDump($this->methodreturn));
3618          $this->debug("in invoke_method, called method $this->methodname, received $this->methodreturn of type ".gettype($this->methodreturn));
3619      }
3620  
3621      /**

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

3623      *

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

3625      *

3626      * responseSOAP

3627      *

3628      * This sets the fault field on error

3629      *

3630      * @access   private

3631      */
3632  	function serialize_return() {
3633          $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
3634          // if fault

3635          if (isset($this->methodreturn) && (get_class($this->methodreturn) == 'soap_fault')) {
3636              $this->debug('got a fault object from method');
3637              $this->fault = $this->methodreturn;
3638              return;
3639          } elseif ($this->methodreturnisliteralxml) {
3640              $return_val = $this->methodreturn;
3641          // returned value(s)

3642          } else {
3643              $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
3644              $this->debug('serializing return value');
3645              if($this->wsdl){
3646                  // weak attempt at supporting multiple output params

3647                  if(sizeof($this->opData['output']['parts']) > 1){
3648                      $opParams = $this->methodreturn;
3649                  } else {
3650                      // TODO: is this really necessary?

3651                      $opParams = array($this->methodreturn);
3652                  }
3653                  $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
3654                  $this->appendDebug($this->wsdl->getDebug());
3655                  $this->wsdl->clearDebug();
3656                  if($errstr = $this->wsdl->getError()){
3657                      $this->debug('got wsdl error: '.$errstr);
3658                      $this->fault('Server', 'unable to serialize result');
3659                      return;
3660                  }
3661              } else {
3662                  if (isset($this->methodreturn)) {
3663                      $return_val = $this->serialize_val($this->methodreturn, 'return');
3664                  } else {
3665                      $return_val = '';
3666                      $this->debug('in absence of WSDL, assume void return for backward compatibility');
3667                  }
3668              }
3669          }
3670          $this->debug('return value:');
3671          $this->appendDebug($this->varDump($return_val));
3672  
3673          $this->debug('serializing response');
3674          if ($this->wsdl) {
3675              $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
3676              if ($this->opData['style'] == 'rpc') {
3677                  $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
3678                  if ($this->opData['output']['use'] == 'literal') {
3679                      $payload = '<'.$this->methodname.'Response xmlns="'.$this->methodURI.'">'.$return_val.'</'.$this->methodname."Response>";
3680                  } else {
3681                      $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
3682                  }
3683              } else {
3684                  $this->debug('style is not rpc for serialization: assume document');
3685                  $payload = $return_val;
3686              }
3687          } else {
3688              $this->debug('do not have WSDL for serialization: assume rpc/encoded');
3689              $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
3690          }
3691          $this->result = 'successful';
3692          if($this->wsdl){
3693              //if($this->debug_flag){

3694                  $this->appendDebug($this->wsdl->getDebug());
3695              //    }

3696              if (isset($opData['output']['encodingStyle'])) {
3697                  $encodingStyle = $opData['output']['encodingStyle'];
3698              } else {
3699                  $encodingStyle = '';
3700              }
3701              // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.

3702              $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$encodingStyle);
3703          } else {
3704              $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
3705          }
3706          $this->debug("Leaving serialize_return");
3707      }
3708  
3709      /**

3710      * sends an HTTP response

3711      *

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

3713      *

3714      * outgoing_headers

3715      * response

3716      *

3717      * @access   private

3718      */
3719  	function send_response() {
3720          $this->debug('Enter send_response');
3721          if ($this->fault) {
3722              $payload = $this->fault->serialize();
3723              $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
3724              $this->outgoing_headers[] = "Status: 500 Internal Server Error";
3725          } else {
3726              $payload = $this->responseSOAP;
3727              // Some combinations of PHP+Web server allow the Status

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

3729              // just do nothing.

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

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

3732          }
3733          // add debug data if in debug mode

3734          if(isset($this->debug_flag) && $this->debug_flag){
3735              $payload .= $this->getDebugAsXMLComment();
3736          }
3737          $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
3738          ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
3739          $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
3740          // Let the Web server decide about this

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

3742          $payload = $this->getHTTPBody($payload);
3743          $type = $this->getHTTPContentType();
3744          $charset = $this->getHTTPContentTypeCharset();
3745          $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
3746          //begin code to compress payload - by John

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

3748          // this data.

3749          if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {    
3750              if (strstr($this->headers['accept-encoding'], 'gzip')) {
3751                  if (function_exists('gzencode')) {
3752                      if (isset($this->debug_flag) && $this->debug_flag) {
3753                          $payload .= "<!-- Content being gzipped -->";
3754                      }
3755                      $this->outgoing_headers[] = "Content-Encoding: gzip";
3756                      $payload = gzencode($payload);
3757                  } else {
3758                      if (isset($this->debug_flag) && $this->debug_flag) {
3759                          $payload .= "<!-- Content will not be gzipped: no gzencode -->";
3760                      }
3761                  }
3762              } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
3763                  // Note: MSIE requires gzdeflate output (no Zlib header and checksum),

3764                  // instead of gzcompress output,

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

3766                  if (function_exists('gzdeflate')) {
3767                      if (isset($this->debug_flag) && $this->debug_flag) {
3768                          $payload .= "<!-- Content being deflated -->";
3769                      }
3770                      $this->outgoing_headers[] = "Content-Encoding: deflate";
3771                      $payload = gzdeflate($payload);
3772                  } else {
3773                      if (isset($this->debug_flag) && $this->debug_flag) {
3774                          $payload .= "<!-- Content will not be deflated: no gzcompress -->";
3775                      }
3776                  }
3777              }
3778          }
3779          //end code

3780          $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
3781          reset($this->outgoing_headers);
3782          foreach($this->outgoing_headers as $hdr){
3783              header($hdr, false);
3784          }
3785          print $payload;
3786          $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
3787      }
3788  
3789      /**

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

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

3792      *

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

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

3795      * @return    boolean    Whether the operation was found

3796      * @access   private

3797      */
3798  	function verify_method($operation,$request){
3799          if(isset($this->wsdl) && is_object($this->wsdl)){
3800              if($this->wsdl->getOperationData($operation)){
3801                  return true;
3802              }
3803          } elseif(isset($this->operations[$operation])){
3804              return true;
3805          }
3806          return false;
3807      }
3808  
3809      /**

3810      * processes SOAP message received from client

3811      *

3812      * @param    array    $headers    The HTTP headers

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

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

3815      * @access   private

3816      */
3817      function parseRequest($headers, $data) {
3818          $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
3819          if (!strstr($headers['content-type'], 'text/xml')) {
3820              $this->setError('Request not of type text/xml');
3821              return false;
3822          }
3823          if (strpos($headers['content-type'], '=')) {
3824              $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
3825              $this->debug('Got response encoding: ' . $enc);
3826              if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
3827                  $this->xml_encoding = strtoupper($enc);
3828              } else {
3829                  $this->xml_encoding = 'US-ASCII';
3830              }
3831          } else {
3832              // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

3833              $this->xml_encoding = 'ISO-8859-1';
3834          }
3835          $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
3836          // parse response, get soap parser obj

3837          $parser = new soap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
3838          // parser debug

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

3841          if($err = $parser->getError()){
3842              $this->result = 'fault: error in msg parsing: '.$err;
3843              $this->fault('Client',"error in msg parsing:\n".$err);
3844          // else successfully parsed request into soapval object

3845          } else {
3846              // get/set methodname

3847              $this->methodURI = $parser->root_struct_namespace;
3848              $this->methodname = $parser->root_struct_name;
3849              $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
3850              $this->debug('calling parser->get_response()');
3851              $this->methodparams = $parser->get_response();
3852              // get SOAP headers

3853              $this->requestHeaders = $parser->getHeaders();
3854              // add document for doclit support

3855              $this->document = $parser->document;
3856          }
3857       }
3858  
3859      /**

3860      * gets the HTTP body for the current response.

3861      *

3862      * @param string $soapmsg The SOAP payload

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

3864      * @access private

3865      */
3866  	function getHTTPBody($soapmsg) {
3867          return $soapmsg;
3868      }
3869      
3870      /**

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

3872      *

3873      * Note: getHTTPBody must be called before this.

3874      *

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

3876      * @access private

3877      */
3878  	function getHTTPContentType() {
3879          return 'text/xml';
3880      }
3881      
3882      /**

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

3884      * returns false for non-text content types.

3885      *

3886      * Note: getHTTPBody must be called before this.

3887      *

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

3889      * @access private

3890      */
3891  	function getHTTPContentTypeCharset() {
3892          return $this->soap_defencoding;
3893      }
3894  
3895      /**

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

3897      *

3898      * @param    string $methodname

3899      * @param    string $in array of input values

3900      * @param    string $out array of output values

3901      * @access   public

3902      * @deprecated

3903      */
3904  	function add_to_map($methodname,$in,$out){
3905              $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
3906      }
3907  
3908      /**

3909      * register a service function with the server

3910      *

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

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

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

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

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

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

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

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

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

3920      * @access   public

3921      */
3922  	function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
3923          global $HTTP_SERVER_VARS;
3924  
3925          if($this->externalWSDLURL){
3926              die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
3927          }
3928          if (! $name) {
3929              die('You must specify a name when you register an operation');
3930          }
3931          if (!is_array($in)) {
3932              die('You must provide an array for operation inputs');
3933          }
3934          if (!is_array($out)) {
3935              die('You must provide an array for operation outputs');
3936          }
3937          if(false == $namespace) {
3938          }
3939          if(false == $soapaction) {
3940              if (isset($_SERVER)) {
3941                  $SERVER_NAME = $_SERVER['SERVER_NAME'];
3942                  $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
3943              } elseif (isset($HTTP_SERVER_VARS)) {
3944                  $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
3945                  $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
3946              } else {
3947                  $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
3948              }
3949              $soapaction = "http://$SERVER_NAME$SCRIPT_NAME/$name";
3950          }
3951          if(false == $style) {
3952              $style = "rpc";
3953          }
3954          if(false == $use) {
3955              $use = "encoded";
3956          }
3957          if ($use == 'encoded' && $encodingStyle = '') {
3958              $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
3959          }
3960  
3961          $this->operations[$name] = array(
3962          'name' => $name,
3963          'in' => $in,
3964          'out' => $out,
3965          'namespace' => $namespace,
3966          'soapaction' => $soapaction,
3967          'style' => $style);
3968          if($this->wsdl){
3969              $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
3970          }
3971          return true;
3972      }
3973  
3974      /**

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

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

3977      *

3978      * @param    string $faultcode

3979      * @param    string $faultstring

3980      * @param    string $faultactor

3981      * @param    string $faultdetail

3982      * @access   public

3983      */
3984  	function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
3985          if ($faultdetail == '' && $this->debug_flag) {
3986              $faultdetail = $this->getDebug();
3987          }
3988          $this->fault = new soap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
3989          $this->fault->soap_defencoding = $this->soap_defencoding;
3990      }
3991  
3992      /**

3993      * Sets up wsdl object.

3994      * Acts as a flag to enable internal WSDL generation

3995      *

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

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

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

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

4000      * @param string $transport optional SOAP transport

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

4002      */
4003      function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4004      {
4005          global $HTTP_SERVER_VARS;
4006  
4007          if (isset($_SERVER)) {
4008              $SERVER_NAME = $_SERVER['SERVER_NAME'];
4009              $SERVER_PORT = $_SERVER['SERVER_PORT'];
4010              $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4011              $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : '';
4012          } elseif (isset($HTTP_SERVER_VARS)) {
4013              $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4014              $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4015              $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4016              $HTTPS = $HTTP_SERVER_VARS['HTTPS'];
4017          } else {
4018              $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4019          }
4020          if ($SERVER_PORT == 80) {
4021              $SERVER_PORT = '';
4022          } else {
4023              $SERVER_PORT = ':' . $SERVER_PORT;
4024          }
4025          if(false == $namespace) {
4026              $namespace = "http://$SERVER_NAME/soap/$serviceName";
4027          }
4028          
4029          if(false == $endpoint) {
4030              if ($HTTPS == '1' || $HTTPS == 'on') {
4031                  $SCHEME = 'https';
4032              } else {
4033                  $SCHEME = 'http';
4034              }
4035              $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4036          }
4037          
4038          if(false == $schemaTargetNamespace) {
4039              $schemaTargetNamespace = $namespace;
4040          }
4041          
4042          $this->wsdl = new wsdl;
4043          $this->wsdl->serviceName = $serviceName;
4044          $this->wsdl->endpoint = $endpoint;
4045          $this->wsdl->namespaces['tns'] = $namespace;
4046          $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4047          $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4048          if ($schemaTargetNamespace != $namespace) {
4049              $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4050          }
4051          $this->wsdl->schemas[$schemaTargetNamespace][0] = new xmlschema('', '', $this->wsdl->namespaces);
4052          $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4053          $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4054          $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4055          $this->wsdl->bindings[$serviceName.'Binding'] = array(
4056              'name'=>$serviceName.'Binding',
4057              'style'=>$style,
4058              'transport'=>$transport,
4059              'portType'=>$serviceName.'PortType');
4060          $this->wsdl->ports[$serviceName.'Port'] = array(
4061              'binding'=>$serviceName.'Binding',
4062              'location'=>$endpoint,
4063              'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4064      }
4065  }
4066  
4067  
4068  
4069  ?><?php
4070  
4071  
4072  
4073  /**

4074  * parses a WSDL file, allows access to it's data, other utility methods

4075  * 

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

4077  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

4078  * @access public 

4079  */
4080  class wsdl extends nusoap_base {
4081      // URL or filename of the root of this WSDL

4082      var $wsdl; 
4083      // define internal arrays of bindings, ports, operations, messages, etc.

4084      var $schemas = array();
4085      var $currentSchema;
4086      var $message = array();
4087      var $complexTypes = array();
4088      var $messages = array();
4089      var $currentMessage;
4090      var $currentOperation;
4091      var $portTypes = array();
4092      var $currentPortType;
4093      var $bindings = array();
4094      var $currentBinding;
4095      var $ports = array();
4096      var $currentPort;
4097      var $opData = array();
4098      var $status = '';
4099      var $documentation = false;
4100      var $endpoint = ''; 
4101      // array of wsdl docs to import

4102      var $import = array(); 
4103      // parser vars

4104      var $parser;
4105      var $position = 0;
4106      var $depth = 0;
4107      var $depth_array = array();
4108      // for getting wsdl

4109      var $proxyhost = '';
4110      var $proxyport = '';
4111      var $proxyusername = '';
4112      var $proxypassword = '';
4113      var $timeout = 0;
4114      var $response_timeout = 30;
4115  
4116      /**

4117       * constructor

4118       * 

4119       * @param string $wsdl WSDL document URL

4120       * @param string $proxyhost

4121       * @param string $proxyport

4122       * @param string $proxyusername

4123       * @param string $proxypassword

4124       * @param integer $timeout set the connection timeout

4125       * @param integer $response_timeout set the response timeout

4126       * @access public 

4127       */
4128      function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30){
4129          parent::nusoap_base();
4130          $this->wsdl = $wsdl;
4131          $this->proxyhost = $proxyhost;
4132          $this->proxyport = $proxyport;
4133          $this->proxyusername = $proxyusername;
4134          $this->proxypassword = $proxypassword;
4135          $this->timeout = $timeout;
4136          $this->response_timeout = $response_timeout;
4137          
4138          // parse wsdl file

4139          if ($wsdl != "") {
4140              $this->debug('initial wsdl URL: ' . $wsdl);
4141              $this->parseWSDL($wsdl);
4142          }
4143          // imports

4144          // TODO: handle imports more properly, grabbing them in-line and nesting them

4145              $imported_urls = array();
4146              $imported = 1;
4147              while ($imported > 0) {
4148                  $imported = 0;
4149                  // Schema imports

4150                  foreach ($this->schemas as $ns => $list) {
4151                      foreach ($list as $xs) {
4152                          $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!

4153                          foreach ($xs->imports as $ns2 => $list2) {
4154                              for ($ii = 0; $ii < count($list2); $ii++) {
4155                                  if (! $list2[$ii]['loaded']) {
4156                                      $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4157                                      $url = $list2[$ii]['location'];
4158                                      if ($url != '') {
4159                                          $urlparts = parse_url($url);
4160                                          if (!isset($urlparts['host'])) {
4161                                              $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
4162                                                      substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4163                                          }
4164                                          if (! in_array($url, $imported_urls)) {
4165                                              $this->parseWSDL($url);
4166                                              $imported++;
4167                                              $imported_urls[] = $url;
4168                                          }
4169                                      } else {
4170                                          $this->debug("Unexpected scenario: empty URL for unloaded import");
4171                                      }
4172                                  }
4173                              }
4174                          } 
4175                      }
4176                  }
4177                  // WSDL imports

4178                  $wsdlparts = parse_url($this->wsdl);    // this is bogusly simple!

4179                  foreach ($this->import as $ns => $list) {
4180                      for ($ii = 0; $ii < count($list); $ii++) {
4181                          if (! $list[$ii]['loaded']) {
4182                              $this->import[$ns][$ii]['loaded'] = true;
4183                              $url = $list[$ii]['location'];
4184                              if ($url != '') {
4185                                  $urlparts = parse_url($url);
4186                                  if (!isset($urlparts['host'])) {
4187                                      $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4188                                              substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4189                                  }
4190                                  if (! in_array($url, $imported_urls)) {
4191                                      $this->parseWSDL($url);
4192                                      $imported++;
4193                                      $imported_urls[] = $url;
4194                                  }
4195                              } else {
4196                                  $this->debug("Unexpected scenario: empty URL for unloaded import");
4197                              }
4198                          }
4199                      }
4200                  } 
4201              }
4202          // add new data to operation data

4203          foreach($this->bindings as $binding => $bindingData) {
4204              if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4205                  foreach($bindingData['operations'] as $operation => $data) {
4206                      $this->debug('post-parse data gathering for ' . $operation);
4207                      $this->bindings[$binding]['operations'][$operation]['input'] = 
4208                          isset($this->bindings[$binding]['operations'][$operation]['input']) ? 
4209                          array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4210                          $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4211                      $this->bindings[$binding]['operations'][$operation]['output'] = 
4212                          isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4213                          array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4214                          $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4215                      if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
4216                          $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4217                      }
4218                      if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
4219                             $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4220                      }
4221                      if (isset($bindingData['style'])) {
4222                          $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4223                      }
4224                      $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4225                      $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4226                      $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4227                  } 
4228              } 
4229          }
4230      }
4231  
4232      /**

4233       * parses the wsdl document

4234       * 

4235       * @param string $wsdl path or URL

4236       * @access private 

4237       */
4238      function parseWSDL($wsdl = '')
4239      {
4240          if ($wsdl == '') {
4241              $this->debug('no wsdl passed to parseWSDL()!!');
4242              $this->setError('no wsdl passed to parseWSDL()!!');
4243              return false;
4244          }
4245          
4246          // parse $wsdl for url format

4247          $wsdl_props = parse_url($wsdl);
4248  
4249          if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4250              $this->debug('getting WSDL http(s) URL ' . $wsdl);
4251              // get wsdl

4252              $tr = new soap_transport_http($wsdl);
4253              $tr->request_method = 'GET';
4254              $tr->useSOAPAction = false;
4255              if($this->proxyhost && $this->proxyport){
4256                  $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
4257              }
4258              $tr->setEncoding('gzip, deflate');
4259              $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4260              //$this->debug("WSDL request\n" . $tr->outgoing_payload);

4261              //$this->debug("WSDL response\n" . $tr->incoming_payload);

4262              $this->appendDebug($tr->getDebug());
4263              // catch errors

4264              if($err = $tr->getError() ){
4265                  $errstr = 'HTTP ERROR: '.$err;
4266                  $this->debug($errstr);
4267                  $this->setError($errstr);
4268                  unset($tr);
4269                  return false;
4270              }
4271              unset($tr);
4272              $this->debug("got WSDL URL");
4273          } else {
4274              // $wsdl is not http(s), so treat it as a file URL or plain file path

4275              if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4276                  $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4277              } else {
4278                  $path = $wsdl;
4279              }
4280              $this->debug('getting WSDL file ' . $path);
4281              if ($fp = @fopen($path, 'r')) {
4282                  $wsdl_string = '';
4283                  while ($data = fread($fp, 32768)) {
4284                      $wsdl_string .= $data;
4285                  } 
4286                  fclose($fp);
4287              } else {
4288                  $errstr = "Bad path to WSDL file $path";
4289                  $this->debug($errstr);
4290                  $this->setError($errstr);
4291                  return false;
4292              } 
4293          }
4294          $this->debug('Parse WSDL');
4295          // end new code added

4296          // Create an XML parser.

4297          $this->parser = xml_parser_create(); 
4298          // Set the options for parsing the XML data.

4299          // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);

4300          xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); 
4301          // Set the object for the parser.

4302          xml_set_object($this->parser, $this); 
4303          // Set the element handlers for the parser.

4304          xml_set_element_handler($this->parser, 'start_element', 'end_element');
4305          xml_set_character_data_handler($this->parser, 'character_data');
4306          // Parse the XML file.

4307          if (!xml_parse($this->parser, $wsdl_string, true)) {
4308              // Display an error message.

4309              $errstr = sprintf(
4310                  'XML error parsing WSDL from %s on line %d: %s',
4311                  $wsdl,
4312                  xml_get_current_line_number($this->parser),
4313                  xml_error_string(xml_get_error_code($this->parser))
4314                  );
4315              $this->debug($errstr);
4316              $this->debug("XML payload:\n" . $wsdl_string);
4317              $this->setError($errstr);
4318              return false;
4319          } 
4320          // free the parser

4321          xml_parser_free($this->parser);
4322          $this->debug('Parsing WSDL done');
4323          // catch wsdl parse errors

4324          if($this->getError()){
4325              return false;
4326          }
4327          return true;
4328      } 
4329  
4330      /**

4331       * start-element handler

4332       * 

4333       * @param string $parser XML parser object

4334       * @param string $name element name

4335       * @param string $attrs associative array of attributes

4336       * @access private 

4337       */
4338      function start_element($parser, $name, $attrs)
4339      {
4340          if ($this->status == 'schema') {
4341              $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4342              $this->appendDebug($this->currentSchema->getDebug());
4343              $this->currentSchema->clearDebug();
4344          } elseif (ereg('schema$', $name)) {
4345              $this->debug('Parsing WSDL schema');
4346              // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");

4347              $this->status = 'schema';
4348              $this->currentSchema = new xmlschema('', '', $this->namespaces);
4349              $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4350              $this->appendDebug($this->currentSchema->getDebug());
4351              $this->currentSchema->clearDebug();
4352          } else {
4353              // position in the total number of elements, starting from 0

4354              $pos = $this->position++;
4355              $depth = $this->depth++; 
4356              // set self as current value for this depth

4357              $this->depth_array[$depth] = $pos;
4358              $this->message[$pos] = array('cdata' => ''); 
4359              // process attributes

4360              if (count($attrs) > 0) {
4361                  // register namespace declarations

4362                  foreach($attrs as $k => $v) {
4363                      if (ereg("^xmlns", $k)) {
4364                          if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4365                              $this->namespaces[$ns_prefix] = $v;
4366                          } else {
4367                              $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4368                          } 
4369                          if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4370                              $this->XMLSchemaVersion = $v;
4371                              $this->namespaces['xsi'] = $v . '-instance';
4372                          } 
4373                      }
4374                  }
4375                  // expand each attribute prefix to its namespace

4376                  foreach($attrs as $k => $v) {
4377                      $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4378                      if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4379                          $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4380                      } 
4381                      $eAttrs[$k] = $v;
4382                  } 
4383                  $attrs = $eAttrs;
4384              } else {
4385                  $attrs = array();
4386              } 
4387              // get element prefix, namespace and name

4388              if (ereg(':', $name)) {
4389                  // get ns prefix

4390                  $prefix = substr($name, 0, strpos($name, ':')); 
4391                  // get ns

4392                  $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : ''; 
4393                  // get unqualified name

4394                  $name = substr(strstr($name, ':'), 1);
4395              } 
4396              // process attributes, expanding any prefixes to namespaces

4397              // find status, register data

4398              switch ($this->status) {
4399                  case 'message':
4400                      if ($name == 'part') {
4401                          if (isset($attrs['type'])) {
4402                              $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
4403                              $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4404                          } 
4405                          if (isset($attrs['element'])) {
4406                              $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
4407                              $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'];
4408                          } 
4409                      } 
4410                      break;
4411                  case 'portType':
4412                      switch ($name) {
4413                          case 'operation':
4414                              $this->currentPortOperation = $attrs['name'];
4415                              $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4416                              if (isset($attrs['parameterOrder'])) {
4417                                  $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4418                              } 
4419                              break;
4420                          case 'documentation':
4421                              $this->documentation = true;
4422                              break; 
4423                          // merge input/output data

4424                          default:
4425                              $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4426                              $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4427                              break;
4428                      } 
4429                      break;
4430                  case 'binding':
4431                      switch ($name) {
4432                          case 'binding': 
4433                              // get ns prefix

4434                              if (isset($attrs['style'])) {
4435                              $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4436                              } 
4437                              $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4438                              break;
4439                          case 'header':
4440                              $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4441                              break;
4442                          case 'operation':
4443                              if (isset($attrs['soapAction'])) {
4444                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4445                              } 
4446                              if (isset($attrs['style'])) {
4447                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4448                              } 
4449                              if (isset($attrs['name'])) {
4450                                  $this->currentOperation = $attrs['name'];
4451                                  $this->debug("current binding operation: $this->currentOperation");
4452                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4453                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4454                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4455                              } 
4456                              break;
4457                          case 'input':
4458                              $this->opStatus = 'input';
4459                              break;
4460                          case 'output':
4461                              $this->opStatus = 'output';
4462                              break;
4463                          case 'body':
4464                              if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
4465                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
4466                              } else {
4467                                  $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
4468                              } 
4469                              break;
4470                      } 
4471                      break;
4472                  case 'service':
4473                      switch ($name) {
4474                          case 'port':
4475                              $this->currentPort = $attrs['name'];
4476                              $this->debug('current port: ' . $this->currentPort);
4477                              $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
4478                      
4479                              break;
4480                          case 'address':
4481                              $this->ports[$this->currentPort]['location'] = $attrs['location'];
4482                              $this->ports[$this->currentPort]['bindingType'] = $namespace;
4483                              $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
4484                              $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
4485                              break;
4486                      } 
4487                      break;
4488              } 
4489          // set status

4490          switch ($name) {
4491              case 'import':
4492                  if (isset($attrs['location'])) {
4493                      $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
4494                      $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
4495                  } else {
4496                      $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
4497                      if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
4498                          $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
4499                      }
4500                      $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
4501                  }
4502                  break;
4503              //wait for schema

4504              //case 'types':

4505              //    $this->status = 'schema';

4506              //    break;

4507              case 'message':
4508                  $this->status = 'message';
4509                  $this->messages[$attrs['name']] = array();
4510                  $this->currentMessage = $attrs['name'];
4511                  break;
4512              case 'portType':
4513                  $this->status = 'portType';
4514                  $this->portTypes[$attrs['name']] = array();
4515                  $this->currentPortType = $attrs['name'];
4516                  break;
4517              case "binding":
4518                  if (isset($attrs['name'])) {
4519                  // get binding name

4520                      if (strpos($attrs['name'], ':')) {
4521                          $this->currentBinding = $this->getLocalPart($attrs['name']);
4522                      } else {
4523                          $this->currentBinding = $attrs['name'];
4524                      } 
4525                      $this->status = 'binding';
4526                      $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
4527                      $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
4528                  } 
4529                  break;
4530              case 'service':
4531                  $this->serviceName = $attrs['name'];
4532                  $this->status = 'service';
4533                  $this->debug('current service: ' . $this->serviceName);
4534                  break;
4535              case 'definitions':
4536                  foreach ($attrs as $name => $value) {
4537                      $this->wsdl_info[$name] = $value;
4538                  } 
4539                  break;
4540              } 
4541          } 
4542      } 
4543  
4544      /**

4545      * end-element handler

4546      * 

4547      * @param string $parser XML parser object

4548      * @param string $name element name

4549      * @access private 

4550      */
4551  	function end_element($parser, $name){ 
4552          // unset schema status

4553          if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
4554              $this->status = "";
4555              $this->appendDebug($this->currentSchema->getDebug());
4556              $this->currentSchema->clearDebug();
4557              $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
4558              $this->debug('Parsing WSDL schema done');
4559          } 
4560          if ($this->status == 'schema') {
4561              $this->currentSchema->schemaEndElement($parser, $name);
4562          } else {
4563              // bring depth down a notch

4564              $this->depth--;
4565          } 
4566          // end documentation

4567          if ($this->documentation) {
4568              //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.

4569              //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;

4570              $this->documentation = false;
4571          } 
4572      } 
4573  
4574      /**

4575       * element content handler

4576       * 

4577       * @param string $parser XML parser object

4578       * @param string $data element content

4579       * @access private 

4580       */
4581  	function character_data($parser, $data)
4582      {
4583          $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
4584          if (isset($this->message[$pos]['cdata'])) {
4585              $this->message[$pos]['cdata'] .= $data;
4586          } 
4587          if ($this->documentation) {
4588              $this->documentation .= $data;
4589          } 
4590      } 
4591      
4592  	function getBindingData($binding)
4593      {
4594          if (is_array($this->bindings[$binding])) {
4595              return $this->bindings[$binding];
4596          } 
4597      }
4598      
4599      /**

4600       * returns an assoc array of operation names => operation data

4601       * 

4602       * @param string $bindingType eg: soap, smtp, dime (only soap is currently supported)

4603       * @return array 

4604       * @access public 

4605       */
4606  	function getOperations($bindingType = 'soap')
4607      {
4608          $ops = array();
4609          if ($bindingType == 'soap') {
4610              $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
4611          }
4612          // loop thru ports

4613          foreach($this->ports as $port => $portData) {
4614              // binding type of port matches parameter

4615              if ($portData['bindingType'] == $bindingType) {
4616                  //$this->debug("getOperations for port $port");

4617                  //$this->debug("port data: " . $this->varDump($portData));

4618                  //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));

4619                  // merge bindings

4620                  if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
4621                      $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
4622                  }
4623              }
4624          } 
4625          return $ops;
4626      } 
4627      
4628      /**

4629       * returns an associative array of data necessary for calling an operation

4630       * 

4631       * @param string $operation , name of operation

4632       * @param string $bindingType , type of binding eg: soap

4633       * @return array 

4634       * @access public 

4635       */
4636  	function getOperationData($operation, $bindingType = 'soap')
4637      {
4638          if ($bindingType == 'soap') {
4639              $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
4640          }
4641          // loop thru ports

4642          foreach($this->ports as $port => $portData) {
4643              // binding type of port matches parameter

4644              if ($portData['bindingType'] == $bindingType) {
4645                  // get binding

4646                  //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {

4647                  foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
4648                      // note that we could/should also check the namespace here

4649                      if ($operation == $bOperation) {
4650                          $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
4651                          return $opData;
4652                      } 
4653                  } 
4654              }
4655          } 
4656      }
4657      
4658      /**

4659       * returns an associative array of data necessary for calling an operation

4660       * 

4661       * @param string $soapAction soapAction for operation

4662       * @param string $bindingType type of binding eg: soap

4663       * @return array 

4664       * @access public 

4665       */
4666  	function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
4667          if ($bindingType == 'soap') {
4668              $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
4669          }
4670          // loop thru ports

4671          foreach($this->ports as $port => $portData) {
4672              // binding type of port matches parameter

4673              if ($portData['bindingType'] == $bindingType) {
4674                  // loop through operations for the binding

4675                  foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
4676                      if ($opData['soapAction'] == $soapAction) {
4677                          return $opData;
4678                      } 
4679                  } 
4680              }
4681          } 
4682      }
4683      
4684      /**

4685      * returns an array of information about a given type

4686      * returns false if no type exists by the given name

4687      *

4688      *     typeDef = array(

4689      *     'elements' => array(), // refs to elements array

4690      *    'restrictionBase' => '',

4691      *    'phpType' => '',

4692      *    'order' => '(sequence|all)',

4693      *    'attrs' => array() // refs to attributes array

4694      *    )

4695      *

4696      * @param $type string the type

4697      * @param $ns string namespace (not prefix) of the type

4698      * @return mixed

4699      * @access public

4700      * @see xmlschema

4701      */
4702  	function getTypeDef($type, $ns) {
4703          $this->debug("in getTypeDef: type=$type, ns=$ns");
4704          if ((! $ns) && isset($this->namespaces['tns'])) {
4705              $ns = $this->namespaces['tns'];
4706              $this->debug("in getTypeDef: type namespace forced to $ns");
4707          }
4708          if (isset($this->schemas[$ns])) {
4709              $this->debug("in getTypeDef: have schema for namespace $ns");
4710              for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
4711                  $xs = &$this->schemas[$ns][$i];
4712                  $t = $xs->getTypeDef($type);
4713                  $this->appendDebug($xs->getDebug());
4714                  $xs->clearDebug();
4715                  if ($t) {
4716                      if (!isset($t['phpType'])) {
4717                          // get info for type to tack onto the element

4718                          $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
4719                          $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
4720                          $etype = $this->getTypeDef($uqType, $ns);
4721                          if ($etype) {
4722                              $this->debug("found type for [element] $type:");
4723                              $this->debug($this->varDump($etype));
4724                              if (isset($etype['phpType'])) {
4725                                  $t['phpType'] = $etype['phpType'];
4726                              }
4727                              if (isset($etype['elements'])) {
4728                                  $t['elements'] = $etype['elements'];
4729                              }
4730                              if (isset($etype['attrs'])) {
4731                                  $t['attrs'] = $etype['attrs'];
4732                              }
4733                          }
4734                      }
4735                      return $t;
4736                  }
4737              }
4738          } else {
4739              $this->debug("in getTypeDef: do not have schema for namespace $ns");
4740          }
4741          return false;
4742      }
4743  
4744      /**

4745      * prints html description of services

4746      *

4747      * @access private

4748      */
4749      function webDescription(){
4750          global $HTTP_SERVER_VARS;
4751  
4752          if (isset($_SERVER)) {
4753              $PHP_SELF = $_SERVER['PHP_SELF'];
4754          } elseif (isset($HTTP_SERVER_VARS)) {
4755              $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
4756          } else {
4757              $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4758          }
4759          
4760          $delimiter = '?';
4761          if (isset($_GET['module']))
4762          {
4763            $PHP_SELF = $PHP_SELF . "?module=". $_GET['module'];
4764            $delimiter = '&amp;';
4765          }
4766  
4767          $b = '
4768          <html><head><title>NuSOAP: '.$this->serviceName.'</title>
4769          <style type="text/css">
4770              body    { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
4771              p       { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
4772              pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
4773              ul      { margin-top: 10px; margin-left: 20px; }
4774              li      { list-style-type: none; margin-top: 10px; color: #000000; }
4775              .content{
4776              margin-left: 0px; padding-bottom: 2em; }
4777              .nav {
4778              padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
4779              margin-top: 10px; margin-left: 0px; color: #000000;
4780              background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
4781              .title {
4782              font-family: arial; font-size: 26px; color: #ffffff;
4783              background-color: #999999; width: 105%; margin-left: 0px;
4784              padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
4785              .hidden {
4786              position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
4787              font-family: arial; overflow: hidden; width: 600;
4788              padding: 20px; font-size: 10px; background-color: #999999;
4789              layer-background-color:#FFFFFF; }
4790              a,a:active  { color: charcoal; font-weight: bold; }
4791              a:visited   { color: #666666; font-weight: bold; }
4792              a:hover     { color: cc3300; font-weight: bold; }
4793          </style>
4794          <script language="JavaScript" type="text/javascript">
4795          <!--
4796          // POP-UP CAPTIONS...

4797  		function lib_bwcheck(){ //Browsercheck (needed)
4798              this.ver=navigator.appVersion
4799              this.agent=navigator.userAgent
4800              this.dom=document.getElementById?1:0
4801              this.opera5=this.agent.indexOf("Opera 5")>-1
4802              this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
4803              this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
4804              this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
4805              this.ie=this.ie4||this.ie5||this.ie6
4806              this.mac=this.agent.indexOf("Mac")>-1
4807              this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
4808              this.ns4=(document.layers && !this.dom)?1:0;
4809              this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
4810              return this
4811          }
4812          var bw = new lib_bwcheck()
4813          //Makes crossbrowser object.

4814  		function makeObj(obj){
4815              this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
4816              if(!this.evnt) return false
4817              this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
4818              this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
4819              this.writeIt=b_writeIt;
4820              return this
4821          }
4822          // A unit of measure that will be added when setting the position of a layer.

4823          //var px = bw.ns4||window.opera?"":"px";

4824  		function b_writeIt(text){
4825              if (bw.ns4){this.wref.write(text);this.wref.close()}
4826              else this.wref.innerHTML = text
4827          }
4828          //Shows the messages

4829          var oDesc;
4830  		function popup(divid){
4831              if(oDesc = new makeObj(divid)){
4832              oDesc.css.visibility = "visible"
4833              }
4834          }
4835  		function popout(){ // Hides message
4836              if(oDesc) oDesc.css.visibility = "hidden"
4837          }
4838          //-->

4839          </script>
4840          </head>
4841          <body>
4842          <div class=content>
4843              <br><br>
4844              <div class=title>'.$this->serviceName.'</div>
4845              <div class=nav>
4846                  <p>View the <a href="'.$PHP_SELF . $delimiter . 'wsdl">WSDL</a> for the service.
4847                  Click on an operation name to view it&apos;s details.</p>
4848                  <ul>';
4849                  foreach($this->getOperations() as $op => $data){
4850                      $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
4851                      // create hidden div

4852                      $b .= "<div id='$op' class='hidden'>
4853                      <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
4854                      foreach($data as $donnie => $marie){ // loop through opdata
4855                          if($donnie == 'input' || $donnie == 'output'){ // show input/output data
4856                              $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
4857                              foreach($marie as $captain => $tenille){ // loop through data
4858                                  if($captain == 'parts'){ // loop thru parts
4859                                      $b .= "&nbsp;&nbsp;$captain:<br>";
4860                                      //if(is_array($tenille)){

4861                                          foreach($tenille as $joanie => $chachi){
4862                                              $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
4863                                          }
4864                                      //}

4865                                  } else {
4866                                      $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
4867                                  }
4868                              }
4869                          } else {
4870                              $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
4871                          }
4872                      }
4873                      $b .= '</div>';
4874                  }
4875                  $b .= '
4876                  <ul>
4877              </div>
4878          </div></body></html>';
4879          return $b;
4880      }
4881  
4882      /**

4883      * serialize the parsed wsdl

4884      *

4885      * @param mixed $debug whether to put debug=1 in endpoint URL

4886      * @return string serialization of WSDL

4887      * @access public 

4888      */
4889  	function serialize($debug = 0)
4890      {
4891          $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
4892          $xml .= "\n<definitions";
4893          foreach($this->namespaces as $k => $v) {
4894              $xml .= " xmlns:$k=\"$v\"";
4895          } 
4896          // 10.9.02 - add poulter fix for wsdl and tns declarations

4897          if (isset($this->namespaces['wsdl'])) {
4898              $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
4899          } 
4900          if (isset($this->namespaces['tns'])) {
4901              $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
4902          } 
4903          $xml .= '>'; 
4904          // imports

4905          if (sizeof($this->import) > 0) {
4906              foreach($this->import as $ns => $list) {
4907                  foreach ($list as $ii) {
4908                      if ($ii['location'] != '') {
4909                          $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
4910                      } else {
4911                          $xml .= '<import namespace="' . $ns . '" />';
4912                      }
4913                  }
4914              } 
4915          } 
4916          // types

4917          if (count($this->schemas)>=1) {
4918              $xml .= "\n<types>";
4919              foreach ($this->schemas as $ns => $list) {
4920                  foreach ($list as $xs) {
4921                      $xml .= $xs->serializeSchema();
4922                  }
4923              }
4924              $xml .= '</types>';
4925          } 
4926          // messages

4927          if (count($this->messages) >= 1) {
4928              foreach($this->messages as $msgName => $msgParts) {
4929                  $xml .= "\n<message name=\"" . $msgName . '">';
4930                  if(is_array($msgParts)){
4931                      foreach($msgParts as $partName => $partType) {
4932                          // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';

4933                          if (strpos($partType, ':')) {
4934                              $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
4935                          } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
4936                              // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';

4937                              $typePrefix = 'xsd';
4938                          } else {
4939                              foreach($this->typemap as $ns => $types) {
4940                                  if (isset($types[$partType])) {
4941                                      $typePrefix = $this->getPrefixFromNamespace($ns);
4942                                  } 
4943                              } 
4944                              if (!isset($typePrefix)) {
4945                                  die("$partType has no namespace!");
4946                              } 
4947                          }
4948                          $ns = $this->getNamespaceFromPrefix($typePrefix);
4949                          $typeDef = $this->getTypeDef($this->getLocalPart($partType), $ns);
4950                          if ($typeDef['typeClass'] == 'element') {
4951                              $elementortype = 'element';
4952                          } else {
4953                              $elementortype = 'type';
4954                          }
4955                          $xml .= '<part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />';
4956                      }
4957                  }
4958                  $xml .= '</message>';
4959              } 
4960          } 
4961          // bindings & porttypes

4962          if (count($this->bindings) >= 1) {
4963              $binding_xml = '';
4964              $portType_xml = '';
4965              foreach($this->bindings as $bindingName => $attrs) {
4966                  $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
4967                  $binding_xml .= '<soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
4968                  $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
4969                  foreach($attrs['operations'] as $opName => $opParts) {
4970                      $binding_xml .= '<operation name="' . $opName . '">';
4971                      $binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
4972                      if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
4973                          $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
4974                      } else {
4975                          $enc_style = '';
4976                      }
4977                      $binding_xml .= '<input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
4978                      if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
4979                          $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
4980                      } else {
4981                          $enc_style = '';
4982                      }
4983                      $binding_xml .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
4984                      $binding_xml .= '</operation>';
4985                      $portType_xml .= '<operation name="' . $opParts['name'] . '"';
4986                      if (isset($opParts['parameterOrder'])) {
4987                          $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
4988                      } 
4989                      $portType_xml .= '>';
4990                      if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
4991                          $portType_xml .= '<documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
4992                      }
4993                      $portType_xml .= '<input message="tns:' . $opParts['input']['message'] . '"/>';
4994                      $portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>';
4995                      $portType_xml .= '</operation>';
4996                  } 
4997                  $portType_xml .= '</portType>';
4998                  $binding_xml .= '</binding>';
4999              } 
5000              $xml .= $portType_xml . $binding_xml;
5001          } 
5002          // services

5003          $xml .= "\n<service name=\"" . $this->serviceName . '">';
5004          if (count($this->ports) >= 1) {
5005              foreach($this->ports as $pName => $attrs) {
5006                  $xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5007                  $xml .= '<soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
5008                  $xml .= '</port>';
5009              } 
5010          } 
5011          $xml .= '</service>';
5012          return $xml . "\n</definitions>";
5013      } 
5014      
5015      /**

5016       * serialize PHP values according to a WSDL message definition

5017       *

5018       * TODO

5019       * - multi-ref serialization

5020       * - validate PHP values against type definitions, return errors if invalid

5021       * 

5022       * @param string $operation operation name

5023       * @param string $direction (input|output)

5024       * @param mixed $parameters parameter value(s)

5025       * @return mixed parameters serialized as XML or false on error (e.g. operation not found)

5026       * @access public

5027       */
5028  	function serializeRPCParameters($operation, $direction, $parameters)
5029      {
5030          $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 
5031          $this->appendDebug('parameters=' . $this->varDump($parameters));
5032          
5033          if ($direction != 'input' && $direction != 'output') {
5034              $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5035              $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5036              return false;
5037          } 
5038          if (!$opData = $this->getOperationData($operation)) {
5039              $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5040              $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5041              return false;
5042          }
5043          $this->debug('opData:');
5044          $this->appendDebug($this->varDump($opData));
5045  
5046          // Get encoding style for output and set to current

5047          $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5048          if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5049              $encodingStyle = $opData['output']['encodingStyle'];
5050              $enc_style = $encodingStyle;
5051          }
5052  
5053          // set input params

5054          $xml = '';
5055          if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5056              
5057              $use = $opData[$direction]['use'];
5058              $this->debug('have ' . count($opData[$direction]['parts']) . ' part(s) to serialize');
5059              if (is_array($parameters)) {
5060                  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5061                  $this->debug('have ' . count($parameters) . ' parameter(s) provided as ' . $parametersArrayType . ' to serialize');
5062                  foreach($opData[$direction]['parts'] as $name => $type) {
5063                      $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5064                      // Track encoding style

5065                      if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5066                          $encodingStyle = $opData[$direction]['encodingStyle'];            
5067                          $enc_style = $encodingStyle;
5068                      } else {
5069                          $enc_style = false;
5070                      }
5071                      // NOTE: add error handling here

5072                      // if serializeType returns false, then catch global error and fault

5073                      if ($parametersArrayType == 'arraySimple') {
5074                          $p = array_shift($parameters);
5075                          $this->debug('calling serializeType w/indexed param');
5076                          $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5077                      } elseif (isset($parameters[$name])) {
5078                          $this->debug('calling serializeType w/named param');
5079                          $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5080                      } else {
5081                          // TODO: only send nillable

5082                          $this->debug('calling serializeType w/null param');
5083                          $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5084                      }
5085                  }
5086              } else {
5087                  $this->debug('no parameters passed.');
5088              }
5089          }
5090          $this->debug("serializeRPCParameters returning: $xml");
5091          return $xml;
5092      } 
5093      
5094      /**

5095       * serialize a PHP value according to a WSDL message definition

5096       * 

5097       * TODO

5098       * - multi-ref serialization

5099       * - validate PHP values against type definitions, return errors if invalid

5100       * 

5101       * @param string $ type name

5102       * @param mixed $ param value

5103       * @return mixed new param or false if initial value didn't validate

5104       * @access public

5105       * @deprecated

5106       */
5107  	function serializeParameters($operation, $direction, $parameters)
5108      {
5109          $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion"); 
5110          $this->appendDebug('parameters=' . $this->varDump($parameters));
5111          
5112          if ($direction != 'input' && $direction != 'output') {
5113              $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5114              $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5115              return false;
5116          } 
5117          if (!$opData = $this->getOperationData($operation)) {
5118              $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5119              $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5120              return false;
5121          }
5122          $this->debug('opData:');
5123          $this->appendDebug($this->varDump($opData));
5124          
5125          // Get encoding style for output and set to current

5126          $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5127          if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5128              $encodingStyle = $opData['output']['encodingStyle'];
5129              $enc_style = $encodingStyle;
5130          }
5131          
5132          // set input params

5133          $xml = '';
5134          if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5135              
5136              $use = $opData[$direction]['use'];
5137              $this->debug("use=$use");
5138              $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5139              if (is_array($parameters)) {
5140                  $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5141                  $this->debug('have ' . $parametersArrayType . ' parameters');
5142                  foreach($opData[$direction]['parts'] as $name => $type) {
5143                      $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5144                      // Track encoding style

5145                      if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5146                          $encodingStyle = $opData[$direction]['encodingStyle'];            
5147                          $enc_style = $encodingStyle;
5148                      } else {
5149                          $enc_style = false;
5150                      }
5151                      // NOTE: add error handling here

5152                      // if serializeType returns false, then catch global error and fault

5153                      if ($parametersArrayType == 'arraySimple') {
5154                          $p = array_shift($parameters);
5155                          $this->debug('calling serializeType w/indexed param');
5156                          $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5157                      } elseif (isset($parameters[$name])) {
5158                          $this->debug('calling serializeType w/named param');
5159                          $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5160                      } else {
5161                          // TODO: only send nillable

5162                          $this->debug('calling serializeType w/null param');
5163                          $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5164                      }
5165                  }
5166              } else {
5167                  $this->debug('no parameters passed.');
5168              }
5169          }
5170          $this->debug("serializeParameters returning: $xml");
5171          return $xml;
5172      } 
5173      
5174      /**

5175       * serializes a PHP value according a given type definition

5176       * 

5177       * @param string $name name of value (part or element)

5178       * @param string $type XML schema type of value (type or element)

5179       * @param mixed $value a native PHP value (parameter value)

5180       * @param string $use use for part (encoded|literal)

5181       * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)

5182       * @param boolean $unqualified a kludge for what should be XML namespace form handling

5183       * @return string value serialized as an XML string

5184       * @access private

5185       */
5186  	function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5187      {
5188          $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5189          $this->appendDebug("value=" . $this->varDump($value));
5190          if($use == 'encoded' && $encodingStyle) {
5191              $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5192          }
5193  
5194          // if a soapval has been supplied, let its type override the WSDL

5195          if (is_object($value) && get_class($value) == 'soapval') {
5196              if ($value->type_ns) {
5197                  $type = $value->type_ns . ':' . $value->type;
5198                  $forceType = true;
5199                  $this->debug("in serializeType: soapval overrides type to $type");
5200              } elseif ($value->type) {
5201                  $type = $value->type;
5202                  $forceType = true;
5203                  $this->debug("in serializeType: soapval overrides type to $type");
5204              } else {
5205                  $forceType = false;
5206                  $this->debug("in serializeType: soapval does not override type");
5207              }
5208              $attrs = $value->attributes;
5209              $value = $value->value;
5210              $this->debug("in serializeType: soapval overrides value to $value");
5211              if ($attrs) {
5212                  if (!is_array($value)) {
5213                      $value['!'] = $value;
5214                  }
5215                  foreach ($attrs as $n => $v) {
5216                      $value['!' . $n] = $v;
5217                  }
5218                  $this->debug("in serializeType: soapval provides attributes");
5219              }
5220          } else {
5221              $forceType = false;
5222          }
5223  
5224          $xml = '';
5225          if (strpos($type, ':')) {
5226              $uqType = substr($type, strrpos($type, ':') + 1);
5227              $ns = substr($type, 0, strrpos($type, ':'));
5228              $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5229              if ($this->getNamespaceFromPrefix($ns)) {
5230                  $ns = $this->getNamespaceFromPrefix($ns);
5231                  $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5232              }
5233  
5234              if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
5235                  $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5236                  if ($unqualified  && $use == 'literal') {
5237                      $elementNS = " xmlns=\"\"";
5238                  } else {
5239                      $elementNS = '';
5240                  }
5241                  if (is_null($value)) {
5242                      if ($use == 'literal') {
5243                          // TODO: depends on minOccurs

5244                          $xml = "<$name$elementNS/>";
5245                      } else {
5246                          // TODO: depends on nillable, which should be checked before calling this method

5247                          $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5248                      }
5249                      $this->debug("in serializeType: returning: $xml");
5250                      return $xml;
5251                  }
5252                  if ($uqType == 'boolean') {
5253                      if ((is_string($value) && $value == 'false') || (! $value)) {
5254                          $value = 'false';
5255                      } else {
5256                          $value = 'true';
5257                      }
5258                  } 
5259                  if ($uqType == 'string' && gettype($value) == 'string') {
5260                      $value = $this->expandEntities($value);
5261                  }
5262                  if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5263                      $value = sprintf("%.0lf", $value);
5264                  }
5265                  // it's a scalar

5266                  // TODO: what about null/nil values?

5267                  // check type isn't a custom type extending xmlschema namespace

5268                  if (!$this->getTypeDef($uqType, $ns)) {
5269                      if ($use == 'literal') {
5270                          if ($forceType) {
5271                              $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5272                          } else {
5273                              $xml = "<$name$elementNS>$value</$name>";
5274                          }
5275                      } else {
5276                          $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5277                      }
5278                      $this->debug("in serializeType: returning: $xml");
5279                      return $xml;
5280                  }
5281                  $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5282              } else if ($ns == 'http://xml.apache.org/xml-soap') {
5283                  $this->debug('in serializeType: appears to be Apache SOAP type');
5284                  if ($uqType == 'Map') {
5285                      $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5286                      if (! $tt_prefix) {
5287                          $this->debug('in serializeType: Add namespace for Apache SOAP type');
5288                          $tt_prefix = 'ns' . rand(1000, 9999);
5289                          $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5290                          // force this to be added to usedNamespaces

5291                          $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5292                      }
5293                      $contents = '';
5294                      foreach($value as $k => $v) {
5295                          $this->debug("serializing map element: key $k, value $v");
5296                          $contents .= '<item>';
5297                          $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
5298                          $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
5299                          $contents .= '</item>';
5300                      }
5301                      if ($use == 'literal') {
5302                          if ($forceType) {
5303                              $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
5304                          } else {
5305                              $xml = "<$name>$contents</$name>";
5306                          }
5307                      } else {
5308                          $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
5309                      }
5310                      $this->debug("in serializeType: returning: $xml");
5311                      return $xml;
5312                  }
5313                  $this->debug('in serializeType: Apache SOAP type, but only support Map');
5314              }
5315          } else {
5316              // TODO: should the type be compared to types in XSD, and the namespace

5317              // set to XSD if the type matches?

5318              $this->debug("in serializeType: No namespace for type $type");
5319              $ns = '';
5320              $uqType = $type;
5321          }
5322          if(!$typeDef = $this->getTypeDef($uqType, $ns)){
5323              $this->setError("$type ($uqType) is not a supported type.");
5324              $this->debug("in serializeType: $type ($uqType) is not a supported type.");
5325              return false;
5326          } else {
5327              $this->debug("in serializeType: found typeDef");
5328              $this->appendDebug('typeDef=' . $this->varDump($typeDef));
5329          }
5330          $phpType = $typeDef['phpType'];
5331          $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); 
5332          // if php type == struct, map value to the <all> element names

5333          if ($phpType == 'struct') {
5334              if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
5335                  $elementName = $uqType;
5336                  if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5337                      $elementNS = " xmlns=\"$ns\"";
5338                  } else {
5339                      $elementNS = " xmlns=\"\"";
5340                  }
5341              } else {
5342                  $elementName = $name;
5343                  if ($unqualified) {
5344                      $elementNS = " xmlns=\"\"";
5345                  } else {
5346                      $elementNS = '';
5347                  }
5348              }
5349              if (is_null($value)) {
5350                  if ($use == 'literal') {
5351                      // TODO: depends on minOccurs

5352                      $xml = "<$elementName$elementNS/>";
5353                  } else {
5354                      $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5355                  }
5356                  $this->debug("in serializeType: returning: $xml");
5357                  return $xml;
5358              }
5359              if (is_object($value)) {
5360                  $value = get_object_vars($value);
5361              }
5362              if (is_array($value)) {
5363                  $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
5364                  if ($use == 'literal') {
5365                      if ($forceType) {
5366                          $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
5367                      } else {
5368                          $xml = "<$elementName$elementNS$elementAttrs>";
5369                      }
5370                  } else {
5371                      $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
5372                  }
5373      
5374                  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
5375                  $xml .= "</$elementName>";
5376              } else {
5377                  $this->debug("in serializeType: phpType is struct, but value is not an array");
5378                  $this->setError("phpType is struct, but value is not an array: see debug output for details");
5379                  $xml = '';
5380              }
5381          } elseif ($phpType == 'array') {
5382              if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5383                  $elementNS = " xmlns=\"$ns\"";
5384              } else {
5385                  if ($unqualified) {
5386                      $elementNS = " xmlns=\"\"";
5387                  } else {
5388                      $elementNS = '';
5389                  }
5390              }
5391              if (is_null($value)) {
5392                  if ($use == 'literal') {
5393                      // TODO: depends on minOccurs

5394                      $xml = "<$name$elementNS/>";
5395                  } else {
5396                      $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
5397                          $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
5398                          ":Array\" " .
5399                          $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
5400                          ':arrayType="' .
5401                          $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
5402                          ':' .
5403                          $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
5404                  }
5405                  $this->debug("in serializeType: returning: $xml");
5406                  return $xml;
5407              }
5408              if (isset($typeDef['multidimensional'])) {
5409                  $nv = array();
5410                  foreach($value as $v) {
5411                      $cols = ',' . sizeof($v);
5412                      $nv = array_merge($nv, $v);
5413                  } 
5414                  $value = $nv;
5415              } else {
5416                  $cols = '';
5417              } 
5418              if (is_array($value) && sizeof($value) >= 1) {
5419                  $rows = sizeof($value);
5420                  $contents = '';
5421                  foreach($value as $k => $v) {
5422                      $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
5423                      //if (strpos($typeDef['arrayType'], ':') ) {

5424                      if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
5425                          $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
5426                      } else {
5427                          $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
5428                      } 
5429                  }
5430              } else {
5431                  $rows = 0;
5432                  $contents = null;
5433              }
5434              // TODO: for now, an empty value will be serialized as a zero element

5435              // array.  Revisit this when coding the handling of null/nil values.

5436              if ($use == 'literal') {
5437                  $xml = "<$name$elementNS>"
5438                      .$contents
5439                      ."</$name>";
5440              } else {
5441                  $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
5442                      $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
5443                      .':arrayType="'
5444                      .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
5445                      .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
5446                      .$contents
5447                      ."</$name>";
5448              }
5449          } elseif ($phpType == 'scalar') {
5450              if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5451                  $elementNS = " xmlns=\"$ns\"";
5452              } else {
5453                  if ($unqualified) {
5454                      $elementNS = " xmlns=\"\"";
5455                  } else {
5456                      $elementNS = '';
5457                  }
5458              }
5459              if ($use == 'literal') {
5460                  if ($forceType) {
5461                      $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5462                  } else {
5463                      $xml = "<$name$elementNS>$value</$name>";
5464                  }
5465              } else {
5466                  $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5467              }
5468          }
5469          $this->debug("in serializeType: returning: $xml");
5470          return $xml;
5471      }
5472      
5473      /**

5474       * serializes the attributes for a complexType

5475       *

5476       * @param array $typeDef our internal representation of an XML schema type (or element)

5477       * @param mixed $value a native PHP value (parameter value)

5478       * @param string $ns the namespace of the type

5479       * @param string $uqType the local part of the type

5480       * @return string value serialized as an XML string

5481       * @access private

5482       */
5483  	function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
5484          $xml = '';
5485          if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
5486              $this->debug("serialize attributes for XML Schema type $ns:$uqType");
5487              if (is_array($value)) {
5488                  $xvalue = $value;
5489              } elseif (is_object($value)) {
5490                  $xvalue = get_object_vars($value);
5491              } else {
5492                  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
5493                  $xvalue = array();
5494              }
5495              foreach ($typeDef['attrs'] as $aName => $attrs) {
5496                  if (isset($xvalue['!' . $aName])) {
5497                      $xname = '!' . $aName;
5498                      $this->debug("value provided for attribute $aName with key $xname");
5499                  } elseif (isset($xvalue[$aName])) {
5500                      $xname = $aName;
5501                      $this->debug("value provided for attribute $aName with key $xname");
5502                  } elseif (isset($attrs['default'])) {
5503                      $xname = '!' . $aName;
5504                      $xvalue[$xname] = $attrs['default'];
5505                      $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
5506                  } else {
5507                      $xname = '';
5508                      $this->debug("no value provided for attribute $aName");
5509                  }
5510                  if ($xname) {
5511                      $xml .=  " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
5512                  }
5513              } 
5514          } else {
5515              $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
5516          }
5517          if (isset($typeDef['extensionBase'])) {
5518              $ns = $this->getPrefix($typeDef['extensionBase']);
5519              $uqType = $this->getLocalPart($typeDef['extensionBase']);
5520              if ($this->getNamespaceFromPrefix($ns)) {
5521                  $ns = $this->getNamespaceFromPrefix($ns);
5522              }
5523              if ($typeDef = $this->getTypeDef($uqType, $ns)) {
5524                  $this->debug("serialize attributes for extension base $ns:$uqType");
5525                  $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
5526              } else {
5527                  $this->debug("extension base $ns:$uqType is not a supported type");
5528              }
5529          }
5530          return $xml;
5531      }
5532  
5533      /**

5534       * serializes the elements for a complexType

5535       *

5536       * @param array $typeDef our internal representation of an XML schema type (or element)

5537       * @param mixed $value a native PHP value (parameter value)

5538       * @param string $ns the namespace of the type

5539       * @param string $uqType the local part of the type

5540       * @param string $use use for part (encoded|literal)

5541       * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)

5542       * @return string value serialized as an XML string

5543       * @access private

5544       */
5545  	function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
5546          $xml = '';
5547          if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5548              $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
5549              if (is_array($value)) {
5550                  $xvalue = $value;
5551              } elseif (is_object($value)) {
5552                  $xvalue = get_object_vars($value);
5553              } else {
5554                  $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
5555                  $xvalue = array();
5556              }
5557              // toggle whether all elements are present - ideally should validate against schema

5558              if (count($typeDef['elements']) != count($xvalue)){
5559                  $optionals = true;
5560              }
5561              foreach ($typeDef['elements'] as $eName => $attrs) {
5562                  if (!isset($xvalue[$eName])) {
5563                      if (isset($attrs['default'])) {
5564                          $xvalue[$eName] = $attrs['default'];
5565                          $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
5566                      }
5567                  }
5568                  // if user took advantage of a minOccurs=0, then only serialize named parameters

5569                  if (isset($optionals)
5570                      && (!isset($xvalue[$eName])) 
5571                      && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
5572                      ){
5573                      if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
5574                          $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
5575                      }
5576                      // do nothing

5577                      $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
5578                  } else {
5579                      // get value

5580                      if (isset($xvalue[$eName])) {
5581                          $v = $xvalue[$eName];
5582                      } else {
5583                          $v = null;
5584                      }
5585                      if (isset($attrs['form'])) {
5586                          $unqualified = ($attrs['form'] == 'unqualified');
5587                      } else {
5588                          $unqualified = false;
5589                      }
5590                      if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
5591                          $vv = $v;
5592                          foreach ($vv as $k => $v) {
5593                              if (isset($attrs['type']) || isset($attrs['ref'])) {
5594                                  // serialize schema-defined type

5595                                  $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
5596                              } else {
5597                                  // serialize generic type (can this ever really happen?)

5598                                  $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
5599                                  $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
5600                              }
5601                          }
5602                      } else {
5603                          if (isset($attrs['type']) || isset($attrs['ref'])) {
5604                              // serialize schema-defined type

5605                              $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
5606                          } else {
5607                              // serialize generic type (can this ever really happen?)

5608                              $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
5609                              $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
5610                          }
5611                      }
5612                  }
5613              } 
5614          } else {
5615              $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
5616          }
5617          if (isset($typeDef['extensionBase'])) {
5618              $ns = $this->getPrefix($typeDef['extensionBase']);
5619              $uqType = $this->getLocalPart($typeDef['extensionBase']);
5620              if ($this->getNamespaceFromPrefix($ns)) {
5621                  $ns = $this->getNamespaceFromPrefix($ns);
5622              }
5623              if ($typeDef = $this->getTypeDef($uqType, $ns)) {
5624                  $this->debug("serialize elements for extension base $ns:$uqType");
5625                  $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
5626              } else {
5627                  $this->debug("extension base $ns:$uqType is not a supported type");
5628              }
5629          }
5630          return $xml;
5631      }
5632  
5633      /**

5634      * adds an XML Schema complex type to the WSDL types

5635      *

5636      * @param string    name

5637      * @param string typeClass (complexType|simpleType|attribute)

5638      * @param string phpType: currently supported are array and struct (php assoc array)

5639      * @param string compositor (all|sequence|choice)

5640      * @param string restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)

5641      * @param array elements = array ( name => array(name=>'',type=>'') )

5642      * @param array attrs =     array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))

5643      * @param string arrayType: namespace:name (xsd:string)

5644      * @see xmlschema

5645      * @access public

5646      */
5647  	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
5648          if (count($elements) > 0) {
5649              foreach($elements as $n => $e){
5650                  // expand each element

5651                  foreach ($e as $k => $v) {
5652                      $k = strpos($k,':') ? $this->expandQname($k) : $k;
5653                      $v = strpos($v,':') ? $this->expandQname($v) : $v;
5654                      $ee[$k] = $v;
5655                  }
5656                  $eElements[$n] = $ee;
5657              }
5658              $elements = $eElements;
5659          }
5660          
5661          if (count($attrs) > 0) {
5662              foreach($attrs as $n => $a){
5663                  // expand each attribute

5664                      $aa = array();
5665                  foreach ($a as $k => $v) {
5666                      $k = strpos($k,':') ? $this->expandQname($k) : $k;
5667                      $v = strpos($v,':') ? $this->expandQname($v) : $v;
5668                      $aa[$k] = $v;
5669                  }
5670                  $eAttrs[$n] = $aa;
5671              }
5672              $attrs = $eAttrs;
5673          }
5674  
5675          $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
5676          $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
5677  
5678          $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
5679          $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
5680      }
5681  
5682      /**

5683      * adds an XML Schema simple type to the WSDL types

5684      *

5685      * @param string $name

5686      * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)

5687      * @param string $typeClass (should always be simpleType)

5688      * @param string $phpType (should always be scalar)

5689      * @param array $enumeration array of values

5690      * @see xmlschema

5691      * @access public

5692      */
5693  	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
5694          $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
5695  
5696          $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
5697          $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
5698      }
5699  
5700      /**

5701      * adds an element to the WSDL types

5702      *

5703      * @param array $attrs attributes that must include name and type

5704      * @see xmlschema

5705      * @access public

5706      */
5707  	function addElement($attrs) {
5708          $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
5709          $this->schemas[$typens][0]->addElement($attrs);
5710      }
5711  
5712      /**

5713      * register an operation with the server

5714      * 

5715      * @param string $name operation (method) name

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

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

5718      * @param string $namespace optional The namespace for the operation

5719      * @param string $soapaction optional The soapaction for the operation

5720      * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically

5721      * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)

5722      * @param string $documentation optional The description to include in the WSDL

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

5724      * @access public 

5725      */
5726  	function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
5727          if ($use == 'encoded' && $encodingStyle == '') {
5728              $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5729          }
5730  
5731          if ($style == 'document') {
5732              $elements = array();
5733              foreach ($in as $n => $t) {
5734                  $elements[$n] = array('name' => $n, 'type' => $t);
5735              }
5736              $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
5737              $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
5738              $in = array('parameters' => 'tns:' . $name);
5739  
5740              $elements = array();
5741              foreach ($out as $n => $t) {
5742                  $elements[$n] = array('name' => $n, 'type' => $t);
5743              }
5744              $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
5745              $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType'));
5746              $out = array('parameters' => 'tns:' . $name . 'Response');
5747          }
5748  
5749          // get binding

5750          $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
5751          array(
5752          'name' => $name,
5753          'binding' => $this->serviceName . 'Binding',
5754          'endpoint' => $this->endpoint,
5755          'soapAction' => $soapaction,
5756          'style' => $style,
5757          'input' => array(
5758              'use' => $use,
5759              'namespace' => $namespace,
5760              'encodingStyle' => $encodingStyle,
5761              'message' => $name . 'Request',
5762              'parts' => $in),
5763          'output' => array(
5764              'use' => $use,
5765              'namespace' => $namespace,
5766              'encodingStyle' => $encodingStyle,
5767              'message' => $name . 'Response',
5768              'parts' => $out),
5769          'namespace' => $namespace,
5770          'transport' => 'http://schemas.xmlsoap.org/soap/http',
5771          'documentation' => $documentation); 
5772          // add portTypes

5773          // add messages

5774          if($in)
5775          {
5776              foreach($in as $pName => $pType)
5777              {
5778                  if(strpos($pType,':')) {
5779                      $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
5780                  }
5781                  $this->messages[$name.'Request'][$pName] = $pType;
5782              }
5783          } else {
5784              $this->messages[$name.'Request']= '0';
5785          }
5786          if($out)
5787          {
5788              foreach($out as $pName => $pType)
5789              {
5790                  if(strpos($pType,':')) {
5791                      $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
5792                  }
5793                  $this->messages[$name.'Response'][$pName] = $pType;
5794              }
5795          } else {
5796              $this->messages[$name.'Response']= '0';
5797          }
5798          return true;
5799      } 
5800  }
5801  ?><?php
5802  
5803  
5804  
5805  /**

5806  *

5807  * soap_parser class parses SOAP XML messages into native PHP values

5808  *

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

5810  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

5811  * @access   public

5812  */
5813  class soap_parser extends nusoap_base {
5814  
5815      var $xml = '';
5816      var $xml_encoding = '';
5817      var $method = '';
5818      var $root_struct = '';
5819      var $root_struct_name = '';
5820      var $root_struct_namespace = '';
5821      var $root_header = '';
5822      var $document = '';            // incoming SOAP body (text)

5823      // determines where in the message we are (envelope,header,body,method)

5824      var $status = '';
5825      var $position = 0;
5826      var $depth = 0;
5827      var $default_namespace = '';
5828      var $namespaces = array();
5829      var $message = array();
5830      var $parent = '';
5831      var $fault = false;
5832      var $fault_code = '';
5833      var $fault_str = '';
5834      var $fault_detail = '';
5835      var $depth_array = array();
5836      var $debug_flag = true;
5837      var $soapresponse = NULL;
5838      var $responseHeaders = '';    // incoming SOAP headers (text)

5839      var $body_position = 0;
5840      // for multiref parsing:

5841      // array of id => pos

5842      var $ids = array();
5843      // array of id => hrefs => pos

5844      var $multirefs = array();
5845      // toggle for auto-decoding element content

5846      var $decode_utf8 = true;
5847  
5848      /**

5849      * constructor that actually does the parsing

5850      *

5851      * @param    string $xml SOAP message

5852      * @param    string $encoding character encoding scheme of message

5853      * @param    string $method method for which XML is parsed (unused?)

5854      * @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1

5855      * @access   public

5856      */
5857  	function soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
5858          parent::nusoap_base();
5859          $this->xml = $xml;
5860          $this->xml_encoding = $encoding;
5861          $this->method = $method;
5862          $this->decode_utf8 = $decode_utf8;
5863  
5864          // Check whether content has been read.

5865          if(!empty($xml)){
5866              // Check XML encoding

5867              $pos_xml = strpos($xml, '<?xml');
5868              if ($pos_xml !== FALSE) {
5869                  $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
5870                  if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
5871                      $xml_encoding = $res[1];
5872                      if (strtoupper($xml_encoding) != $encoding) {
5873                          $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
5874                          $this->debug($err);
5875                          if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
5876                              $this->setError($err);
5877                              return;
5878                          }
5879                          // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed

5880                      } else {
5881                          $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
5882                      }
5883                  } else {
5884                      $this->debug('No encoding specified in XML declaration');
5885                  }
5886              } else {
5887                  $this->debug('No XML declaration');
5888              }
5889              $this->debug('Entering soap_parser(), length='.strlen($xml).', encoding='.$encoding);
5890              // Create an XML parser - why not xml_parser_create_ns?

5891              $this->parser = xml_parser_create($this->xml_encoding);
5892              // Set the options for parsing the XML data.

5893              //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);

5894              xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
5895              xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
5896              // Set the object for the parser.

5897              xml_set_object($this->parser, $this);
5898              // Set the element handlers for the parser.

5899              xml_set_element_handler($this->parser, 'start_element','end_element');
5900              xml_set_character_data_handler($this->parser,'character_data');
5901  
5902              // Parse the XML file.

5903              if(!xml_parse($this->parser,$xml,true)){
5904                  // Display an error message.

5905                  $err = sprintf('XML error parsing SOAP payload on line %d: %s',
5906                  xml_get_current_line_number($this->parser),
5907                  xml_error_string(xml_get_error_code($this->parser)));
5908                  $this->debug($err);
5909                  $this->debug("XML payload:\n" . $xml);
5910                  $this->setError($err);
5911              } else {
5912                  $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
5913                  // get final value

5914                  $this->soapresponse = $this->message[$this->root_struct]['result'];
5915                  // get header value: no, because this is documented as XML string

5916  //                if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){

5917  //                    $this->responseHeaders = $this->message[$this->root_header]['result'];

5918  //                }

5919                  // resolve hrefs/ids

5920                  if(sizeof($this->multirefs) > 0){
5921                      foreach($this->multirefs as $id => $hrefs){
5922                          $this->debug('resolving multirefs for id: '.$id);
5923                          $idVal = $this->buildVal($this->ids[$id]);
5924                          if (is_array($idVal) && isset($idVal['!id'])) {
5925                              unset($idVal['!id']);
5926                          }
5927                          foreach($hrefs as $refPos => $ref){
5928                              $this->debug('resolving href at pos '.$refPos);
5929                              $this->multirefs[$id][$refPos] = $idVal;
5930                          }
5931                      }
5932                  }
5933              }
5934              xml_parser_free($this->parser);
5935          } else {
5936              $this->debug('xml was empty, didn\'t parse!');
5937              $this->setError('xml was empty, didn\'t parse!');
5938          }
5939      }
5940  
5941      /**

5942      * start-element handler

5943      *

5944      * @param    resource $parser XML parser object

5945      * @param    string $name element name

5946      * @param    array $attrs associative array of attributes

5947      * @access   private

5948      */
5949  	function start_element($parser, $name, $attrs) {
5950          // position in a total number of elements, starting from 0

5951          // update class level pos

5952          $pos = $this->position++;
5953          // and set mine

5954          $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
5955          // depth = how many levels removed from root?

5956          // set mine as current global depth and increment global depth value

5957          $this->message[$pos]['depth'] = $this->depth++;
5958  
5959          // else add self as child to whoever the current parent is

5960          if($pos != 0){
5961              $this->message[$this->parent]['children'] .= '|'.$pos;
5962          }
5963          // set my parent

5964          $this->message[$pos]['parent'] = $this->parent;
5965          // set self as current parent

5966          $this->parent = $pos;
5967          // set self as current value for this depth

5968          $this->depth_array[$this->depth] = $pos;
5969          // get element prefix

5970          if(strpos($name,':')){
5971              // get ns prefix

5972              $prefix = substr($name,0,strpos($name,':'));
5973              // get unqualified name

5974              $name = substr(strstr($name,':'),1);
5975          }
5976          // set status

5977          if($name == 'Envelope'){
5978              $this->status = 'envelope';
5979          } elseif($name == 'Header'){
5980              $this->root_header = $pos;
5981              $this->status = 'header';
5982          } elseif($name == 'Body'){
5983              $this->status = 'body';
5984              $this->body_position = $pos;
5985          // set method

5986          } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
5987              $this->status = 'method';
5988              $this->root_struct_name = $name;
5989              $this->root_struct = $pos;
5990              $this->message[$pos]['type'] = 'struct';
5991              $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
5992          }
5993          // set my status

5994          $this->message[$pos]['status'] = $this->status;
5995          // set name

5996          $this->message[$pos]['name'] = htmlspecialchars($name);
5997          // set attrs

5998          $this->message[$pos]['attrs'] = $attrs;
5999  
6000          // loop through atts, logging ns and type declarations

6001          $attstr = '';
6002          foreach($attrs as $key => $value){
6003              $key_prefix = $this->getPrefix($key);
6004              $key_localpart = $this->getLocalPart($key);
6005              // if ns declarations, add to class level array of valid namespaces

6006              if($key_prefix == 'xmlns'){
6007                  if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
6008                      $this->XMLSchemaVersion = $value;
6009                      $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6010                      $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
6011                  }
6012                  $this->namespaces[$key_localpart] = $value;
6013                  // set method namespace

6014                  if($name == $this->root_struct_name){
6015                      $this->methodNamespace = $value;
6016                  }
6017              // if it's a type declaration, set type

6018              } elseif($key_localpart == 'type'){
6019                  $value_prefix = $this->getPrefix($value);
6020                  $value_localpart = $this->getLocalPart($value);
6021                  $this->message[$pos]['type'] = $value_localpart;
6022                  $this->message[$pos]['typePrefix'] = $value_prefix;
6023                  if(isset($this->namespaces[$value_prefix])){
6024                      $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6025                  } else if(isset($attrs['xmlns:'.$value_prefix])) {
6026                      $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
6027                  }
6028                  // should do something here with the namespace of specified type?

6029              } elseif($key_localpart == 'arrayType'){
6030                  $this->message[$pos]['type'] = 'array';
6031                  /* do arrayType ereg here

6032                  [1]    arrayTypeValue    ::=    atype asize

6033                  [2]    atype    ::=    QName rank*

6034                  [3]    rank    ::=    '[' (',')* ']'

6035                  [4]    asize    ::=    '[' length~ ']'

6036                  [5]    length    ::=    nextDimension* Digit+

6037                  [6]    nextDimension    ::=    Digit+ ','

6038                  */
6039                  $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
6040                  if(ereg($expr,$value,$regs)){
6041                      $this->message[$pos]['typePrefix'] = $regs[1];
6042                      $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6043                      if (isset($this->namespaces[$regs[1]])) {
6044                          $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6045                      } else if (isset($attrs['xmlns:'.$regs[1]])) {
6046                          $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
6047                      }
6048                      $this->message[$pos]['arrayType'] = $regs[2];
6049                      $this->message[$pos]['arraySize'] = $regs[3];
6050                      $this->message[$pos]['arrayCols'] = $regs[4];
6051                  }
6052              // specifies nil value (or not)

6053              } elseif ($key_localpart == 'nil'){
6054                  $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6055              // some other attribute

6056              } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6057                  $this->message[$pos]['xattrs']['!' . $key] = $value;
6058              }
6059  
6060              if ($key == 'xmlns') {
6061                  $this->default_namespace = $value;
6062              }
6063              // log id

6064              if($key == 'id'){
6065                  $this->ids[$value] = $pos;
6066              }
6067              // root

6068              if($key_localpart == 'root' && $value == 1){
6069                  $this->status = 'method';
6070                  $this->root_struct_name = $name;
6071                  $this->root_struct = $pos;
6072                  $this->debug("found root struct $this->root_struct_name, pos $pos");
6073              }
6074              // for doclit

6075              $attstr .= " $key=\"$value\"";
6076          }
6077          // get namespace - must be done after namespace atts are processed

6078          if(isset($prefix)){
6079              $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6080              $this->default_namespace = $this->namespaces[$prefix];
6081          } else {
6082              $this->message[$pos]['namespace'] = $this->default_namespace;
6083          }
6084          if($this->status == 'header'){
6085              if ($this->root_header != $pos) {
6086                  $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6087              }
6088          } elseif($this->root_struct_name != ''){
6089              $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6090          }
6091      }
6092  
6093      /**

6094      * end-element handler

6095      *

6096      * @param    resource $parser XML parser object

6097      * @param    string $name element name

6098      * @access   private

6099      */
6100  	function end_element($parser, $name) {
6101          // position of current element is equal to the last value left in depth_array for my depth

6102          $pos = $this->depth_array[$this->depth--];
6103  
6104          // get element prefix

6105          if(strpos($name,':')){
6106              // get ns prefix

6107              $prefix = substr($name,0,strpos($name,':'));
6108              // get unqualified name

6109              $name = substr(strstr($name,':'),1);
6110          }
6111          
6112          // build to native type

6113          if(isset($this->body_position) && $pos > $this->body_position){
6114              // deal w/ multirefs

6115              if(isset($this->message[$pos]['attrs']['href'])){
6116                  // get id

6117                  $id = substr($this->message[$pos]['attrs']['href'],1);
6118                  // add placeholder to href array

6119                  $this->multirefs[$id][$pos] = 'placeholder';
6120                  // add set a reference to it as the result value

6121                  $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6122              // build complexType values

6123              } elseif($this->message[$pos]['children'] != ''){
6124                  // if result has already been generated (struct/array)

6125                  if(!isset($this->message[$pos]['result'])){
6126                      $this->message[$pos]['result'] = $this->buildVal($pos);
6127                  }
6128              // build complexType values of attributes and possibly simpleContent

6129              } elseif (isset($this->message[$pos]['xattrs'])) {
6130                  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6131                      $this->message[$pos]['xattrs']['!'] = null;
6132                  } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6133                      if (isset($this->message[$pos]['type'])) {
6134                          $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6135                      } else {
6136                          $parent = $this->message[$pos]['parent'];
6137                          if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6138                              $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6139                          } else {
6140                              $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6141                          }
6142                      }
6143                  }
6144                  $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6145              // set value of simpleType (or nil complexType)

6146              } else {
6147                  //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);

6148                  if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6149                      $this->message[$pos]['xattrs']['!'] = null;
6150                  } elseif (isset($this->message[$pos]['type'])) {
6151                      $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6152                  } else {
6153                      $parent = $this->message[$pos]['parent'];
6154                      if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6155                          $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6156                      } else {
6157                          $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6158                      }
6159                  }
6160  
6161                  /* add value to parent's result, if parent is struct/array

6162                  $parent = $this->message[$pos]['parent'];

6163                  if($this->message[$parent]['type'] != 'map'){

6164                      if(strtolower($this->message[$parent]['type']) == 'array'){

6165                          $this->message[$parent]['result'][] = $this->message[$pos]['result'];

6166                      } else {

6167                          $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];

6168                      }

6169                  }

6170                  */
6171              }
6172          }
6173          
6174          // for doclit

6175          if($this->status == 'header'){
6176              if ($this->root_header != $pos) {
6177                  $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6178              }
6179          } elseif($pos >= $this->root_struct){
6180              $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6181          }
6182          // switch status

6183          if($pos == $this->root_struct){
6184              $this->status = 'body';
6185              $this->root_struct_namespace = $this->message[$pos]['namespace'];
6186          } elseif($name == 'Body'){
6187              $this->status = 'envelope';
6188           } elseif($name == 'Header'){
6189              $this->status = 'envelope';
6190          } elseif($name == 'Envelope'){
6191              //

6192          }
6193          // set parent back to my parent

6194          $this->parent = $this->message[$pos]['parent'];
6195      }
6196  
6197      /**

6198      * element content handler

6199      *

6200      * @param    resource $parser XML parser object

6201      * @param    string $data element content

6202      * @access   private

6203      */
6204  	function character_data($parser, $data){
6205          $pos = $this->depth_array[$this->depth];
6206          if ($this->xml_encoding=='UTF-8'){
6207              // TODO: add an option to disable this for folks who want

6208              // raw UTF-8 that, e.g., might not map to iso-8859-1

6209              // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");

6210              if($this->decode_utf8){
6211                  $data = utf8_decode($data);
6212              }
6213          }
6214          $this->message[$pos]['cdata'] .= $data;
6215          // for doclit

6216          if($this->status == 'header'){
6217              $this->responseHeaders .= $data;
6218          } else {
6219              $this->document .= $data;
6220          }
6221      }
6222  
6223      /**

6224      * get the parsed message

6225      *

6226      * @return    mixed

6227      * @access   public

6228      */
6229  	function get_response(){
6230          return $this->soapresponse;
6231      }
6232  
6233      /**

6234      * get the parsed headers

6235      *

6236      * @return    string XML or empty if no headers

6237      * @access   public

6238      */
6239  	function getHeaders(){
6240          return $this->responseHeaders;
6241      }
6242  
6243      /**

6244      * decodes simple types into PHP variables

6245      *

6246      * @param    string $value value to decode

6247      * @param    string $type XML type to decode

6248      * @param    string $typens XML type namespace to decode

6249      * @return    mixed PHP value

6250      * @access   private

6251      */
6252  	function decodeSimple($value, $type, $typens) {
6253          // TODO: use the namespace!

6254          if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6255              return (string) $value;
6256          }
6257          if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
6258              return (int) $value;
6259          }
6260          if ($type == 'float' || $type == 'double' || $type == 'decimal') {
6261              return (double) $value;
6262          }
6263          if ($type == 'boolean') {
6264              if (strtolower($value) == 'false' || strtolower($value) == 'f') {
6265                  return false;
6266              }
6267              return (boolean) $value;
6268          }
6269          if ($type == 'base64' || $type == 'base64Binary') {
6270              $this->debug('Decode base64 value');
6271              return base64_decode($value);
6272          }
6273          // obscure numeric types

6274          if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
6275              || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
6276              || $type == 'unsignedInt'
6277              || $type == 'unsignedShort' || $type == 'unsignedByte') {
6278              return (int) $value;
6279          }
6280          // bogus: parser treats array with no elements as a simple type

6281          if ($type == 'array') {
6282              return array();
6283          }
6284          // everything else

6285          return (string) $value;
6286      }
6287  
6288      /**

6289      * builds response structures for compound values (arrays/structs)

6290      * and scalars

6291      *

6292      * @param    integer $pos position in node tree

6293      * @return    mixed    PHP value

6294      * @access   private

6295      */
6296  	function buildVal($pos){
6297          if(!isset($this->message[$pos]['type'])){
6298              $this->message[$pos]['type'] = '';
6299          }
6300          $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
6301          // if there are children...

6302          if($this->message[$pos]['children'] != ''){
6303              $this->debug('in buildVal, there are children');
6304              $children = explode('|',$this->message[$pos]['children']);
6305              array_shift($children); // knock off empty

6306              // md array

6307              if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
6308                  $r=0; // rowcount

6309                  $c=0; // colcount

6310                  foreach($children as $child_pos){
6311                      $this->debug("in buildVal, got an MD array element: $r, $c");
6312                      $params[$r][] = $this->message[$child_pos]['result'];
6313                      $c++;
6314                      if($c == $this->message[$pos]['arrayCols']){
6315                          $c = 0;
6316                          $r++;
6317                      }
6318                  }
6319              // array

6320              } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
6321                  $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
6322                  foreach($children as $child_pos){
6323                      $params[] = &$this->message[$child_pos]['result'];
6324                  }
6325              // apache Map type: java hashtable

6326              } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
6327                  $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
6328                  foreach($children as $child_pos){
6329                      $kv = explode("|",$this->message[$child_pos]['children']);
6330                         $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
6331                  }
6332              // generic compound type

6333              //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {

6334              } else {
6335                  // Apache Vector type: treat as an array

6336                  $this->debug('in buildVal, adding Java Vector '.$this->message[$pos]['name']);
6337                  if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
6338                      $notstruct = 1;
6339                  } else {
6340                      $notstruct = 0;
6341                  }
6342                  //

6343                  foreach($children as $child_pos){
6344                      if($notstruct){
6345                          $params[] = &$this->message[$child_pos]['result'];
6346                      } else {
6347                          if (isset($params[$this->message[$child_pos]['name']])) {
6348                              // de-serialize repeated element name into an array

6349                              if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
6350                                  $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
6351                              }
6352                              $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
6353                          } else {
6354                              $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
6355                          }
6356                      }
6357                  }
6358              }
6359              if (isset($this->message[$pos]['xattrs'])) {
6360                  $this->debug('in buildVal, handling attributes');
6361                  foreach ($this->message[$pos]['xattrs'] as $n => $v) {
6362                      $params[$n] = $v;
6363                  }
6364              }
6365              // handle simpleContent

6366              if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6367                  $this->debug('in buildVal, handling simpleContent');
6368                  if (isset($this->message[$pos]['type'])) {
6369                      $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6370                  } else {
6371                      $parent = $this->message[$pos]['parent'];
6372                      if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6373                          $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6374                      } else {
6375                          $params['!'] = $this->message[$pos]['cdata'];
6376                      }
6377                  }
6378              }
6379              return is_array($params) ? $params : array();
6380          } else {
6381              $this->debug('in buildVal, no children, building scalar');
6382              $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
6383              if (isset($this->message[$pos]['type'])) {
6384                  return $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6385              }
6386              $parent = $this->message[$pos]['parent'];
6387              if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6388                  return $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6389              }
6390                 return $this->message[$pos]['cdata'];
6391          }
6392      }
6393  }
6394  
6395  
6396  
6397  ?><?php
6398  
6399  
6400  
6401  /**

6402  *

6403  * nu_soapclient higher level class for easy usage.

6404  *

6405  * usage:

6406  *

6407  * // instantiate client with server info

6408  * $nu_soapclient = new nu_soapclient( string path [ ,boolean wsdl] );

6409  *

6410  * // call method, get results

6411  * echo $nu_soapclient->call( string methodname [ ,array parameters] );

6412  *

6413  * // bye bye client

6414  * unset($nu_soapclient);

6415  *

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

6417  * @version  $Id: nusoap.php,v 1.94 2005/08/04 01:27:42 snichol Exp $

6418  * @access   public

6419  */
6420  class nu_soapclient extends nusoap_base  {
6421  
6422      var $username = '';
6423      var $password = '';
6424      var $authtype = '';
6425      var $certRequest = array();
6426      var $requestHeaders = false;    // SOAP headers in request (text)

6427      var $responseHeaders = '';        // SOAP headers from response (incomplete namespace resolution) (text)

6428      var $document = '';                // SOAP body response portion (incomplete namespace resolution) (text)

6429      var $endpoint;
6430      var $forceEndpoint = '';        // overrides WSDL endpoint

6431      var $proxyhost = '';
6432      var $proxyport = '';
6433      var $proxyusername = '';
6434      var $proxypassword = '';
6435      var $xml_encoding = '';            // character set encoding of incoming (response) messages

6436      var $http_encoding = false;
6437      var $timeout = 0;                // HTTP connection timeout

6438      var $response_timeout = 30;        // HTTP response timeout

6439      var $endpointType = '';            // soap|wsdl, empty for WSDL initialization error

6440      var $persistentConnection = false;
6441      var $defaultRpcParams = false;    // This is no longer used

6442      var $request = '';                // HTTP request

6443      var $response = '';                // HTTP response

6444      var $responseData = '';            // SOAP payload of response

6445      var $cookies = array();            // Cookies from response or for request

6446      var $decode_utf8 = true;        // toggles whether the parser decodes element content w/ utf8_decode()

6447      var $operations = array();        // WSDL operations, empty for WSDL initialization error

6448      
6449      /*

6450       * fault related variables

6451       */
6452      /**

6453       * @var      fault

6454       * @access   public

6455       */
6456      var $fault;
6457      /**

6458       * @var      faultcode

6459       * @access   public

6460       */
6461      var $faultcode;
6462      /**

6463       * @var      faultstring

6464       * @access   public

6465       */
6466      var $faultstring;
6467      /**

6468       * @var      faultdetail

6469       * @access   public

6470       */
6471      var $faultdetail;
6472  
6473      /**

6474      * constructor

6475      *

6476      * @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)

6477      * @param    bool $wsdl optional, set to true if using WSDL

6478      * @param    int $portName optional portName in WSDL document

6479      * @param    string $proxyhost

6480      * @param    string $proxyport

6481      * @param    string $proxyusername

6482      * @param    string $proxypassword

6483      * @param    integer $timeout set the connection timeout

6484      * @param    integer $response_timeout set the response timeout

6485      * @access   public

6486      */
6487  	function nu_soapclient($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
6488          parent::nusoap_base();
6489          $this->endpoint = $endpoint;
6490          $this->proxyhost = $proxyhost;
6491          $this->proxyport = $proxyport;
6492          $this->proxyusername = $proxyusername;
6493          $this->proxypassword = $proxypassword;
6494          $this->timeout = $timeout;
6495          $this->response_timeout = $response_timeout;
6496  
6497          // make values

6498          if($wsdl){
6499              if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
6500                  $this->wsdl = $endpoint;
6501                  $this->endpoint = $this->wsdl->wsdl;
6502                  $this->wsdlFile = $this->endpoint;
6503                  $this->debug('existing wsdl instance created from ' . $this->endpoint);
6504              } else {
6505                  $this->wsdlFile = $this->endpoint;
6506                  
6507                  // instantiate wsdl object and parse wsdl file

6508                  $this->debug('instantiating wsdl class with doc: '.$endpoint);
6509                  $this->wsdl =& new wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout);
6510              }
6511              $this->appendDebug($this->wsdl->getDebug());
6512              $this->wsdl->clearDebug();
6513              // catch errors

6514              if($errstr = $this->wsdl->getError()){
6515                  $this->debug('got wsdl error: '.$errstr);
6516                  $this->setError('wsdl error: '.$errstr);
6517              } elseif($this->operations = $this->wsdl->getOperations()){
6518                  $this->debug( 'got '.count($this->operations).' operations from wsdl '.$this->wsdlFile);
6519                  $this->endpointType = 'wsdl';
6520              } else {
6521                  $this->debug( 'getOperations returned false');
6522                  $this->setError('no operations defined in the WSDL document!');
6523              }
6524          } else {
6525              $this->debug("instantiate SOAP with endpoint at $endpoint");
6526              $this->endpointType = 'soap';
6527          }
6528      }
6529  
6530      /**

6531      * calls method, returns PHP native type

6532      *

6533      * @param    string $method SOAP server URL or path

6534      * @param    mixed $params An array, associative or simple, of the parameters

6535      *                          for the method call, or a string that is the XML

6536      *                          for the call.  For rpc style, this call will

6537      *                          wrap the XML in a tag named after the method, as

6538      *                          well as the SOAP Envelope and Body.  For document

6539      *                          style, this will only wrap with the Envelope and Body.

6540      *                          IMPORTANT: when using an array with document style,

6541      *                          in which case there

6542      *                         is really one parameter, the root of the fragment

6543      *                         used in the call, which encloses what programmers

6544      *                         normally think of parameters.  A parameter array

6545      *                         *must* include the wrapper.

6546      * @param    string $namespace optional method namespace (WSDL can override)

6547      * @param    string $soapAction optional SOAPAction value (WSDL can override)

6548      * @param    mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers

6549      * @param    boolean $rpcParams optional (no longer used)

6550      * @param    string    $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)

6551      * @param    string    $use optional (encoded|literal) the use when serializing parameters (WSDL can override)

6552      * @return    mixed    response from SOAP call

6553      * @access   public

6554      */
6555  	function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
6556          $this->operation = $operation;
6557          $this->fault = false;
6558          $this->setError('');
6559          $this->request = '';
6560          $this->response = '';
6561          $this->responseData = '';
6562          $this->faultstring = '';
6563          $this->faultcode = '';
6564          $this->opData = array();
6565          
6566          $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
6567          $this->appendDebug('params=' . $this->varDump($params));
6568          $this->appendDebug('headers=' . $this->varDump($headers));
6569          if ($headers) {
6570              $this->requestHeaders = $headers;
6571          }
6572          // serialize parameters

6573          if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
6574              // use WSDL for operation

6575              $this->opData = $opData;
6576              $this->debug("found operation");
6577              $this->appendDebug('opData=' . $this->varDump($opData));
6578              if (isset($opData['soapAction'])) {
6579                  $soapAction = $opData['soapAction'];
6580              }
6581              if (! $this->forceEndpoint) {
6582                  $this->endpoint = $opData['endpoint'];
6583              } else {
6584                  $this->endpoint = $this->forceEndpoint;
6585              }
6586              $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] :    $namespace;
6587              $style = $opData['style'];
6588              $use = $opData['input']['use'];
6589              // add ns to ns array

6590              if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
6591                  $nsPrefix = 'ns' . rand(1000, 9999);
6592                  $this->wsdl->namespaces[$nsPrefix] = $namespace;
6593              }
6594              $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
6595              // serialize payload

6596              if (is_string($params)) {
6597                  $this->debug("serializing param string for WSDL operation $operation");
6598                  $payload = $params;
6599              } elseif (is_array($params)) {
6600                  $this->debug("serializing param array for WSDL operation $operation");
6601                  $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params);
6602              } else {
6603                  $this->debug('params must be array or string');
6604                  $this->setError('params must be array or string');
6605                  return false;
6606              }
6607              $usedNamespaces = $this->wsdl->usedNamespaces;
6608              if (isset($opData['input']['encodingStyle'])) {
6609                  $encodingStyle = $opData['input']['encodingStyle'];
6610              } else {
6611                  $encodingStyle = '';
6612              }
6613              $this->appendDebug($this->wsdl->getDebug());
6614              $this->wsdl->clearDebug();
6615              if ($errstr = $this->wsdl->getError()) {
6616                  $this->debug('got wsdl error: '.$errstr);
6617                  $this->setError('wsdl error: '.$errstr);
6618                  return false;
6619              }
6620          } elseif($this->endpointType == 'wsdl') {
6621              // operation not in WSDL

6622              $this->appendDebug($this->wsdl->getDebug());
6623              $this->wsdl->clearDebug();
6624              $this->setError( 'operation '.$operation.' not present.');
6625              $this->debug("operation '$operation' not present.");
6626              return false;
6627          } else {
6628              // no WSDL

6629              //$this->namespaces['ns1'] = $namespace;

6630              $nsPrefix = 'ns' . rand(1000, 9999);
6631              // serialize 

6632              $payload = '';
6633              if (is_string($params)) {
6634                  $this->debug("serializing param string for operation $operation");
6635                  $payload = $params;
6636              } elseif (is_array($params)) {
6637                  $this->debug("serializing param array for operation $operation");
6638                  foreach($params as $k => $v){
6639                      $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
6640                  }
6641              } else {
6642                  $this->debug('params must be array or string');
6643                  $this->setError('params must be array or string');
6644                  return false;
6645              }
6646              $usedNamespaces = array();
6647              if ($use == 'encoded') {
6648                  $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6649              } else {
6650                  $encodingStyle = '';
6651              }
6652          }
6653          // wrap RPC calls with method element

6654          if ($style == 'rpc') {
6655              if ($use == 'literal') {
6656                  $this->debug("wrapping RPC request with literal method element");
6657                  if ($namespace) {
6658                      $payload = "<$operation xmlns=\"$namespace\">" . $payload . "</$operation>";
6659                  } else {
6660                      $payload = "<$operation>" . $payload . "</$operation>";
6661                  }
6662              } else {
6663                  $this->debug("wrapping RPC request with encoded method element");
6664                  if ($namespace) {
6665                      $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
6666                                  $payload .
6667                                  "</$nsPrefix:$operation>";
6668                  } else {
6669                      $payload = "<$operation>" .
6670                                  $payload .
6671                                  "</$operation>";
6672                  }
6673              }
6674          }
6675          // serialize envelope

6676          $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
6677          $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
6678          $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
6679          // send

6680          $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
6681          if($errstr = $this->getError()){
6682              $this->debug('Error: '.$errstr);
6683              return false;
6684          } else {
6685              $this->return = $return;
6686              $this->debug('sent message successfully and got a(n) '.gettype($return));
6687                 $this->appendDebug('return=' . $this->varDump($return));
6688              
6689              // fault?

6690              if(is_array($return) && isset($return['faultcode'])){
6691                  $this->debug('got fault');
6692                  $this->setError($return['faultcode'].': '.$return['faultstring']);
6693                  $this->fault = true;
6694                  foreach($return as $k => $v){
6695                      $this->$k = $v;
6696                      $this->debug("$k = $v<br>");
6697                  }
6698                  return $return;
6699              } elseif ($style == 'document') {
6700                  // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),

6701                  // we are only going to return the first part here...sorry about that

6702                  return $return;
6703              } else {
6704                  // array of return values

6705                  if(is_array($return)){
6706                      // multiple 'out' parameters, which we return wrapped up

6707                      // in the array

6708                      if(sizeof($return) > 1){
6709                          return $return;
6710                      }
6711                      // single 'out' parameter (normally the return value)

6712                      $return = array_shift($return);
6713                      $this->debug('return shifted value: ');
6714                      $this->appendDebug($this->varDump($return));
6715                         return $return;
6716                  // nothing returned (ie, echoVoid)

6717                  } else {
6718                      return "";
6719                  }
6720              }
6721          }
6722      }
6723  
6724      /**

6725      * get available data pertaining to an operation

6726      *

6727      * @param    string $operation operation name

6728      * @return    array array of data pertaining to the operation

6729      * @access   public

6730      */
6731  	function getOperationData($operation){
6732          if(isset($this->operations[$operation])){
6733              return $this->operations[$operation];
6734          }
6735          $this->debug("No data for operation: $operation");
6736      }
6737  
6738      /**

6739      * send the SOAP message

6740      *

6741      * Note: if the operation has multiple return values

6742      * the return value of this method will be an array

6743      * of those values.

6744      *

6745      * @param    string $msg a SOAPx4 soapmsg object

6746      * @param    string $soapaction SOAPAction value

6747      * @param    integer $timeout set connection timeout in seconds

6748      * @param    integer $response_timeout set response timeout in seconds

6749      * @return    mixed native PHP types.

6750      * @access   private

6751      */
6752  	function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
6753          $this->checkCookies();
6754          // detect transport

6755          switch(true){
6756              // http(s)

6757              case ereg('^http',$this->endpoint):
6758                  $this->debug('transporting via HTTP');
6759                  if($this->persistentConnection == true && is_object($this->persistentConnection)){
6760                      $http =& $this->persistentConnection;
6761                  } else {
6762                      $http = new soap_transport_http($this->endpoint);
6763                      if ($this->persistentConnection) {
6764                          $http->usePersistentConnection();
6765                      }
6766                  }
6767                  $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
6768                  $http->setSOAPAction($soapaction);
6769                  if($this->proxyhost && $this->proxyport){
6770                      $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
6771                  }
6772                  if($this->authtype != '') {
6773                      $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
6774                  }
6775                  if($this->http_encoding != ''){
6776                      $http->setEncoding($this->http_encoding);
6777                  }
6778                  $this->debug('sending message, length='.strlen($msg));
6779                  if(ereg('^http:',$this->endpoint)){
6780                  //if(strpos($this->endpoint,'http:')){

6781                      $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
6782                  } elseif(ereg('^https',$this->endpoint)){
6783                  //} elseif(strpos($this->endpoint,'https:')){

6784                      //if(phpversion() == '4.3.0-dev'){

6785                          //$response = $http->send($msg,$timeout,$response_timeout);

6786                             //$this->request = $http->outgoing_payload;

6787                          //$this->response = $http->incoming_payload;

6788                      //} else

6789                      $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
6790                  } else {
6791                      $this->setError('no http/s in endpoint url');
6792                  }
6793                  $this->request = $http->outgoing_payload;
6794                  $this->response = $http->incoming_payload;
6795                  $this->appendDebug($http->getDebug());
6796                  $this->UpdateCookies($http->incoming_cookies);
6797  
6798                  // save transport object if using persistent connections

6799                  if ($this->persistentConnection) {
6800                      $http->clearDebug();
6801                      if (!is_object($this->persistentConnection)) {
6802                          $this->persistentConnection = $http;
6803                      }
6804                  }
6805                  
6806                  if($err = $http->getError()){
6807                      $this->setError('HTTP Error: '.$err);
6808                      return false;
6809                  } elseif($this->getError()){
6810                      return false;
6811                  } else {
6812                      $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
6813                      return $this->parseResponse($http->incoming_headers, $this->responseData);
6814                  }
6815              break;
6816              default:
6817                  $this->setError('no transport found, or selected transport is not yet supported!');
6818              return false;
6819              break;
6820          }
6821      }
6822  
6823      /**

6824      * processes SOAP message returned from server

6825      *

6826      * @param    array    $headers    The HTTP headers

6827      * @param    string    $data        unprocessed response data from server

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

6829      * @access   private

6830      */
6831      function parseResponse($headers, $data) {
6832          $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
6833          if (!strstr($headers['content-type'], 'text/xml')) {
6834              $this->setError('Response not of type text/xml');
6835              return false;
6836          }
6837          if (strpos($headers['content-type'], '=')) {
6838              $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
6839              $this->debug('Got response encoding: ' . $enc);
6840              if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
6841                  $this->xml_encoding = strtoupper($enc);
6842              } else {
6843                  $this->xml_encoding = 'US-ASCII';
6844              }
6845          } else {
6846              // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1

6847              $this->xml_encoding = 'ISO-8859-1';
6848          }
6849          $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
6850          $parser = new soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
6851          // add parser debug data to our debug

6852          $this->appendDebug($parser->getDebug());
6853          // if parse errors

6854          if($errstr = $parser->getError()){
6855              $this->setError( $errstr);
6856              // destroy the parser object

6857              unset($parser);
6858              return false;
6859          } else {
6860              // get SOAP headers

6861              $this->responseHeaders = $parser->getHeaders();
6862              // get decoded message

6863              $return = $parser->get_response();
6864              // add document for doclit support

6865              $this->document = $parser->document;
6866              // destroy the parser object

6867              unset($parser);
6868              // return decode message

6869              return $return;
6870          }
6871       }
6872  
6873      /**

6874      * sets the SOAP endpoint, which can override WSDL

6875      *

6876      * @param    $endpoint string The endpoint URL to use, or empty string or false to prevent override

6877      * @access   public

6878      */
6879  	function setEndpoint($endpoint) {
6880          $this->forceEndpoint = $endpoint;
6881      }
6882  
6883      /**

6884      * set the SOAP headers

6885      *

6886      * @param    $headers mixed String of XML with SOAP header content, or array of soapval objects for SOAP headers

6887      * @access   public

6888      */
6889  	function setHeaders($headers){
6890          $this->requestHeaders = $headers;
6891      }
6892  
6893      /**

6894      * get the SOAP response headers (namespace resolution incomplete)

6895      *

6896      * @return    string

6897      * @access   public

6898      */
6899  	function getHeaders(){
6900          return $this->responseHeaders;
6901      }
6902  
6903      /**

6904      * set proxy info here

6905      *

6906      * @param    string $proxyhost

6907      * @param    string $proxyport

6908      * @param    string $proxyusername

6909      * @param    string $proxypassword

6910      * @access   public

6911      */
6912  	function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
6913          $this->proxyhost = $proxyhost;
6914          $this->proxyport = $proxyport;
6915          $this->proxyusername = $proxyusername;
6916          $this->proxypassword = $proxypassword;
6917      }
6918  
6919      /**

6920      * if authenticating, set user credentials here

6921      *

6922      * @param    string $username

6923      * @param    string $password

6924      * @param    string $authtype (basic|digest|certificate)

6925      * @param    array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)

6926      * @access   public

6927      */
6928  	function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
6929          $this->username = $username;
6930          $this->password = $password;
6931          $this->authtype = $authtype;
6932          $this->certRequest = $certRequest;
6933      }
6934      
6935      /**

6936      * use HTTP encoding

6937      *

6938      * @param    string $enc

6939      * @access   public

6940      */
6941  	function setHTTPEncoding($enc='gzip, deflate'){
6942          $this->http_encoding = $enc;
6943      }
6944      
6945      /**

6946      * use HTTP persistent connections if possible

6947      *

6948      * @access   public

6949      */
6950  	function useHTTPPersistentConnection(){
6951          $this->persistentConnection = true;
6952      }
6953      
6954      /**

6955      * gets the default RPC parameter setting.

6956      * If true, default is that call params are like RPC even for document style.

6957      * Each call() can override this value.

6958      *

6959      * This is no longer used.

6960      *

6961      * @return boolean

6962      * @access public

6963      * @deprecated

6964      */
6965  	function getDefaultRpcParams() {
6966          return $this->defaultRpcParams;
6967      }
6968  
6969      /**

6970      * sets the default RPC parameter setting.

6971      * If true, default is that call params are like RPC even for document style

6972      * Each call() can override this value.

6973      *

6974      * This is no longer used.

6975      *

6976      * @param    boolean $rpcParams

6977      * @access public

6978      * @deprecated

6979      */
6980  	function setDefaultRpcParams($rpcParams) {
6981          $this->defaultRpcParams = $rpcParams;
6982      }
6983      
6984      /**

6985      * dynamically creates an instance of a proxy class,

6986      * allowing user to directly call methods from wsdl

6987      *

6988      * @return   object soap_proxy object

6989      * @access   public

6990      */
6991  	function getProxy(){
6992          $r = rand();
6993          $evalStr = $this->_getProxyClassCode($r);
6994          //$this->debug("proxy class: $evalStr";

6995          // eval the class

6996          eval($evalStr);
6997          // instantiate proxy object

6998          eval("\$proxy = new soap_proxy_$r('');");
6999          // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice

7000          $proxy->endpointType = 'wsdl';
7001          $proxy->wsdlFile = $this->wsdlFile;
7002          $proxy->wsdl = $this->wsdl;
7003          $proxy->operations = $this->operations;
7004          $proxy->defaultRpcParams = $this->defaultRpcParams;
7005          // transfer other state

7006          $proxy->username = $this->username;
7007          $proxy->password = $this->password;
7008          $proxy->authtype = $this->authtype;
7009          $proxy->proxyhost = $this->proxyhost;
7010          $proxy->proxyport = $this->proxyport;
7011          $proxy->proxyusername = $this->proxyusername;
7012          $proxy->proxypassword = $this->proxypassword;
7013          $proxy->timeout = $this->timeout;
7014          $proxy->response_timeout = $this->response_timeout;
7015          $proxy->http_encoding = $this->http_encoding;
7016          $proxy->persistentConnection = $this->persistentConnection;
7017          $proxy->requestHeaders = $this->requestHeaders;
7018          $proxy->soap_defencoding = $this->soap_defencoding;
7019          $proxy->endpoint = $this->endpoint;
7020          $proxy->forceEndpoint = $this->forceEndpoint;
7021          return $proxy;
7022      }
7023  
7024      /**

7025      * dynamically creates proxy class code

7026      *

7027      * @return   string PHP/NuSOAP code for the proxy class

7028      * @access   private

7029      */
7030  	function _getProxyClassCode($r) {
7031          if ($this->endpointType != 'wsdl') {
7032              $evalStr = 'A proxy can only be created for a WSDL client';
7033              $this->setError($evalStr);
7034              return $evalStr;
7035          }
7036          $evalStr = '';
7037          foreach ($this->operations as $operation => $opData) {
7038              if ($operation != '') {
7039                  // create param string and param comment string

7040                  if (sizeof($opData['input']['parts']) > 0) {
7041                      $paramStr = '';
7042                      $paramArrayStr = '';
7043                      $paramCommentStr = '';
7044                      foreach ($opData['input']['parts'] as $name => $type) {
7045                          $paramStr .= "\$$name, ";
7046                          $paramArrayStr .= "'$name' => \$$name, ";
7047                          $paramCommentStr .= "$type \$$name, ";
7048                      }
7049                      $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7050                      $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7051                      $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7052                  } else {
7053                      $paramStr = '';
7054                      $paramCommentStr = 'void';
7055                  }
7056                  $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7057                  $evalStr .= "// $paramCommentStr
7058      function " . str_replace('.', '__', $operation) . "($paramStr) {
7059          \$params = array($paramArrayStr);
7060          return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
7061      }
7062      ";
7063                  unset($paramStr);
7064                  unset($paramCommentStr);
7065              }
7066          }
7067          $evalStr = 'class soap_proxy_'.$r.' extends nu_soapclient {
7068      '.$evalStr.'
7069  }';
7070          return $evalStr;
7071      }
7072  
7073      /**

7074      * dynamically creates proxy class code

7075      *

7076      * @return   string PHP/NuSOAP code for the proxy class

7077      * @access   public

7078      */
7079  	function getProxyClassCode() {
7080          $r = rand();
7081          return $this->_getProxyClassCode($r);
7082      }
7083  
7084      /**

7085      * gets the HTTP body for the current request.

7086      *

7087      * @param string $soapmsg The SOAP payload

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

7089      * @access private

7090      */
7091  	function getHTTPBody($soapmsg) {
7092          return $soapmsg;
7093      }
7094      
7095      /**

7096      * gets the HTTP content type for the current request.

7097      *

7098      * Note: getHTTPBody must be called before this.

7099      *

7100      * @return string the HTTP content type for the current request.

7101      * @access private

7102      */
7103  	function getHTTPContentType() {
7104          return 'text/xml';
7105      }
7106      
7107      /**

7108      * gets the HTTP content type charset for the current request.

7109      * returns false for non-text content types.

7110      *

7111      * Note: getHTTPBody must be called before this.

7112      *

7113      * @return string the HTTP content type charset for the current request.

7114      * @access private

7115      */
7116  	function getHTTPContentTypeCharset() {
7117          return $this->soap_defencoding;
7118      }
7119  
7120      /*

7121      * whether or not parser should decode utf8 element content

7122      *

7123      * @return   always returns true

7124      * @access   public

7125      */
7126      function decodeUTF8($bool){
7127          $this->decode_utf8 = $bool;
7128          return true;
7129      }
7130  
7131      /**

7132       * adds a new Cookie into $this->cookies array

7133       *

7134       * @param    string $name Cookie Name

7135       * @param    string $value Cookie Value

7136       * @return    if cookie-set was successful returns true, else false

7137       * @access    public

7138       */
7139  	function setCookie($name, $value) {
7140          if (strlen($name) == 0) {
7141              return false;
7142          }
7143          $this->cookies[] = array('name' => $name, 'value' => $value);
7144          return true;
7145      }
7146  
7147      /**

7148       * gets all Cookies

7149       *

7150       * @return   array with all internal cookies

7151       * @access   public

7152       */
7153  	function getCookies() {
7154          return $this->cookies;
7155      }
7156  
7157      /**

7158       * checks all Cookies and delete those which are expired

7159       *

7160       * @return   always return true

7161       * @access   private

7162       */
7163  	function checkCookies() {
7164          if (sizeof($this->cookies) == 0) {
7165              return true;
7166          }
7167          $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
7168          $curr_cookies = $this->cookies;
7169          $this->cookies = array();
7170          foreach ($curr_cookies as $cookie) {
7171              if (! is_array($cookie)) {
7172                  $this->debug('Remove cookie that is not an array');
7173                  continue;
7174              }
7175              if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
7176                  if (strtotime($cookie['expires']) > time()) {
7177                      $this->cookies[] = $cookie;
7178                  } else {
7179                      $this->debug('Remove expired cookie ' . $cookie['name']);
7180                  }
7181              } else {
7182                  $this->cookies[] = $cookie;
7183              }
7184          }
7185          $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
7186          return true;
7187      }
7188  
7189      /**

7190       * updates the current cookies with a new set

7191       *

7192       * @param    array $cookies new cookies with which to update current ones

7193       * @return    always return true

7194       * @access    private

7195       */
7196  	function UpdateCookies($cookies) {
7197          if (sizeof($this->cookies) == 0) {
7198              // no existing cookies: take whatever is new

7199              if (sizeof($cookies) > 0) {
7200                  $this->debug('Setting new cookie(s)');
7201                  $this->cookies = $cookies;
7202              }
7203              return true;
7204          }
7205          if (sizeof($cookies) == 0) {
7206              // no new cookies: keep what we've got

7207              return true;
7208          }
7209          // merge

7210          foreach ($cookies as $newCookie) {
7211              if (!is_array($newCookie)) {
7212                  continue;
7213              }
7214              if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
7215                  continue;
7216              }
7217              $newName = $newCookie['name'];
7218  
7219              $found = false;
7220              for ($i = 0; $i < count($this->cookies); $i++) {
7221                  $cookie = $this->cookies[$i];
7222                  if (!is_array($cookie)) {
7223                      continue;
7224                  }
7225                  if (!isset($cookie['name'])) {
7226                      continue;
7227                  }
7228                  if ($newName != $cookie['name']) {
7229                      continue;
7230                  }
7231                  $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
7232                  $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
7233                  if ($newDomain != $domain) {
7234                      continue;
7235                  }
7236                  $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
7237                  $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
7238                  if ($newPath != $path) {
7239                      continue;
7240                  }
7241                  $this->cookies[$i] = $newCookie;
7242                  $found = true;
7243                  $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
7244                  break;
7245              }
7246              if (! $found) {
7247                  $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
7248                  $this->cookies[] = $newCookie;
7249              }
7250          }
7251          return true;
7252      }
7253  }
7254  ?>


Généré le : Tue Apr 3 18:50:37 2007 par Balluche grâce à PHPXref 0.7