4
$Id: class.nusoap_base.php,v 1.51 2007/11/06 15:17:46 snichol Exp $
6
NuSOAP - Web Services Toolkit for PHP
8
Copyright (c) 2002 NuSphere Corporation
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.
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.
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
24
The NuSOAP project home is:
25
http://sourceforge.net/projects/nusoap/
27
The primary support for NuSOAP is the mailing list:
28
nusoap-general@lists.sourceforge.net
30
If you have any questions or comments, please email:
34
http://dietrich.ganx4.com/nusoap
37
http://www.nusphere.com
42
* Some of the standards implmented in whole or part by NuSOAP:
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
58
require_once('class.soapclient.php');
59
require_once('class.soap_val.php');
60
require_once('class.soap_parser.php');
61
require_once('class.soap_fault.php');
64
require_once('class.soap_transport_http.php');
66
// optional add-on classes
67
require_once('class.xmlschema.php');
68
require_once('class.wsdl.php');
71
require_once('class.soap_server.php');*/
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;
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 $
88
* Identification for HTTP headers.
93
var $title = 'NuSOAP';
95
* Version for HTTP headers.
100
var $version = '0.7.3';
102
* CVS revision for HTTP headers.
107
var $revision = '$Revision: 1.51 $';
109
* Current error string (manipulated by getError/setError)
116
* Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
123
* toggles automatic encoding of special characters as entities
124
* (should always be true, I think)
129
var $charencoding = true;
131
* the debug level for this instance
144
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
147
* charset encoding for outgoing messages
152
var $soap_defencoding = 'ISO-8859-1';
153
//var $soap_defencoding = 'UTF-8';
156
* namespaces in an array of prefix => uri
158
* this is "seeded" by a set of constants, but it may be altered by code
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/'
171
* namespaces used in the current context, e.g. during serialization
176
var $usedNamespaces = array();
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.
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',
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')
211
* XML entities to convert
216
* @see expandEntities
218
var $xmlEntities = array('quot' => '"','amp' => '&',
219
'lt' => '<','gt' => '>','apos' => "'");
226
function nusoap_base() {
227
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
231
* gets the global debug level, which applies to future instances
233
* @return integer Debug level 0-9, where 0 turns off
236
function getGlobalDebugLevel() {
237
return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
241
* sets the global debug level, which applies to future instances
243
* @param int $level Debug level 0-9, where 0 turns off
246
function setGlobalDebugLevel($level) {
247
$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
251
* gets the debug level for this instance
253
* @return int Debug level 0-9, where 0 turns off
256
function getDebugLevel() {
257
return $this->debugLevel;
261
* sets the debug level for this instance
263
* @param int $level Debug level 0-9, where 0 turns off
266
function setDebugLevel($level) {
267
$this->debugLevel = $level;
271
* adds debug data to the instance debug string with formatting
273
* @param string $string debug data
276
function debug($string){
277
if ($this->debugLevel > 0) {
278
$this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
283
* adds debug data to the instance debug string without formatting
285
* @param string $string debug data
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;
297
* clears the current debug data for this instance
301
function clearDebug() {
302
// it would be nice to use a memory stream here to use
303
// memory more efficiently
304
$this->debug_str = '';
308
* gets the current debug data for this instance
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;
320
* gets the current debug data for this instance as an XML comment
321
* this may change the contents of the debug data
323
* @return debug data as an XML comment
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);
332
$ret = "<!--\n" . $this->debug_str . "\n-->";
337
* expands entities, e.g. changes '<' to '<'.
339
* @param string $val The string in which to expand entities.
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);
354
* returns error string if present
356
* @return mixed error string or false
360
if($this->error_str != ''){
361
return $this->error_str;
369
* @return boolean $string error string
372
function setError($str){
373
$this->error_str = $str;
377
* detect if array is a simple array or a struct (associative array)
379
* @param mixed $val The PHP array
380
* @return string (arraySimple|arrayStruct)
383
function isArraySimpleOrStruct($val) {
384
$keyList = array_keys($val);
385
foreach ($keyList as $keyListValue) {
386
if (!is_int($keyListValue)) {
387
return 'arrayStruct';
390
return 'arraySimple';
394
* serializes PHP values in accordance w/ section 5. Type information is
395
* not serialized if $use == 'literal'.
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
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));
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());
418
$this->debug("serialize_val of soapval returning $xml");
421
// force valid name if necessary
422
if (is_numeric($name)) {
423
$name = '__numeric_' . $name;
427
// if name has ns, add ns prefix to name
430
$prefix = 'nu'.rand(1000,9999);
431
$name = $prefix.':'.$name;
432
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
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';
440
$type_prefix = 'ns'.rand(1000,9999);
441
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
443
// serialize attributes if present
446
foreach($attributes as $k => $v){
447
$atts .= " $k=\"".$this->expandEntities($v).'"';
450
// serialize null value
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");
459
if (isset($type) && isset($type_prefix)) {
460
$type_str = " xsi:type=\"$type_prefix:$type\"";
464
$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
465
$this->debug("serialize_val returning $xml");
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");
473
if ($type == 'boolean') {
474
$val = $val ? 'true' : 'false';
478
} else if (is_string($val)) {
479
$val = $this->expandEntities($val);
481
if ($use == 'literal') {
482
$xml = "<$name$xmlns$atts>$val</$name>";
483
$this->debug("serialize_val returning $xml");
486
$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
487
$this->debug("serialize_val returning $xml");
491
// detect type and serialize
494
case (is_bool($val) || $type == 'boolean'):
495
$this->debug("serialize_val: serialize boolean");
496
if ($type == 'boolean') {
497
$val = $val ? 'true' : 'false';
501
if ($use == 'literal') {
502
$xml .= "<$name$xmlns$atts>$val</$name>";
504
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
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>";
512
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
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>";
520
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
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>";
529
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
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());
541
$name = get_class($val);
542
$this->debug("In serialize_val, used class name $name as element name");
544
$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
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);
550
if(isset($type) && isset($type_prefix)){
551
$type_str = " xsi:type=\"$type_prefix:$type\"";
555
if ($use == 'literal') {
556
$xml .= "<$name$xmlns$atts>$pXml</$name>";
558
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
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");
568
if(is_array($val) && count($val)> 0){
570
if(is_object($v) && get_class($v) == 'soapval'){
571
$tt_ns = $v->type_ns;
573
} elseif (is_array($v)) {
574
$tt = $this->isArraySimpleOrStruct($v);
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);
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') {
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';
595
// if type is prefixed, create type prefix
596
if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
597
$array_typename = 'xsd:' . $tt;
599
$tt_prefix = 'ns' . rand(1000, 9999);
600
$array_typename = "$tt_prefix:$tt";
601
$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
603
$array_typename = $tt;
607
if ($use == 'literal') {
609
} else if (isset($type) && isset($type_prefix)) {
610
$type_str = " xsi:type=\"$type_prefix:$type\"";
612
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
616
if ($use == 'literal') {
618
} else if (isset($type) && isset($type_prefix)) {
619
$type_str = " xsi:type=\"$type_prefix:$type\"";
621
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
624
// TODO: for array in literal, there is no wrapper here
625
$xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
628
$this->debug("serialize_val: serialize struct");
629
if(isset($type) && isset($type_prefix)){
630
$type_str = " xsi:type=\"$type_prefix:$type\"";
634
if ($use == 'literal') {
635
$xml .= "<$name$xmlns$atts>";
637
$xml .= "<$name$xmlns$type_str$atts>";
639
foreach($val as $k => $v){
641
if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
643
$xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
644
$xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
647
$xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
654
$this->debug("serialize_val: serialize unknown");
655
$xml .= 'not detected, got '.gettype($val).' for '.$val;
658
$this->debug("serialize_val returning $xml");
663
* serializes a message
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
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
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));
685
// serialize namespaces
687
foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
688
$ns_string .= " xmlns:$k=\"$v\"";
691
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
696
if (is_array($headers)) {
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);
702
$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
706
$this->debug("In serializeEnvelope, serialized array of headers to $headers");
708
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
710
// serialize envelope
712
'<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
713
'<SOAP-ENV:Envelope'.$ns_string.">".
718
"</SOAP-ENV:Envelope>";
722
* formats a string to be inserted into an HTML stream
724
* @param string $str The string to format
725
* @return string The formatted string
729
function formatDump($str){
730
$str = htmlspecialchars($str);
735
* contracts (changes namespace to prefix) a qualified name
737
* @param string $qname qname
738
* @return string contracted qname
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);
748
$ns = substr($qname, 0, strrpos($qname, ':'));
749
$p = $this->getPrefixFromNamespace($ns);
751
return $p . ':' . $name;
760
* expands (changes prefix to namespace) a qualified name
762
* @param string $qname qname
763
* @return string expanded qname
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);
772
$prefix = substr($qname,0,strpos($qname,':'));
773
if(isset($this->namespaces[$prefix])){
774
return $this->namespaces[$prefix].':'.$name;
784
* returns the local part of a prefixed string
785
* returns the original string, if not prefixed
787
* @param string $str The prefixed string
788
* @return string The local part
791
function getLocalPart($str){
792
if($sstr = strrchr($str,':')){
793
// get unqualified name
794
return substr( $sstr, 1 );
801
* returns the prefix part of a prefixed string
802
* returns false, if not prefixed
804
* @param string $str The prefixed string
805
* @return mixed The prefix or false if there is no prefix
808
function getPrefix($str){
809
if($pos = strrpos($str,':')){
811
return substr($str,0,$pos);
817
* pass it a prefix, it returns a namespace
819
* @param string $prefix The prefix
820
* @return mixed The namespace, false if no namespace has the specified prefix
823
function getNamespaceFromPrefix($prefix){
824
if (isset($this->namespaces[$prefix])) {
825
return $this->namespaces[$prefix];
827
//$this->setError("No namespace registered for prefix '$prefix'");
832
* returns the prefix for a given namespace (or prefix)
833
* or false if no prefixes registered for the given namespace
835
* @param string $ns The namespace
836
* @return mixed The prefix, false if the namespace has no prefixes
839
function getPrefixFromNamespace($ns) {
840
foreach ($this->namespaces as $p => $n) {
841
if ($ns == $n || $ns == $p) {
842
$this->usedNamespaces[$p] = $n;
850
* returns the time in ODBC canonical form with microseconds
852
* @return string The time in ODBC canonical form with microseconds
855
function getmicrotime() {
856
if (function_exists('gettimeofday')) {
857
$tod = gettimeofday();
859
$usec = $tod['usec'];
864
return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
868
* Returns a string with the output of var_dump
870
* @param mixed $data The variable to var_dump
871
* @return string The output of var_dump
874
function varDump($data) {
877
$ret_val = ob_get_contents();
883
* represents the object as a string
888
function __toString() {
889
return $this->varDump($this);
893
// XML Schema Datatype Helper Functions
895
//xsd:dateTime helpers
898
* convert unix timestamp to ISO 8601 compliant date string
900
* @param string $timestamp Unix time stamp
901
* @param boolean $utc Whether the time stamp is UTC or local
904
function timestamp_to_iso8601($timestamp,$utc=true){
905
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
908
'([0-9]{4})-'. // centuries & years CCYY-
909
'([0-9]{2})-'. // months MM-
910
'([0-9]{2})'. // days DD
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
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]);
927
* convert ISO 8601 compliant date string to unix timestamp
929
* @param string $datestr ISO 8601 compliant date string
932
function iso8601_to_timestamp($datestr){
934
'([0-9]{4})-'. // centuries & years CCYY-
935
'([0-9]{2})-'. // months MM-
936
'([0-9]{2})'. // days DD
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)){
945
$op = substr($regs[8],0,1);
946
$h = substr($regs[8],1,2);
947
$m = substr($regs[8],strlen($regs[8])-2,2);
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;
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");
964
* sleeps some number of microseconds
966
* @param string $usec the number of microseconds to sleep
970
function usleepWindows($usec)
972
$start = gettimeofday();
976
$stop = gettimeofday();
977
$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
978
+ $stop['usec'] - $start['usec'];
980
while ($timePassed < $usec);
b'\\ No newline at end of file'