[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/soap/ -> nusoap.php (source)

   1  <?php
   2  
   3  /*
   4  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler 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  /* load classes
  36  
  37  // necessary classes
  38  require_once('class.soap_client.php');
  39  require_once('class.soap_val.php');
  40  require_once('class.soap_parser.php');
  41  require_once('class.soap_fault.php');
  42  
  43  // transport classes
  44  require_once('class.soap_transport_http.php');
  45  
  46  // optional add-on classes
  47  require_once('class.xmlschema.php');
  48  require_once('class.wsdl.php');
  49  
  50  // server class
  51  require_once('class.soap_server.php');*/
  52  
  53  // class variable emulation
  54  // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
  55  $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
  56  
  57  /**
  58  *
  59  * nusoap_base
  60  *
  61  * @author   Dietrich Ayala <dietrich@ganx4.com>
  62  * @version  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler Exp $
  63  * @access   public
  64  */
  65  class nusoap_base {
  66      /**
  67       * Identification for HTTP headers.
  68       *
  69       * @var string
  70       * @access private
  71       */
  72      var $title = 'NuSOAP';
  73      /**
  74       * Version for HTTP headers.
  75       *
  76       * @var string
  77       * @access private
  78       */
  79      var $version = '0.7.2';
  80      /**
  81       * CVS revision for HTTP headers.
  82       *
  83       * @var string
  84       * @access private
  85       */
  86      var $revision = '$Revision: 1.2 $';
  87      /**
  88       * Current error string (manipulated by getError/setError)
  89       *
  90       * @var string
  91       * @access private
  92       */
  93      var $error_str = '';
  94      /**
  95       * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
  96       *
  97       * @var string
  98       * @access private
  99       */
 100      var $debug_str = '';
 101      /**
 102       * toggles automatic encoding of special characters as entities
 103       * (should always be true, I think)
 104       *
 105       * @var boolean
 106       * @access private
 107       */
 108      var $charencoding = true;
 109      /**
 110       * the debug level for this instance
 111       *
 112       * @var    integer
 113       * @access private
 114       */
 115      var $debugLevel;
 116  
 117      /**
 118      * set schema version
 119      *
 120      * @var      string
 121      * @access   public
 122      */
 123      var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
 124      
 125      /**
 126      * charset encoding for outgoing messages
 127      *
 128      * @var      string
 129      * @access   public
 130      */
 131      var $soap_defencoding = 'ISO-8859-1';
 132      //var $soap_defencoding = 'UTF-8';
 133  
 134      /**
 135      * namespaces in an array of prefix => uri
 136      *
 137      * this is "seeded" by a set of constants, but it may be altered by code
 138      *
 139      * @var      array
 140      * @access   public
 141      */
 142      var $namespaces = array(
 143          'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
 144          'xsd' => 'http://www.w3.org/2001/XMLSchema',
 145          'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
 146          'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
 147          );
 148  
 149      /**
 150      * namespaces used in the current context, e.g. during serialization
 151      *
 152      * @var      array
 153      * @access   private
 154      */
 155      var $usedNamespaces = array();
 156  
 157      /**
 158      * XML Schema types in an array of uri => (array of xml type => php type)
 159      * is this legacy yet?
 160      * no, this is used by the xmlschema class to verify type => namespace mappings.
 161      * @var      array
 162      * @access   public
 163      */
 164      var $typemap = array(
 165      'http://www.w3.org/2001/XMLSchema' => array(
 166          'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
 167          'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
 168          'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
 169          // abstract "any" types
 170          'anyType'=>'string','anySimpleType'=>'string',
 171          // derived datatypes
 172          'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
 173          'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
 174          'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
 175          'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
 176      'http://www.w3.org/2000/10/XMLSchema' => array(
 177          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 178          'float'=>'double','dateTime'=>'string',
 179          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 180      'http://www.w3.org/1999/XMLSchema' => array(
 181          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 182          'float'=>'double','dateTime'=>'string',
 183          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 184      'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
 185      'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
 186      'http://xml.apache.org/xml-soap' => array('Map')
 187      );
 188  
 189      /**
 190      * XML entities to convert
 191      *
 192      * @var      array
 193      * @access   public
 194      * @deprecated
 195      * @see    expandEntities
 196      */
 197      var $xmlEntities = array('quot' => '"','amp' => '&',
 198          'lt' => '<','gt' => '>','apos' => "'");
 199  
 200      /**
 201      * constructor
 202      *
 203      * @access    public
 204      */
 205  	function nusoap_base() {
 206          $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
 207      }
 208  
 209      /**
 210      * gets the global debug level, which applies to future instances
 211      *
 212      * @return    integer    Debug level 0-9, where 0 turns off
 213      * @access    public
 214      */
 215  	function getGlobalDebugLevel() {
 216          return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
 217      }
 218  
 219      /**
 220      * sets the global debug level, which applies to future instances
 221      *
 222      * @param    int    $level    Debug level 0-9, where 0 turns off
 223      * @access    public
 224      */
 225  	function setGlobalDebugLevel($level) {
 226          $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
 227      }
 228  
 229      /**
 230      * gets the debug level for this instance
 231      *
 232      * @return    int    Debug level 0-9, where 0 turns off
 233      * @access    public
 234      */
 235  	function getDebugLevel() {
 236          return $this->debugLevel;
 237      }
 238  
 239      /**
 240      * sets the debug level for this instance
 241      *
 242      * @param    int    $level    Debug level 0-9, where 0 turns off
 243      * @access    public
 244      */
 245  	function setDebugLevel($level) {
 246          $this->debugLevel = $level;
 247      }
 248  
 249      /**
 250      * adds debug data to the instance debug string with formatting
 251      *
 252      * @param    string $string debug data
 253      * @access   private
 254      */
 255  	function debug($string){
 256          if ($this->debugLevel > 0) {
 257              $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
 258          }
 259      }
 260  
 261      /**
 262      * adds debug data to the instance debug string without formatting
 263      *
 264      * @param    string $string debug data
 265      * @access   public
 266      */
 267  	function appendDebug($string){
 268          if ($this->debugLevel > 0) {
 269              // it would be nice to use a memory stream here to use
 270              // memory more efficiently
 271              $this->debug_str .= $string;
 272          }
 273      }
 274  
 275      /**
 276      * clears the current debug data for this instance
 277      *
 278      * @access   public
 279      */
 280  	function clearDebug() {
 281          // it would be nice to use a memory stream here to use
 282          // memory more efficiently
 283          $this->debug_str = '';
 284      }
 285  
 286      /**
 287      * gets the current debug data for this instance
 288      *
 289      * @return   debug data
 290      * @access   public
 291      */
 292      function &getDebug() {
 293          // it would be nice to use a memory stream here to use
 294          // memory more efficiently
 295          return $this->debug_str;
 296      }
 297  
 298      /**
 299      * gets the current debug data for this instance as an XML comment
 300      * this may change the contents of the debug data
 301      *
 302      * @return   debug data as an XML comment
 303      * @access   public
 304      */
 305      function &getDebugAsXMLComment() {
 306          // it would be nice to use a memory stream here to use
 307          // memory more efficiently
 308          while (strpos($this->debug_str, '--')) {
 309              $this->debug_str = str_replace('--', '- -', $this->debug_str);
 310          }
 311          return "<!--\n" . $this->debug_str . "\n-->";
 312      }
 313  
 314      /**
 315      * expands entities, e.g. changes '<' to '&lt;'.
 316      *
 317      * @param    string    $val    The string in which to expand entities.
 318      * @access    private
 319      */
 320  	function expandEntities($val) {
 321          if ($this->charencoding) {
 322              $val = str_replace('&', '&amp;', $val);
 323              $val = str_replace("'", '&apos;', $val);
 324              $val = str_replace('"', '&quot;', $val);
 325              $val = str_replace('<', '&lt;', $val);
 326              $val = str_replace('>', '&gt;', $val);
 327          }
 328          return $val;
 329      }
 330  
 331      /**
 332      * returns error string if present
 333      *
 334      * @return   mixed error string or false
 335      * @access   public
 336      */
 337  	function getError(){
 338          if($this->error_str != ''){
 339              return $this->error_str;
 340          }
 341          return false;
 342      }
 343  
 344      /**
 345      * sets error string
 346      *
 347      * @return   boolean $string error string
 348      * @access   private
 349      */
 350  	function setError($str){
 351          $this->error_str = $str;
 352      }
 353  
 354      /**
 355      * detect if array is a simple array or a struct (associative array)
 356      *
 357      * @param    mixed    $val    The PHP array
 358      * @return    string    (arraySimple|arrayStruct)
 359      * @access    private
 360      */
 361  	function isArraySimpleOrStruct($val) {
 362          $keyList = array_keys($val);
 363          foreach ($keyList as $keyListValue) {
 364              if (!is_int($keyListValue)) {
 365                  return 'arrayStruct';
 366              }
 367          }
 368          return 'arraySimple';
 369      }
 370  
 371      /**
 372      * serializes PHP values in accordance w/ section 5. Type information is
 373      * not serialized if $use == 'literal'.
 374      *
 375      * @param    mixed    $val    The value to serialize
 376      * @param    string    $name    The name (local part) of the XML element
 377      * @param    string    $type    The XML schema type (local part) for the element
 378      * @param    string    $name_ns    The namespace for the name of the XML element
 379      * @param    string    $type_ns    The namespace for the type of the element
 380      * @param    array    $attributes    The attributes to serialize as name=>value pairs
 381      * @param    string    $use    The WSDL "use" (encoded|literal)
 382      * @return    string    The serialized element, possibly with child elements
 383      * @access    public
 384      */
 385  	function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){
 386          $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use");
 387          $this->appendDebug('value=' . $this->varDump($val));
 388          $this->appendDebug('attributes=' . $this->varDump($attributes));
 389          
 390          if(is_object($val) && get_class($val) == 'soapval'){
 391              return $val->serialize($use);
 392          }
 393          // force valid name if necessary
 394          if (is_numeric($name)) {
 395              $name = '__numeric_' . $name;
 396          } elseif (! $name) {
 397              $name = 'noname';
 398          }
 399          // if name has ns, add ns prefix to name
 400          $xmlns = '';
 401          if($name_ns){
 402              $prefix = 'nu'.rand(1000,9999);
 403              $name = $prefix.':'.$name;
 404              $xmlns .= " xmlns:$prefix=\"$name_ns\"";
 405          }
 406          // if type is prefixed, create type prefix
 407          if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
 408              // need to fix this. shouldn't default to xsd if no ns specified
 409              // w/o checking against typemap
 410              $type_prefix = 'xsd';
 411          } elseif($type_ns){
 412              $type_prefix = 'ns'.rand(1000,9999);
 413              $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
 414          }
 415          // serialize attributes if present
 416          $atts = '';
 417          if($attributes){
 418              foreach($attributes as $k => $v){
 419                  $atts .= " $k=\"".$this->expandEntities($v).'"';
 420              }
 421          }
 422          // serialize null value
 423          if (is_null($val)) {
 424              if ($use == 'literal') {
 425                  // TODO: depends on minOccurs
 426                  return "<$name$xmlns $atts/>";
 427              } else {
 428                  if (isset($type) && isset($type_prefix)) {
 429                      $type_str = " xsi:type=\"$type_prefix:$type\"";
 430                  } else {
 431                      $type_str = '';
 432                  }
 433                  return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
 434              }
 435          }
 436          // serialize if an xsd built-in primitive type
 437          if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
 438              if (is_bool($val)) {
 439                  if ($type == 'boolean') {
 440                      $val = $val ? 'true' : 'false';
 441                  } elseif (! $val) {
 442                      $val = 0;
 443                  }
 444              } else if (is_string($val)) {
 445                  $val = $this->expandEntities($val);
 446              }
 447              if ($use == 'literal') {
 448                  return "<$name$xmlns $atts>$val</$name>";
 449              } else {
 450                  return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</$name>";
 451              }
 452          }
 453          // detect type and serialize
 454          $xml = '';
 455          switch(true) {
 456              case (is_bool($val) || $type == 'boolean'):
 457                  if ($type == 'boolean') {
 458                      $val = $val ? 'true' : 'false';
 459                  } elseif (! $val) {
 460                      $val = 0;
 461                  }
 462                  if ($use == 'literal') {
 463                      $xml .= "<$name$xmlns $atts>$val</$name>";
 464                  } else {
 465                      $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
 466                  }
 467                  break;
 468              case (is_int($val) || is_long($val) || $type == 'int'):
 469                  if ($use == 'literal') {
 470                      $xml .= "<$name$xmlns $atts>$val</$name>";
 471                  } else {
 472                      $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
 473                  }
 474                  break;
 475              case (is_float($val)|| is_double($val) || $type == 'float'):
 476                  if ($use == 'literal') {
 477                      $xml .= "<$name$xmlns $atts>$val</$name>";
 478                  } else {
 479                      $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
 480                  }
 481                  break;
 482              case (is_string($val) || $type == 'string'):
 483                  $val = $this->expandEntities($val);
 484                  if ($use == 'literal') {
 485                      $xml .= "<$name$xmlns $atts>$val</$name>";
 486                  } else {
 487                      $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
 488                  }
 489                  break;
 490              case is_object($val):
 491                  if (! $name) {
 492                      $name = get_class($val);
 493                      $this->debug("In serialize_val, used class name $name as element name");
 494                  } else {
 495                      $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
 496                  }
 497                  foreach(get_object_vars($val) as $k => $v){
 498                      $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
 499                  }
 500                  $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
 501                  break;
 502              break;
 503              case (is_array($val) || $type):
 504                  // detect if struct or array
 505                  $valueType = $this->isArraySimpleOrStruct($val);
 506                  if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
 507                      $i = 0;
 508                      if(is_array($val) && count($val)> 0){
 509                          foreach($val as $v){
 510                              if(is_object($v) && get_class($v) ==  'soapval'){
 511                                  $tt_ns = $v->type_ns;
 512                                  $tt = $v->type;
 513                              } elseif (is_array($v)) {
 514                                  $tt = $this->isArraySimpleOrStruct($v);
 515                              } else {
 516                                  $tt = gettype($v);
 517                              }
 518                              $array_types[$tt] = 1;
 519                              // TODO: for literal, the name should be $name
 520                              $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
 521                              ++$i;
 522                          }
 523                          if(count($array_types) > 1){
 524                              $array_typename = 'xsd:anyType';
 525                          } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
 526                              if ($tt == 'integer') {
 527                                  $tt = 'int';
 528                              }
 529                              $array_typename = 'xsd:'.$tt;
 530                          } elseif(isset($tt) && $tt == 'arraySimple'){
 531                              $array_typename = 'SOAP-ENC:Array';
 532                          } elseif(isset($tt) && $tt == 'arrayStruct'){
 533                              $array_typename = 'unnamed_struct_use_soapval';
 534                          } else {
 535                              // if type is prefixed, create type prefix
 536                              if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
 537                                   $array_typename = 'xsd:' . $tt;
 538                              } elseif ($tt_ns) {
 539                                  $tt_prefix = 'ns' . rand(1000, 9999);
 540                                  $array_typename = "$tt_prefix:$tt";
 541                                  $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
 542                              } else {
 543                                  $array_typename = $tt;
 544                              }
 545                          }
 546                          $array_type = $i;
 547                          if ($use == 'literal') {
 548                              $type_str = '';
 549                          } else if (isset($type) && isset($type_prefix)) {
 550                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 551                          } else {
 552                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
 553                          }
 554                      // empty array
 555                      } else {
 556                          if ($use == 'literal') {
 557                              $type_str = '';
 558                          } else if (isset($type) && isset($type_prefix)) {
 559                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 560                          } else {
 561                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
 562                          }
 563                      }
 564                      // TODO: for array in literal, there is no wrapper here
 565                      $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
 566                  } else {
 567                      // got a struct
 568                      if(isset($type) && isset($type_prefix)){
 569                          $type_str = " xsi:type=\"$type_prefix:$type\"";
 570                      } else {
 571                          $type_str = '';
 572                      }
 573                      if ($use == 'literal') {
 574                          $xml .= "<$name$xmlns $atts>";
 575                      } else {
 576                          $xml .= "<$name$xmlns$type_str$atts>";
 577                      }
 578                      foreach($val as $k => $v){
 579                          // Apache Map
 580                          if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
 581                              $xml .= '<item>';
 582                              $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
 583                              $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
 584                              $xml .= '</item>';
 585                          } else {
 586                              $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
 587                          }
 588                      }
 589                      $xml .= "</$name>";
 590                  }
 591                  break;
 592              default:
 593                  $xml .= 'not detected, got '.gettype($val).' for '.$val;
 594                  break;
 595          }
 596          return $xml;
 597      }
 598  
 599      /**
 600      * serializes a message
 601      *
 602      * @param string $body the XML of the SOAP body
 603      * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers
 604      * @param array $namespaces optional the namespaces used in generating the body and headers
 605      * @param string $style optional (rpc|document)
 606      * @param string $use optional (encoded|literal)
 607      * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
 608      * @return string the message
 609      * @access public
 610      */
 611      function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
 612      // TODO: add an option to automatically run utf8_encode on $body and $headers
 613      // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
 614      // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
 615  
 616      $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
 617      $this->debug("headers:");
 618      $this->appendDebug($this->varDump($headers));
 619      $this->debug("namespaces:");
 620      $this->appendDebug($this->varDump($namespaces));
 621  
 622      // serialize namespaces
 623      $ns_string = '';
 624      foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
 625          $ns_string .= " xmlns:$k=\"$v\"";
 626      }
 627      if($encodingStyle) {
 628          $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
 629      }
 630  
 631      // serialize headers
 632      if($headers){
 633          if (is_array($headers)) {
 634              $xml = '';
 635              foreach ($headers as $header) {
 636                  $xml .= $this->serialize_val($header, false, false, false, false, false, $use);
 637              }
 638              $headers = $xml;
 639              $this->debug("In serializeEnvelope, serialzied array of headers to $headers");
 640          }
 641          $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
 642      }
 643      // serialize envelope
 644      return
 645      '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
 646      '<SOAP-ENV:Envelope'.$ns_string.">".
 647      $headers.
 648      "<SOAP-ENV:Body>".
 649          $body.
 650      "</SOAP-ENV:Body>".
 651      "</SOAP-ENV:Envelope>";
 652      }
 653  
 654      /**
 655       * formats a string to be inserted into an HTML stream
 656       *
 657       * @param string $str The string to format
 658       * @return string The formatted string
 659       * @access public
 660       * @deprecated
 661       */
 662      function formatDump($str){
 663          $str = htmlspecialchars($str);
 664          return nl2br($str);
 665      }
 666  
 667      /**
 668      * contracts (changes namespace to prefix) a qualified name
 669      *
 670      * @param    string $qname qname
 671      * @return    string contracted qname
 672      * @access   private
 673      */
 674  	function contractQname($qname){
 675          // get element namespace
 676          //$this->xdebug("Contract $qname");
 677          if (strrpos($qname, ':')) {
 678              // get unqualified name
 679              $name = substr($qname, strrpos($qname, ':') + 1);
 680              // get ns
 681              $ns = substr($qname, 0, strrpos($qname, ':'));
 682              $p = $this->getPrefixFromNamespace($ns);
 683              if ($p) {
 684                  return $p . ':' . $name;
 685              }
 686              return $qname;
 687          } else {
 688              return $qname;
 689          }
 690      }
 691  
 692      /**
 693      * expands (changes prefix to namespace) a qualified name
 694      *
 695      * @param    string $string qname
 696      * @return    string expanded qname
 697      * @access   private
 698      */
 699  	function expandQname($qname){
 700          // get element prefix
 701          if(strpos($qname,':') && !ereg('^http://',$qname)){
 702              // get unqualified name
 703              $name = substr(strstr($qname,':'),1);
 704              // get ns prefix
 705              $prefix = substr($qname,0,strpos($qname,':'));
 706              if(isset($this->namespaces[$prefix])){
 707                  return $this->namespaces[$prefix].':'.$name;
 708              } else {
 709                  return $qname;
 710              }
 711          } else {
 712              return $qname;
 713          }
 714      }
 715  
 716      /**
 717      * returns the local part of a prefixed string
 718      * returns the original string, if not prefixed
 719      *
 720      * @param string $str The prefixed string
 721      * @return string The local part
 722      * @access public
 723      */
 724  	function getLocalPart($str){
 725          if($sstr = strrchr($str,':')){
 726              // get unqualified name
 727              return substr( $sstr, 1 );
 728          } else {
 729              return $str;
 730          }
 731      }
 732  
 733      /**
 734      * returns the prefix part of a prefixed string
 735      * returns false, if not prefixed
 736      *
 737      * @param string $str The prefixed string
 738      * @return mixed The prefix or false if there is no prefix
 739      * @access public
 740      */
 741  	function getPrefix($str){
 742          if($pos = strrpos($str,':')){
 743              // get prefix
 744              return substr($str,0,$pos);
 745          }
 746          return false;
 747      }
 748  
 749      /**
 750      * pass it a prefix, it returns a namespace
 751      *
 752      * @param string $prefix The prefix
 753      * @return mixed The namespace, false if no namespace has the specified prefix
 754      * @access public
 755      */
 756  	function getNamespaceFromPrefix($prefix){
 757          if (isset($this->namespaces[$prefix])) {
 758              return $this->namespaces[$prefix];
 759          }
 760          //$this->setError("No namespace registered for prefix '$prefix'");
 761          return false;
 762      }
 763  
 764      /**
 765      * returns the prefix for a given namespace (or prefix)
 766      * or false if no prefixes registered for the given namespace
 767      *
 768      * @param string $ns The namespace
 769      * @return mixed The prefix, false if the namespace has no prefixes
 770      * @access public
 771      */
 772  	function getPrefixFromNamespace($ns) {
 773          foreach ($this->namespaces as $p => $n) {
 774              if ($ns == $n || $ns == $p) {
 775                  $this->usedNamespaces[$p] = $n;
 776                  return $p;
 777              }
 778          }
 779          return false;
 780      }
 781  
 782      /**
 783      * returns the time in ODBC canonical form with microseconds
 784      *
 785      * @return string The time in ODBC canonical form with microseconds
 786      * @access public
 787      */
 788  	function getmicrotime() {
 789          if (function_exists('gettimeofday')) {
 790              $tod = gettimeofday();
 791              $sec = $tod['sec'];
 792              $usec = $tod['usec'];
 793          } else {
 794              $sec = time();
 795              $usec = 0;
 796          }
 797          return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
 798      }
 799  
 800      /**
 801       * Returns a string with the output of var_dump
 802       *
 803       * @param mixed $data The variable to var_dump
 804       * @return string The output of var_dump
 805       * @access public
 806       */
 807      function varDump($data) {
 808          ob_start();
 809          var_dump($data);
 810          $ret_val = ob_get_contents();
 811          ob_end_clean();
 812          return $ret_val;
 813      }
 814  }
 815  
 816  // XML Schema Datatype Helper Functions
 817  
 818  //xsd:dateTime helpers
 819  
 820  /**
 821  * convert unix timestamp to ISO 8601 compliant date string
 822  *
 823  * @param    string $timestamp Unix time stamp
 824  * @access   public
 825  */
 826  function timestamp_to_iso8601($timestamp,$utc=true){
 827      $datestr = date('Y-m-d\TH:i:sO',$timestamp);
 828      if($utc){
 829          $eregStr =
 830          '([0-9]{4})-'.    // centuries & years CCYY-
 831          '([0-9]{2})-'.    // months MM-
 832          '([0-9]{2})'.    // days DD
 833          'T'.            // separator T
 834          '([0-9]{2}):'.    // hours hh:
 835          '([0-9]{2}):'.    // minutes mm:
 836          '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
 837          '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
 838  
 839          if(ereg($eregStr,$datestr,$regs)){
 840              return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
 841          }
 842          return false;
 843      } else {
 844          return $datestr;
 845      }
 846  }
 847  
 848  /**
 849  * convert ISO 8601 compliant date string to unix timestamp
 850  *
 851  * @param    string $datestr ISO 8601 compliant date string
 852  * @access   public
 853  */
 854  function iso8601_to_timestamp($datestr){
 855      $eregStr =
 856      '([0-9]{4})-'.    // centuries & years CCYY-
 857      '([0-9]{2})-'.    // months MM-
 858      '([0-9]{2})'.    // days DD
 859      'T'.            // separator T
 860      '([0-9]{2}):'.    // hours hh:
 861      '([0-9]{2}):'.    // minutes mm:
 862      '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
 863      '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
 864      if(ereg($eregStr,$datestr,$regs)){
 865          // not utc
 866          if($regs[8] != 'Z'){
 867              $op = substr($regs[8],0,1);
 868              $h = substr($regs[8],1,2);
 869              $m = substr($regs[8],strlen($regs[8])-2,2);
 870              if($op == '-'){
 871                  $regs[4] = $regs[4] + $h;
 872                  $regs[5] = $regs[5] + $m;
 873              } elseif($op == '+'){
 874                  $regs[4] = $regs[4] - $h;
 875                  $regs[5] = $regs[5] - $m;
 876              }
 877          }
 878          return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
 879      } else {
 880          return false;
 881      }
 882  }
 883  
 884  /**
 885  * sleeps some number of microseconds
 886  *
 887  * @param    string $usec the number of microseconds to sleep
 888  * @access   public
 889  * @deprecated
 890  */
 891  function usleepWindows($usec)
 892  {
 893      $start = gettimeofday();
 894      
 895      do
 896      {
 897          $stop = gettimeofday();
 898          $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
 899          + $stop['usec'] - $start['usec'];
 900      }
 901      while ($timePassed < $usec);
 902  }
 903  
 904  ?><?php
 905  
 906  
 907  
 908  /**
 909  * Contains information for a SOAP fault.
 910  * Mainly used for returning faults from deployed functions
 911  * in a server instance.
 912  * @author   Dietrich Ayala <dietrich@ganx4.com>
 913  * @version  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler Exp $
 914  * @access public
 915  */
 916  class soap_fault extends nusoap_base {
 917      /**
 918       * The fault code (client|server)
 919       * @var string
 920       * @access private
 921       */
 922      var $faultcode;
 923      /**
 924       * The fault actor
 925       * @var string
 926       * @access private
 927       */
 928      var $faultactor;
 929      /**
 930       * The fault string, a description of the fault
 931       * @var string
 932       * @access private
 933       */
 934      var $faultstring;
 935      /**
 936       * The fault detail, typically a string or array of string
 937       * @var mixed
 938       * @access private
 939       */
 940      var $faultdetail;
 941  
 942      /**
 943      * constructor
 944      *
 945      * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
 946      * @param string $faultactor only used when msg routed between multiple actors
 947      * @param string $faultstring human readable error message
 948      * @param mixed $faultdetail detail, typically a string or array of string
 949      */
 950  	function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
 951          parent::nusoap_base();
 952          $this->faultcode = $faultcode;
 953          $this->faultactor = $faultactor;
 954          $this->faultstring = $faultstring;
 955          $this->faultdetail = $faultdetail;
 956      }
 957  
 958      /**
 959      * serialize a fault
 960      *
 961      * @return    string    The serialization of the fault instance.
 962      * @access   public
 963      */
 964  	function serialize(){
 965          $ns_string = '';
 966          foreach($this->namespaces as $k => $v){
 967              $ns_string .= "\n  xmlns:$k=\"$v\"";
 968          }
 969          $return_msg =
 970              '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
 971              '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
 972                  '<SOAP-ENV:Body>'.
 973                  '<SOAP-ENV:Fault>'.
 974                      $this->serialize_val($this->faultcode, 'faultcode').
 975                      $this->serialize_val($this->faultactor, 'faultactor').
 976                      $this->serialize_val($this->faultstring, 'faultstring').
 977                      $this->serialize_val($this->faultdetail, 'detail').
 978                  '</SOAP-ENV:Fault>'.
 979                  '</SOAP-ENV:Body>'.
 980              '</SOAP-ENV:Envelope>';
 981          return $return_msg;
 982      }
 983  }
 984  
 985  
 986  
 987  ?><?php
 988  
 989  
 990  
 991  /**
 992  * parses an XML Schema, allows access to it's data, other utility methods
 993  * no validation... yet.
 994  * very experimental and limited. As is discussed on XML-DEV, I'm one of the people
 995  * that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
 996  * tutorials I refer to :)
 997  *
 998  * @author   Dietrich Ayala <dietrich@ganx4.com>
 999  * @version  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler Exp $
1000  * @access   public
1001  */
1002  class XMLSchema extends nusoap_base  {
1003      
1004      // files
1005      var $schema = '';
1006      var $xml = '';
1007      // namespaces
1008      var $enclosingNamespaces;
1009      // schema info
1010      var $schemaInfo = array();
1011      var $schemaTargetNamespace = '';
1012      // types, elements, attributes defined by the schema
1013      var $attributes = array();
1014      var $complexTypes = array();
1015      var $complexTypeStack = array();
1016      var $currentComplexType = null;
1017      var $elements = array();
1018      var $elementStack = array();
1019      var $currentElement = null;
1020      var $simpleTypes = array();
1021      var $simpleTypeStack = array();
1022      var $currentSimpleType = null;
1023      // imports
1024      var $imports = array();
1025      // parser vars
1026      var $parser;
1027      var $position = 0;
1028      var $depth = 0;
1029      var $depth_array = array();
1030      var $message = array();
1031      var $defaultNamespace = array();
1032      
1033      /**
1034      * constructor
1035      *
1036      * @param    string $schema schema document URI
1037      * @param    string $xml xml document URI
1038      * @param    string $namespaces namespaces defined in enclosing XML
1039      * @access   public
1040      */
1041  	function XMLSchema($schema='',$xml='',$namespaces=array()){
1042          parent::nusoap_base();
1043          $this->debug('xmlschema class instantiated, inside constructor');
1044          // files
1045          $this->schema = $schema;
1046          $this->xml = $xml;
1047  
1048          // namespaces
1049          $this->enclosingNamespaces = $namespaces;
1050          $this->namespaces = array_merge($this->namespaces, $namespaces);
1051  
1052          // parse schema file
1053          if($schema != ''){
1054              $this->debug('initial schema file: '.$schema);
1055              $this->parseFile($schema, 'schema');
1056          }
1057  
1058          // parse xml file
1059          if($xml != ''){
1060              $this->debug('initial xml file: '.$xml);
1061              $this->parseFile($xml, 'xml');
1062          }
1063  
1064      }
1065  
1066      /**
1067      * parse an XML file
1068      *
1069      * @param string $xml, path/URL to XML file
1070      * @param string $type, (schema | xml)
1071      * @return boolean
1072      * @access public
1073      */
1074  	function parseFile($xml,$type){
1075          // parse xml file
1076          if($xml != ""){
1077              $xmlStr = @join("",@file($xml));
1078              if($xmlStr == ""){
1079                  $msg = 'Error reading XML from '.$xml;
1080                  $this->setError($msg);
1081                  $this->debug($msg);
1082              return false;
1083              } else {
1084                  $this->debug("parsing $xml");
1085                  $this->parseString($xmlStr,$type);
1086                  $this->debug("done parsing $xml");
1087              return true;
1088              }
1089          }
1090          return false;
1091      }
1092  
1093      /**
1094      * parse an XML string
1095      *
1096      * @param    string $xml path or URL
1097      * @param string $type, (schema|xml)
1098      * @access   private
1099      */
1100  	function parseString($xml,$type){
1101          // parse xml string
1102          if($xml != ""){
1103  
1104              // Create an XML parser.
1105              $this->parser = xml_parser_create();
1106              // Set the options for parsing the XML data.
1107              xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1108  
1109              // Set the object for the parser.
1110              xml_set_object($this->parser, $this);
1111  
1112              // Set the element handlers for the parser.
1113              if($type == "schema"){
1114                  xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1115                  xml_set_character_data_handler($this->parser,'schemaCharacterData');
1116              } elseif($type == "xml"){
1117                  xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1118                  xml_set_character_data_handler($this->parser,'xmlCharacterData');
1119              }
1120  
1121              // Parse the XML file.
1122              if(!xml_parse($this->parser,$xml,true)){
1123              // Display an error message.
1124                  $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1125                  xml_get_current_line_number($this->parser),
1126                  xml_error_string(xml_get_error_code($this->parser))
1127                  );
1128                  $this->debug($errstr);
1129                  $this->debug("XML payload:\n" . $xml);
1130                  $this->setError($errstr);
1131              }
1132              
1133              xml_parser_free($this->parser);
1134          } else{
1135              $this->debug('no xml passed to parseString()!!');
1136              $this->setError('no xml passed to parseString()!!');
1137          }
1138      }
1139  
1140      /**
1141      * start-element handler
1142      *
1143      * @param    string $parser XML parser object
1144      * @param    string $name element name
1145      * @param    string $attrs associative array of attributes
1146      * @access   private
1147      */
1148  	function schemaStartElement($parser, $name, $attrs) {
1149          
1150          // position in the total number of elements, starting from 0
1151          $pos = $this->position++;
1152          $depth = $this->depth++;
1153          // set self as current value for this depth
1154          $this->depth_array[$depth] = $pos;
1155          $this->message[$pos] = array('cdata' => ''); 
1156          if ($depth > 0) {
1157              $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1158          } else {
1159              $this->defaultNamespace[$pos] = false;
1160          }
1161  
1162          // get element prefix
1163          if($prefix = $this->getPrefix($name)){
1164              // get unqualified name
1165              $name = $this->getLocalPart($name);
1166          } else {
1167              $prefix = '';
1168          }
1169          
1170          // loop thru attributes, expanding, and registering namespace declarations
1171          if(count($attrs) > 0){
1172              foreach($attrs as $k => $v){
1173                  // if ns declarations, add to class level array of valid namespaces
1174                  if(ereg("^xmlns",$k)){
1175                      //$this->xdebug("$k: $v");
1176                      //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1177                      if($ns_prefix = substr(strrchr($k,':'),1)){
1178                          //$this->xdebug("Add namespace[$ns_prefix] = $v");
1179                          $this->namespaces[$ns_prefix] = $v;
1180                      } else {
1181                          $this->defaultNamespace[$pos] = $v;
1182                          if (! $this->getPrefixFromNamespace($v)) {
1183                              $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1184                          }
1185                      }
1186                      if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1187                          $this->XMLSchemaVersion = $v;
1188                          $this->namespaces['xsi'] = $v.'-instance';
1189                      }
1190                  }
1191              }
1192              foreach($attrs as $k => $v){
1193                  // expand each attribute
1194                  $k = strpos($k,':') ? $this->expandQname($k) : $k;
1195                  $v = strpos($v,':') ? $this->expandQname($v) : $v;
1196                  $eAttrs[$k] = $v;
1197              }
1198              $attrs = $eAttrs;
1199          } else {
1200              $attrs = array();
1201          }
1202          // find status, register data
1203          switch($name){
1204              case 'all':            // (optional) compositor content for a complexType
1205              case 'choice':
1206              case 'group':
1207              case 'sequence':
1208                  //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1209                  $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1210                  //if($name == 'all' || $name == 'sequence'){
1211                  //    $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1212                  //}
1213              break;
1214              case 'attribute':    // complexType attribute
1215                  //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1216                  $this->xdebug("parsing attribute:");
1217                  $this->appendDebug($this->varDump($attrs));
1218                  if (!isset($attrs['form'])) {
1219                      $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1220                  }
1221                  if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1222                      $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1223                      if (!strpos($v, ':')) {
1224                          // no namespace in arrayType attribute value...
1225                          if ($this->defaultNamespace[$pos]) {
1226                              // ...so use the default
1227                              $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1228                          }
1229                      }
1230                  }
1231                  if(isset($attrs['name'])){
1232                      $this->attributes[$attrs['name']] = $attrs;
1233                      $aname = $attrs['name'];
1234                  } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1235                      if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1236                          $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1237                      } else {
1238                          $aname = '';
1239                      }
1240                  } elseif(isset($attrs['ref'])){
1241                      $aname = $attrs['ref'];
1242                      $this->attributes[$attrs['ref']] = $attrs;
1243                  }
1244                  
1245                  if($this->currentComplexType){    // This should *always* be
1246                      $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1247                  }
1248                  // arrayType attribute
1249                  if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1250                      $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1251                      $prefix = $this->getPrefix($aname);
1252                      if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1253                          $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1254                      } else {
1255                          $v = '';
1256                      }
1257                      if(strpos($v,'[,]')){
1258                          $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1259                      }
1260                      $v = substr($v,0,strpos($v,'[')); // clip the []
1261                      if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1262                          $v = $this->XMLSchemaVersion.':'.$v;
1263                      }
1264                      $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1265                  }
1266              break;
1267              case 'complexContent':    // (optional) content for a complexType
1268              break;
1269              case 'complexType':
1270                  array_push($this->complexTypeStack, $this->currentComplexType);
1271                  if(isset($attrs['name'])){
1272                      $this->xdebug('processing named complexType '.$attrs['name']);
1273                      //$this->currentElement = false;
1274                      $this->currentComplexType = $attrs['name'];
1275                      $this->complexTypes[$this->currentComplexType] = $attrs;
1276                      $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1277                      // This is for constructs like
1278                      //           <complexType name="ListOfString" base="soap:Array">
1279                      //                <sequence>
1280                      //                    <element name="string" type="xsd:string"
1281                      //                        minOccurs="0" maxOccurs="unbounded" />
1282                      //                </sequence>
1283                      //            </complexType>
1284                      if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1285                          $this->xdebug('complexType is unusual array');
1286                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1287                      } else {
1288                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1289                      }
1290                  }else{
1291                      $this->xdebug('processing unnamed complexType for element '.$this->currentElement);
1292                      $this->currentComplexType = $this->currentElement . '_ContainedType';
1293                      //$this->currentElement = false;
1294                      $this->complexTypes[$this->currentComplexType] = $attrs;
1295                      $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1296                      // This is for constructs like
1297                      //           <complexType name="ListOfString" base="soap:Array">
1298                      //                <sequence>
1299                      //                    <element name="string" type="xsd:string"
1300                      //                        minOccurs="0" maxOccurs="unbounded" />
1301                      //                </sequence>
1302                      //            </complexType>
1303                      if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1304                          $this->xdebug('complexType is unusual array');
1305                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1306                      } else {
1307                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1308                      }
1309                  }
1310              break;
1311              case 'element':
1312                  array_push($this->elementStack, $this->currentElement);
1313                  // elements defined as part of a complex type should
1314                  // not really be added to $this->elements, but for some
1315                  // reason, they are
1316                  if (!isset($attrs['form'])) {
1317                      $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1318                  }
1319                  if(isset($attrs['type'])){
1320                      $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1321                      if (! $this->getPrefix($attrs['type'])) {
1322                          if ($this->defaultNamespace[$pos]) {
1323                              $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1324                              $this->xdebug('used default namespace to make type ' . $attrs['type']);
1325                          }
1326                      }
1327                      // This is for constructs like
1328                      //           <complexType name="ListOfString" base="soap:Array">
1329                      //                <sequence>
1330                      //                    <element name="string" type="xsd:string"
1331                      //                        minOccurs="0" maxOccurs="unbounded" />
1332                      //                </sequence>
1333                      //            </complexType>
1334                      if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1335                          $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1336                          $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1337                      }
1338                      $this->currentElement = $attrs['name'];
1339                      $this->elements[ $attrs['name'] ] = $attrs;
1340                      $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1341                      $ename = $attrs['name'];
1342                  } elseif(isset($attrs['ref'])){
1343                      $this->xdebug("processing element as ref to ".$attrs['ref']);
1344                      $this->currentElement = "ref to ".$attrs['ref'];
1345                      $ename = $this->getLocalPart($attrs['ref']);
1346                  } else {
1347                      $this->xdebug("processing untyped element ".$attrs['name']);
1348                      $this->currentElement = $attrs['name'];
1349                      $this->elements[ $attrs['name'] ] = $attrs;
1350                      $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1351                      $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
1352                      $this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
1353                      $ename = $attrs['name'];
1354                  }
1355                  if(isset($ename) && $this->currentComplexType){
1356                      $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1357                  }
1358              break;
1359              case 'enumeration':    //    restriction value list member
1360                  $this->xdebug('enumeration ' . $attrs['value']);
1361                  if ($this->currentSimpleType) {
1362                      $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1363                  } elseif ($this->currentComplexType) {
1364                      $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1365                  }
1366              break;
1367              case 'extension':    // simpleContent or complexContent type extension
1368                  $this->xdebug('extension ' . $attrs['base']);
1369                  if ($this->currentComplexType) {
1370                      $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1371                  }
1372              break;
1373              case 'import':
1374                  if (isset($attrs['schemaLocation'])) {
1375                      //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1376                      $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1377                  } else {
1378                      //$this->xdebug('import namespace ' . $attrs['namespace']);
1379                      $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1380                      if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1381                          $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1382                      }
1383                  }
1384              break;
1385              case 'list':    // simpleType value list
1386              break;
1387              case 'restriction':    // simpleType, simpleContent or complexContent value restriction
1388                  $this->xdebug('restriction ' . $attrs['base']);
1389                  if($this->currentSimpleType){
1390                      $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1391                  } elseif($this->currentComplexType){
1392                      $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1393                      if(strstr($attrs['base'],':') == ':Array'){
1394                          $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1395                      }
1396                  }
1397              break;
1398              case 'schema':
1399                  $this->schemaInfo = $attrs;
1400                  $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1401                  if (isset($attrs['targetNamespace'])) {
1402                      $this->schemaTargetNamespace = $attrs['targetNamespace'];
1403                  }
1404                  if (!isset($attrs['elementFormDefault'])) {
1405                      $this->schemaInfo['elementFormDefault'] = 'unqualified';
1406                  }
1407                  if (!isset($attrs['attributeFormDefault'])) {
1408                      $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1409                  }
1410              break;
1411              case 'simpleContent':    // (optional) content for a complexType
1412              break;
1413              case 'simpleType':
1414                  array_push($this->simpleTypeStack, $this->currentSimpleType);
1415                  if(isset($attrs['name'])){
1416                      $this->xdebug("processing simpleType for name " . $attrs['name']);
1417                      $this->currentSimpleType = $attrs['name'];
1418                      $this->simpleTypes[ $attrs['name'] ] = $attrs;
1419                      $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1420                      $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1421                  } else {
1422                      $this->xdebug('processing unnamed simpleType for element '.$this->currentElement);
1423                      $this->currentSimpleType = $this->currentElement . '_ContainedType';
1424                      //$this->currentElement = false;
1425                      $this->simpleTypes[$this->currentSimpleType] = $attrs;
1426                      $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1427                  }
1428              break;
1429              case 'union':    // simpleType type list
1430              break;
1431              default:
1432                  //$this->xdebug("do not have anything to do for element $name");
1433          }
1434      }
1435  
1436      /**
1437      * end-element handler
1438      *
1439      * @param    string $parser XML parser object
1440      * @param    string $name element name
1441      * @access   private
1442      */
1443  	function schemaEndElement($parser, $name) {
1444          // bring depth down a notch
1445          $this->depth--;
1446          // position of current element is equal to the last value left in depth_array for my depth
1447          if(isset($this->depth_array[$this->depth])){
1448              $pos = $this->depth_array[$this->depth];
1449          }
1450          // get element prefix
1451          if ($prefix = $this->getPrefix($name)){
1452              // get unqualified name
1453              $name = $this->getLocalPart($name);
1454          } else {
1455              $prefix = '';
1456          }
1457          // move on...
1458          if($name == 'complexType'){
1459              $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1460              $this->currentComplexType = array_pop($this->complexTypeStack);
1461              //$this->currentElement = false;
1462          }
1463          if($name == 'element'){
1464              $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1465              $this->currentElement = array_pop($this->elementStack);
1466          }
1467          if($name == 'simpleType'){
1468              $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1469              $this->currentSimpleType = array_pop($this->simpleTypeStack);
1470          }
1471      }
1472  
1473      /**
1474      * element content handler
1475      *
1476      * @param    string $parser XML parser object
1477      * @param    string $data element content
1478      * @access   private
1479      */
1480  	function schemaCharacterData($parser, $data){
1481          $pos = $this->depth_array[$this->depth - 1];
1482          $this->message[$pos]['cdata'] .= $data;
1483      }
1484  
1485      /**
1486      * serialize the schema
1487      *
1488      * @access   public
1489      */
1490  	function serializeSchema(){
1491  
1492          $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1493          $xml = '';
1494          // imports
1495          if (sizeof($this->imports) > 0) {
1496              foreach($this->imports as $ns => $list) {
1497                  foreach ($list as $ii) {
1498                      if ($ii['location'] != '') {
1499                          $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1500                      } else {
1501                          $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1502                      }
1503                  }
1504              } 
1505          } 
1506          // complex types
1507          foreach($this->complexTypes as $typeName => $attrs){
1508              $contentStr = '';
1509              // serialize child elements
1510              if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1511                  foreach($attrs['elements'] as $element => $eParts){
1512                      if(isset($eParts['ref'])){
1513                          $contentStr .= "   <$schemaPrefix:element ref=\"$element\"/>\n";
1514                      } else {
1515                          $contentStr .= "   <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1516                          foreach ($eParts as $aName => $aValue) {
1517                              // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1518                              if ($aName != 'name' && $aName != 'type') {
1519                                  $contentStr .= " $aName=\"$aValue\"";
1520                              }
1521                          }
1522                          $contentStr .= "/>\n";
1523                      }
1524                  }
1525                  // compositor wraps elements
1526                  if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1527                      $contentStr = "  <$schemaPrefix:$attrs[compositor]>\n".$contentStr."  </$schemaPrefix:$attrs[compositor]>\n";
1528                  }
1529              }
1530              // attributes
1531              if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1532                  foreach($attrs['attrs'] as $attr => $aParts){
1533                      $contentStr .= "    <$schemaPrefix:attribute";
1534                      foreach ($aParts as $a => $v) {
1535                          if ($a == 'ref' || $a == 'type') {
1536                              $contentStr .= " $a=\"".$this->contractQName($v).'"';
1537                          } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1538                              $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1539                              $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1540                          } else {
1541                              $contentStr .= " $a=\"$v\"";
1542                          }
1543                      }
1544                      $contentStr .= "/>\n";
1545                  }
1546              }
1547              // if restriction
1548              if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1549                  $contentStr = "   <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."   </$schemaPrefix:restriction>\n";
1550                  // complex or simple content
1551                  if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1552                      $contentStr = "  <$schemaPrefix:complexContent>\n".$contentStr."  </$schemaPrefix:complexContent>\n";
1553                  }
1554              }
1555              // finalize complex type
1556              if($contentStr != ''){
1557                  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1558              } else {
1559                  $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1560              }
1561              $xml .= $contentStr;
1562          }
1563          // simple types
1564          if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1565              foreach($this->simpleTypes as $typeName => $eParts){
1566                  $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n  <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\"/>\n";
1567                  if (isset($eParts['enumeration'])) {
1568                      foreach ($eParts['enumeration'] as $e) {
1569                          $xml .= "  <$schemaPrefix:enumeration value=\"$e\"/>\n";
1570                      }
1571                  }
1572                  $xml .= " </$schemaPrefix:simpleType>";
1573              }
1574          }
1575          // elements
1576          if(isset($this->elements) && count($this->elements) > 0){
1577              foreach($this->elements as $element => $eParts){
1578                  $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1579              }
1580          }
1581          // attributes
1582          if(isset($this->attributes) && count($this->attributes) > 0){
1583              foreach($this->attributes as $attr => $aParts){
1584                  $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1585              }
1586          }
1587          // finish 'er up
1588          $el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
1589          foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1590              $el .= " xmlns:$nsp=\"$ns\"";
1591          }
1592          $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1593          return $xml;
1594      }
1595  
1596      /**
1597      * adds debug data to the clas level debug string
1598      *
1599      * @param    string $string debug data
1600      * @access   private
1601      */
1602  	function xdebug($string){
1603          $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1604      }
1605  
1606      /**
1607      * get the PHP type of a user defined type in the schema
1608      * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1609      * returns false if no type exists, or not w/ the given namespace
1610      * else returns a string that is either a native php type, or 'struct'
1611      *
1612      * @param string $type, name of defined type
1613      * @param string $ns, namespace of type
1614      * @return mixed
1615      * @access public
1616      * @deprecated
1617      */
1618  	function getPHPType($type,$ns){
1619          if(isset($this->typemap[$ns][$type])){
1620              //print "found type '$type' and ns $ns in typemap<br>";
1621              return $this->typemap[$ns][$type];
1622          } elseif(isset($this->complexTypes[$type])){
1623              //print "getting type '$type' and ns $ns from complexTypes array<br>";
1624              return $this->complexTypes[$type]['phpType'];
1625          }
1626          return false;
1627      }
1628  
1629      /**
1630      * returns an associative array of information about a given type
1631      * returns false if no type exists by the given name
1632      *
1633      *    For a complexType typeDef = array(
1634      *    'restrictionBase' => '',
1635      *    'phpType' => '',
1636      *    'compositor' => '(sequence|all)',
1637      *    'elements' => array(), // refs to elements array
1638      *    'attrs' => array() // refs to attributes array
1639      *    ... and so on (see addComplexType)
1640      *    )
1641      *
1642      *   For simpleType or element, the array has different keys.
1643      *
1644      * @param string
1645      * @return mixed
1646      * @access public
1647      * @see addComplexType
1648      * @see addSimpleType
1649      * @see addElement
1650      */
1651  	function getTypeDef($type){
1652          //$this->debug("in getTypeDef for type $type");
1653          if(isset($this->complexTypes[$type])){
1654              $this->xdebug("in getTypeDef, found complexType $type");
1655              return $this->complexTypes[$type];
1656          } elseif(isset($this->simpleTypes[$type])){
1657              $this->xdebug("in getTypeDef, found simpleType $type");
1658              if (!isset($this->simpleTypes[$type]['phpType'])) {
1659                  // get info for type to tack onto the simple type
1660                  // TODO: can this ever really apply (i.e. what is a simpleType really?)
1661                  $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1662                  $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1663                  $etype = $this->getTypeDef($uqType);
1664                  if ($etype) {
1665                      $this->xdebug("in getTypeDef, found type for simpleType $type:");
1666                      $this->xdebug($this->varDump($etype));
1667                      if (isset($etype['phpType'])) {
1668                          $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1669                      }
1670                      if (isset($etype['elements'])) {
1671                          $this->simpleTypes[$type]['elements'] = $etype['elements'];
1672                      }
1673                  }
1674              }
1675              return $this->simpleTypes[$type];
1676          } elseif(isset($this->elements[$type])){
1677              $this->xdebug("in getTypeDef, found element $type");
1678              if (!isset($this->elements[$type]['phpType'])) {
1679                  // get info for type to tack onto the element
1680                  $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1681                  $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1682                  $etype = $this->getTypeDef($uqType);
1683                  if ($etype) {
1684                      $this->xdebug("in getTypeDef, found type for element $type:");
1685                      $this->xdebug($this->varDump($etype));
1686                      if (isset($etype['phpType'])) {
1687                          $this->elements[$type]['phpType'] = $etype['phpType'];
1688                      }
1689                      if (isset($etype['elements'])) {
1690                          $this->elements[$type]['elements'] = $etype['elements'];
1691                      }
1692                  } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1693                      $this->xdebug("in getTypeDef, element $type is an XSD type");
1694                      $this->elements[$type]['phpType'] = 'scalar';
1695                  }
1696              }
1697              return $this->elements[$type];
1698          } elseif(isset($this->attributes[$type])){
1699              $this->xdebug("in getTypeDef, found attribute $type");
1700              return $this->attributes[$type];
1701          } elseif (ereg('_ContainedType$', $type)) {
1702              $this->xdebug("in getTypeDef, have an untyped element $type");
1703              $typeDef['typeClass'] = 'simpleType';
1704              $typeDef['phpType'] = 'scalar';
1705              $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1706              return $typeDef;
1707          }
1708          $this->xdebug("in getTypeDef, did not find $type");
1709          return false;
1710      }
1711  
1712      /**
1713      * returns a sample serialization of a given type, or false if no type by the given name
1714      *
1715      * @param string $type, name of type
1716      * @return mixed
1717      * @access public
1718      * @deprecated
1719      */
1720      function serializeTypeDef($type){
1721          //print "in sTD() for type $type<br>";
1722      if($typeDef = $this->getTypeDef($type)){
1723          $str .= '<'.$type;
1724          if(is_array($typeDef['attrs'])){
1725          foreach($attrs as $attName => $data){
1726              $str .= " $attName=\"{type = ".$data['type']."}\"";
1727          }
1728          }
1729          $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1730          if(count($typeDef['elements']) > 0){
1731          $str .= ">";
1732          foreach($typeDef['elements'] as $element => $eData){
1733              $str .= $this->serializeTypeDef($element);
1734          }
1735          $str .= "</$type>";
1736          } elseif($typeDef['typeClass'] == 'element') {
1737          $str .= "></$type>";
1738          } else {
1739          $str .= "/>";
1740          }
1741              return $str;
1742      }
1743          return false;
1744      }
1745  
1746      /**
1747      * returns HTML form elements that allow a user
1748      * to enter values for creating an instance of the given type.
1749      *
1750      * @param string $name, name for type instance
1751      * @param string $type, name of type
1752      * @return string
1753      * @access public
1754      * @deprecated
1755      */
1756  	function typeToForm($name,$type){
1757          // get typedef
1758          if($typeDef = $this->getTypeDef($type)){
1759              // if struct
1760              if($typeDef['phpType'] == 'struct'){
1761                  $buffer .= '<table>';
1762                  foreach($typeDef['elements'] as $child => $childDef){
1763                      $buffer .= "
1764                      <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1765                      <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1766                  }
1767                  $buffer .= '</table>';
1768              // if array
1769              } elseif($typeDef['phpType'] == 'array'){
1770                  $buffer .= '<table>';
1771                  for($i=0;$i < 3; $i++){
1772                      $buffer .= "
1773                      <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1774                      <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1775                  }
1776                  $buffer .= '</table>';
1777              // if scalar
1778              } else {
1779                  $buffer .= "<input type='text' name='parameters[$name]'>";
1780              }
1781          } else {
1782              $buffer .= "<input type='text' name='parameters[$name]'>";
1783          }
1784          return $buffer;
1785      }
1786      
1787      /**
1788      * adds a complex type to the schema
1789      * 
1790      * example: array
1791      * 
1792      * addType(
1793      *     'ArrayOfstring',
1794      *     'complexType',
1795      *     'array',
1796      *     '',
1797      *     'SOAP-ENC:Array',
1798      *     array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1799      *     'xsd:string'
1800      * );
1801      * 
1802      * example: PHP associative array ( SOAP Struct )
1803      * 
1804      * addType(
1805      *     'SOAPStruct',
1806      *     'complexType',
1807      *     'struct',
1808      *     'all',
1809      *     array('myVar'=> array('name'=>'myVar','type'=>'string')
1810      * );
1811      * 
1812      * @param name
1813      * @param typeClass (complexType|simpleType|attribute)
1814      * @param phpType: currently supported are array and struct (php assoc array)
1815      * @param compositor (all|sequence|choice)
1816      * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1817      * @param elements = array ( name = array(name=>'',type=>'') )
1818      * @param attrs = array(
1819      *     array(
1820      *        'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1821      *        "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1822      *     )
1823      * )
1824      * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1825      * @access public
1826      * @see getTypeDef
1827      */
1828  	function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1829          $this->complexTypes[$name] = array(
1830          'name'        => $name,
1831          'typeClass'    => $typeClass,
1832          'phpType'    => $phpType,
1833          'compositor'=> $compositor,
1834          'restrictionBase' => $restrictionBase,
1835          'elements'    => $elements,
1836          'attrs'        => $attrs,
1837          'arrayType'    => $arrayType
1838          );
1839          
1840          $this->xdebug("addComplexType $name:");
1841          $this->appendDebug($this->varDump($this->complexTypes[$name]));
1842      }
1843      
1844      /**
1845      * adds a simple type to the schema
1846      *
1847      * @param string $name
1848      * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1849      * @param string $typeClass (should always be simpleType)
1850      * @param string $phpType (should always be scalar)
1851      * @param array $enumeration array of values
1852      * @access public
1853      * @see xmlschema
1854      * @see getTypeDef
1855      */
1856  	function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1857          $this->simpleTypes[$name] = array(
1858          'name'            => $name,
1859          'typeClass'        => $typeClass,
1860          'phpType'        => $phpType,
1861          'type'            => $restrictionBase,
1862          'enumeration'    => $enumeration
1863          );
1864          
1865          $this->xdebug("addSimpleType $name:");
1866          $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1867      }
1868  
1869      /**
1870      * adds an element to the schema
1871      *
1872      * @param array $attrs attributes that must include name and type
1873      * @see xmlschema
1874      * @access public
1875      */
1876  	function addElement($attrs) {
1877          if (! $this->getPrefix($attrs['type'])) {
1878              $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1879          }
1880          $this->elements[ $attrs['name'] ] = $attrs;
1881          $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1882          
1883          $this->xdebug("addElement " . $attrs['name']);
1884          $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
1885      }
1886  }
1887  
1888  
1889  
1890  ?><?php
1891  
1892  
1893  
1894  /**
1895  * For creating serializable abstractions of native PHP types.  This class
1896  * allows element name/namespace, XSD type, and XML attributes to be
1897  * associated with a value.  This is extremely useful when WSDL is not
1898  * used, but is also useful when WSDL is used with polymorphic types, including
1899  * xsd:anyType and user-defined types.
1900  *
1901  * @author   Dietrich Ayala <dietrich@ganx4.com>
1902  * @version  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler Exp $
1903  * @access   public
1904  */
1905  class soapval extends nusoap_base {
1906      /**
1907       * The XML element name
1908       *
1909       * @var string
1910       * @access private
1911       */
1912      var $name;
1913      /**
1914       * The XML type name (string or false)
1915       *
1916       * @var mixed
1917       * @access private
1918       */
1919      var $type;
1920      /**
1921       * The PHP value
1922       *
1923       * @var mixed
1924       * @access private
1925       */
1926      var $value;
1927      /**
1928       * The XML element namespace (string or false)
1929       *
1930       * @var mixed
1931       * @access private
1932       */
1933      var $element_ns;
1934      /**
1935       * The XML type namespace (string or false)
1936       *
1937       * @var mixed
1938       * @access private
1939       */
1940      var $type_ns;
1941      /**
1942       * The XML element attributes (array or false)
1943       *
1944       * @var mixed
1945       * @access private
1946       */
1947      var $attributes;
1948  
1949      /**
1950      * constructor
1951      *
1952      * @param    string $name optional name
1953      * @param    mixed $type optional type name
1954      * @param    mixed $value optional value
1955      * @param    mixed $element_ns optional namespace of value
1956      * @param    mixed $type_ns optional namespace of type
1957      * @param    mixed $attributes associative array of attributes to add to element serialization
1958      * @access   public
1959      */
1960    	function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
1961          parent::nusoap_base();
1962          $this->name = $name;
1963          $this->type = $type;
1964          $this->value = $value;
1965          $this->element_ns = $element_ns;
1966          $this->type_ns = $type_ns;
1967          $this->attributes = $attributes;
1968      }
1969  
1970      /**
1971      * return serialized value
1972      *
1973      * @param    string $use The WSDL use value (encoded|literal)
1974      * @return    string XML data
1975      * @access   public
1976      */
1977  	function serialize($use='encoded') {
1978          return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
1979      }
1980  
1981      /**
1982      * decodes a soapval object into a PHP native type
1983      *
1984      * @return    mixed
1985      * @access   public
1986      */
1987  	function decode(){
1988          return $this->value;
1989      }
1990  }
1991  
1992  
1993  
1994  ?><?php
1995  
1996  
1997  
1998  /**
1999  * transport class for sending/receiving data via HTTP and HTTPS
2000  * NOTE: PHP must be compiled with the CURL extension for HTTPS support
2001  *
2002  * @author   Dietrich Ayala <dietrich@ganx4.com>
2003  * @version  $Id: nusoap.php,v 1.2 2007/01/03 14:44:42 moodler Exp $
2004  * @access public
2005  */
2006  class soap_transport_http extends nusoap_base {
2007  
2008      var $url = '';
2009      var $uri = '';
2010      var $digest_uri = '';
2011      var $scheme = '';
2012      var $host = '';
2013      var $port = '';
2014      var $path = '';
2015      var $request_method = 'POST';
2016      var $protocol_version = '1.0';
2017      var $encoding = '';
2018      var $outgoing_headers = array();
2019      var $incoming_headers = array();
2020      var $incoming_cookies = array();
2021      var $outgoing_payload = '';
2022      var $incoming_payload = '';
2023      var $useSOAPAction = true;
2024      var $persistentConnection = false;
2025      var $ch = false;    // cURL handle
2026      var $username = '';
2027      var $password = '';
2028      var $authtype = '';
2029      var $digestRequest = array();
2030      var $certRequest = array();    // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional)
2031                                  // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2032                                  // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2033                                  // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2034                                  // passphrase: SSL key password/passphrase
2035                                  // verifypeer: default is 1
2036                                  // verifyhost: default is 1
2037  
2038      /**
2039      * constructor
2040      */
2041  	function soap_transport_http($url){
2042          parent::nusoap_base();
2043          $this->setURL($url);
2044          ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
2045          $this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')';
2046          $this->debug('set User-Agent: ' . $this->outgoing_headers['User-Agent']);
2047      }
2048  
2049  	function setURL($url) {
2050          $this->url = $url;
2051  
2052          $u = parse_url($url);
2053          foreach($u as $k => $v){
2054              $this->debug("$k = $v");
2055              $this->$k = $v;
2056          }
2057          
2058