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