00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
00075
00085 class nusoap_base {
00092 var $title = 'NuSOAP';
00099 var $version = '1.0rc1';
00106 var $revision = '$Revision: 1.121 $';
00113 var $error_str = '';
00120 var $debug_str = '';
00128 var $charencoding = true;
00135 var $debugLevel;
00136
00143 var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
00144
00151 var $soap_defencoding = 'ISO-8859-1';
00152
00153
00162 var $namespaces = array(
00163 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
00164 'xsd' => 'http://www.w3.org/2001/XMLSchema',
00165 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
00166 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
00167 );
00168
00175 var $usedNamespaces = array();
00176
00184 var $typemap = array(
00185 'http://www.w3.org/2001/XMLSchema' => array(
00186 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
00187 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
00188 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
00189
00190 'anyType'=>'string','anySimpleType'=>'string',
00191
00192 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
00193 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
00194 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
00195 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
00196 'http://www.w3.org/2000/10/XMLSchema' => array(
00197 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
00198 'float'=>'double','dateTime'=>'string',
00199 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
00200 'http://www.w3.org/1999/XMLSchema' => array(
00201 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
00202 'float'=>'double','dateTime'=>'string',
00203 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
00204 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
00205 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
00206 'http://xml.apache.org/xml-soap' => array('Map')
00207 );
00208
00217 var $xmlEntities = array('quot' => '"','amp' => '&',
00218 'lt' => '<','gt' => '>','apos' => "'");
00219
00225 function nusoap_base() {
00226 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
00227 }
00228
00235 function getGlobalDebugLevel() {
00236 return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
00237 }
00238
00245 function setGlobalDebugLevel($level) {
00246 $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
00247 }
00248
00255 function getDebugLevel() {
00256 return $this->debugLevel;
00257 }
00258
00265 function setDebugLevel($level) {
00266 $this->debugLevel = $level;
00267 }
00268
00275 function debug($string){
00276 if ($this->debugLevel > 0) {
00277 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
00278 }
00279 }
00280
00287 function appendDebug($string){
00288 if ($this->debugLevel > 0) {
00289
00290
00291 $this->debug_str .= $string;
00292 }
00293 }
00294
00300 function clearDebug() {
00301
00302
00303 $this->debug_str = '';
00304 }
00305
00312 function &getDebug() {
00313
00314
00315 return $this->debug_str;
00316 }
00317
00325 function &getDebugAsXMLComment() {
00326
00327
00328 while (strpos($this->debug_str, '--')) {
00329 $this->debug_str = str_replace('--', '- -', $this->debug_str);
00330 }
00331 $ret = "<!--\n" . $this->debug_str . "\n-->";
00332 return $ret;
00333 }
00334
00341 function expandEntities($val) {
00342 if ($this->charencoding) {
00343 $val = str_replace('&', '&', $val);
00344 $val = str_replace("'", ''', $val);
00345 $val = str_replace('"', '"', $val);
00346 $val = str_replace('<', '<', $val);
00347 $val = str_replace('>', '>', $val);
00348 }
00349 return $val;
00350 }
00351
00358 function getError(){
00359 if($this->error_str != ''){
00360 return $this->error_str;
00361 }
00362 return false;
00363 }
00364
00371 function setError($str){
00372 $this->error_str = $str;
00373 }
00374
00382 function isArraySimpleOrStruct($val) {
00383 $keyList = array_keys($val);
00384 foreach ($keyList as $keyListValue) {
00385 if (!is_int($keyListValue)) {
00386 return 'arrayStruct';
00387 }
00388 }
00389 return 'arraySimple';
00390 }
00391
00407 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
00408 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
00409 $this->appendDebug('value=' . $this->varDump($val));
00410 $this->appendDebug('attributes=' . $this->varDump($attributes));
00411
00412 if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
00413 $this->debug("serialize_val: serialize soapval");
00414 $xml = $val->serialize($use);
00415 $this->appendDebug($val->getDebug());
00416 $val->clearDebug();
00417 $this->debug("serialize_val of soapval returning $xml");
00418 return $xml;
00419 }
00420
00421 if (is_numeric($name)) {
00422 $name = '__numeric_' . $name;
00423 } elseif (! $name) {
00424 $name = 'noname';
00425 }
00426
00427 $xmlns = '';
00428 if($name_ns){
00429 $prefix = 'nu'.rand(1000,9999);
00430 $name = $prefix.':'.$name;
00431 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
00432 }
00433
00434 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
00435
00436
00437 $type_prefix = 'xsd';
00438 } elseif($type_ns){
00439 $type_prefix = 'ns'.rand(1000,9999);
00440 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
00441 }
00442
00443 $atts = '';
00444 if($attributes){
00445 foreach($attributes as $k => $v){
00446 $atts .= " $k=\"".$this->expandEntities($v).'"';
00447 }
00448 }
00449
00450 if (is_null($val)) {
00451 $this->debug("serialize_val: serialize null");
00452 if ($use == 'literal') {
00453
00454 $xml = "<$name$xmlns$atts/>";
00455 $this->debug("serialize_val returning $xml");
00456 return $xml;
00457 } else {
00458 if (isset($type) && isset($type_prefix)) {
00459 $type_str = " xsi:type=\"$type_prefix:$type\"";
00460 } else {
00461 $type_str = '';
00462 }
00463 $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
00464 $this->debug("serialize_val returning $xml");
00465 return $xml;
00466 }
00467 }
00468
00469 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
00470 $this->debug("serialize_val: serialize xsd built-in primitive type");
00471 if (is_bool($val)) {
00472 if ($type == 'boolean') {
00473 $val = $val ? 'true' : 'false';
00474 } elseif (! $val) {
00475 $val = 0;
00476 }
00477 } else if (is_string($val)) {
00478 $val = $this->expandEntities($val);
00479 }
00480 if ($use == 'literal') {
00481 $xml = "<$name$xmlns$atts>$val</$name>";
00482 $this->debug("serialize_val returning $xml");
00483 return $xml;
00484 } else {
00485 $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
00486 $this->debug("serialize_val returning $xml");
00487 return $xml;
00488 }
00489 }
00490
00491 $xml = '';
00492 switch(true) {
00493 case (is_bool($val) || $type == 'boolean'):
00494 $this->debug("serialize_val: serialize boolean");
00495 if ($type == 'boolean') {
00496 $val = $val ? 'true' : 'false';
00497 } elseif (! $val) {
00498 $val = 0;
00499 }
00500 if ($use == 'literal') {
00501 $xml .= "<$name$xmlns$atts>$val</$name>";
00502 } else {
00503 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
00504 }
00505 break;
00506 case (is_int($val) || is_long($val) || $type == 'int'):
00507 $this->debug("serialize_val: serialize int");
00508 if ($use == 'literal') {
00509 $xml .= "<$name$xmlns$atts>$val</$name>";
00510 } else {
00511 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
00512 }
00513 break;
00514 case (is_float($val)|| is_double($val) || $type == 'float'):
00515 $this->debug("serialize_val: serialize float");
00516 if ($use == 'literal') {
00517 $xml .= "<$name$xmlns$atts>$val</$name>";
00518 } else {
00519 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
00520 }
00521 break;
00522 case (is_string($val) || $type == 'string'):
00523 $this->debug("serialize_val: serialize string");
00524 $val = $this->expandEntities($val);
00525 if ($use == 'literal') {
00526 $xml .= "<$name$xmlns$atts>$val</$name>";
00527 } else {
00528 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
00529 }
00530 break;
00531 case is_object($val):
00532 $this->debug("serialize_val: serialize object");
00533 if (get_class($val) == 'soapval') {
00534 $this->debug("serialize_val: serialize soapval object");
00535 $pXml = $val->serialize($use);
00536 $this->appendDebug($val->getDebug());
00537 $val->clearDebug();
00538 } else {
00539 if (! $name) {
00540 $name = get_class($val);
00541 $this->debug("In serialize_val, used class name $name as element name");
00542 } else {
00543 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
00544 }
00545 foreach(get_object_vars($val) as $k => $v){
00546 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
00547 }
00548 }
00549 if(isset($type) && isset($type_prefix)){
00550 $type_str = " xsi:type=\"$type_prefix:$type\"";
00551 } else {
00552 $type_str = '';
00553 }
00554 if ($use == 'literal') {
00555 $xml .= "<$name$xmlns$atts>$pXml</$name>";
00556 } else {
00557 $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
00558 }
00559 break;
00560 break;
00561 case (is_array($val) || $type):
00562
00563 $valueType = $this->isArraySimpleOrStruct($val);
00564 if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
00565 $this->debug("serialize_val: serialize array");
00566 $i = 0;
00567 if(is_array($val) && count($val)> 0){
00568 foreach($val as $v){
00569 if(is_object($v) && get_class($v) == 'soapval'){
00570 $tt_ns = $v->type_ns;
00571 $tt = $v->type;
00572 } elseif (is_array($v)) {
00573 $tt = $this->isArraySimpleOrStruct($v);
00574 } else {
00575 $tt = gettype($v);
00576 }
00577 $array_types[$tt] = 1;
00578
00579 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
00580 ++$i;
00581 }
00582 if(count($array_types) > 1){
00583 $array_typename = 'xsd:anyType';
00584 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
00585 if ($tt == 'integer') {
00586 $tt = 'int';
00587 }
00588 $array_typename = 'xsd:'.$tt;
00589 } elseif(isset($tt) && $tt == 'arraySimple'){
00590 $array_typename = 'SOAP-ENC:Array';
00591 } elseif(isset($tt) && $tt == 'arrayStruct'){
00592 $array_typename = 'unnamed_struct_use_soapval';
00593 } else {
00594
00595 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
00596 $array_typename = 'xsd:' . $tt;
00597 } elseif ($tt_ns) {
00598 $tt_prefix = 'ns' . rand(1000, 9999);
00599 $array_typename = "$tt_prefix:$tt";
00600 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
00601 } else {
00602 $array_typename = $tt;
00603 }
00604 }
00605 $array_type = $i;
00606 if ($use == 'literal') {
00607 $type_str = '';
00608 } else if (isset($type) && isset($type_prefix)) {
00609 $type_str = " xsi:type=\"$type_prefix:$type\"";
00610 } else {
00611 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
00612 }
00613
00614 } else {
00615 if ($use == 'literal') {
00616 $type_str = '';
00617 } else if (isset($type) && isset($type_prefix)) {
00618 $type_str = " xsi:type=\"$type_prefix:$type\"";
00619 } else {
00620 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
00621 }
00622 }
00623
00624 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
00625 } else {
00626
00627 $this->debug("serialize_val: serialize struct");
00628 if(isset($type) && isset($type_prefix)){
00629 $type_str = " xsi:type=\"$type_prefix:$type\"";
00630 } else {
00631 $type_str = '';
00632 }
00633 if ($use == 'literal') {
00634 $xml .= "<$name$xmlns$atts>";
00635 } else {
00636 $xml .= "<$name$xmlns$type_str$atts>";
00637 }
00638 foreach($val as $k => $v){
00639
00640 if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
00641 $xml .= '<item>';
00642 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
00643 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
00644 $xml .= '</item>';
00645 } else {
00646 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
00647 }
00648 }
00649 $xml .= "</$name>";
00650 }
00651 break;
00652 default:
00653 $this->debug("serialize_val: serialize unknown");
00654 $xml .= 'not detected, got '.gettype($val).' for '.$val;
00655 break;
00656 }
00657 $this->debug("serialize_val returning $xml");
00658 return $xml;
00659 }
00660
00673 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
00674
00675
00676
00677
00678 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
00679 $this->debug("headers:");
00680 $this->appendDebug($this->varDump($headers));
00681 $this->debug("namespaces:");
00682 $this->appendDebug($this->varDump($namespaces));
00683
00684
00685 $ns_string = '';
00686 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
00687 $ns_string .= " xmlns:$k=\"$v\"";
00688 }
00689 if($encodingStyle) {
00690 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
00691 }
00692
00693
00694 if($headers){
00695 if (is_array($headers)) {
00696 $xml = '';
00697 foreach ($headers as $k => $v) {
00698 if (is_object($v) && get_class($v) == 'soapval') {
00699 $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
00700 } else {
00701 $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
00702 }
00703 }
00704 $headers = $xml;
00705 $this->debug("In serializeEnvelope, serialized array of headers to $headers");
00706 }
00707 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
00708 }
00709
00710 return
00711 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
00712 '<SOAP-ENV:Envelope'.$ns_string.">".
00713 $headers.
00714 "<SOAP-ENV:Body>".
00715 $body.
00716 "</SOAP-ENV:Body>".
00717 "</SOAP-ENV:Envelope>";
00718 }
00719
00728 function formatDump($str){
00729 $str = htmlspecialchars($str);
00730 return nl2br($str);
00731 }
00732
00740 function contractQname($qname){
00741
00742
00743 if (strrpos($qname, ':')) {
00744
00745 $name = substr($qname, strrpos($qname, ':') + 1);
00746
00747 $ns = substr($qname, 0, strrpos($qname, ':'));
00748 $p = $this->getPrefixFromNamespace($ns);
00749 if ($p) {
00750 return $p . ':' . $name;
00751 }
00752 return $qname;
00753 } else {
00754 return $qname;
00755 }
00756 }
00757
00765 function expandQname($qname){
00766
00767 if(strpos($qname,':') && !ereg('^http://',$qname)){
00768
00769 $name = substr(strstr($qname,':'),1);
00770
00771 $prefix = substr($qname,0,strpos($qname,':'));
00772 if(isset($this->namespaces[$prefix])){
00773 return $this->namespaces[$prefix].':'.$name;
00774 } else {
00775 return $qname;
00776 }
00777 } else {
00778 return $qname;
00779 }
00780 }
00781
00790 function getLocalPart($str){
00791 if($sstr = strrchr($str,':')){
00792
00793 return substr( $sstr, 1 );
00794 } else {
00795 return $str;
00796 }
00797 }
00798
00807 function getPrefix($str){
00808 if($pos = strrpos($str,':')){
00809
00810 return substr($str,0,$pos);
00811 }
00812 return false;
00813 }
00814
00822 function getNamespaceFromPrefix($prefix){
00823 if (isset($this->namespaces[$prefix])) {
00824 return $this->namespaces[$prefix];
00825 }
00826
00827 return false;
00828 }
00829
00838 function getPrefixFromNamespace($ns) {
00839 foreach ($this->namespaces as $p => $n) {
00840 if ($ns == $n || $ns == $p) {
00841 $this->usedNamespaces[$p] = $n;
00842 return $p;
00843 }
00844 }
00845 return false;
00846 }
00847
00854 function getmicrotime() {
00855 if (function_exists('gettimeofday')) {
00856 $tod = gettimeofday();
00857 $sec = $tod['sec'];
00858 $usec = $tod['usec'];
00859 } else {
00860 $sec = time();
00861 $usec = 0;
00862 }
00863 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
00864 }
00865
00873 function varDump($data) {
00874 ob_start();
00875 var_dump($data);
00876 $ret_val = ob_get_contents();
00877 ob_end_clean();
00878 return $ret_val;
00879 }
00880
00887 function __toString() {
00888 return $this->varDump($this);
00889 }
00890 }
00891
00892
00893
00894
00895
00904 function timestamp_to_iso8601($timestamp,$utc=true){
00905 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
00906 $pos = strrpos($datestr, "+");
00907 if ($pos === FALSE) {
00908 $pos = strrpos($datestr, "-");
00909 }
00910 if ($pos !== FALSE) {
00911 if (strlen($datestr) == $pos + 5) {
00912 $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
00913 }
00914 }
00915 if($utc){
00916 $eregStr =
00917 '([0-9]{4})-'.
00918 '([0-9]{2})-'.
00919 '([0-9]{2})'.
00920 'T'.
00921 '([0-9]{2}):'.
00922 '([0-9]{2}):'.
00923 '([0-9]{2})(\.[0-9]*)?'.
00924 '(Z|[+\-][0-9]{2}:?[0-9]{2})?';
00925
00926 if(ereg($eregStr,$datestr,$regs)){
00927 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
00928 }
00929 return false;
00930 } else {
00931 return $datestr;
00932 }
00933 }
00934
00942 function iso8601_to_timestamp($datestr){
00943 $eregStr =
00944 '([0-9]{4})-'.
00945 '([0-9]{2})-'.
00946 '([0-9]{2})'.
00947 'T'.
00948 '([0-9]{2}):'.
00949 '([0-9]{2}):'.
00950 '([0-9]{2})(\.[0-9]+)?'.
00951 '(Z|[+\-][0-9]{2}:?[0-9]{2})?';
00952 if(ereg($eregStr,$datestr,$regs)){
00953
00954 if($regs[8] != 'Z'){
00955 $op = substr($regs[8],0,1);
00956 $h = substr($regs[8],1,2);
00957 $m = substr($regs[8],strlen($regs[8])-2,2);
00958 if($op == '-'){
00959 $regs[4] = $regs[4] + $h;
00960 $regs[5] = $regs[5] + $m;
00961 } elseif($op == '+'){
00962 $regs[4] = $regs[4] - $h;
00963 $regs[5] = $regs[5] - $m;
00964 }
00965 }
00966 return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
00967
00968 } else {
00969 return false;
00970 }
00971 }
00972
00980 function usleepWindows($usec)
00981 {
00982 $start = gettimeofday();
00983
00984 do
00985 {
00986 $stop = gettimeofday();
00987 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
00988 + $stop['usec'] - $start['usec'];
00989 }
00990 while ($timePassed < $usec);
00991 }
00992
00993 ?><?php
00994
00995
00996
01005 class nusoap_fault extends nusoap_base {
01011 var $faultcode;
01017 var $faultactor;
01023 var $faultstring;
01029 var $faultdetail;
01030
01039 function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
01040 parent::nusoap_base();
01041 $this->faultcode = $faultcode;
01042 $this->faultactor = $faultactor;
01043 $this->faultstring = $faultstring;
01044 $this->faultdetail = $faultdetail;
01045 }
01046
01053 function serialize(){
01054 $ns_string = '';
01055 foreach($this->namespaces as $k => $v){
01056 $ns_string .= "\n xmlns:$k=\"$v\"";
01057 }
01058 $return_msg =
01059 '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
01060 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
01061 '<SOAP-ENV:Body>'.
01062 '<SOAP-ENV:Fault>'.
01063 $this->serialize_val($this->faultcode, 'faultcode').
01064 $this->serialize_val($this->faultactor, 'faultactor').
01065 $this->serialize_val($this->faultstring, 'faultstring').
01066 $this->serialize_val($this->faultdetail, 'detail').
01067 '</SOAP-ENV:Fault>'.
01068 '</SOAP-ENV:Body>'.
01069 '</SOAP-ENV:Envelope>';
01070 return $return_msg;
01071 }
01072 }
01073
01077 class soap_fault extends nusoap_fault {
01078 }
01079
01080 ?><?php
01081
01082
01083
01093 class nusoap_xmlschema extends nusoap_base {
01094
01095
01096 var $schema = '';
01097 var $xml = '';
01098
01099 var $enclosingNamespaces;
01100
01101 var $schemaInfo = array();
01102 var $schemaTargetNamespace = '';
01103
01104 var $attributes = array();
01105 var $complexTypes = array();
01106 var $complexTypeStack = array();
01107 var $currentComplexType = null;
01108 var $elements = array();
01109 var $elementStack = array();
01110 var $currentElement = null;
01111 var $simpleTypes = array();
01112 var $simpleTypeStack = array();
01113 var $currentSimpleType = null;
01114
01115 var $imports = array();
01116
01117 var $parser;
01118 var $position = 0;
01119 var $depth = 0;
01120 var $depth_array = array();
01121 var $message = array();
01122 var $defaultNamespace = array();
01123
01132 function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
01133 parent::nusoap_base();
01134 $this->debug('nusoap_xmlschema class instantiated, inside constructor');
01135
01136 $this->schema = $schema;
01137 $this->xml = $xml;
01138
01139
01140 $this->enclosingNamespaces = $namespaces;
01141 $this->namespaces = array_merge($this->namespaces, $namespaces);
01142
01143
01144 if($schema != ''){
01145 $this->debug('initial schema file: '.$schema);
01146 $this->parseFile($schema, 'schema');
01147 }
01148
01149
01150 if($xml != ''){
01151 $this->debug('initial xml file: '.$xml);
01152 $this->parseFile($xml, 'xml');
01153 }
01154
01155 }
01156
01165 function parseFile($xml,$type){
01166
01167 if($xml != ""){
01168 $xmlStr = @join("",@file($xml));
01169 if($xmlStr == ""){
01170 $msg = 'Error reading XML from '.$xml;
01171 $this->setError($msg);
01172 $this->debug($msg);
01173 return false;
01174 } else {
01175 $this->debug("parsing $xml");
01176 $this->parseString($xmlStr,$type);
01177 $this->debug("done parsing $xml");
01178 return true;
01179 }
01180 }
01181 return false;
01182 }
01183
01191 function parseString($xml,$type){
01192
01193 if($xml != ""){
01194
01195
01196 $this->parser = xml_parser_create();
01197
01198 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
01199
01200
01201 xml_set_object($this->parser, $this);
01202
01203
01204 if($type == "schema"){
01205 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
01206 xml_set_character_data_handler($this->parser,'schemaCharacterData');
01207 } elseif($type == "xml"){
01208 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
01209 xml_set_character_data_handler($this->parser,'xmlCharacterData');
01210 }
01211
01212
01213 if(!xml_parse($this->parser,$xml,true)){
01214
01215 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
01216 xml_get_current_line_number($this->parser),
01217 xml_error_string(xml_get_error_code($this->parser))
01218 );
01219 $this->debug($errstr);
01220 $this->debug("XML payload:\n" . $xml);
01221 $this->setError($errstr);
01222 }
01223
01224 xml_parser_free($this->parser);
01225 } else{
01226 $this->debug('no xml passed to parseString()!!');
01227 $this->setError('no xml passed to parseString()!!');
01228 }
01229 }
01230
01238 function CreateTypeName($ename) {
01239 $scope = '';
01240 for ($i = 0; $i < count($this->complexTypeStack); $i++) {
01241 $scope .= $this->complexTypeStack[$i] . '_';
01242 }
01243 return $scope . $ename . '_ContainedType';
01244 }
01245
01254 function schemaStartElement($parser, $name, $attrs) {
01255
01256
01257 $pos = $this->position++;
01258 $depth = $this->depth++;
01259
01260 $this->depth_array[$depth] = $pos;
01261 $this->message[$pos] = array('cdata' => '');
01262 if ($depth > 0) {
01263 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
01264 } else {
01265 $this->defaultNamespace[$pos] = false;
01266 }
01267
01268
01269 if($prefix = $this->getPrefix($name)){
01270
01271 $name = $this->getLocalPart($name);
01272 } else {
01273 $prefix = '';
01274 }
01275
01276
01277 if(count($attrs) > 0){
01278 foreach($attrs as $k => $v){
01279
01280 if(ereg("^xmlns",$k)){
01281
01282
01283 if($ns_prefix = substr(strrchr($k,':'),1)){
01284
01285 $this->namespaces[$ns_prefix] = $v;
01286 } else {
01287 $this->defaultNamespace[$pos] = $v;
01288 if (! $this->getPrefixFromNamespace($v)) {
01289 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
01290 }
01291 }
01292 if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
01293 $this->XMLSchemaVersion = $v;
01294 $this->namespaces['xsi'] = $v.'-instance';
01295 }
01296 }
01297 }
01298 foreach($attrs as $k => $v){
01299
01300 $k = strpos($k,':') ? $this->expandQname($k) : $k;
01301 $v = strpos($v,':') ? $this->expandQname($v) : $v;
01302 $eAttrs[$k] = $v;
01303 }
01304 $attrs = $eAttrs;
01305 } else {
01306 $attrs = array();
01307 }
01308
01309 switch($name){
01310 case 'all':
01311 case 'choice':
01312 case 'group':
01313 case 'sequence':
01314
01315 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
01316
01317
01318
01319 break;
01320 case 'attribute':
01321
01322 $this->xdebug("parsing attribute:");
01323 $this->appendDebug($this->varDump($attrs));
01324 if (!isset($attrs['form'])) {
01325
01326 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
01327 }
01328 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
01329 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
01330 if (!strpos($v, ':')) {
01331
01332 if ($this->defaultNamespace[$pos]) {
01333
01334 $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
01335 }
01336 }
01337 }
01338 if(isset($attrs['name'])){
01339 $this->attributes[$attrs['name']] = $attrs;
01340 $aname = $attrs['name'];
01341 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
01342 if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
01343 $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
01344 } else {
01345 $aname = '';
01346 }
01347 } elseif(isset($attrs['ref'])){
01348 $aname = $attrs['ref'];
01349 $this->attributes[$attrs['ref']] = $attrs;
01350 }
01351
01352 if($this->currentComplexType){
01353 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
01354 }
01355
01356 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
01357 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01358 $prefix = $this->getPrefix($aname);
01359 if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
01360 $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
01361 } else {
01362 $v = '';
01363 }
01364 if(strpos($v,'[,]')){
01365 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
01366 }
01367 $v = substr($v,0,strpos($v,'['));
01368 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
01369 $v = $this->XMLSchemaVersion.':'.$v;
01370 }
01371 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
01372 }
01373 break;
01374 case 'complexContent':
01375 $this->xdebug("do nothing for element $name");
01376 break;
01377 case 'complexType':
01378 array_push($this->complexTypeStack, $this->currentComplexType);
01379 if(isset($attrs['name'])){
01380
01381
01382 $this->xdebug('processing named complexType '.$attrs['name']);
01383
01384 $this->currentComplexType = $attrs['name'];
01385 $this->complexTypes[$this->currentComplexType] = $attrs;
01386 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
01387
01388
01389
01390
01391
01392
01393
01394 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
01395 $this->xdebug('complexType is unusual array');
01396 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01397 } else {
01398 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
01399 }
01400 } else {
01401 $name = $this->CreateTypeName($this->currentElement);
01402 $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
01403 $this->currentComplexType = $name;
01404
01405 $this->complexTypes[$this->currentComplexType] = $attrs;
01406 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
01407
01408
01409
01410
01411
01412
01413
01414 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
01415 $this->xdebug('complexType is unusual array');
01416 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01417 } else {
01418 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
01419 }
01420 }
01421 break;
01422 case 'element':
01423 array_push($this->elementStack, $this->currentElement);
01424 if (!isset($attrs['form'])) {
01425 if ($this->currentComplexType) {
01426 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
01427 } else {
01428
01429 $attrs['form'] = 'qualified';
01430 }
01431 }
01432 if(isset($attrs['type'])){
01433 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
01434 if (! $this->getPrefix($attrs['type'])) {
01435 if ($this->defaultNamespace[$pos]) {
01436 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
01437 $this->xdebug('used default namespace to make type ' . $attrs['type']);
01438 }
01439 }
01440
01441
01442
01443
01444
01445
01446
01447 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
01448 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
01449 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
01450 }
01451 $this->currentElement = $attrs['name'];
01452 $ename = $attrs['name'];
01453 } elseif(isset($attrs['ref'])){
01454 $this->xdebug("processing element as ref to ".$attrs['ref']);
01455 $this->currentElement = "ref to ".$attrs['ref'];
01456 $ename = $this->getLocalPart($attrs['ref']);
01457 } else {
01458 $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
01459 $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
01460 $this->currentElement = $attrs['name'];
01461 $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
01462 $ename = $attrs['name'];
01463 }
01464 if (isset($ename) && $this->currentComplexType) {
01465 $this->xdebug("add element $ename to complexType $this->currentComplexType");
01466 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
01467 } elseif (!isset($attrs['ref'])) {
01468 $this->xdebug("add element $ename to elements array");
01469 $this->elements[ $attrs['name'] ] = $attrs;
01470 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
01471 }
01472 break;
01473 case 'enumeration':
01474 $this->xdebug('enumeration ' . $attrs['value']);
01475 if ($this->currentSimpleType) {
01476 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
01477 } elseif ($this->currentComplexType) {
01478 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
01479 }
01480 break;
01481 case 'extension':
01482 $this->xdebug('extension ' . $attrs['base']);
01483 if ($this->currentComplexType) {
01484 $ns = $this->getPrefix($attrs['base']);
01485 if ($ns == '') {
01486 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
01487 } elseif ($this->getNamespaceFromPrefix($ns)) {
01488 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
01489 }
01490 }
01491 break;
01492 case 'import':
01493 if (isset($attrs['schemaLocation'])) {
01494 $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
01495 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
01496 } else {
01497 $this->xdebug('import namespace ' . $attrs['namespace']);
01498 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
01499 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
01500 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
01501 }
01502 }
01503 break;
01504 case 'include':
01505 if (isset($attrs['schemaLocation'])) {
01506 $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
01507 $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
01508 } else {
01509 $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
01510 }
01511 break;
01512 case 'list':
01513 $this->xdebug("do nothing for element $name");
01514 break;
01515 case 'restriction':
01516 $this->xdebug('restriction ' . $attrs['base']);
01517 if($this->currentSimpleType){
01518 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
01519 } elseif($this->currentComplexType){
01520 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
01521 if(strstr($attrs['base'],':') == ':Array'){
01522 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01523 }
01524 }
01525 break;
01526 case 'schema':
01527 $this->schemaInfo = $attrs;
01528 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
01529 if (isset($attrs['targetNamespace'])) {
01530 $this->schemaTargetNamespace = $attrs['targetNamespace'];
01531 }
01532 if (!isset($attrs['elementFormDefault'])) {
01533 $this->schemaInfo['elementFormDefault'] = 'unqualified';
01534 }
01535 if (!isset($attrs['attributeFormDefault'])) {
01536 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
01537 }
01538 break;
01539 case 'simpleContent':
01540 $this->xdebug("do nothing for element $name");
01541 break;
01542 case 'simpleType':
01543 array_push($this->simpleTypeStack, $this->currentSimpleType);
01544 if(isset($attrs['name'])){
01545 $this->xdebug("processing simpleType for name " . $attrs['name']);
01546 $this->currentSimpleType = $attrs['name'];
01547 $this->simpleTypes[ $attrs['name'] ] = $attrs;
01548 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
01549 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
01550 } else {
01551 $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
01552 $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
01553 $this->currentSimpleType = $name;
01554
01555 $this->simpleTypes[$this->currentSimpleType] = $attrs;
01556 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
01557 }
01558 break;
01559 case 'union':
01560 $this->xdebug("do nothing for element $name");
01561 break;
01562 default:
01563 $this->xdebug("do not have any logic to process element $name");
01564 }
01565 }
01566
01574 function schemaEndElement($parser, $name) {
01575
01576 $this->depth--;
01577
01578 if(isset($this->depth_array[$this->depth])){
01579 $pos = $this->depth_array[$this->depth];
01580 }
01581
01582 if ($prefix = $this->getPrefix($name)){
01583
01584 $name = $this->getLocalPart($name);
01585 } else {
01586 $prefix = '';
01587 }
01588
01589 if($name == 'complexType'){
01590 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
01591 $this->currentComplexType = array_pop($this->complexTypeStack);
01592
01593 }
01594 if($name == 'element'){
01595 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
01596 $this->currentElement = array_pop($this->elementStack);
01597 }
01598 if($name == 'simpleType'){
01599 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
01600 $this->currentSimpleType = array_pop($this->simpleTypeStack);
01601 }
01602 }
01603
01611 function schemaCharacterData($parser, $data){
01612 $pos = $this->depth_array[$this->depth - 1];
01613 $this->message[$pos]['cdata'] .= $data;
01614 }
01615
01621 function serializeSchema(){
01622
01623 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
01624 $xml = '';
01625
01626 if (sizeof($this->imports) > 0) {
01627 foreach($this->imports as $ns => $list) {
01628 foreach ($list as $ii) {
01629 if ($ii['location'] != '') {
01630 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
01631 } else {
01632 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
01633 }
01634 }
01635 }
01636 }
01637
01638 foreach($this->complexTypes as $typeName => $attrs){
01639 $contentStr = '';
01640
01641 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
01642 foreach($attrs['elements'] as $element => $eParts){
01643 if(isset($eParts['ref'])){
01644 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
01645 } else {
01646 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
01647 foreach ($eParts as $aName => $aValue) {
01648
01649 if ($aName != 'name' && $aName != 'type') {
01650 $contentStr .= " $aName=\"$aValue\"";
01651 }
01652 }
01653 $contentStr .= "/>\n";
01654 }
01655 }
01656
01657 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
01658 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
01659 }
01660 }
01661
01662 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
01663 foreach($attrs['attrs'] as $attr => $aParts){
01664 $contentStr .= " <$schemaPrefix:attribute";
01665 foreach ($aParts as $a => $v) {
01666 if ($a == 'ref' || $a == 'type') {
01667 $contentStr .= " $a=\"".$this->contractQName($v).'"';
01668 } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
01669 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
01670 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
01671 } else {
01672 $contentStr .= " $a=\"$v\"";
01673 }
01674 }
01675 $contentStr .= "/>\n";
01676 }
01677 }
01678
01679 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
01680 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
01681
01682 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
01683 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
01684 }
01685 }
01686
01687 if($contentStr != ''){
01688 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
01689 } else {
01690 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
01691 }
01692 $xml .= $contentStr;
01693 }
01694
01695 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
01696 foreach($this->simpleTypes as $typeName => $eParts){
01697 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
01698 if (isset($eParts['enumeration'])) {
01699 foreach ($eParts['enumeration'] as $e) {
01700 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
01701 }
01702 }
01703 $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
01704 }
01705 }
01706
01707 if(isset($this->elements) && count($this->elements) > 0){
01708 foreach($this->elements as $element => $eParts){
01709 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
01710 }
01711 }
01712
01713 if(isset($this->attributes) && count($this->attributes) > 0){
01714 foreach($this->attributes as $attr => $aParts){
01715 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
01716 }
01717 }
01718
01719 $attr = '';
01720 foreach ($this->schemaInfo as $k => $v) {
01721 if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
01722 $attr .= " $k=\"$v\"";
01723 }
01724 }
01725 $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
01726 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
01727 $el .= " xmlns:$nsp=\"$ns\"";
01728 }
01729 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
01730 return $xml;
01731 }
01732
01739 function xdebug($string){
01740 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
01741 }
01742
01755 function getPHPType($type,$ns){
01756 if(isset($this->typemap[$ns][$type])){
01757
01758 return $this->typemap[$ns][$type];
01759 } elseif(isset($this->complexTypes[$type])){
01760
01761 return $this->complexTypes[$type]['phpType'];
01762 }
01763 return false;
01764 }
01765
01788 function getTypeDef($type){
01789
01790 if (substr($type, -1) == '^') {
01791 $is_element = 1;
01792 $type = substr($type, 0, -1);
01793 } else {
01794 $is_element = 0;
01795 }
01796
01797 if((! $is_element) && isset($this->complexTypes[$type])){
01798 $this->xdebug("in getTypeDef, found complexType $type");
01799 return $this->complexTypes[$type];
01800 } elseif((! $is_element) && isset($this->simpleTypes[$type])){
01801 $this->xdebug("in getTypeDef, found simpleType $type");
01802 if (!isset($this->simpleTypes[$type]['phpType'])) {
01803
01804
01805 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
01806 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
01807 $etype = $this->getTypeDef($uqType);
01808 if ($etype) {
01809 $this->xdebug("in getTypeDef, found type for simpleType $type:");
01810 $this->xdebug($this->varDump($etype));
01811 if (isset($etype['phpType'])) {
01812 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
01813 }
01814 if (isset($etype['elements'])) {
01815 $this->simpleTypes[$type]['elements'] = $etype['elements'];
01816 }
01817 }
01818 }
01819 return $this->simpleTypes[$type];
01820 } elseif(isset($this->elements[$type])){
01821 $this->xdebug("in getTypeDef, found element $type");
01822 if (!isset($this->elements[$type]['phpType'])) {
01823
01824 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
01825 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
01826 $etype = $this->getTypeDef($uqType);
01827 if ($etype) {
01828 $this->xdebug("in getTypeDef, found type for element $type:");
01829 $this->xdebug($this->varDump($etype));
01830 if (isset($etype['phpType'])) {
01831 $this->elements[$type]['phpType'] = $etype['phpType'];
01832 }
01833 if (isset($etype['elements'])) {
01834 $this->elements[$type]['elements'] = $etype['elements'];
01835 }
01836 if (isset($etype['extensionBase'])) {
01837 $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
01838 }
01839 } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
01840 $this->xdebug("in getTypeDef, element $type is an XSD type");
01841 $this->elements[$type]['phpType'] = 'scalar';
01842 }
01843 }
01844 return $this->elements[$type];
01845 } elseif(isset($this->attributes[$type])){
01846 $this->xdebug("in getTypeDef, found attribute $type");
01847 return $this->attributes[$type];
01848 } elseif (ereg('_ContainedType$', $type)) {
01849 $this->xdebug("in getTypeDef, have an untyped element $type");
01850 $typeDef['typeClass'] = 'simpleType';
01851 $typeDef['phpType'] = 'scalar';
01852 $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
01853 return $typeDef;
01854 }
01855 $this->xdebug("in getTypeDef, did not find $type");
01856 return false;
01857 }
01858
01867 function serializeTypeDef($type){
01868
01869 if($typeDef = $this->getTypeDef($type)){
01870 $str .= '<'.$type;
01871 if(is_array($typeDef['attrs'])){
01872 foreach($typeDef['attrs'] as $attName => $data){
01873 $str .= " $attName=\"{type = ".$data['type']."}\"";
01874 }
01875 }
01876 $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
01877 if(count($typeDef['elements']) > 0){
01878 $str .= ">";
01879 foreach($typeDef['elements'] as $element => $eData){
01880 $str .= $this->serializeTypeDef($element);
01881 }
01882 $str .= "</$type>";
01883 } elseif($typeDef['typeClass'] == 'element') {
01884 $str .= "></$type>";
01885 } else {
01886 $str .= "/>";
01887 }
01888 return $str;
01889 }
01890 return false;
01891 }
01892
01903 function typeToForm($name,$type){
01904
01905 if($typeDef = $this->getTypeDef($type)){
01906
01907 if($typeDef['phpType'] == 'struct'){
01908 $buffer .= '<table>';
01909 foreach($typeDef['elements'] as $child => $childDef){
01910 $buffer .= "
01911 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
01912 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
01913 }
01914 $buffer .= '</table>';
01915
01916 } elseif($typeDef['phpType'] == 'array'){
01917 $buffer .= '<table>';
01918 for($i=0;$i < 3; $i++){
01919 $buffer .= "
01920 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
01921 <td><input type='text' name='parameters[".$name."][]'></td></tr>";
01922 }
01923 $buffer .= '</table>';
01924
01925 } else {
01926 $buffer .= "<input type='text' name='parameters[$name]'>";
01927 }
01928 } else {
01929 $buffer .= "<input type='text' name='parameters[$name]'>";
01930 }
01931 return $buffer;
01932 }
01933
01975 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
01976 $this->complexTypes[$name] = array(
01977 'name' => $name,
01978 'typeClass' => $typeClass,
01979 'phpType' => $phpType,
01980 'compositor'=> $compositor,
01981 'restrictionBase' => $restrictionBase,
01982 'elements' => $elements,
01983 'attrs' => $attrs,
01984 'arrayType' => $arrayType
01985 );
01986
01987 $this->xdebug("addComplexType $name:");
01988 $this->appendDebug($this->varDump($this->complexTypes[$name]));
01989 }
01990
02003 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
02004 $this->simpleTypes[$name] = array(
02005 'name' => $name,
02006 'typeClass' => $typeClass,
02007 'phpType' => $phpType,
02008 'type' => $restrictionBase,
02009 'enumeration' => $enumeration
02010 );
02011
02012 $this->xdebug("addSimpleType $name:");
02013 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
02014 }
02015
02023 function addElement($attrs) {
02024 if (! $this->getPrefix($attrs['type'])) {
02025 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
02026 }
02027 $this->elements[ $attrs['name'] ] = $attrs;
02028 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
02029
02030 $this->xdebug("addElement " . $attrs['name']);
02031 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
02032 }
02033 }
02034
02038 class XMLSchema extends nusoap_xmlschema {
02039 }
02040
02041 ?><?php
02042
02043
02044
02056 class soapval extends nusoap_base {
02063 var $name;
02070 var $type;
02077 var $value;
02084 var $element_ns;
02091 var $type_ns;
02098 var $attributes;
02099
02111 function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
02112 parent::nusoap_base();
02113 $this->name = $name;
02114 $this->type = $type;
02115 $this->value = $value;
02116 $this->element_ns = $element_ns;
02117 $this->type_ns = $type_ns;
02118 $this->attributes = $attributes;
02119 }
02120
02128 function serialize($use='encoded') {
02129 return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
02130 }
02131
02138 function decode(){
02139 return $this->value;
02140 }
02141 }
02142
02143
02144
02145 ?><?php
02146
02147
02148
02158 class soap_transport_http extends nusoap_base {
02159
02160 var $url = '';
02161 var $uri = '';
02162 var $digest_uri = '';
02163 var $scheme = '';
02164 var $host = '';
02165 var $port = '';
02166 var $path = '';
02167 var $request_method = 'POST';
02168 var $protocol_version = '1.0';
02169 var $encoding = '';
02170 var $outgoing_headers = array();
02171 var $incoming_headers = array();
02172 var $incoming_cookies = array();
02173 var $outgoing_payload = '';
02174 var $incoming_payload = '';
02175 var $response_status_line;
02176 var $useSOAPAction = true;
02177 var $persistentConnection = false;
02178 var $ch = false;
02179 var $ch_options = array();
02180 var $use_curl = false;
02181 var $proxy = null;
02182 var $username = '';
02183 var $password = '';
02184 var $authtype = '';
02185 var $digestRequest = array();
02186 var $certRequest = array();
02187
02188
02189
02190
02191
02192
02193
02194
02203 function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
02204 parent::nusoap_base();
02205 $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
02206 $this->appendDebug($this->varDump($curl_options));
02207 $this->setURL($url);
02208 if (is_array($curl_options)) {
02209 $this->ch_options = $curl_options;
02210 }
02211 $this->use_curl = $use_curl;
02212 ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
02213 $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
02214 }
02215
02223 function setCurlOption($option, $value) {
02224 $this->debug("setCurlOption option=$option, value=");
02225 $this->appendDebug($this->varDump($value));
02226 curl_setopt($this->ch, $option, $value);
02227 }
02228
02236 function setHeader($name, $value) {
02237 $this->outgoing_headers[$name] = $value;
02238 $this->debug("set header $name: $value");
02239 }
02240
02247 function unsetHeader($name) {
02248 if (isset($this->outgoing_headers[$name])) {
02249 $this->debug("unset header $name");
02250 unset($this->outgoing_headers[$name]);
02251 }
02252 }
02253
02260 function setURL($url) {
02261 $this->url = $url;
02262
02263 $u = parse_url($url);
02264 foreach($u as $k => $v){
02265 $this->debug("parsed URL $k = $v");
02266 $this->$k = $v;
02267 }
02268
02269
02270 if(isset($u['query']) && $u['query'] != ''){
02271 $this->path .= '?' . $u['query'];
02272 }
02273
02274
02275 if(!isset($u['port'])){
02276 if($u['scheme'] == 'https'){
02277 $this->port = 443;
02278 } else {
02279 $this->port = 80;
02280 }
02281 }
02282
02283 $this->uri = $this->path;
02284 $this->digest_uri = $this->uri;
02285
02286
02287 if (!isset($u['port'])) {
02288 $this->setHeader('Host', $this->host);
02289 } else {
02290 $this->setHeader('Host', $this->host.':'.$this->port);
02291 }
02292
02293 if (isset($u['user']) && $u['user'] != '') {
02294 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
02295 }
02296 }
02297
02304 function io_method() {
02305 if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
02306 return 'curl';
02307 if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
02308 return 'socket';
02309 return 'unknown';
02310 }
02311
02320 function connect($connection_timeout=0,$response_timeout=30){
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
02334 if ($this->io_method() == 'socket') {
02335 if (!is_array($this->proxy)) {
02336 $host = $this->host;
02337 $port = $this->port;
02338 } else {
02339 $host = $this->proxy['host'];
02340 $port = $this->proxy['port'];
02341 }
02342
02343
02344 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
02345 if (!feof($this->fp)) {
02346 $this->debug('Re-use persistent connection');
02347 return true;
02348 }
02349 fclose($this->fp);
02350 $this->debug('Closed persistent connection at EOF');
02351 }
02352
02353
02354 if ($this->scheme == 'ssl') {
02355 $host = 'ssl://' . $host;
02356 }
02357 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
02358
02359
02360 if($connection_timeout > 0){
02361 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
02362 } else {
02363 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
02364 }
02365
02366
02367 if(!$this->fp) {
02368 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
02369 if ($this->errno) {
02370 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
02371 } else {
02372 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
02373 }
02374 $this->debug($msg);
02375 $this->setError($msg);
02376 return false;
02377 }
02378
02379
02380 $this->debug('set response timeout to ' . $response_timeout);
02381 socket_set_timeout( $this->fp, $response_timeout);
02382
02383 $this->debug('socket connected');
02384 return true;
02385 } else if ($this->io_method() == 'curl') {
02386 if (!extension_loaded('curl')) {
02387
02388 $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
02389 return false;
02390 }
02391
02392 if (defined('CURLOPT_CONNECTIONTIMEOUT'))
02393 $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
02394 else
02395 $CURLOPT_CONNECTIONTIMEOUT = 78;
02396 if (defined('CURLOPT_HTTPAUTH'))
02397 $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
02398 else
02399 $CURLOPT_HTTPAUTH = 107;
02400 if (defined('CURLOPT_PROXYAUTH'))
02401 $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
02402 else
02403 $CURLOPT_PROXYAUTH = 111;
02404 if (defined('CURLAUTH_BASIC'))
02405 $CURLAUTH_BASIC = CURLAUTH_BASIC;
02406 else
02407 $CURLAUTH_BASIC = 1;
02408 if (defined('CURLAUTH_DIGEST'))
02409 $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
02410 else
02411 $CURLAUTH_DIGEST = 2;
02412 if (defined('CURLAUTH_NTLM'))
02413 $CURLAUTH_NTLM = CURLAUTH_NTLM;
02414 else
02415 $CURLAUTH_NTLM = 8;
02416
02417 $this->debug('connect using cURL');
02418
02419 $this->ch = curl_init();
02420
02421 $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
02422
02423 $hostURL .= $this->path;
02424 $this->setCurlOption(CURLOPT_URL, $hostURL);
02425
02426 if (ini_get('safe_mode') || ini_get('open_basedir')) {
02427 $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
02428 $this->debug('safe_mode = ');
02429 $this->appendDebug($this->varDump(ini_get('safe_mode')));
02430 $this->debug('open_basedir = ');
02431 $this->appendDebug($this->varDump(ini_get('open_basedir')));
02432 } else {
02433 $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
02434 }
02435
02436 $this->setCurlOption(CURLOPT_HEADER, 1);
02437
02438 $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
02439
02440
02441
02442
02443
02444
02445 if ($this->persistentConnection) {
02446
02447
02448
02449
02450
02451 $this->persistentConnection = false;
02452 $this->setHeader('Connection', 'close');
02453 }
02454
02455 if ($connection_timeout != 0) {
02456 $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
02457 }
02458 if ($response_timeout != 0) {
02459 $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
02460 }
02461
02462 if ($this->scheme == 'https') {
02463 $this->debug('set cURL SSL verify options');
02464
02465
02466
02467
02468 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
02469 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
02470
02471
02472 if ($this->authtype == 'certificate') {
02473 $this->debug('set cURL certificate options');
02474 if (isset($this->certRequest['cainfofile'])) {
02475 $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
02476 }
02477 if (isset($this->certRequest['verifypeer'])) {
02478 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
02479 } else {
02480 $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
02481 }
02482 if (isset($this->certRequest['verifyhost'])) {
02483 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
02484 } else {
02485 $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
02486 }
02487 if (isset($this->certRequest['sslcertfile'])) {
02488 $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
02489 }
02490 if (isset($this->certRequest['sslkeyfile'])) {
02491 $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
02492 }
02493 if (isset($this->certRequest['passphrase'])) {
02494 $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
02495 }
02496 if (isset($this->certRequest['certpassword'])) {
02497 $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
02498 }
02499 }
02500 }
02501 if ($this->authtype && ($this->authtype != 'certificate')) {
02502 if ($this->username) {
02503 $this->debug('set cURL username/password');
02504 $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
02505 }
02506 if ($this->authtype == 'basic') {
02507 $this->debug('set cURL for Basic authentication');
02508 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
02509 }
02510 if ($this->authtype == 'digest') {
02511 $this->debug('set cURL for digest authentication');
02512 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
02513 }
02514 if ($this->authtype == 'ntlm') {
02515 $this->debug('set cURL for NTLM authentication');
02516 $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
02517 }
02518 }
02519 if (is_array($this->proxy)) {
02520 $this->debug('set cURL proxy options');
02521 if ($this->proxy['port'] != '') {
02522 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
02523 } else {
02524 $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
02525 }
02526 if ($this->proxy['username'] || $this->proxy['password']) {
02527 $this->debug('set cURL proxy authentication options');
02528 $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
02529 if ($this->proxy['authtype'] == 'basic') {
02530 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
02531 }
02532 if ($this->proxy['authtype'] == 'ntlm') {
02533 $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
02534 }
02535 }
02536 }
02537 $this->debug('cURL connection set up');
02538 return true;
02539 } else {
02540 $this->setError('Unknown scheme ' . $this->scheme);
02541 $this->debug('Unknown scheme ' . $this->scheme);
02542 return false;
02543 }
02544 }
02545
02556 function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
02557
02558 $this->debug('entered send() with data of length: '.strlen($data));
02559
02560 $this->tryagain = true;
02561 $tries = 0;
02562 while ($this->tryagain) {
02563 $this->tryagain = false;
02564 if ($tries++ < 2) {
02565
02566 if (!$this->connect($timeout, $response_timeout)){
02567 return false;
02568 }
02569
02570
02571 if (!$this->sendRequest($data, $cookies)){
02572 return false;
02573 }
02574
02575
02576 $respdata = $this->getResponse();
02577 } else {
02578 $this->setError("Too many tries to get an OK response ($this->response_status_line)");
02579 }
02580 }
02581 $this->debug('end of send()');
02582 return $respdata;
02583 }
02584
02585
02597 function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
02598 return $this->send($data, $timeout, $response_timeout, $cookies);
02599 }
02600
02611 function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
02612 $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
02613 $this->appendDebug($this->varDump($digestRequest));
02614 $this->debug("certRequest=");
02615 $this->appendDebug($this->varDump($certRequest));
02616
02617 if ($authtype == 'basic') {
02618 $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
02619 } elseif ($authtype == 'digest') {
02620 if (isset($digestRequest['nonce'])) {
02621 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
02622
02623
02624
02625
02626 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
02627
02628
02629 $HA1 = md5($A1);
02630
02631
02632 $A2 = $this->request_method . ':' . $this->digest_uri;
02633
02634
02635 $HA2 = md5($A2);
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648 $unhashedDigest = '';
02649 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
02650 $cnonce = $nonce;
02651 if ($digestRequest['qop'] != '') {
02652 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
02653 } else {
02654 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
02655 }
02656
02657 $hashedDigest = md5($unhashedDigest);
02658
02659 $opaque = '';
02660 if (isset($digestRequest['opaque'])) {
02661 $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
02662 }
02663
02664 $this->setHeader('Authorization', 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"');
02665 }
02666 } elseif ($authtype == 'certificate') {
02667 $this->certRequest = $certRequest;
02668 $this->debug('Authorization header not set for certificate');
02669 } elseif ($authtype == 'ntlm') {
02670
02671 $this->debug('Authorization header not set for ntlm');
02672 }
02673 $this->username = $username;
02674 $this->password = $password;
02675 $this->authtype = $authtype;
02676 $this->digestRequest = $digestRequest;
02677 }
02678
02685 function setSOAPAction($soapaction) {
02686 $this->setHeader('SOAPAction', '"' . $soapaction . '"');
02687 }
02688
02695 function setEncoding($enc='gzip, deflate') {
02696 if (function_exists('gzdeflate')) {
02697 $this->protocol_version = '1.1';
02698 $this->setHeader('Accept-Encoding', $enc);
02699 if (!isset($this->outgoing_headers['Connection'])) {
02700 $this->setHeader('Connection', 'close');
02701 $this->persistentConnection = false;
02702 }
02703 set_magic_quotes_runtime(0);
02704
02705 $this->encoding = $enc;
02706 }
02707 }
02708
02719 function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
02720 if ($proxyhost) {
02721 $this->proxy = array(
02722 'host' => $proxyhost,
02723 'port' => $proxyport,
02724 'username' => $proxyusername,
02725 'password' => $proxypassword,
02726 'authtype' => $proxyauthtype
02727 );
02728 if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
02729 $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
02730 }
02731 } else {
02732 $this->debug('remove proxy');
02733 $proxy = null;
02734 unsetHeader('Proxy-Authorization');
02735 }
02736 }
02737
02738
02747 function isSkippableCurlHeader(&$data) {
02748 $skipHeaders = array( 'HTTP/1.1 100',
02749 'HTTP/1.0 301',
02750 'HTTP/1.1 301',
02751 'HTTP/1.0 302',
02752 'HTTP/1.1 302',
02753 'HTTP/1.0 401',
02754 'HTTP/1.1 401',
02755 'HTTP/1.0 200 Connection established');
02756 foreach ($skipHeaders as $hd) {
02757 $prefix = substr($data, 0, strlen($hd));
02758 if ($prefix == $hd) return true;
02759 }
02760
02761 return false;
02762 }
02763
02774 function decodeChunked($buffer, $lb){
02775
02776 $length = 0;
02777 $new = '';
02778
02779
02780
02781 $chunkend = strpos($buffer, $lb);
02782 if ($chunkend == FALSE) {
02783 $this->debug('no linebreak found in decodeChunked');
02784 return $new;
02785 }
02786 $temp = substr($buffer,0,$chunkend);
02787 $chunk_size = hexdec( trim($temp) );
02788 $chunkstart = $chunkend + strlen($lb);
02789
02790 while ($chunk_size > 0) {
02791 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
02792 $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
02793
02794
02795 if ($chunkend == FALSE) {
02796 $chunk = substr($buffer,$chunkstart);
02797
02798 $new .= $chunk;
02799 $length += strlen($chunk);
02800 break;
02801 }
02802
02803
02804 $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
02805
02806 $new .= $chunk;
02807
02808 $length += strlen($chunk);
02809
02810 $chunkstart = $chunkend + strlen($lb);
02811
02812 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
02813 if ($chunkend == FALSE) {
02814 break;
02815 }
02816 $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
02817 $chunk_size = hexdec( trim($temp) );
02818 $chunkstart = $chunkend;
02819 }
02820 return $new;
02821 }
02822
02831 function buildPayload($data, $cookie_str = '') {
02832
02833
02834
02835
02836
02837 if ($this->request_method != 'GET') {
02838 $this->setHeader('Content-Length', strlen($data));
02839 }
02840
02841
02842 if ($this->proxy) {
02843 $uri = $this->url;
02844 } else {
02845 $uri = $this->uri;
02846 }
02847 $req = "$this->request_method $uri HTTP/$this->protocol_version";
02848 $this->debug("HTTP request: $req");
02849 $this->outgoing_payload = "$req\r\n";
02850
02851
02852 foreach($this->outgoing_headers as $k => $v){
02853 $hdr = $k.': '.$v;
02854 $this->debug("HTTP header: $hdr");
02855 $this->outgoing_payload .= "$hdr\r\n";
02856 }
02857
02858
02859 if ($cookie_str != '') {
02860 $hdr = 'Cookie: '.$cookie_str;
02861 $this->debug("HTTP header: $hdr");
02862 $this->outgoing_payload .= "$hdr\r\n";
02863 }
02864
02865
02866 $this->outgoing_payload .= "\r\n";
02867
02868
02869 $this->outgoing_payload .= $data;
02870 }
02871
02880 function sendRequest($data, $cookies = NULL) {
02881
02882 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
02883
02884
02885 $this->buildPayload($data, $cookie_str);
02886
02887 if ($this->io_method() == 'socket') {
02888
02889 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
02890 $this->setError('couldn\'t write message data to socket');
02891 $this->debug('couldn\'t write message data to socket');
02892 return false;
02893 }
02894 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
02895 return true;
02896 } else if ($this->io_method() == 'curl') {
02897
02898
02899
02900
02901
02902 $curl_headers = array();
02903 foreach($this->outgoing_headers as $k => $v){
02904 if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
02905 $this->debug("Skip cURL header $k: $v");
02906 } else {
02907 $curl_headers[] = "$k: $v";
02908 }
02909 }
02910 if ($cookie_str != '') {
02911 $curl_headers[] = 'Cookie: ' . $cookie_str;
02912 }
02913 $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
02914 $this->debug('set cURL HTTP headers');
02915 if ($this->request_method == "POST") {
02916 $this->setCurlOption(CURLOPT_POST, 1);
02917 $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
02918 $this->debug('set cURL POST data');
02919 } else {
02920 }
02921
02922 foreach ($this->ch_options as $key => $val) {
02923 $this->setCurlOption($key, $val);
02924 }
02925
02926 $this->debug('set cURL payload');
02927 return true;
02928 }
02929 }
02930
02937 function getResponse(){
02938 $this->incoming_payload = '';
02939
02940 if ($this->io_method() == 'socket') {
02941
02942 $data = '';
02943 while (!isset($lb)){
02944
02945
02946 if(feof($this->fp)) {
02947 $this->incoming_payload = $data;
02948 $this->debug('found no headers before EOF after length ' . strlen($data));
02949 $this->debug("received before EOF:\n" . $data);
02950 $this->setError('server failed to send headers');
02951 return false;
02952 }
02953
02954 $tmp = fgets($this->fp, 256);
02955 $tmplen = strlen($tmp);
02956 $this->debug("read line of $tmplen bytes: " . trim($tmp));
02957
02958 if ($tmplen == 0) {
02959 $this->incoming_payload = $data;
02960 $this->debug('socket read of headers timed out after length ' . strlen($data));
02961 $this->debug("read before timeout: " . $data);
02962 $this->setError('socket read of headers timed out');
02963 return false;
02964 }
02965
02966 $data .= $tmp;
02967 $pos = strpos($data,"\r\n\r\n");
02968 if($pos > 1){
02969 $lb = "\r\n";
02970 } else {
02971 $pos = strpos($data,"\n\n");
02972 if($pos > 1){
02973 $lb = "\n";
02974 }
02975 }
02976
02977 if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
02978 unset($lb);
02979 $data = '';
02980 }
02981 }
02982
02983 $this->incoming_payload .= $data;
02984 $this->debug('found end of headers after length ' . strlen($data));
02985
02986 $header_data = trim(substr($data,0,$pos));
02987 $header_array = explode($lb,$header_data);
02988 $this->incoming_headers = array();
02989 $this->incoming_cookies = array();
02990 foreach($header_array as $header_line){
02991 $arr = explode(':',$header_line, 2);
02992 if(count($arr) > 1){
02993 $header_name = strtolower(trim($arr[0]));
02994 $this->incoming_headers[$header_name] = trim($arr[1]);
02995 if ($header_name == 'set-cookie') {
02996
02997 $cookie = $this->parseCookie(trim($arr[1]));
02998 if ($cookie) {
02999 $this->incoming_cookies[] = $cookie;
03000 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
03001 } else {
03002 $this->debug('did not find cookie in ' . trim($arr[1]));
03003 }
03004 }
03005 } else if (isset($header_name)) {
03006
03007 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
03008 }
03009 }
03010
03011
03012 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
03013 $content_length = 2147483647;
03014 $chunked = true;
03015 $this->debug("want to read chunked content");
03016 } elseif (isset($this->incoming_headers['content-length'])) {
03017 $content_length = $this->incoming_headers['content-length'];
03018 $chunked = false;
03019 $this->debug("want to read content of length $content_length");
03020 } else {
03021 $content_length = 2147483647;
03022 $chunked = false;
03023 $this->debug("want to read content to EOF");
03024 }
03025 $data = '';
03026 do {
03027 if ($chunked) {
03028 $tmp = fgets($this->fp, 256);
03029 $tmplen = strlen($tmp);
03030 $this->debug("read chunk line of $tmplen bytes");
03031 if ($tmplen == 0) {
03032 $this->incoming_payload = $data;
03033 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
03034 $this->debug("read before timeout:\n" . $data);
03035 $this->setError('socket read of chunk length timed out');
03036 return false;
03037 }
03038 $content_length = hexdec(trim($tmp));
03039 $this->debug("chunk length $content_length");
03040 }
03041 $strlen = 0;
03042 while (($strlen < $content_length) && (!feof($this->fp))) {
03043 $readlen = min(8192, $content_length - $strlen);
03044 $tmp = fread($this->fp, $readlen);
03045 $tmplen = strlen($tmp);
03046 $this->debug("read buffer of $tmplen bytes");
03047 if (($tmplen == 0) && (!feof($this->fp))) {
03048 $this->incoming_payload = $data;
03049 $this->debug('socket read of body timed out after length ' . strlen($data));
03050 $this->debug("read before timeout:\n" . $data);
03051 $this->setError('socket read of body timed out');
03052 return false;
03053 }
03054 $strlen += $tmplen;
03055 $data .= $tmp;
03056 }
03057 if ($chunked && ($content_length > 0)) {
03058 $tmp = fgets($this->fp, 256);
03059 $tmplen = strlen($tmp);
03060 $this->debug("read chunk terminator of $tmplen bytes");
03061 if ($tmplen == 0) {
03062 $this->incoming_payload = $data;
03063 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
03064 $this->debug("read before timeout:\n" . $data);
03065 $this->setError('socket read of chunk terminator timed out');
03066 return false;
03067 }
03068 }
03069 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
03070 if (feof($this->fp)) {
03071 $this->debug('read to EOF');
03072 }
03073 $this->debug('read body of length ' . strlen($data));
03074 $this->incoming_payload .= $data;
03075 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
03076
03077
03078 if(
03079 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
03080 (! $this->persistentConnection) || feof($this->fp)){
03081 fclose($this->fp);
03082 $this->fp = false;
03083 $this->debug('closed socket');
03084 }
03085
03086
03087 if($this->incoming_payload == ''){
03088 $this->setError('no response from server');
03089 return false;
03090 }
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103 } else if ($this->io_method() == 'curl') {
03104
03105 $this->debug('send and receive with cURL');
03106 $this->incoming_payload = curl_exec($this->ch);
03107 $data = $this->incoming_payload;
03108
03109 $cErr = curl_error($this->ch);
03110 if ($cErr != '') {
03111 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
03112
03113 foreach(curl_getinfo($this->ch) as $k => $v){
03114 $err .= "$k: $v<br>";
03115 }
03116 $this->debug($err);
03117 $this->setError($err);
03118 curl_close($this->ch);
03119 return false;
03120 } else {
03121
03122
03123
03124 }
03125
03126 $this->debug('No cURL error, closing cURL');
03127 curl_close($this->ch);
03128
03129
03130 $savedata = $data;
03131 while ($this->isSkippableCurlHeader($data)) {
03132 $this->debug("Found HTTP header to skip");
03133 if ($pos = strpos($data,"\r\n\r\n")) {
03134 $data = ltrim(substr($data,$pos));
03135 } elseif($pos = strpos($data,"\n\n") ) {
03136 $data = ltrim(substr($data,$pos));
03137 }
03138 }
03139
03140 if ($data == '') {
03141
03142 $data = $savedata;
03143 while (ereg('^HTTP/1.1 100',$data)) {
03144 if ($pos = strpos($data,"\r\n\r\n")) {
03145 $data = ltrim(substr($data,$pos));
03146 } elseif($pos = strpos($data,"\n\n") ) {
03147 $data = ltrim(substr($data,$pos));
03148 }
03149 }
03150 }
03151
03152
03153 if ($pos = strpos($data,"\r\n\r\n")) {
03154 $lb = "\r\n";
03155 } elseif( $pos = strpos($data,"\n\n")) {
03156 $lb = "\n";
03157 } else {
03158 $this->debug('no proper separation of headers and document');
03159 $this->setError('no proper separation of headers and document');
03160 return false;
03161 }
03162 $header_data = trim(substr($data,0,$pos));
03163 $header_array = explode($lb,$header_data);
03164 $data = ltrim(substr($data,$pos));
03165 $this->debug('found proper separation of headers and document');
03166 $this->debug('cleaned data, stringlen: '.strlen($data));
03167
03168 foreach ($header_array as $header_line) {
03169 $arr = explode(':',$header_line,2);
03170 if(count($arr) > 1){
03171 $header_name = strtolower(trim($arr[0]));
03172 $this->incoming_headers[$header_name] = trim($arr[1]);
03173 if ($header_name == 'set-cookie') {
03174
03175 $cookie = $this->parseCookie(trim($arr[1]));
03176 if ($cookie) {
03177 $this->incoming_cookies[] = $cookie;
03178 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
03179 } else {
03180 $this->debug('did not find cookie in ' . trim($arr[1]));
03181 }
03182 }
03183 } else if (isset($header_name)) {
03184
03185 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
03186 }
03187 }
03188 }
03189
03190 $this->response_status_line = $header_array[0];
03191 $arr = explode(' ', $this->response_status_line, 3);
03192 $http_version = $arr[0];
03193 $http_status = intval($arr[1]);
03194 $http_reason = count($arr) > 2 ? $arr[2] : '';
03195
03196
03197 if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
03198 $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
03199 $this->setURL($this->incoming_headers['location']);
03200 $this->tryagain = true;
03201 return false;
03202 }
03203
03204
03205 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
03206 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
03207 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
03208 $this->debug('Server wants digest authentication');
03209
03210 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
03211
03212
03213 $digestElements = explode(',', $digestString);
03214 foreach ($digestElements as $val) {
03215 $tempElement = explode('=', trim($val), 2);
03216 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
03217 }
03218
03219
03220 if (isset($digestRequest['nonce'])) {
03221 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
03222 $this->tryagain = true;
03223 return false;
03224 }
03225 }
03226 $this->debug('HTTP authentication failed');
03227 $this->setError('HTTP authentication failed');
03228 return false;
03229 }
03230
03231 if (
03232 ($http_status >= 300 && $http_status <= 307) ||
03233 ($http_status >= 400 && $http_status <= 417) ||
03234 ($http_status >= 501 && $http_status <= 505)
03235 ) {
03236 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
03237 return false;
03238 }
03239
03240
03241 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
03242 if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
03243
03244 if(function_exists('gzinflate')){
03245
03246
03247
03248 $this->debug('The gzinflate function exists');
03249 $datalen = strlen($data);
03250 if ($this->incoming_headers['content-encoding'] == 'deflate') {
03251 if ($degzdata = @gzinflate($data)) {
03252 $data = $degzdata;
03253 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
03254 if (strlen($data) < $datalen) {
03255
03256 $this->debug('The inflated payload is smaller than the gzipped one; try again');
03257 if ($degzdata = @gzinflate($data)) {
03258 $data = $degzdata;
03259 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
03260 }
03261 }
03262 } else {
03263 $this->debug('Error using gzinflate to inflate the payload');
03264 $this->setError('Error using gzinflate to inflate the payload');
03265 }
03266 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
03267 if ($degzdata = @gzinflate(substr($data, 10))) {
03268 $data = $degzdata;
03269 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
03270 if (strlen($data) < $datalen) {
03271
03272 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
03273 if ($degzdata = @gzinflate(substr($data, 10))) {
03274 $data = $degzdata;
03275 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
03276 }
03277 }
03278 } else {
03279 $this->debug('Error using gzinflate to un-gzip the payload');
03280 $this->setError('Error using gzinflate to un-gzip the payload');
03281 }
03282 }
03283
03284
03285
03286 $this->incoming_payload = $header_data.$lb.$lb.$data;
03287 } else {
03288 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
03289 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
03290 }
03291 } else {
03292 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
03293 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
03294 }
03295 } else {
03296 $this->debug('No Content-Encoding header');
03297 }
03298
03299 if(strlen($data) == 0){
03300 $this->debug('no data after headers!');
03301 $this->setError('no data present after HTTP headers');
03302 return false;
03303 }
03304
03305 return $data;
03306 }
03307
03315 function setContentType($type, $charset = false) {
03316 $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
03317 }
03318
03325 function usePersistentConnection(){
03326 if (isset($this->outgoing_headers['Accept-Encoding'])) {
03327 return false;
03328 }
03329 $this->protocol_version = '1.1';
03330 $this->persistentConnection = true;
03331 $this->setHeader('Connection', 'Keep-Alive');
03332 return true;
03333 }
03334
03342
03343
03344
03345 function parseCookie($cookie_str) {
03346 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
03347 $data = split(';', $cookie_str);
03348 $value_str = $data[0];
03349
03350 $cookie_param = 'domain=';
03351 $start = strpos($cookie_str, $cookie_param);
03352 if ($start > 0) {
03353 $domain = substr($cookie_str, $start + strlen($cookie_param));
03354 $domain = substr($domain, 0, strpos($domain, ';'));
03355 } else {
03356 $domain = '';
03357 }
03358
03359 $cookie_param = 'expires=';
03360 $start = strpos($cookie_str, $cookie_param);
03361 if ($start > 0) {
03362 $expires = substr($cookie_str, $start + strlen($cookie_param));
03363 $expires = substr($expires, 0, strpos($expires, ';'));
03364 } else {
03365 $expires = '';
03366 }
03367
03368 $cookie_param = 'path=';
03369 $start = strpos($cookie_str, $cookie_param);
03370 if ( $start > 0 ) {
03371 $path = substr($cookie_str, $start + strlen($cookie_param));
03372 $path = substr($path, 0, strpos($path, ';'));
03373 } else {
03374 $path = '/';
03375 }
03376
03377 $cookie_param = ';secure;';
03378 if (strpos($cookie_str, $cookie_param) !== FALSE) {
03379 $secure = true;
03380 } else {
03381 $secure = false;
03382 }
03383
03384 $sep_pos = strpos($value_str, '=');
03385
03386 if ($sep_pos) {
03387 $name = substr($value_str, 0, $sep_pos);
03388 $value = substr($value_str, $sep_pos + 1);
03389 $cookie= array( 'name' => $name,
03390 'value' => $value,
03391 'domain' => $domain,
03392 'path' => $path,
03393 'expires' => $expires,
03394 'secure' => $secure
03395 );
03396 return $cookie;
03397 }
03398 return false;
03399 }
03400
03409 function getCookiesForRequest($cookies, $secure=false) {
03410 $cookie_str = '';
03411 if ((! is_null($cookies)) && (is_array($cookies))) {
03412 foreach ($cookies as $cookie) {
03413 if (! is_array($cookie)) {
03414 continue;
03415 }
03416 $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
03417 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
03418 if (strtotime($cookie['expires']) <= time()) {
03419 $this->debug('cookie has expired');
03420 continue;
03421 }
03422 }
03423 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
03424 $domain = preg_quote($cookie['domain']);
03425 if (! preg_match("'.*$domain$'i", $this->host)) {
03426 $this->debug('cookie has different domain');
03427 continue;
03428 }
03429 }
03430 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
03431 $path = preg_quote($cookie['path']);
03432 if (! preg_match("'^$path.*'i", $this->path)) {
03433 $this->debug('cookie is for a different path');
03434 continue;
03435 }
03436 }
03437 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
03438 $this->debug('cookie is secure, transport is not');
03439 continue;
03440 }
03441 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
03442 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
03443 }
03444 }
03445 return $cookie_str;
03446 }
03447 }
03448
03449 ?><?php
03450
03451
03452
03463 class nusoap_server extends nusoap_base {
03469 var $headers = array();
03475 var $request = '';
03481 var $requestHeaders = '';
03487 var $requestHeader = NULL;
03493 var $document = '';
03499 var $requestSOAP = '';
03505 var $methodURI = '';
03511 var $methodname = '';
03517 var $methodparams = array();
03523 var $SOAPAction = '';
03529 var $xml_encoding = '';
03535 var $decode_utf8 = true;
03536
03542 var $outgoing_headers = array();
03548 var $response = '';
03554 var $responseHeaders = '';
03560 var $responseSOAP = '';
03566 var $methodreturn = false;
03572 var $methodreturnisliteralxml = false;
03578 var $fault = false;
03584 var $result = 'successful';
03585
03592 var $operations = array();
03598 var $wsdl = false;
03604 var $externalWSDLURL = false;
03610 var $debug_flag = false;
03611
03612
03620 function nusoap_server($wsdl=false){
03621 parent::nusoap_base();
03622
03623 global $debug;
03624 global $HTTP_SERVER_VARS;
03625
03626 if (isset($_SERVER)) {
03627 $this->debug("_SERVER is defined:");
03628 $this->appendDebug($this->varDump($_SERVER));
03629 } elseif (isset($HTTP_SERVER_VARS)) {
03630 $this->debug("HTTP_SERVER_VARS is defined:");
03631 $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
03632 } else {
03633 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
03634 }
03635
03636 if (isset($debug)) {
03637 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
03638 $this->debug_flag = $debug;
03639 } elseif (isset($_SERVER['QUERY_STRING'])) {
03640 $qs = explode('&', $_SERVER['QUERY_STRING']);
03641 foreach ($qs as $v) {
03642 if (substr($v, 0, 6) == 'debug=') {
03643 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
03644 $this->debug_flag = substr($v, 6);
03645 }
03646 }
03647 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
03648 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
03649 foreach ($qs as $v) {
03650 if (substr($v, 0, 6) == 'debug=') {
03651 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
03652 $this->debug_flag = substr($v, 6);
03653 }
03654 }
03655 }
03656
03657
03658 if($wsdl){
03659 $this->debug("In nusoap_server, WSDL is specified");
03660 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
03661 $this->wsdl = $wsdl;
03662 $this->externalWSDLURL = $this->wsdl->wsdl;
03663 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
03664 } else {
03665 $this->debug('Create wsdl from ' . $wsdl);
03666 $this->wsdl = new wsdl($wsdl);
03667 $this->externalWSDLURL = $wsdl;
03668 }
03669 $this->appendDebug($this->wsdl->getDebug());
03670 $this->wsdl->clearDebug();
03671 if($err = $this->wsdl->getError()){
03672 die('WSDL ERROR: '.$err);
03673 }
03674 }
03675 }
03676
03683 function service($data){
03684 global $HTTP_SERVER_VARS;
03685
03686 if (isset($_SERVER['REQUEST_METHOD'])) {
03687 $rm = $_SERVER['REQUEST_METHOD'];
03688 } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
03689 $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
03690 } else {
03691 $rm = '';
03692 }
03693
03694 if (isset($_SERVER['QUERY_STRING'])) {
03695 $qs = $_SERVER['QUERY_STRING'];
03696 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
03697 $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
03698 } else {
03699 $qs = '';
03700 }
03701 $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
03702
03703 if ($rm == 'POST') {
03704 $this->debug("In service, invoke the request");
03705 $this->parse_request($data);
03706 if (! $this->fault) {
03707 $this->invoke_method();
03708 }
03709 if (! $this->fault) {
03710 $this->serialize_return();
03711 }
03712 $this->send_response();
03713 } elseif (ereg('wsdl', $qs) ){
03714 $this->debug("In service, this is a request for WSDL");
03715 if ($this->externalWSDLURL){
03716 if (strpos($this->externalWSDLURL, "http://") !== false) {
03717 $this->debug("In service, re-direct for WSDL");
03718 header('Location: '.$this->externalWSDLURL);
03719 } else {
03720 $this->debug("In service, use file passthru for WSDL");
03721 header("Content-Type: text/xml\r\n");
03722 $pos = strpos($this->externalWSDLURL, "file://");
03723 if ($pos === false) {
03724 $filename = $this->externalWSDLURL;
03725 } else {
03726 $filename = substr($this->externalWSDLURL, $pos + 7);
03727 }
03728 $fp = fopen($this->externalWSDLURL, 'r');
03729 fpassthru($fp);
03730 }
03731 } elseif ($this->wsdl) {
03732 $this->debug("In service, serialize WSDL");
03733 header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
03734 print $this->wsdl->serialize($this->debug_flag);
03735 if ($this->debug_flag) {
03736 $this->debug('wsdl:');
03737 $this->appendDebug($this->varDump($this->wsdl));
03738 print $this->getDebugAsXMLComment();
03739 }
03740 } else {
03741 $this->debug("In service, there is no WSDL");
03742 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
03743 print "This service does not provide WSDL";
03744 }
03745 } elseif ($this->wsdl) {
03746 $this->debug("In service, return Web description");
03747 print $this->wsdl->webDescription();
03748 } else {
03749 $this->debug("In service, no Web description");
03750 header("Content-Type: text/html; charset=ISO-8859-1\r\n");
03751 print "This service does not provide a Web description";
03752 }
03753 }
03754
03767 function parse_http_headers() {
03768 global $HTTP_SERVER_VARS;
03769
03770 $this->request = '';
03771 $this->SOAPAction = '';
03772 if(function_exists('getallheaders')){
03773 $this->debug("In parse_http_headers, use getallheaders");
03774 $headers = getallheaders();
03775 foreach($headers as $k=>$v){
03776 $k = strtolower($k);
03777 $this->headers[$k] = $v;
03778 $this->request .= "$k: $v\r\n";
03779 $this->debug("$k: $v");
03780 }
03781
03782 if(isset($this->headers['soapaction'])){
03783 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
03784 }
03785
03786 if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
03787 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
03788 if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
03789 $this->xml_encoding = strtoupper($enc);
03790 } else {
03791 $this->xml_encoding = 'US-ASCII';
03792 }
03793 } else {
03794
03795 $this->xml_encoding = 'ISO-8859-1';
03796 }
03797 } elseif(isset($_SERVER) && is_array($_SERVER)){
03798 $this->debug("In parse_http_headers, use _SERVER");
03799 foreach ($_SERVER as $k => $v) {
03800 if (substr($k, 0, 5) == 'HTTP_') {
03801 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
03802 } else {
03803 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
03804 }
03805 if ($k == 'soapaction') {
03806
03807 $k = 'SOAPAction';
03808 $v = str_replace('"', '', $v);
03809 $v = str_replace('\\', '', $v);
03810 $this->SOAPAction = $v;
03811 } else if ($k == 'content-type') {
03812
03813 if (strpos($v, '=')) {
03814 $enc = substr(strstr($v, '='), 1);
03815 $enc = str_replace('"', '', $enc);
03816 $enc = str_replace('\\', '', $enc);
03817 if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
03818 $this->xml_encoding = strtoupper($enc);
03819 } else {
03820 $this->xml_encoding = 'US-ASCII';
03821 }
03822 } else {
03823
03824 $this->xml_encoding = 'ISO-8859-1';
03825 }
03826 }
03827 $this->headers[$k] = $v;
03828 $this->request .= "$k: $v\r\n";
03829 $this->debug("$k: $v");
03830 }
03831 } elseif (is_array($HTTP_SERVER_VARS)) {
03832 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
03833 foreach ($HTTP_SERVER_VARS as $k => $v) {
03834 if (substr($k, 0, 5) == 'HTTP_') {
03835 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
03836 } else {
03837 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
03838 }
03839 if ($k == 'soapaction') {
03840
03841 $k = 'SOAPAction';
03842 $v = str_replace('"', '', $v);
03843 $v = str_replace('\\', '', $v);
03844 $this->SOAPAction = $v;
03845 } else if ($k == 'content-type') {
03846
03847 if (strpos($v, '=')) {
03848 $enc = substr(strstr($v, '='), 1);
03849 $enc = str_replace('"', '', $enc);
03850 $enc = str_replace('\\', '', $enc);
03851 if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
03852 $this->xml_encoding = strtoupper($enc);
03853 } else {
03854 $this->xml_encoding = 'US-ASCII';
03855 }
03856 } else {
03857
03858 $this->xml_encoding = 'ISO-8859-1';
03859 }
03860 }
03861 $this->headers[$k] = $v;
03862 $this->request .= "$k: $v\r\n";
03863 $this->debug("$k: $v");
03864 }
03865 } else {
03866 $this->debug("In parse_http_headers, HTTP headers not accessible");
03867 $this->setError("HTTP headers not accessible");
03868 }
03869 }
03870
03893 function parse_request($data='') {
03894 $this->debug('entering parse_request()');
03895 $this->parse_http_headers();
03896 $this->debug('got character encoding: '.$this->xml_encoding);
03897
03898 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
03899 $this->debug('got content encoding: ' . $this->headers['content-encoding']);
03900 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
03901
03902 if (function_exists('gzuncompress')) {
03903 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
03904 $data = $degzdata;
03905 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
03906 $data = $degzdata;
03907 } else {
03908 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
03909 return;
03910 }
03911 } else {
03912 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
03913 return;
03914 }
03915 }
03916 }
03917 $this->request .= "\r\n".$data;
03918 $data = $this->parseRequest($this->headers, $data);
03919 $this->requestSOAP = $data;
03920 $this->debug('leaving parse_request');
03921 }
03922
03940 function invoke_method() {
03941 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
03942
03943 if ($this->wsdl) {
03944 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
03945 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
03946 $this->appendDebug('opData=' . $this->varDump($this->opData));
03947 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
03948
03949 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
03950 $this->appendDebug('opData=' . $this->varDump($this->opData));
03951 $this->methodname = $this->opData['name'];
03952 } else {
03953 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
03954 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
03955 return;
03956 }
03957 } else {
03958 $this->debug('in invoke_method, no WSDL to validate method');
03959 }
03960
03961
03962
03963
03964 $class = '';
03965 $method = '';
03966 if (strpos($this->methodname, '..') > 0) {
03967 $delim = '..';
03968 } else if (strpos($this->methodname, '.') > 0) {
03969 $delim = '.';
03970 } else {
03971 $delim = '';
03972 }
03973
03974 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
03975 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
03976
03977 $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
03978 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
03979 $this->debug("in invoke_method, class=$class method=$method delim=$delim");
03980 }
03981
03982
03983 if ($class == '') {
03984 if (!function_exists($this->methodname)) {
03985 $this->debug("in invoke_method, function '$this->methodname' not found!");
03986 $this->result = 'fault: method not found';
03987 $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
03988 return;
03989 }
03990 } else {
03991 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
03992 if (!in_array($method_to_compare, get_class_methods($class))) {
03993 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
03994 $this->result = 'fault: method not found';
03995 $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
03996 return;
03997 }
03998 }
03999
04000
04001
04002 if(! $this->verify_method($this->methodname,$this->methodparams)){
04003
04004 $this->debug('ERROR: request not verified against method signature');
04005 $this->result = 'fault: request failed validation against method signature';
04006
04007 $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
04008 return;
04009 }
04010
04011
04012 $this->debug('in invoke_method, params:');
04013 $this->appendDebug($this->varDump($this->methodparams));
04014 $this->debug("in invoke_method, calling '$this->methodname'");
04015 if (!function_exists('call_user_func_array')) {
04016 if ($class == '') {
04017 $this->debug('in invoke_method, calling function using eval()');
04018 $funcCall = "\$this->methodreturn = $this->methodname(";
04019 } else {
04020 if ($delim == '..') {
04021 $this->debug('in invoke_method, calling class method using eval()');
04022 $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
04023 } else {
04024 $this->debug('in invoke_method, calling instance method using eval()');
04025
04026 $instname = "\$inst_".time();
04027 $funcCall = $instname." = new ".$class."(); ";
04028 $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
04029 }
04030 }
04031 if ($this->methodparams) {
04032 foreach ($this->methodparams as $param) {
04033 if (is_array($param) || is_object($param)) {
04034 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
04035 return;
04036 }
04037 $funcCall .= "\"$param\",";
04038 }
04039 $funcCall = substr($funcCall, 0, -1);
04040 }
04041 $funcCall .= ');';
04042 $this->debug('in invoke_method, function call: '.$funcCall);
04043 @eval($funcCall);
04044 } else {
04045 if ($class == '') {
04046 $this->debug('in invoke_method, calling function using call_user_func_array()');
04047 $call_arg = "$this->methodname";
04048 } elseif ($delim == '..') {
04049 $this->debug('in invoke_method, calling class method using call_user_func_array()');
04050 $call_arg = array ($class, $method);
04051 } else {
04052 $this->debug('in invoke_method, calling instance method using call_user_func_array()');
04053 $instance = new $class ();
04054 $call_arg = array(&$instance, $method);
04055 }
04056 if (is_array($this->methodparams)) {
04057 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
04058 } else {
04059 $this->methodreturn = call_user_func_array($call_arg, array());
04060 }
04061 }
04062 $this->debug('in invoke_method, methodreturn:');
04063 $this->appendDebug($this->varDump($this->methodreturn));
04064 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
04065 }
04066
04078 function serialize_return() {
04079 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
04080
04081 if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
04082 $this->debug('got a fault object from method');
04083 $this->fault = $this->methodreturn;
04084 return;
04085 } elseif ($this->methodreturnisliteralxml) {
04086 $return_val = $this->methodreturn;
04087
04088 } else {
04089 $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
04090 $this->debug('serializing return value');
04091 if($this->wsdl){
04092 if (sizeof($this->opData['output']['parts']) > 1) {
04093 $this->debug('more than one output part, so use the method return unchanged');
04094 $opParams = $this->methodreturn;
04095 } elseif (sizeof($this->opData['output']['parts']) == 1) {
04096 $this->debug('exactly one output part, so wrap the method return in a simple array');
04097
04098
04099
04100
04101 $opParams = array($this->methodreturn);
04102 }
04103 $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
04104 $this->appendDebug($this->wsdl->getDebug());
04105 $this->wsdl->clearDebug();
04106 if($errstr = $this->wsdl->getError()){
04107 $this->debug('got wsdl error: '.$errstr);
04108 $this->fault('SOAP-ENV:Server', 'unable to serialize result');
04109 return;
04110 }
04111 } else {
04112 if (isset($this->methodreturn)) {
04113 $return_val = $this->serialize_val($this->methodreturn, 'return');
04114 } else {
04115 $return_val = '';
04116 $this->debug('in absence of WSDL, assume void return for backward compatibility');
04117 }
04118 }
04119 }
04120 $this->debug('return value:');
04121 $this->appendDebug($this->varDump($return_val));
04122
04123 $this->debug('serializing response');
04124 if ($this->wsdl) {
04125 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
04126 if ($this->opData['style'] == 'rpc') {
04127 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
04128 if ($this->opData['output']['use'] == 'literal') {
04129
04130 if ($this->methodURI) {
04131 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
04132 } else {
04133 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
04134 }
04135 } else {
04136 if ($this->methodURI) {
04137 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
04138 } else {
04139 $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
04140 }
04141 }
04142 } else {
04143 $this->debug('style is not rpc for serialization: assume document');
04144 $payload = $return_val;
04145 }
04146 } else {
04147 $this->debug('do not have WSDL for serialization: assume rpc/encoded');
04148 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
04149 }
04150 $this->result = 'successful';
04151 if($this->wsdl){
04152
04153 $this->appendDebug($this->wsdl->getDebug());
04154
04155 if (isset($opData['output']['encodingStyle'])) {
04156 $encodingStyle = $opData['output']['encodingStyle'];
04157 } else {
04158 $encodingStyle = '';
04159 }
04160
04161 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
04162 } else {
04163 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
04164 }
04165 $this->debug("Leaving serialize_return");
04166 }
04167
04178 function send_response() {
04179 $this->debug('Enter send_response');
04180 if ($this->fault) {
04181 $payload = $this->fault->serialize();
04182 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
04183 $this->outgoing_headers[] = "Status: 500 Internal Server Error";
04184 } else {
04185 $payload = $this->responseSOAP;
04186
04187
04188
04189
04190
04191 }
04192
04193 if(isset($this->debug_flag) && $this->debug_flag){
04194 $payload .= $this->getDebugAsXMLComment();
04195 }
04196 $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
04197 ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
04198 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
04199
04200
04201 $payload = $this->getHTTPBody($payload);
04202 $type = $this->getHTTPContentType();
04203 $charset = $this->getHTTPContentTypeCharset();
04204 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
04205
04206
04207
04208 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
04209 if (strstr($this->headers['accept-encoding'], 'gzip')) {
04210 if (function_exists('gzencode')) {
04211 if (isset($this->debug_flag) && $this->debug_flag) {
04212 $payload .= "<!-- Content being gzipped -->";
04213 }
04214 $this->outgoing_headers[] = "Content-Encoding: gzip";
04215 $payload = gzencode($payload);
04216 } else {
04217 if (isset($this->debug_flag) && $this->debug_flag) {
04218 $payload .= "<!-- Content will not be gzipped: no gzencode -->";
04219 }
04220 }
04221 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
04222
04223
04224
04225 if (function_exists('gzdeflate')) {
04226 if (isset($this->debug_flag) && $this->debug_flag) {
04227 $payload .= "<!-- Content being deflated -->";
04228 }
04229 $this->outgoing_headers[] = "Content-Encoding: deflate";
04230 $payload = gzdeflate($payload);
04231 } else {
04232 if (isset($this->debug_flag) && $this->debug_flag) {
04233 $payload .= "<!-- Content will not be deflated: no gzcompress -->";
04234 }
04235 }
04236 }
04237 }
04238
04239 $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
04240 reset($this->outgoing_headers);
04241 foreach($this->outgoing_headers as $hdr){
04242 header($hdr, false);
04243 }
04244 print $payload;
04245 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
04246 }
04247
04257 function verify_method($operation,$request){
04258 if(isset($this->wsdl) && is_object($this->wsdl)){
04259 if($this->wsdl->getOperationData($operation)){
04260 return true;
04261 }
04262 } elseif(isset($this->operations[$operation])){
04263 return true;
04264 }
04265 return false;
04266 }
04267
04276 function parseRequest($headers, $data) {
04277 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
04278 $this->appendDebug($this->varDump($headers));
04279 if (!isset($headers['content-type'])) {
04280 $this->setError('Request not of type text/xml (no content-type header)');
04281 return false;
04282 }
04283 if (!strstr($headers['content-type'], 'text/xml')) {
04284 $this->setError('Request not of type text/xml');
04285 return false;
04286 }
04287 if (strpos($headers['content-type'], '=')) {
04288 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
04289 $this->debug('Got response encoding: ' . $enc);
04290 if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
04291 $this->xml_encoding = strtoupper($enc);
04292 } else {
04293 $this->xml_encoding = 'US-ASCII';
04294 }
04295 } else {
04296
04297 $this->xml_encoding = 'ISO-8859-1';
04298 }
04299 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
04300
04301 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
04302
04303 $this->debug("parser debug: \n".$parser->getDebug());
04304
04305 if($err = $parser->getError()){
04306 $this->result = 'fault: error in msg parsing: '.$err;
04307 $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
04308
04309 } else {
04310
04311 $this->methodURI = $parser->root_struct_namespace;
04312 $this->methodname = $parser->root_struct_name;
04313 $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
04314 $this->debug('calling parser->get_soapbody()');
04315 $this->methodparams = $parser->get_soapbody();
04316
04317 $this->requestHeaders = $parser->getHeaders();
04318
04319 $this->requestHeader = $parser->get_soapheader();
04320
04321 $this->document = $parser->document;
04322 }
04323 }
04324
04332 function getHTTPBody($soapmsg) {
04333 return $soapmsg;
04334 }
04335
04344 function getHTTPContentType() {
04345 return 'text/xml';
04346 }
04347
04357 function getHTTPContentTypeCharset() {
04358 return $this->soap_defencoding;
04359 }
04360
04370 function add_to_map($methodname,$in,$out){
04371 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
04372 }
04373
04388 function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
04389 global $HTTP_SERVER_VARS;
04390
04391 if($this->externalWSDLURL){
04392 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
04393 }
04394 if (! $name) {
04395 die('You must specify a name when you register an operation');
04396 }
04397 if (!is_array($in)) {
04398 die('You must provide an array for operation inputs');
04399 }
04400 if (!is_array($out)) {
04401 die('You must provide an array for operation outputs');
04402 }
04403 if(false == $namespace) {
04404 }
04405 if(false == $soapaction) {
04406 if (isset($_SERVER)) {
04407 $SERVER_NAME = $_SERVER['SERVER_NAME'];
04408 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
04409 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
04410 } elseif (isset($HTTP_SERVER_VARS)) {
04411 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
04412 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
04413 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
04414 } else {
04415 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
04416 }
04417 if ($HTTPS == '1' || $HTTPS == 'on') {
04418 $SCHEME = 'https';
04419 } else {
04420 $SCHEME = 'http';
04421 }
04422 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
04423 }
04424 if(false == $style) {
04425 $style = "rpc";
04426 }
04427 if(false == $use) {
04428 $use = "encoded";
04429 }
04430 if ($use == 'encoded' && $encodingStyle == '') {
04431 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
04432 }
04433
04434 $this->operations[$name] = array(
04435 'name' => $name,
04436 'in' => $in,
04437 'out' => $out,
04438 'namespace' => $namespace,
04439 'soapaction' => $soapaction,
04440 'style' => $style);
04441 if($this->wsdl){
04442 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
04443 }
04444 return true;
04445 }
04446
04457 function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
04458 if ($faultdetail == '' && $this->debug_flag) {
04459 $faultdetail = $this->getDebug();
04460 }
04461 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
04462 $this->fault->soap_defencoding = $this->soap_defencoding;
04463 }
04464
04476 function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
04477 {
04478 global $HTTP_SERVER_VARS;
04479
04480 if (isset($_SERVER)) {
04481 $SERVER_NAME = $_SERVER['SERVER_NAME'];
04482 $SERVER_PORT = $_SERVER['SERVER_PORT'];
04483 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
04484 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
04485 } elseif (isset($HTTP_SERVER_VARS)) {
04486 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
04487 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
04488 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
04489 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
04490 } else {
04491 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
04492 }
04493
04494 $colon = strpos($SERVER_NAME,":");
04495 if ($colon) {
04496 $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
04497 }
04498 if ($SERVER_PORT == 80) {
04499 $SERVER_PORT = '';
04500 } else {
04501 $SERVER_PORT = ':' . $SERVER_PORT;
04502 }
04503 if(false == $namespace) {
04504 $namespace = "http://$SERVER_NAME/soap/$serviceName";
04505 }
04506
04507 if(false == $endpoint) {
04508 if ($HTTPS == '1' || $HTTPS == 'on') {
04509 $SCHEME = 'https';
04510 } else {
04511 $SCHEME = 'http';
04512 }
04513 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
04514 }
04515
04516 if(false == $schemaTargetNamespace) {
04517 $schemaTargetNamespace = $namespace;
04518 }
04519
04520 $this->wsdl = new wsdl;
04521 $this->wsdl->serviceName = $serviceName;
04522 $this->wsdl->endpoint = $endpoint;
04523 $this->wsdl->namespaces['tns'] = $namespace;
04524 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
04525 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
04526 if ($schemaTargetNamespace != $namespace) {
04527 $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
04528 }
04529 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
04530 if ($style == 'document') {
04531 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
04532 }
04533 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
04534 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
04535 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
04536 $this->wsdl->bindings[$serviceName.'Binding'] = array(
04537 'name'=>$serviceName.'Binding',
04538 'style'=>$style,
04539 'transport'=>$transport,
04540 'portType'=>$serviceName.'PortType');
04541 $this->wsdl->ports[$serviceName.'Port'] = array(
04542 'binding'=>$serviceName.'Binding',
04543 'location'=>$endpoint,
04544 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
04545 }
04546 }
04547
04551 class soap_server extends nusoap_server {
04552 }
04553
04554 ?><?php
04555
04556
04557
04567 class wsdl extends nusoap_base {
04568
04569 var $wsdl;
04570
04571 var $schemas = array();
04572 var $currentSchema;
04573 var $message = array();
04574 var $complexTypes = array();
04575 var $messages = array();
04576 var $currentMessage;
04577 var $currentOperation;
04578 var $portTypes = array();
04579 var $currentPortType;
04580 var $bindings = array();
04581 var $currentBinding;
04582 var $ports = array();
04583 var $currentPort;
04584 var $opData = array();
04585 var $status = '';
04586 var $documentation = false;
04587 var $endpoint = '';
04588
04589 var $import = array();
04590
04591 var $parser;
04592 var $position = 0;
04593 var $depth = 0;
04594 var $depth_array = array();
04595
04596 var $proxyhost = '';
04597 var $proxyport = '';
04598 var $proxyusername = '';
04599 var $proxypassword = '';
04600 var $timeout = 0;
04601 var $response_timeout = 30;
04602 var $curl_options = array();
04603 var $use_curl = false;
04604
04605 var $username = '';
04606 var $password = '';
04607 var $authtype = '';
04608 var $certRequest = array();
04609
04624 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
04625 parent::nusoap_base();
04626 $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
04627 $this->proxyhost = $proxyhost;
04628 $this->proxyport = $proxyport;
04629 $this->proxyusername = $proxyusername;
04630 $this->proxypassword = $proxypassword;
04631 $this->timeout = $timeout;
04632 $this->response_timeout = $response_timeout;
04633 if (is_array($curl_options))
04634 $this->curl_options = $curl_options;
04635 $this->use_curl = $use_curl;
04636 $this->fetchWSDL($wsdl);
04637 }
04638
04644 function fetchWSDL($wsdl) {
04645 $this->debug("parse and process WSDL path=$wsdl");
04646 $this->wsdl = $wsdl;
04647
04648 if ($this->wsdl != "") {
04649 $this->parseWSDL($this->wsdl);
04650 }
04651
04652
04653 $imported_urls = array();
04654 $imported = 1;
04655 while ($imported > 0) {
04656 $imported = 0;
04657
04658 foreach ($this->schemas as $ns => $list) {
04659 foreach ($list as $xs) {
04660 $wsdlparts = parse_url($this->wsdl);
04661 foreach ($xs->imports as $ns2 => $list2) {
04662 for ($ii = 0; $ii < count($list2); $ii++) {
04663 if (! $list2[$ii]['loaded']) {
04664 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
04665 $url = $list2[$ii]['location'];
04666 if ($url != '') {
04667 $urlparts = parse_url($url);
04668 if (!isset($urlparts['host'])) {
04669 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
04670 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
04671 }
04672 if (! in_array($url, $imported_urls)) {
04673 $this->parseWSDL($url);
04674 $imported++;
04675 $imported_urls[] = $url;
04676 }
04677 } else {
04678 $this->debug("Unexpected scenario: empty URL for unloaded import");
04679 }
04680 }
04681 }
04682 }
04683 }
04684 }
04685
04686 $wsdlparts = parse_url($this->wsdl);
04687 foreach ($this->import as $ns => $list) {
04688 for ($ii = 0; $ii < count($list); $ii++) {
04689 if (! $list[$ii]['loaded']) {
04690 $this->import[$ns][$ii]['loaded'] = true;
04691 $url = $list[$ii]['location'];
04692 if ($url != '') {
04693 $urlparts = parse_url($url);
04694 if (!isset($urlparts['host'])) {
04695 $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
04696 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
04697 }
04698 if (! in_array($url, $imported_urls)) {
04699 $this->parseWSDL($url);
04700 $imported++;
04701 $imported_urls[] = $url;
04702 }
04703 } else {
04704 $this->debug("Unexpected scenario: empty URL for unloaded import");
04705 }
04706 }
04707 }
04708 }
04709 }
04710
04711 foreach($this->bindings as $binding => $bindingData) {
04712 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
04713 foreach($bindingData['operations'] as $operation => $data) {
04714 $this->debug('post-parse data gathering for ' . $operation);
04715 $this->bindings[$binding]['operations'][$operation]['input'] =
04716 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
04717 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
04718 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
04719 $this->bindings[$binding]['operations'][$operation]['output'] =
04720 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
04721 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
04722 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
04723 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
04724 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
04725 }
04726 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
04727 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
04728 }
04729
04730 if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
04731 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
04732 }
04733 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
04734 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
04735 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
04736 }
04737 }
04738 }
04739 }
04740
04747 function parseWSDL($wsdl = '') {
04748 $this->debug("parse WSDL at path=$wsdl");
04749
04750 if ($wsdl == '') {
04751 $this->debug('no wsdl passed to parseWSDL()!!');
04752 $this->setError('no wsdl passed to parseWSDL()!!');
04753 return false;
04754 }
04755
04756
04757 $wsdl_props = parse_url($wsdl);
04758
04759 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
04760 $this->debug('getting WSDL http(s) URL ' . $wsdl);
04761
04762 $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
04763 $tr->request_method = 'GET';
04764 $tr->useSOAPAction = false;
04765 if($this->proxyhost && $this->proxyport){
04766 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
04767 }
04768 if ($this->authtype != '') {
04769 $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
04770 }
04771 $tr->setEncoding('gzip, deflate');
04772 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
04773
04774
04775 $this->appendDebug($tr->getDebug());
04776
04777 if($err = $tr->getError() ){
04778 $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
04779 $this->debug($errstr);
04780 $this->setError($errstr);
04781 unset($tr);
04782 return false;
04783 }
04784 unset($tr);
04785 $this->debug("got WSDL URL");
04786 } else {
04787
04788 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
04789 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
04790 } else {
04791 $path = $wsdl;
04792 }
04793 $this->debug('getting WSDL file ' . $path);
04794 if ($fp = @fopen($path, 'r')) {
04795 $wsdl_string = '';
04796 while ($data = fread($fp, 32768)) {
04797 $wsdl_string .= $data;
04798 }
04799 fclose($fp);
04800 } else {
04801 $errstr = "Bad path to WSDL file $path";
04802 $this->debug($errstr);
04803 $this->setError($errstr);
04804 return false;
04805 }
04806 }
04807 $this->debug('Parse WSDL');
04808
04809
04810 $this->parser = xml_parser_create();
04811
04812
04813 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
04814
04815 xml_set_object($this->parser, $this);
04816
04817 xml_set_element_handler($this->parser, 'start_element', 'end_element');
04818 xml_set_character_data_handler($this->parser, 'character_data');
04819
04820 if (!xml_parse($this->parser, $wsdl_string, true)) {
04821
04822 $errstr = sprintf(
04823 'XML error parsing WSDL from %s on line %d: %s',
04824 $wsdl,
04825 xml_get_current_line_number($this->parser),
04826 xml_error_string(xml_get_error_code($this->parser))
04827 );
04828 $this->debug($errstr);
04829 $this->debug("XML payload:\n" . $wsdl_string);
04830 $this->setError($errstr);
04831 return false;
04832 }
04833
04834 xml_parser_free($this->parser);
04835 $this->debug('Parsing WSDL done');
04836
04837 if($this->getError()){
04838 return false;
04839 }
04840 return true;
04841 }
04842
04851 function start_element($parser, $name, $attrs)
04852 {
04853 if ($this->status == 'schema') {
04854 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
04855 $this->appendDebug($this->currentSchema->getDebug());
04856 $this->currentSchema->clearDebug();
04857 } elseif (ereg('schema$', $name)) {
04858 $this->debug('Parsing WSDL schema');
04859
04860 $this->status = 'schema';
04861 $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
04862 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
04863 $this->appendDebug($this->currentSchema->getDebug());
04864 $this->currentSchema->clearDebug();
04865 } else {
04866
04867 $pos = $this->position++;
04868 $depth = $this->depth++;
04869
04870 $this->depth_array[$depth] = $pos;
04871 $this->message[$pos] = array('cdata' => '');
04872
04873 if (count($attrs) > 0) {
04874
04875 foreach($attrs as $k => $v) {
04876 if (ereg("^xmlns", $k)) {
04877 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
04878 $this->namespaces[$ns_prefix] = $v;
04879 } else {
04880 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
04881 }
04882 if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
04883 $this->XMLSchemaVersion = $v;
04884 $this->namespaces['xsi'] = $v . '-instance';
04885 }
04886 }
04887 }
04888
04889 foreach($attrs as $k => $v) {
04890 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
04891 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
04892 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
04893 }
04894 $eAttrs[$k] = $v;
04895 }
04896 $attrs = $eAttrs;
04897 } else {
04898 $attrs = array();
04899 }
04900