5 Modification information for LGPL compliance
7 r57813 - 2010-08-19 10:34:44 -0700 (Thu, 19 Aug 2010) - kjing - Author: John Mertic <jmertic@sugarcrm.com>
8 Bug 39085 - When loading the opposite search panel via ajax on the ListViews, call the index action instead of the ListView action to avoid touching pre-MVC code by accident.
10 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
12 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
14 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
16 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
18 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
20 r51516 - 2009-10-14 10:22:42 -0700 (Wed, 14 Oct 2009) - jmertic - More fallout fixes from the PHP 5.3 ereg to preg changes.
22 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
23 - Changing all ereg function to either preg or simple string based ones
24 - No more references to magic quotes.
25 - Change all the session_unregister() functions to just unset() the correct session variable instead.
27 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
29 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
31 r14701 - 2006-07-17 13:37:26 -0700 (Mon, 17 Jul 2006) - roger - RRS: bug 5801
33 r13782 - 2006-06-06 10:58:55 -0700 (Tue, 06 Jun 2006) - majed - changes entry point code
35 r11115 - 2006-01-17 14:54:45 -0800 (Tue, 17 Jan 2006) - majed - add entry point validation
37 r8846 - 2005-10-31 11:01:12 -0800 (Mon, 31 Oct 2005) - majed - new version of nusoap
39 r5462 - 2005-05-25 13:50:11 -0700 (Wed, 25 May 2005) - majed - upgraded nusoap to .6.9
41 r573 - 2004-09-04 13:03:32 -0700 (Sat, 04 Sep 2004) - sugarclint - undoing copyrights added in inadvertantly. --clint
43 r546 - 2004-09-03 11:49:38 -0700 (Fri, 03 Sep 2004) - sugarmsi - removed echo count
45 r354 - 2004-08-02 23:00:37 -0700 (Mon, 02 Aug 2004) - sugarjacob - Adding Soap
51 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
54 $Id: class.nusoap_base.php 57813 2010-08-19 17:34:44Z kjing $
56 NuSOAP - Web Services Toolkit for PHP
58 Copyright (c) 2002 NuSphere Corporation
60 This library is free software; you can redistribute it and/or
61 modify it under the terms of the GNU Lesser General Public
62 License as published by the Free Software Foundation; either
63 version 2.1 of the License, or (at your option) any later version.
65 This library is distributed in the hope that it will be useful,
66 but WITHOUT ANY WARRANTY; without even the implied warranty of
67 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
68 Lesser General Public License for more details.
70 You should have received a copy of the GNU Lesser General Public
71 License along with this library; if not, write to the Free Software
72 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
74 The NuSOAP project home is:
75 http://sourceforge.net/projects/nusoap/
77 The primary support for NuSOAP is the Help forum on the project home page.
79 If you have any questions or comments, please email:
83 http://dietrich.ganx4.com/nusoap
86 http://www.nusphere.com
91 * Some of the standards implmented in whole or part by NuSOAP:
93 * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
94 * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
95 * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
96 * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
97 * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
98 * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
99 * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
100 * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
101 * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
107 require_once('class.soapclient.php');
108 require_once('class.soap_val.php');
109 require_once('class.soap_parser.php');
110 require_once('class.soap_fault.php');
113 require_once('class.soap_transport_http.php');
115 // optional add-on classes
116 require_once('class.xmlschema.php');
117 require_once('class.wsdl.php');
120 require_once('class.soap_server.php');*/
122 // class variable emulation
123 // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
124 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
130 * @author Dietrich Ayala <dietrich@ganx4.com>
131 * @author Scott Nichol <snichol@users.sourceforge.net>
137 * Identification for HTTP headers.
142 var $title = 'NuSOAP';
144 * Version for HTTP headers.
149 var $version = '0.9.5';
151 * CVS revision for HTTP headers.
156 var $revision = '$Revision: 57813 $';
158 * Current error string (manipulated by getError/setError)
165 * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
172 * toggles automatic encoding of special characters as entities
173 * (should always be true, I think)
178 var $charencoding = true;
180 * the debug level for this instance
193 var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
196 * charset encoding for outgoing messages
201 //var $soap_defencoding = 'ISO-8859-1';
202 var $soap_defencoding = 'UTF-8';
205 * namespaces in an array of prefix => uri
207 * this is "seeded" by a set of constants, but it may be altered by code
212 var $namespaces = array(
213 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
214 'xsd' => 'http://www.w3.org/2001/XMLSchema',
215 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
216 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
220 * namespaces used in the current context, e.g. during serialization
225 var $usedNamespaces = array();
228 * XML Schema types in an array of uri => (array of xml type => php type)
229 * is this legacy yet?
230 * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
234 var $typemap = array(
235 'http://www.w3.org/2001/XMLSchema' => array(
236 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
237 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
238 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
239 // abstract "any" types
240 'anyType'=>'string','anySimpleType'=>'string',
242 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
243 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
244 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
245 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
246 'http://www.w3.org/2000/10/XMLSchema' => array(
247 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
248 'float'=>'double','dateTime'=>'string',
249 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
250 'http://www.w3.org/1999/XMLSchema' => array(
251 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
252 'float'=>'double','dateTime'=>'string',
253 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
254 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
255 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
256 'http://xml.apache.org/xml-soap' => array('Map')
260 * XML entities to convert
265 * @see expandEntities
267 var $xmlEntities = array('quot' => '"','amp' => '&',
268 'lt' => '<','gt' => '>','apos' => "'");
275 function nusoap_base() {
276 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
280 * gets the global debug level, which applies to future instances
282 * @return integer Debug level 0-9, where 0 turns off
285 function getGlobalDebugLevel() {
286 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
290 * sets the global debug level, which applies to future instances
292 * @param int $level Debug level 0-9, where 0 turns off
295 function setGlobalDebugLevel($level) {
296 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
300 * gets the debug level for this instance
302 * @return int Debug level 0-9, where 0 turns off
305 function getDebugLevel() {
306 return $this->debugLevel;
310 * sets the debug level for this instance
312 * @param int $level Debug level 0-9, where 0 turns off
315 function setDebugLevel($level) {
316 $this->debugLevel = $level;
320 * adds debug data to the instance debug string with formatting
322 * @param string $string debug data
325 function debug($string){
326 if ($this->debugLevel > 0) {
327 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
332 * adds debug data to the instance debug string without formatting
334 * @param string $string debug data
337 function appendDebug($string){
338 if ($this->debugLevel > 0) {
339 // it would be nice to use a memory stream here to use
340 // memory more efficiently
341 $this->debug_str .= $string;
346 * clears the current debug data for this instance
350 function clearDebug() {
351 // it would be nice to use a memory stream here to use
352 // memory more efficiently
353 $this->debug_str = '';
357 * gets the current debug data for this instance
362 function &getDebug() {
363 // it would be nice to use a memory stream here to use
364 // memory more efficiently
365 return $this->debug_str;
369 * gets the current debug data for this instance as an XML comment
370 * this may change the contents of the debug data
372 * @return debug data as an XML comment
375 function &getDebugAsXMLComment() {
376 // it would be nice to use a memory stream here to use
377 // memory more efficiently
378 while (strpos($this->debug_str, '--')) {
379 $this->debug_str = str_replace('--', '- -', $this->debug_str);
381 $ret = "<!--\n" . $this->debug_str . "\n-->";
386 * expands entities, e.g. changes '<' to '<'.
388 * @param string $val The string in which to expand entities.
391 function expandEntities($val) {
392 if ($this->charencoding) {
393 $val = str_replace('&', '&', $val);
394 $val = str_replace("'", ''', $val);
395 $val = str_replace('"', '"', $val);
396 $val = str_replace('<', '<', $val);
397 $val = str_replace('>', '>', $val);
403 * returns error string if present
405 * @return mixed error string or false
409 if($this->error_str != ''){
410 return $this->error_str;
418 * @return boolean $string error string
421 function setError($str){
422 $this->error_str = $str;
426 * detect if array is a simple array or a struct (associative array)
428 * @param mixed $val The PHP array
429 * @return string (arraySimple|arrayStruct)
432 function isArraySimpleOrStruct($val) {
433 $keyList = array_keys($val);
434 foreach ($keyList as $keyListValue) {
435 if (!is_int($keyListValue)) {
436 return 'arrayStruct';
439 return 'arraySimple';
443 * serializes PHP values in accordance w/ section 5. Type information is
444 * not serialized if $use == 'literal'.
446 * @param mixed $val The value to serialize
447 * @param string $name The name (local part) of the XML element
448 * @param string $type The XML schema type (local part) for the element
449 * @param string $name_ns The namespace for the name of the XML element
450 * @param string $type_ns The namespace for the type of the element
451 * @param array $attributes The attributes to serialize as name=>value pairs
452 * @param string $use The WSDL "use" (encoded|literal)
453 * @param boolean $soapval Whether this is called from soapval.
454 * @return string The serialized element, possibly with child elements
457 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
458 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
459 $this->appendDebug('value=' . $this->varDump($val));
460 $this->appendDebug('attributes=' . $this->varDump($attributes));
462 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
463 $this->debug("serialize_val: serialize soapval");
464 $xml = $val->serialize($use);
465 $this->appendDebug($val->getDebug());
467 $this->debug("serialize_val of soapval returning $xml");
470 // force valid name if necessary
471 if (is_numeric($name)) {
472 $name = '__numeric_' . $name;
476 // if name has ns, add ns prefix to name
479 $prefix = 'nu'.rand(1000,9999);
480 $name = $prefix.':'.$name;
481 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
483 // if type is prefixed, create type prefix
484 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
485 // need to fix this. shouldn't default to xsd if no ns specified
486 // w/o checking against typemap
487 $type_prefix = 'xsd';
489 $type_prefix = 'ns'.rand(1000,9999);
490 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
492 // serialize attributes if present
495 foreach($attributes as $k => $v){
496 $atts .= " $k=\"".$this->expandEntities($v).'"';
499 // serialize null value
501 $this->debug("serialize_val: serialize null");
502 if ($use == 'literal') {
503 // TODO: depends on minOccurs
504 $xml = "<$name$xmlns$atts/>";
505 $this->debug("serialize_val returning $xml");
508 if (isset($type) && isset($type_prefix)) {
509 $type_str = " xsi:type=\"$type_prefix:$type\"";
513 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
514 $this->debug("serialize_val returning $xml");
518 // serialize if an xsd built-in primitive type
519 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
520 $this->debug("serialize_val: serialize xsd built-in primitive type");
522 if ($type == 'boolean') {
523 $val = $val ? 'true' : 'false';
527 } else if (is_string($val)) {
528 $val = $this->expandEntities($val);
530 if ($use == 'literal') {
531 $xml = "<$name$xmlns$atts>$val</$name>";
532 $this->debug("serialize_val returning $xml");
535 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
536 $this->debug("serialize_val returning $xml");
540 // detect type and serialize
543 case (is_bool($val) || $type == 'boolean'):
544 $this->debug("serialize_val: serialize boolean");
545 if ($type == 'boolean') {
546 $val = $val ? 'true' : 'false';
550 if ($use == 'literal') {
551 $xml .= "<$name$xmlns$atts>$val</$name>";
553 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
556 case (is_int($val) || is_long($val) || $type == 'int'):
557 $this->debug("serialize_val: serialize int");
558 if ($use == 'literal') {
559 $xml .= "<$name$xmlns$atts>$val</$name>";
561 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
564 case (is_float($val)|| is_double($val) || $type == 'float'):
565 $this->debug("serialize_val: serialize float");
566 if ($use == 'literal') {
567 $xml .= "<$name$xmlns$atts>$val</$name>";
569 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
572 case (is_string($val) || $type == 'string'):
573 $this->debug("serialize_val: serialize string");
574 $val = $this->expandEntities($val);
575 if ($use == 'literal') {
576 $xml .= "<$name$xmlns$atts>$val</$name>";
578 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
581 case is_object($val):
582 $this->debug("serialize_val: serialize object");
583 if (get_class($val) == 'soapval') {
584 $this->debug("serialize_val: serialize soapval object");
585 $pXml = $val->serialize($use);
586 $this->appendDebug($val->getDebug());
590 $name = get_class($val);
591 $this->debug("In serialize_val, used class name $name as element name");
593 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
595 foreach(get_object_vars($val) as $k => $v){
596 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
599 if(isset($type) && isset($type_prefix)){
600 $type_str = " xsi:type=\"$type_prefix:$type\"";
604 if ($use == 'literal') {
605 $xml .= "<$name$xmlns$atts>$pXml</$name>";
607 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
611 case (is_array($val) || $type):
612 // detect if struct or array
613 $valueType = $this->isArraySimpleOrStruct($val);
614 if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
615 $this->debug("serialize_val: serialize array");
617 if(is_array($val) && count($val)> 0){
619 if(is_object($v) && get_class($v) == 'soapval'){
620 $tt_ns = $v->type_ns;
622 } elseif (is_array($v)) {
623 $tt = $this->isArraySimpleOrStruct($v);
627 $array_types[$tt] = 1;
628 // TODO: for literal, the name should be $name
629 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
632 if(count($array_types) > 1){
633 $array_typename = 'xsd:anyType';
634 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
635 if ($tt == 'integer') {
638 $array_typename = 'xsd:'.$tt;
639 } elseif(isset($tt) && $tt == 'arraySimple'){
640 $array_typename = 'SOAP-ENC:Array';
641 } elseif(isset($tt) && $tt == 'arrayStruct'){
642 $array_typename = 'unnamed_struct_use_soapval';
644 // if type is prefixed, create type prefix
645 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
646 $array_typename = 'xsd:' . $tt;
648 $tt_prefix = 'ns' . rand(1000, 9999);
649 $array_typename = "$tt_prefix:$tt";
650 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
652 $array_typename = $tt;
656 if ($use == 'literal') {
658 } else if (isset($type) && isset($type_prefix)) {
659 $type_str = " xsi:type=\"$type_prefix:$type\"";
661 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
665 if ($use == 'literal') {
667 } else if (isset($type) && isset($type_prefix)) {
668 $type_str = " xsi:type=\"$type_prefix:$type\"";
670 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
673 // TODO: for array in literal, there is no wrapper here
674 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
677 $this->debug("serialize_val: serialize struct");
678 if(isset($type) && isset($type_prefix)){
679 $type_str = " xsi:type=\"$type_prefix:$type\"";
683 if ($use == 'literal') {
684 $xml .= "<$name$xmlns$atts>";
686 $xml .= "<$name$xmlns$type_str$atts>";
688 foreach($val as $k => $v){
690 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
692 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
693 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
696 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
703 $this->debug("serialize_val: serialize unknown");
704 $xml .= 'not detected, got '.gettype($val).' for '.$val;
707 $this->debug("serialize_val returning $xml");
712 * serializes a message
714 * @param string $body the XML of the SOAP body
715 * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
716 * @param array $namespaces optional the namespaces used in generating the body and headers
717 * @param string $style optional (rpc|document)
718 * @param string $use optional (encoded|literal)
719 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
720 * @return string the message
723 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
724 // TODO: add an option to automatically run utf8_encode on $body and $headers
725 // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
726 // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
728 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
729 $this->debug("headers:");
730 $this->appendDebug($this->varDump($headers));
731 $this->debug("namespaces:");
732 $this->appendDebug($this->varDump($namespaces));
734 // serialize namespaces
736 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
737 $ns_string .= " xmlns:$k=\"$v\"";
740 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
745 if (is_array($headers)) {
747 foreach ($headers as $k => $v) {
748 if (is_object($v) && get_class($v) == 'soapval') {
749 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
751 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
755 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
757 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
759 // serialize envelope
761 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
762 '<SOAP-ENV:Envelope'.$ns_string.">".
767 "</SOAP-ENV:Envelope>";
771 * formats a string to be inserted into an HTML stream
773 * @param string $str The string to format
774 * @return string The formatted string
778 function formatDump($str){
779 $str = htmlspecialchars($str);
784 * contracts (changes namespace to prefix) a qualified name
786 * @param string $qname qname
787 * @return string contracted qname
790 function contractQname($qname){
791 // get element namespace
792 //$this->xdebug("Contract $qname");
793 if (strrpos($qname, ':')) {
794 // get unqualified name
795 $name = substr($qname, strrpos($qname, ':') + 1);
797 $ns = substr($qname, 0, strrpos($qname, ':'));
798 $p = $this->getPrefixFromNamespace($ns);
800 return $p . ':' . $name;
809 * expands (changes prefix to namespace) a qualified name
811 * @param string $qname qname
812 * @return string expanded qname
815 function expandQname($qname){
816 // get element prefix
817 if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
818 // get unqualified name
819 $name = substr(strstr($qname,':'),1);
821 $prefix = substr($qname,0,strpos($qname,':'));
822 if(isset($this->namespaces[$prefix])){
823 return $this->namespaces[$prefix].':'.$name;
833 * returns the local part of a prefixed string
834 * returns the original string, if not prefixed
836 * @param string $str The prefixed string
837 * @return string The local part
840 function getLocalPart($str){
841 if($sstr = strrchr($str,':')){
842 // get unqualified name
843 return substr( $sstr, 1 );
850 * returns the prefix part of a prefixed string
851 * returns false, if not prefixed
853 * @param string $str The prefixed string
854 * @return mixed The prefix or false if there is no prefix
857 function getPrefix($str){
858 if($pos = strrpos($str,':')){
860 return substr($str,0,$pos);
866 * pass it a prefix, it returns a namespace
868 * @param string $prefix The prefix
869 * @return mixed The namespace, false if no namespace has the specified prefix
872 function getNamespaceFromPrefix($prefix){
873 if (isset($this->namespaces[$prefix])) {
874 return $this->namespaces[$prefix];
876 //$this->setError("No namespace registered for prefix '$prefix'");
881 * returns the prefix for a given namespace (or prefix)
882 * or false if no prefixes registered for the given namespace
884 * @param string $ns The namespace
885 * @return mixed The prefix, false if the namespace has no prefixes
888 function getPrefixFromNamespace($ns) {
889 foreach ($this->namespaces as $p => $n) {
890 if ($ns == $n || $ns == $p) {
891 $this->usedNamespaces[$p] = $n;
899 * returns the time in ODBC canonical form with microseconds
901 * @return string The time in ODBC canonical form with microseconds
904 function getmicrotime() {
905 if (function_exists('gettimeofday')) {
906 $tod = gettimeofday();
908 $usec = $tod['usec'];
913 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
917 * Returns a string with the output of var_dump
919 * @param mixed $data The variable to var_dump
920 * @return string The output of var_dump
923 function varDump($data) {
926 $ret_val = ob_get_contents();
932 * represents the object as a string
937 function __toString() {
938 return $this->varDump($this);
942 // XML Schema Datatype Helper Functions
944 //xsd:dateTime helpers
947 * convert unix timestamp to ISO 8601 compliant date string
949 * @param int $timestamp Unix time stamp
950 * @param boolean $utc Whether the time stamp is UTC or local
951 * @return mixed ISO 8601 date string or false
954 function timestamp_to_iso8601($timestamp,$utc=true){
955 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
956 $pos = strrpos($datestr, "+");
957 if ($pos === FALSE) {
958 $pos = strrpos($datestr, "-");
960 if ($pos !== FALSE) {
961 if (strlen($datestr) == $pos + 5) {
962 $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
967 '([0-9]{4})-'. // centuries & years CCYY-
968 '([0-9]{2})-'. // months MM-
969 '([0-9]{2})'. // days DD
971 '([0-9]{2}):'. // hours hh:
972 '([0-9]{2}):'. // minutes mm:
973 '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
974 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
977 if(preg_match($pattern,$datestr,$regs)){
978 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
987 * convert ISO 8601 compliant date string to unix timestamp
989 * @param string $datestr ISO 8601 compliant date string
990 * @return mixed Unix timestamp (int) or false
993 function iso8601_to_timestamp($datestr){
995 '([0-9]{4})-'. // centuries & years CCYY-
996 '([0-9]{2})-'. // months MM-
997 '([0-9]{2})'. // days DD
999 '([0-9]{2}):'. // hours hh:
1000 '([0-9]{2}):'. // minutes mm:
1001 '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
1002 '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
1004 if(preg_match($pattern,$datestr,$regs)){
1006 if($regs[8] != 'Z'){
1007 $op = substr($regs[8],0,1);
1008 $h = substr($regs[8],1,2);
1009 $m = substr($regs[8],strlen($regs[8])-2,2);
1011 $regs[4] = $regs[4] + $h;
1012 $regs[5] = $regs[5] + $m;
1013 } elseif($op == '+'){
1014 $regs[4] = $regs[4] - $h;
1015 $regs[5] = $regs[5] - $m;
1018 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1019 // return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
1026 * sleeps some number of microseconds
1028 * @param string $usec the number of microseconds to sleep
1032 function usleepWindows($usec)
1034 $start = gettimeofday();
1038 $stop = gettimeofday();
1039 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
1040 + $stop['usec'] - $start['usec'];
1042 while ($timePassed < $usec);