[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/library/nusoap/ -> class.nusoap_base.php (source)

   1  <?php
   2  
   3  /*
   4  $Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 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  The NuSOAP project home is:
  25  http://sourceforge.net/projects/nusoap/
  26  
  27  The primary support for NuSOAP is the Help forum on the project home page.
  28  
  29  If you have any questions or comments, please email:
  30  
  31  Dietrich Ayala
  32  dietrich@ganx4.com
  33  http://dietrich.ganx4.com/nusoap
  34  
  35  NuSphere Corporation
  36  http://www.nusphere.com
  37  
  38  */
  39  
  40  /*
  41   *    Some of the standards implmented in whole or part by NuSOAP:
  42   *
  43   *    SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
  44   *    WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
  45   *    SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
  46   *    XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
  47   *    Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
  48   *    XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
  49   *    RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
  50   *    RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
  51   *    RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
  52   */
  53  
  54  /* load classes
  55  
  56  // necessary classes
  57  require_once('class.soapclient.php');
  58  require_once('class.soap_val.php');
  59  require_once('class.soap_parser.php');
  60  require_once('class.soap_fault.php');
  61  
  62  // transport classes
  63  require_once('class.soap_transport_http.php');
  64  
  65  // optional add-on classes
  66  require_once('class.xmlschema.php');
  67  require_once('class.wsdl.php');
  68  
  69  // server class
  70  require_once('class.soap_server.php');*/
  71  
  72  // class variable emulation
  73  // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
  74  $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
  75  
  76  /**
  77  *
  78  * nusoap_base
  79  *
  80  * @author   Dietrich Ayala <dietrich@ganx4.com>
  81  * @author   Scott Nichol <snichol@users.sourceforge.net>
  82  * @version  $Id: class.nusoap_base.php,v 1.56 2010/04/26 20:15:08 snichol Exp $
  83  * @access   public
  84  */
  85  class nusoap_base {
  86      /**
  87       * Identification for HTTP headers.
  88       *
  89       * @var string
  90       * @access private
  91       */
  92      var $title = 'NuSOAP';
  93      /**
  94       * Version for HTTP headers.
  95       *
  96       * @var string
  97       * @access private
  98       */
  99      var $version = '0.9.5';
 100      /**
 101       * CVS revision for HTTP headers.
 102       *
 103       * @var string
 104       * @access private
 105       */
 106      var $revision = '$Revision: 1.56 $';
 107      /**
 108       * Current error string (manipulated by getError/setError)
 109       *
 110       * @var string
 111       * @access private
 112       */
 113      var $error_str = '';
 114      /**
 115       * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
 116       *
 117       * @var string
 118       * @access private
 119       */
 120      var $debug_str = '';
 121      /**
 122       * toggles automatic encoding of special characters as entities
 123       * (should always be true, I think)
 124       *
 125       * @var boolean
 126       * @access private
 127       */
 128      var $charencoding = true;
 129      /**
 130       * the debug level for this instance
 131       *
 132       * @var    integer
 133       * @access private
 134       */
 135      var $debugLevel;
 136  
 137      /**
 138      * set schema version
 139      *
 140      * @var      string
 141      * @access   public
 142      */
 143      var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
 144      
 145      /**
 146      * charset encoding for outgoing messages
 147      *
 148      * @var      string
 149      * @access   public
 150      */
 151      var $soap_defencoding = 'ISO-8859-1';
 152      //var $soap_defencoding = 'UTF-8';
 153  
 154      /**
 155      * namespaces in an array of prefix => uri
 156      *
 157      * this is "seeded" by a set of constants, but it may be altered by code
 158      *
 159      * @var      array
 160      * @access   public
 161      */
 162      var $namespaces = array(
 163          'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
 164          'xsd' => 'http://www.w3.org/2001/XMLSchema',
 165          'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
 166          'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
 167          );
 168  
 169      /**
 170      * namespaces used in the current context, e.g. during serialization
 171      *
 172      * @var      array
 173      * @access   private
 174      */
 175      var $usedNamespaces = array();
 176  
 177      /**
 178      * XML Schema types in an array of uri => (array of xml type => php type)
 179      * is this legacy yet?
 180      * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
 181      * @var      array
 182      * @access   public
 183      */
 184      var $typemap = array(
 185      'http://www.w3.org/2001/XMLSchema' => array(
 186          'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
 187          'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
 188          'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
 189          // abstract "any" types
 190          'anyType'=>'string','anySimpleType'=>'string',
 191          // derived datatypes
 192          'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
 193          'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
 194          'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
 195          'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
 196      'http://www.w3.org/2000/10/XMLSchema' => array(
 197          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 198          'float'=>'double','dateTime'=>'string',
 199          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 200      'http://www.w3.org/1999/XMLSchema' => array(
 201          'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
 202          'float'=>'double','dateTime'=>'string',
 203          'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
 204      'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
 205      'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
 206      'http://xml.apache.org/xml-soap' => array('Map')
 207      );
 208  
 209      /**
 210      * XML entities to convert
 211      *
 212      * @var      array
 213      * @access   public
 214      * @deprecated
 215      * @see    expandEntities
 216      */
 217      var $xmlEntities = array('quot' => '"','amp' => '&',
 218          'lt' => '<','gt' => '>','apos' => "'");
 219  
 220      /**
 221      * constructor
 222      *
 223      * @access    public
 224      */
 225  	function nusoap_base() {
 226          $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
 227      }
 228  
 229      /**
 230      * gets the global debug level, which applies to future instances
 231      *
 232      * @return    integer    Debug level 0-9, where 0 turns off
 233      * @access    public
 234      */
 235  	function getGlobalDebugLevel() {
 236          return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
 237      }
 238  
 239      /**
 240      * sets the global debug level, which applies to future instances
 241      *
 242      * @param    int    $level    Debug level 0-9, where 0 turns off
 243      * @access    public
 244      */
 245  	function setGlobalDebugLevel($level) {
 246          $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
 247      }
 248  
 249      /**
 250      * gets the debug level for this instance
 251      *
 252      * @return    int    Debug level 0-9, where 0 turns off
 253      * @access    public
 254      */
 255  	function getDebugLevel() {
 256          return $this->debugLevel;
 257      }
 258  
 259      /**
 260      * sets the debug level for this instance
 261      *
 262      * @param    int    $level    Debug level 0-9, where 0 turns off
 263      * @access    public
 264      */
 265  	function setDebugLevel($level) {
 266          $this->debugLevel = $level;
 267      }
 268  
 269      /**
 270      * adds debug data to the instance debug string with formatting
 271      *
 272      * @param    string $string debug data
 273      * @access   private
 274      */
 275  	function debug($string){
 276          if ($this->debugLevel > 0) {
 277              $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
 278          }
 279      }
 280  
 281      /**
 282      * adds debug data to the instance debug string without formatting
 283      *
 284      * @param    string $string debug data
 285      * @access   public
 286      */
 287  	function appendDebug($string){
 288          if ($this->debugLevel > 0) {
 289              // it would be nice to use a memory stream here to use
 290              // memory more efficiently
 291              $this->debug_str .= $string;
 292          }
 293      }
 294  
 295      /**
 296      * clears the current debug data for this instance
 297      *
 298      * @access   public
 299      */
 300  	function clearDebug() {
 301          // it would be nice to use a memory stream here to use
 302          // memory more efficiently
 303          $this->debug_str = '';
 304      }
 305  
 306      /**
 307      * gets the current debug data for this instance
 308      *
 309      * @return   debug data
 310      * @access   public
 311      */
 312      function &getDebug() {
 313          // it would be nice to use a memory stream here to use
 314          // memory more efficiently
 315          return $this->debug_str;
 316      }
 317  
 318      /**
 319      * gets the current debug data for this instance as an XML comment
 320      * this may change the contents of the debug data
 321      *
 322      * @return   debug data as an XML comment
 323      * @access   public
 324      */
 325      function &getDebugAsXMLComment() {
 326          // it would be nice to use a memory stream here to use
 327          // memory more efficiently
 328          while (strpos($this->debug_str, '--')) {
 329              $this->debug_str = str_replace('--', '- -', $this->debug_str);
 330          }
 331          $ret = "<!--\n" . $this->debug_str . "\n-->";
 332          return $ret;
 333      }
 334  
 335      /**
 336      * expands entities, e.g. changes '<' to '&lt;'.
 337      *
 338      * @param    string    $val    The string in which to expand entities.
 339      * @access    private
 340      */
 341  	function expandEntities($val) {
 342          if ($this->charencoding) {
 343              $val = str_replace('&', '&amp;', $val);
 344              $val = str_replace("'", '&apos;', $val);
 345              $val = str_replace('"', '&quot;', $val);
 346              $val = str_replace('<', '&lt;', $val);
 347              $val = str_replace('>', '&gt;', $val);
 348          }
 349          return $val;
 350      }
 351  
 352      /**
 353      * returns error string if present
 354      *
 355      * @return   mixed error string or false
 356      * @access   public
 357      */
 358  	function getError(){
 359          if($this->error_str != ''){
 360              return $this->error_str;
 361          }
 362          return false;
 363      }
 364  
 365      /**
 366      * sets error string
 367      *
 368      * @return   boolean $string error string
 369      * @access   private
 370      */
 371  	function setError($str){
 372          $this->error_str = $str;
 373      }
 374  
 375      /**
 376      * detect if array is a simple array or a struct (associative array)
 377      *
 378      * @param    mixed    $val    The PHP array
 379      * @return    string    (arraySimple|arrayStruct)
 380      * @access    private
 381      */
 382  	function isArraySimpleOrStruct($val) {
 383          $keyList = array_keys($val);
 384          foreach ($keyList as $keyListValue) {
 385              if (!is_int($keyListValue)) {
 386                  return 'arrayStruct';
 387              }
 388          }
 389          return 'arraySimple';
 390      }
 391  
 392      /**
 393      * serializes PHP values in accordance w/ section 5. Type information is
 394      * not serialized if $use == 'literal'.
 395      *
 396      * @param    mixed    $val    The value to serialize
 397      * @param    string    $name    The name (local part) of the XML element
 398      * @param    string    $type    The XML schema type (local part) for the element
 399      * @param    string    $name_ns    The namespace for the name of the XML element
 400      * @param    string    $type_ns    The namespace for the type of the element
 401      * @param    array    $attributes    The attributes to serialize as name=>value pairs
 402      * @param    string    $use    The WSDL "use" (encoded|literal)
 403      * @param    boolean    $soapval    Whether this is called from soapval.
 404      * @return    string    The serialized element, possibly with child elements
 405      * @access    public
 406      */
 407  	function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
 408          $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
 409          $this->appendDebug('value=' . $this->varDump($val));
 410          $this->appendDebug('attributes=' . $this->varDump($attributes));
 411          
 412          if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
 413              $this->debug("serialize_val: serialize soapval");
 414              $xml = $val->serialize($use);
 415              $this->appendDebug($val->getDebug());
 416              $val->clearDebug();
 417              $this->debug("serialize_val of soapval returning $xml");
 418              return $xml;
 419          }
 420          // force valid name if necessary
 421          if (is_numeric($name)) {
 422              $name = '__numeric_' . $name;
 423          } elseif (! $name) {
 424              $name = 'noname';
 425          }
 426          // if name has ns, add ns prefix to name
 427          $xmlns = '';
 428          if($name_ns){
 429              $prefix = 'nu'.rand(1000,9999);
 430              $name = $prefix.':'.$name;
 431              $xmlns .= " xmlns:$prefix=\"$name_ns\"";
 432          }
 433          // if type is prefixed, create type prefix
 434          if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
 435              // need to fix this. shouldn't default to xsd if no ns specified
 436              // w/o checking against typemap
 437              $type_prefix = 'xsd';
 438          } elseif($type_ns){
 439              $type_prefix = 'ns'.rand(1000,9999);
 440              $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
 441          }
 442          // serialize attributes if present
 443          $atts = '';
 444          if($attributes){
 445              foreach($attributes as $k => $v){
 446                  $atts .= " $k=\"".$this->expandEntities($v).'"';
 447              }
 448          }
 449          // serialize null value
 450          if (is_null($val)) {
 451              $this->debug("serialize_val: serialize null");
 452              if ($use == 'literal') {
 453                  // TODO: depends on minOccurs
 454                  $xml = "<$name$xmlns$atts/>";
 455                  $this->debug("serialize_val returning $xml");
 456                  return $xml;
 457              } else {
 458                  if (isset($type) && isset($type_prefix)) {
 459                      $type_str = " xsi:type=\"$type_prefix:$type\"";
 460                  } else {
 461                      $type_str = '';
 462                  }
 463                  $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
 464                  $this->debug("serialize_val returning $xml");
 465                  return $xml;
 466              }
 467          }
 468          // serialize if an xsd built-in primitive type
 469          if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
 470              $this->debug("serialize_val: serialize xsd built-in primitive type");
 471              if (is_bool($val)) {
 472                  if ($type == 'boolean') {
 473                      $val = $val ? 'true' : 'false';
 474                  } elseif (! $val) {
 475                      $val = 0;
 476                  }
 477              } else if (is_string($val)) {
 478                  $val = $this->expandEntities($val);
 479              }
 480              if ($use == 'literal') {
 481                  $xml = "<$name$xmlns$atts>$val</$name>";
 482                  $this->debug("serialize_val returning $xml");
 483                  return $xml;
 484              } else {
 485                  $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
 486                  $this->debug("serialize_val returning $xml");
 487                  return $xml;
 488              }
 489          }
 490          // detect type and serialize
 491          $xml = '';
 492          switch(true) {
 493              case (is_bool($val) || $type == 'boolean'):
 494                     $this->debug("serialize_val: serialize boolean");
 495                  if ($type == 'boolean') {
 496                      $val = $val ? 'true' : 'false';
 497                  } elseif (! $val) {
 498                      $val = 0;
 499                  }
 500                  if ($use == 'literal') {
 501                      $xml .= "<$name$xmlns$atts>$val</$name>";
 502                  } else {
 503                      $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
 504                  }
 505                  break;
 506              case (is_int($val) || is_long($val) || $type == 'int'):
 507                     $this->debug("serialize_val: serialize int");
 508                  if ($use == 'literal') {
 509                      $xml .= "<$name$xmlns$atts>$val</$name>";
 510                  } else {
 511                      $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
 512                  }
 513                  break;
 514              case (is_float($val)|| is_double($val) || $type == 'float'):
 515                     $this->debug("serialize_val: serialize float");
 516                  if ($use == 'literal') {
 517                      $xml .= "<$name$xmlns$atts>$val</$name>";
 518                  } else {
 519                      $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
 520                  }
 521                  break;
 522              case (is_string($val) || $type == 'string'):
 523                     $this->debug("serialize_val: serialize string");
 524                  $val = $this->expandEntities($val);
 525                  if ($use == 'literal') {
 526                      $xml .= "<$name$xmlns$atts>$val</$name>";
 527                  } else {
 528                      $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
 529                  }
 530                  break;
 531              case is_object($val):
 532                     $this->debug("serialize_val: serialize object");
 533                  if (get_class($val) == 'soapval') {
 534                      $this->debug("serialize_val: serialize soapval object");
 535                      $pXml = $val->serialize($use);
 536                      $this->appendDebug($val->getDebug());
 537                      $val->clearDebug();
 538                  } else {
 539                      if (! $name) {
 540                          $name = get_class($val);
 541                          $this->debug("In serialize_val, used class name $name as element name");
 542                      } else {
 543                          $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
 544                      }
 545                      foreach(get_object_vars($val) as $k => $v){
 546                          $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
 547                      }
 548                  }
 549                  if(isset($type) && isset($type_prefix)){
 550                      $type_str = " xsi:type=\"$type_prefix:$type\"";
 551                  } else {
 552                      $type_str = '';
 553                  }
 554                  if ($use == 'literal') {
 555                      $xml .= "<$name$xmlns$atts>$pXml</$name>";
 556                  } else {
 557                      $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
 558                  }
 559                  break;
 560              break;
 561              case (is_array($val) || $type):
 562                  // detect if struct or array
 563                  $valueType = $this->isArraySimpleOrStruct($val);
 564                  if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
 565                         $this->debug("serialize_val: serialize array");
 566                      $i = 0;
 567                      if(is_array($val) && count($val)> 0){
 568                          foreach($val as $v){
 569                              if(is_object($v) && get_class($v) ==  'soapval'){
 570                                  $tt_ns = $v->type_ns;
 571                                  $tt = $v->type;
 572                              } elseif (is_array($v)) {
 573                                  $tt = $this->isArraySimpleOrStruct($v);
 574                              } else {
 575                                  $tt = gettype($v);
 576                              }
 577                              $array_types[$tt] = 1;
 578                              // TODO: for literal, the name should be $name
 579                              $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
 580                              ++$i;
 581                          }
 582                          if(count($array_types) > 1){
 583                              $array_typename = 'xsd:anyType';
 584                          } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
 585                              if ($tt == 'integer') {
 586                                  $tt = 'int';
 587                              }
 588                              $array_typename = 'xsd:'.$tt;
 589                          } elseif(isset($tt) && $tt == 'arraySimple'){
 590                              $array_typename = 'SOAP-ENC:Array';
 591                          } elseif(isset($tt) && $tt == 'arrayStruct'){
 592                              $array_typename = 'unnamed_struct_use_soapval';
 593                          } else {
 594                              // if type is prefixed, create type prefix
 595                              if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
 596                                   $array_typename = 'xsd:' . $tt;
 597                              } elseif ($tt_ns) {
 598                                  $tt_prefix = 'ns' . rand(1000, 9999);
 599                                  $array_typename = "$tt_prefix:$tt";
 600                                  $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
 601                              } else {
 602                                  $array_typename = $tt;
 603                              }
 604                          }
 605                          $array_type = $i;
 606                          if ($use == 'literal') {
 607                              $type_str = '';
 608                          } else if (isset($type) && isset($type_prefix)) {
 609                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 610                          } else {
 611                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
 612                          }
 613                      // empty array
 614                      } else {
 615                          if ($use == 'literal') {
 616                              $type_str = '';
 617                          } else if (isset($type) && isset($type_prefix)) {
 618                              $type_str = " xsi:type=\"$type_prefix:$type\"";
 619                          } else {
 620                              $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
 621                          }
 622                      }
 623                      // TODO: for array in literal, there is no wrapper here
 624                      $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
 625                  } else {
 626                      // got a struct
 627                         $this->debug("serialize_val: serialize struct");
 628                      if(isset($type) && isset($type_prefix)){
 629                          $type_str = " xsi:type=\"$type_prefix:$type\"";
 630                      } else {
 631                          $type_str = '';
 632                      }
 633                      if ($use == 'literal') {
 634                          $xml .= "<$name$xmlns$atts>";
 635                      } else {
 636                          $xml .= "<$name$xmlns$type_str$atts>";
 637                      }
 638                      foreach($val as $k => $v){
 639                          // Apache Map
 640                          if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
 641                              $xml .= '<item>';
 642                              $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
 643                              $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
 644                              $xml .= '</item>';
 645                          } else {
 646                              $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
 647                          }
 648                      }
 649                      $xml .= "</$name>";
 650                  }
 651                  break;
 652              default:
 653                     $this->debug("serialize_val: serialize unknown");
 654                  $xml .= 'not detected, got '.gettype($val).' for '.$val;
 655                  break;
 656          }
 657          $this->debug("serialize_val returning $xml");
 658          return $xml;
 659      }
 660  
 661      /**
 662      * serializes a message
 663      *
 664      * @param string $body the XML of the SOAP body
 665      * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
 666      * @param array $namespaces optional the namespaces used in generating the body and headers
 667      * @param string $style optional (rpc|document)
 668      * @param string $use optional (encoded|literal)
 669      * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
 670      * @return string the message
 671      * @access public
 672      */
 673      function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
 674      // TODO: add an option to automatically run utf8_encode on $body and $headers
 675      // if $this->soap_defencoding is UTF-8.  Not doing this automatically allows
 676      // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
 677  
 678      $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
 679      $this->debug("headers:");
 680      $this->appendDebug($this->varDump($headers));
 681      $this->debug("namespaces:");
 682      $this->appendDebug($this->varDump($namespaces));
 683  
 684      // serialize namespaces
 685      $ns_string = '';
 686      foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
 687          $ns_string .= " xmlns:$k=\"$v\"";
 688      }
 689      if($encodingStyle) {
 690          $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
 691      }
 692  
 693      // serialize headers
 694      if($headers){
 695          if (is_array($headers)) {
 696              $xml = '';
 697              foreach ($headers as $k => $v) {
 698                  if (is_object($v) && get_class($v) == 'soapval') {
 699                      $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
 700                  } else {
 701                      $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
 702                  }
 703              }
 704              $headers = $xml;
 705              $this->debug("In serializeEnvelope, serialized array of headers to $headers");
 706          }
 707          $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
 708      }
 709      // serialize envelope
 710      return
 711      '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
 712      '<SOAP-ENV:Envelope'.$ns_string.">".
 713      $headers.
 714      "<SOAP-ENV:Body>".
 715          $body.
 716      "</SOAP-ENV:Body>".
 717      "</SOAP-ENV:Envelope>";
 718      }
 719  
 720      /**
 721       * formats a string to be inserted into an HTML stream
 722       *
 723       * @param string $str The string to format
 724       * @return string The formatted string
 725       * @access public
 726       * @deprecated
 727       */
 728      function formatDump($str){
 729          $str = htmlspecialchars($str);
 730          return nl2br($str);
 731      }
 732  
 733      /**
 734      * contracts (changes namespace to prefix) a qualified name
 735      *
 736      * @param    string $qname qname
 737      * @return    string contracted qname
 738      * @access   private
 739      */
 740  	function contractQname($qname){
 741          // get element namespace
 742          //$this->xdebug("Contract $qname");
 743          if (strrpos($qname, ':')) {
 744              // get unqualified name
 745              $name = substr($qname, strrpos($qname, ':') + 1);
 746              // get ns
 747              $ns = substr($qname, 0, strrpos($qname, ':'));
 748              $p = $this->getPrefixFromNamespace($ns);
 749              if ($p) {
 750                  return $p . ':' . $name;
 751              }
 752              return $qname;
 753          } else {
 754              return $qname;
 755          }
 756      }
 757  
 758      /**
 759      * expands (changes prefix to namespace) a qualified name
 760      *
 761      * @param    string $qname qname
 762      * @return    string expanded qname
 763      * @access   private
 764      */
 765  	function expandQname($qname){
 766          // get element prefix
 767          if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
 768              // get unqualified name
 769              $name = substr(strstr($qname,':'),1);
 770              // get ns prefix
 771              $prefix = substr($qname,0,strpos($qname,':'));
 772              if(isset($this->namespaces[$prefix])){
 773                  return $this->namespaces[$prefix].':'.$name;
 774              } else {
 775                  return $qname;
 776              }
 777          } else {
 778              return $qname;
 779          }
 780      }
 781  
 782      /**
 783      * returns the local part of a prefixed string
 784      * returns the original string, if not prefixed
 785      *
 786      * @param string $str The prefixed string
 787      * @return string The local part
 788      * @access public
 789      */
 790  	function getLocalPart($str){
 791          if($sstr = strrchr($str,':')){
 792              // get unqualified name
 793              return substr( $sstr, 1 );
 794          } else {
 795              return $str;
 796          }
 797      }
 798  
 799      /**
 800      * returns the prefix part of a prefixed string
 801      * returns false, if not prefixed
 802      *
 803      * @param string $str The prefixed string
 804      * @return mixed The prefix or false if there is no prefix
 805      * @access public
 806      */
 807  	function getPrefix($str){
 808          if($pos = strrpos($str,':')){
 809              // get prefix
 810              return substr($str,0,$pos);
 811          }
 812          return false;
 813      }
 814  
 815      /**
 816      * pass it a prefix, it returns a namespace
 817      *
 818      * @param string $prefix The prefix
 819      * @return mixed The namespace, false if no namespace has the specified prefix
 820      * @access public
 821      */
 822  	function getNamespaceFromPrefix($prefix){
 823          if (isset($this->namespaces[$prefix])) {
 824              return $this->namespaces[$prefix];
 825          }
 826          //$this->setError("No namespace registered for prefix '$prefix'");
 827          return false;
 828      }
 829  
 830      /**
 831      * returns the prefix for a given namespace (or prefix)
 832      * or false if no prefixes registered for the given namespace
 833      *
 834      * @param string $ns The namespace
 835      * @return mixed The prefix, false if the namespace has no prefixes
 836      * @access public
 837      */
 838  	function getPrefixFromNamespace($ns) {
 839          foreach ($this->namespaces as $p => $n) {
 840              if ($ns == $n || $ns == $p) {
 841                  $this->usedNamespaces[$p] = $n;
 842                  return $p;
 843              }
 844          }
 845          return false;
 846      }
 847  
 848      /**
 849      * returns the time in ODBC canonical form with microseconds
 850      *
 851      * @return string The time in ODBC canonical form with microseconds
 852      * @access public
 853      */
 854  	function getmicrotime() {
 855          if (function_exists('gettimeofday')) {
 856              $tod = gettimeofday();
 857              $sec = $tod['sec'];
 858              $usec = $tod['usec'];
 859          } else {
 860              $sec = time();
 861              $usec = 0;
 862          }
 863          return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
 864      }
 865  
 866      /**
 867       * Returns a string with the output of var_dump
 868       *
 869       * @param mixed $data The variable to var_dump
 870       * @return string The output of var_dump
 871       * @access public
 872       */
 873      function varDump($data) {
 874          ob_start();
 875          var_dump($data);
 876          $ret_val = ob_get_contents();
 877          ob_end_clean();
 878          return $ret_val;
 879      }
 880  
 881      /**
 882      * represents the object as a string
 883      *
 884      * @return    string
 885      * @access   public
 886      */
 887  	function __toString() {
 888          return $this->varDump($this);
 889      }
 890  }
 891  
 892  // XML Schema Datatype Helper Functions
 893  
 894  //xsd:dateTime helpers
 895  
 896  /**
 897  * convert unix timestamp to ISO 8601 compliant date string
 898  *
 899  * @param    int $timestamp Unix time stamp
 900  * @param    boolean $utc Whether the time stamp is UTC or local
 901  * @return    mixed ISO 8601 date string or false
 902  * @access   public
 903  */
 904  function timestamp_to_iso8601($timestamp,$utc=true){
 905      $datestr = date('Y-m-d\TH:i:sO',$timestamp);
 906      $pos = strrpos($datestr, "+");
 907      if ($pos === FALSE) {
 908          $pos = strrpos($datestr, "-");
 909      }
 910      if ($pos !== FALSE) {
 911          if (strlen($datestr) == $pos + 5) {
 912              $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
 913          }
 914      }
 915      if($utc){
 916          $pattern = '/'.
 917          '([0-9]{4})-'.    // centuries & years CCYY-
 918          '([0-9]{2})-'.    // months MM-
 919          '([0-9]{2})'.    // days DD
 920          'T'.            // separator T
 921          '([0-9]{2}):'.    // hours hh:
 922          '([0-9]{2}):'.    // minutes mm:
 923          '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
 924          '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
 925          '/';
 926  
 927          if(preg_match($pattern,$datestr,$regs)){
 928              return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
 929          }
 930          return false;
 931      } else {
 932          return $datestr;
 933      }
 934  }
 935  
 936  /**
 937  * convert ISO 8601 compliant date string to unix timestamp
 938  *
 939  * @param    string $datestr ISO 8601 compliant date string
 940  * @return    mixed Unix timestamp (int) or false
 941  * @access   public
 942  */
 943  function iso8601_to_timestamp($datestr){
 944      $pattern = '/'.
 945      '([0-9]{4})-'.    // centuries & years CCYY-
 946      '([0-9]{2})-'.    // months MM-
 947      '([0-9]{2})'.    // days DD
 948      'T'.            // separator T
 949      '([0-9]{2}):'.    // hours hh:
 950      '([0-9]{2}):'.    // minutes mm:
 951      '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
 952      '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
 953      '/';
 954      if(preg_match($pattern,$datestr,$regs)){
 955          // not utc
 956          if($regs[8] != 'Z'){
 957              $op = substr($regs[8],0,1);
 958              $h = substr($regs[8],1,2);
 959              $m = substr($regs[8],strlen($regs[8])-2,2);
 960              if($op == '-'){
 961                  $regs[4] = $regs[4] + $h;
 962                  $regs[5] = $regs[5] + $m;
 963              } elseif($op == '+'){
 964                  $regs[4] = $regs[4] - $h;
 965                  $regs[5] = $regs[5] - $m;
 966              }
 967          }
 968          return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
 969  //        return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
 970      } else {
 971          return false;
 972      }
 973  }
 974  
 975  /**
 976  * sleeps some number of microseconds
 977  *
 978  * @param    string $usec the number of microseconds to sleep
 979  * @access   public
 980  * @deprecated
 981  */
 982  function usleepWindows($usec)
 983  {
 984      $start = gettimeofday();
 985      
 986      do
 987      {
 988          $stop = gettimeofday();
 989          $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
 990          + $stop['usec'] - $start['usec'];
 991      }
 992      while ($timePassed < $usec);
 993  }
 994  
 995  
 996  ?>


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7