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 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
00053
00062 class nusoap_base {
00069 var $title = 'NuSOAP';
00076 var $version = '0.7.2';
00083 var $revision = '$Revision: 1421 $';
00090 var $error_str = '';
00097 var $debug_str = '';
00105 var $charencoding = true;
00112 var $debugLevel;
00113
00120 var $XMLSchemaVersion = 'http:
00121
00128 var $soap_defencoding = 'ISO-8859-1';
00129
00130
00139 var $namespaces = array(
00140 'SOAP-ENV' => 'http:
00141 'xsd' => 'http:
00142 'xsi' => 'http:
00143 'SOAP-ENC' => 'http:
00144 );
00145
00152 var $usedNamespaces = array();
00153
00161 var $typemap = array(
00162 'http:
00163 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
00164 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
00165 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
00166
00167 'anyType'=>'string','anySimpleType'=>'string',
00168
00169 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
00170 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
00171 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
00172 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
00173 'http:
00174 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
00175 'float'=>'double','dateTime'=>'string',
00176 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
00177 'http:
00178 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
00179 'float'=>'double','dateTime'=>'string',
00180 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
00181 'http:
00182 'http:
00183 'http:
00184 );
00185
00194 var $xmlEntities = array('quot' => '"','amp' => '&',
00195 'lt' => '<','gt' => '>','apos' => "'");
00196
00202 function nusoap_base() {
00203 $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
00204 }
00205
00212 function getGlobalDebugLevel() {
00213 return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
00214 }
00215
00222 function setGlobalDebugLevel($level) {
00223 $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
00224 }
00225
00232 function getDebugLevel() {
00233 return $this->debugLevel;
00234 }
00235
00242 function setDebugLevel($level) {
00243 $this->debugLevel = $level;
00244 }
00245
00252 function debug($string){
00253 if ($this->debugLevel > 0) {
00254 $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
00255 }
00256 }
00257
00264 function appendDebug($string){
00265 if ($this->debugLevel > 0) {
00266
00267
00268 $this->debug_str .= $string;
00269 }
00270 }
00271
00277 function clearDebug() {
00278
00279
00280 $this->debug_str = '';
00281 }
00282
00289 function &getDebug() {
00290
00291
00292 return $this->debug_str;
00293 }
00294
00302 function &getDebugAsXMLComment() {
00303
00304
00305 while (strpos($this->debug_str, '--')) {
00306 $this->debug_str = str_replace('--', '- -', $this->debug_str);
00307 }
00308 return "<!--\n" . $this->debug_str . "\n-->";
00309 }
00310
00317 function expandEntities($val) {
00318 if ($this->charencoding) {
00319 $val = str_replace('&', '&', $val);
00320 $val = str_replace("'", ''', $val);
00321 $val = str_replace('"', '"', $val);
00322 $val = str_replace('<', '<', $val);
00323 $val = str_replace('>', '>', $val);
00324 }
00325 return $val;
00326 }
00327
00334 function getError(){
00335 if($this->error_str != ''){
00336 return $this->error_str;
00337 }
00338 return false;
00339 }
00340
00347 function setError($str){
00348 $this->error_str = $str;
00349 }
00350
00358 function isArraySimpleOrStruct($val) {
00359 $keyList = array_keys($val);
00360 foreach ($keyList as $keyListValue) {
00361 if (!is_int($keyListValue)) {
00362 return 'arrayStruct';
00363 }
00364 }
00365 return 'arraySimple';
00366 }
00367
00382 function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){
00383 $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use");
00384 $this->appendDebug('value=' . $this->varDump($val));
00385 $this->appendDebug('attributes=' . $this->varDump($attributes));
00386
00387 if(is_object($val) && get_class($val) == 'soapval'){
00388 return $val->serialize($use);
00389 }
00390
00391 if (is_numeric($name)) {
00392 $name = '__numeric_' . $name;
00393 } elseif (! $name) {
00394 $name = 'noname';
00395 }
00396
00397 $xmlns = '';
00398 if($name_ns){
00399 $prefix = 'nu'.rand(1000,9999);
00400 $name = $prefix.':'.$name;
00401 $xmlns .= " xmlns:$prefix=\"$name_ns\"";
00402 }
00403
00404 if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
00405
00406
00407 $type_prefix = 'xsd';
00408 } elseif($type_ns){
00409 $type_prefix = 'ns'.rand(1000,9999);
00410 $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
00411 }
00412
00413 $atts = '';
00414 if($attributes){
00415 foreach($attributes as $k => $v){
00416 $atts .= " $k=\"".$this->expandEntities($v).'"';
00417 }
00418 }
00419
00420 if (is_null($val)) {
00421 if ($use == 'literal') {
00422
00423 return "<$name$xmlns $atts/>";
00424 } else {
00425 if (isset($type) && isset($type_prefix)) {
00426 $type_str = " xsi:type=\"$type_prefix:$type\"";
00427 } else {
00428 $type_str = '';
00429 }
00430 return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
00431 }
00432 }
00433
00434 if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
00435 if (is_bool($val)) {
00436 if ($type == 'boolean') {
00437 $val = $val ? 'true' : 'false';
00438 } elseif (! $val) {
00439 $val = 0;
00440 }
00441 } else if (is_string($val)) {
00442 $val = $this->expandEntities($val);
00443 }
00444 if ($use == 'literal') {
00445 return "<$name$xmlns $atts>$val</$name>";
00446 } else {
00447 return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</$name>";
00448 }
00449 }
00450
00451 $xml = '';
00452 switch(true) {
00453 case (is_bool($val) || $type == 'boolean'):
00454 if ($type == 'boolean') {
00455 $val = $val ? 'true' : 'false';
00456 } elseif (! $val) {
00457 $val = 0;
00458 }
00459 if ($use == 'literal') {
00460 $xml .= "<$name$xmlns $atts>$val</$name>";
00461 } else {
00462 $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
00463 }
00464 break;
00465 case (is_int($val) || is_long($val) || $type == 'int'):
00466 if ($use == 'literal') {
00467 $xml .= "<$name$xmlns $atts>$val</$name>";
00468 } else {
00469 $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
00470 }
00471 break;
00472 case (is_float($val)|| is_double($val) || $type == 'float'):
00473 if ($use == 'literal') {
00474 $xml .= "<$name$xmlns $atts>$val</$name>";
00475 } else {
00476 $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
00477 }
00478 break;
00479 case (is_string($val) || $type == 'string'):
00480 $val = $this->expandEntities($val);
00481 if ($use == 'literal') {
00482 $xml .= "<$name$xmlns $atts>$val</$name>";
00483 } else {
00484 $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
00485 }
00486 break;
00487 case is_object($val):
00488 if (! $name) {
00489 $name = get_class($val);
00490 $this->debug("In serialize_val, used class name $name as element name");
00491 } else {
00492 $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
00493 }
00494 foreach(get_object_vars($val) as $k => $v){
00495 $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
00496 }
00497 $xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
00498 break;
00499 break;
00500 case (is_array($val) || $type):
00501
00502 $valueType = $this->isArraySimpleOrStruct($val);
00503 if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
00504 $i = 0;
00505 if(is_array($val) && count($val)> 0){
00506 foreach($val as $v){
00507 if(is_object($v) && get_class($v) == 'soapval'){
00508 $tt_ns = $v->type_ns;
00509 $tt = $v->type;
00510 } elseif (is_array($v)) {
00511 $tt = $this->isArraySimpleOrStruct($v);
00512 } else {
00513 $tt = gettype($v);
00514 }
00515 $array_types[$tt] = 1;
00516
00517 $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
00518 ++$i;
00519 }
00520 if(count($array_types) > 1){
00521 $array_typename = 'xsd:anyType';
00522 } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
00523 if ($tt == 'integer') {
00524 $tt = 'int';
00525 }
00526 $array_typename = 'xsd:'.$tt;
00527 } elseif(isset($tt) && $tt == 'arraySimple'){
00528 $array_typename = 'SOAP-ENC:Array';
00529 } elseif(isset($tt) && $tt == 'arrayStruct'){
00530 $array_typename = 'unnamed_struct_use_soapval';
00531 } else {
00532
00533 if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
00534 $array_typename = 'xsd:' . $tt;
00535 } elseif ($tt_ns) {
00536 $tt_prefix = 'ns' . rand(1000, 9999);
00537 $array_typename = "$tt_prefix:$tt";
00538 $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
00539 } else {
00540 $array_typename = $tt;
00541 }
00542 }
00543 $array_type = $i;
00544 if ($use == 'literal') {
00545 $type_str = '';
00546 } else if (isset($type) && isset($type_prefix)) {
00547 $type_str = " xsi:type=\"$type_prefix:$type\"";
00548 } else {
00549 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
00550 }
00551
00552 } else {
00553 if ($use == 'literal') {
00554 $type_str = '';
00555 } else if (isset($type) && isset($type_prefix)) {
00556 $type_str = " xsi:type=\"$type_prefix:$type\"";
00557 } else {
00558 $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
00559 }
00560 }
00561
00562 $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
00563 } else {
00564
00565 if(isset($type) && isset($type_prefix)){
00566 $type_str = " xsi:type=\"$type_prefix:$type\"";
00567 } else {
00568 $type_str = '';
00569 }
00570 if ($use == 'literal') {
00571 $xml .= "<$name$xmlns $atts>";
00572 } else {
00573 $xml .= "<$name$xmlns$type_str$atts>";
00574 }
00575 foreach($val as $k => $v){
00576
00577 if ($type == 'Map' && $type_ns == 'http:
00578 $xml .= '<item>';
00579 $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
00580 $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
00581 $xml .= '</item>';
00582 } else {
00583 $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
00584 }
00585 }
00586 $xml .= "</$name>";
00587 }
00588 break;
00589 default:
00590 $xml .= 'not detected, got '.gettype($val).' for '.$val;
00591 break;
00592 }
00593 return $xml;
00594 }
00595
00608 function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http:
00609
00610
00611
00612
00613 $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
00614 $this->debug("headers:");
00615 $this->appendDebug($this->varDump($headers));
00616 $this->debug("namespaces:");
00617 $this->appendDebug($this->varDump($namespaces));
00618
00619
00620 $ns_string = '';
00621 foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
00622 $ns_string .= " xmlns:$k=\"$v\"";
00623 }
00624 if($encodingStyle) {
00625 $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
00626 }
00627
00628
00629 if($headers){
00630 if (is_array($headers)) {
00631 $xml = '';
00632 foreach ($headers as $header) {
00633 $xml .= $this->serialize_val($header, false, false, false, false, false, $use);
00634 }
00635 $headers = $xml;
00636 $this->debug("In serializeEnvelope, serialzied array of headers to $headers");
00637 }
00638 $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
00639 }
00640
00641 return
00642 '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
00643 '<SOAP-ENV:Envelope'.$ns_string.">".
00644 $headers.
00645 "<SOAP-ENV:Body>".
00646 $body.
00647 "</SOAP-ENV:Body>".
00648 "</SOAP-ENV:Envelope>";
00649 }
00650
00659 function formatDump($str){
00660 $str = htmlspecialchars($str);
00661 return nl2br($str);
00662 }
00663
00671 function contractQname($qname){
00672
00673
00674 if (strrpos($qname, ':')) {
00675
00676 $name = substr($qname, strrpos($qname, ':') + 1);
00677
00678 $ns = substr($qname, 0, strrpos($qname, ':'));
00679 $p = $this->getPrefixFromNamespace($ns);
00680 if ($p) {
00681 return $p . ':' . $name;
00682 }
00683 return $qname;
00684 } else {
00685 return $qname;
00686 }
00687 }
00688
00696 function expandQname($qname){
00697
00698 if(strpos($qname,':') && !ereg('^http:
00699
00700 $name = substr(strstr($qname,':'),1);
00701
00702 $prefix = substr($qname,0,strpos($qname,':'));
00703 if(isset($this->namespaces[$prefix])){
00704 return $this->namespaces[$prefix].':'.$name;
00705 } else {
00706 return $qname;
00707 }
00708 } else {
00709 return $qname;
00710 }
00711 }
00712
00721 function getLocalPart($str){
00722 if($sstr = strrchr($str,':')){
00723
00724 return substr( $sstr, 1 );
00725 } else {
00726 return $str;
00727 }
00728 }
00729
00738 function getPrefix($str){
00739 if($pos = strrpos($str,':')){
00740
00741 return substr($str,0,$pos);
00742 }
00743 return false;
00744 }
00745
00753 function getNamespaceFromPrefix($prefix){
00754 if (isset($this->namespaces[$prefix])) {
00755 return $this->namespaces[$prefix];
00756 }
00757
00758 return false;
00759 }
00760
00769 function getPrefixFromNamespace($ns) {
00770 foreach ($this->namespaces as $p => $n) {
00771 if ($ns == $n || $ns == $p) {
00772 $this->usedNamespaces[$p] = $n;
00773 return $p;
00774 }
00775 }
00776 return false;
00777 }
00778
00785 function getmicrotime() {
00786 if (function_exists('gettimeofday')) {
00787 $tod = gettimeofday();
00788 $sec = $tod['sec'];
00789 $usec = $tod['usec'];
00790 } else {
00791 $sec = time();
00792 $usec = 0;
00793 }
00794 return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
00795 }
00796
00804 function varDump($data) {
00805 ob_start();
00806 var_dump($data);
00807 $ret_val = ob_get_contents();
00808 ob_end_clean();
00809 return $ret_val;
00810 }
00811 }
00812
00813
00814
00815
00816
00823 function timestamp_to_iso8601($timestamp,$utc=true){
00824 $datestr = date('Y-m-d\TH:i:sO',$timestamp);
00825 if($utc){
00826 $eregStr =
00827 '([0-9]{4})-'.
00828 '([0-9]{2})-'.
00829 '([0-9]{2})'.
00830 'T'.
00831 '([0-9]{2}):'.
00832 '([0-9]{2}):'.
00833 '([0-9]{2})(\.[0-9]*)?'.
00834 '(Z|[+\-][0-9]{2}:?[0-9]{2})?';
00835
00836 if(ereg($eregStr,$datestr,$regs)){
00837 return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
00838 }
00839 return false;
00840 } else {
00841 return $datestr;
00842 }
00843 }
00844
00851 function iso8601_to_timestamp($datestr){
00852 $eregStr =
00853 '([0-9]{4})-'.
00854 '([0-9]{2})-'.
00855 '([0-9]{2})'.
00856 'T'.
00857 '([0-9]{2}):'.
00858 '([0-9]{2}):'.
00859 '([0-9]{2})(\.[0-9]+)?'.
00860 '(Z|[+\-][0-9]{2}:?[0-9]{2})?';
00861 if(ereg($eregStr,$datestr,$regs)){
00862
00863 if($regs[8] != 'Z'){
00864 $op = substr($regs[8],0,1);
00865 $h = substr($regs[8],1,2);
00866 $m = substr($regs[8],strlen($regs[8])-2,2);
00867 if($op == '-'){
00868 $regs[4] = $regs[4] + $h;
00869 $regs[5] = $regs[5] + $m;
00870 } elseif($op == '+'){
00871 $regs[4] = $regs[4] - $h;
00872 $regs[5] = $regs[5] - $m;
00873 }
00874 }
00875 return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
00876 } else {
00877 return false;
00878 }
00879 }
00880
00888 function usleepWindows($usec)
00889 {
00890 $start = gettimeofday();
00891
00892 do
00893 {
00894 $stop = gettimeofday();
00895 $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
00896 + $stop['usec'] - $start['usec'];
00897 }
00898 while ($timePassed < $usec);
00899 }
00900
00901
00902
00911 class soap_fault extends nusoap_base {
00917 var $faultcode;
00923 var $faultactor;
00929 var $faultstring;
00935 var $faultdetail;
00936
00945 function soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
00946 parent::nusoap_base();
00947 $this->faultcode = $faultcode;
00948 $this->faultactor = $faultactor;
00949 $this->faultstring = $faultstring;
00950 $this->faultdetail = $faultdetail;
00951 }
00952
00959 function serialize(){
00960 $ns_string = '';
00961 foreach($this->namespaces as $k => $v){
00962 $ns_string .= "\n xmlns:$k=\"$v\"";
00963 }
00964 $return_msg =
00965 '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
00966 '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
00967 '<SOAP-ENV:Body>'.
00968 '<SOAP-ENV:Fault>'.
00969 $this->serialize_val($this->faultcode, 'faultcode').
00970 $this->serialize_val($this->faultactor, 'faultactor').
00971 $this->serialize_val($this->faultstring, 'faultstring').
00972 $this->serialize_val($this->faultdetail, 'detail').
00973 '</SOAP-ENV:Fault>'.
00974 '</SOAP-ENV:Body>'.
00975 '</SOAP-ENV:Envelope>';
00976 return $return_msg;
00977 }
00978 }
00979
00980
00981
00993 class XMLSchema extends nusoap_base {
00994
00995
00996 var $schema = '';
00997 var $xml = '';
00998
00999 var $enclosingNamespaces;
01000
01001 var $schemaInfo = array();
01002 var $schemaTargetNamespace = '';
01003
01004 var $attributes = array();
01005 var $complexTypes = array();
01006 var $complexTypeStack = array();
01007 var $currentComplexType = null;
01008 var $elements = array();
01009 var $elementStack = array();
01010 var $currentElement = null;
01011 var $simpleTypes = array();
01012 var $simpleTypeStack = array();
01013 var $currentSimpleType = null;
01014
01015 var $imports = array();
01016
01017 var $parser;
01018 var $position = 0;
01019 var $depth = 0;
01020 var $depth_array = array();
01021 var $message = array();
01022 var $defaultNamespace = array();
01023
01032 function XMLSchema($schema='',$xml='',$namespaces=array()){
01033 parent::nusoap_base();
01034 $this->debug('xmlschema class instantiated, inside constructor');
01035
01036 $this->schema = $schema;
01037 $this->xml = $xml;
01038
01039
01040 $this->enclosingNamespaces = $namespaces;
01041 $this->namespaces = array_merge($this->namespaces, $namespaces);
01042
01043
01044 if($schema != ''){
01045 $this->debug('initial schema file: '.$schema);
01046 $this->parseFile($schema, 'schema');
01047 }
01048
01049
01050 if($xml != ''){
01051 $this->debug('initial xml file: '.$xml);
01052 $this->parseFile($xml, 'xml');
01053 }
01054
01055 }
01056
01065 function parseFile($xml,$type){
01066
01067 if($xml != ""){
01068 $xmlStr = @join("",@file($xml));
01069 if($xmlStr == ""){
01070 $msg = 'Error reading XML from '.$xml;
01071 $this->setError($msg);
01072 $this->debug($msg);
01073 return false;
01074 } else {
01075 $this->debug("parsing $xml");
01076 $this->parseString($xmlStr,$type);
01077 $this->debug("done parsing $xml");
01078 return true;
01079 }
01080 }
01081 return false;
01082 }
01083
01091 function parseString($xml,$type){
01092
01093 if($xml != ""){
01094
01095
01096 $this->parser = xml_parser_create();
01097
01098 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
01099
01100
01101 xml_set_object($this->parser, $this);
01102
01103
01104 if($type == "schema"){
01105 xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
01106 xml_set_character_data_handler($this->parser,'schemaCharacterData');
01107 } elseif($type == "xml"){
01108 xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
01109 xml_set_character_data_handler($this->parser,'xmlCharacterData');
01110 }
01111
01112
01113 if(!xml_parse($this->parser,$xml,true)){
01114
01115 $errstr = sprintf('XML error parsing XML schema on line %d: %s',
01116 xml_get_current_line_number($this->parser),
01117 xml_error_string(xml_get_error_code($this->parser))
01118 );
01119 $this->debug($errstr);
01120 $this->debug("XML payload:\n" . $xml);
01121 $this->setError($errstr);
01122 }
01123
01124 xml_parser_free($this->parser);
01125 } else{
01126 $this->debug('no xml passed to parseString()!!');
01127 $this->setError('no xml passed to parseString()!!');
01128 }
01129 }
01130
01139 function schemaStartElement($parser, $name, $attrs) {
01140
01141
01142 $pos = $this->position++;
01143 $depth = $this->depth++;
01144
01145 $this->depth_array[$depth] = $pos;
01146 $this->message[$pos] = array('cdata' => '');
01147 if ($depth > 0) {
01148 $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
01149 } else {
01150 $this->defaultNamespace[$pos] = false;
01151 }
01152
01153
01154 if($prefix = $this->getPrefix($name)){
01155
01156 $name = $this->getLocalPart($name);
01157 } else {
01158 $prefix = '';
01159 }
01160
01161
01162 if(count($attrs) > 0){
01163 foreach($attrs as $k => $v){
01164
01165 if(ereg("^xmlns",$k)){
01166
01167
01168 if($ns_prefix = substr(strrchr($k,':'),1)){
01169
01170 $this->namespaces[$ns_prefix] = $v;
01171 } else {
01172 $this->defaultNamespace[$pos] = $v;
01173 if (! $this->getPrefixFromNamespace($v)) {
01174 $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
01175 }
01176 }
01177 if($v == 'http:
01178 $this->XMLSchemaVersion = $v;
01179 $this->namespaces['xsi'] = $v.'-instance';
01180 }
01181 }
01182 }
01183 foreach($attrs as $k => $v){
01184
01185 $k = strpos($k,':') ? $this->expandQname($k) : $k;
01186 $v = strpos($v,':') ? $this->expandQname($v) : $v;
01187 $eAttrs[$k] = $v;
01188 }
01189 $attrs = $eAttrs;
01190 } else {
01191 $attrs = array();
01192 }
01193
01194 switch($name){
01195 case 'all':
01196 case 'choice':
01197 case 'group':
01198 case 'sequence':
01199
01200 $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
01201
01202
01203
01204 break;
01205 case 'attribute':
01206
01207 $this->xdebug("parsing attribute:");
01208 $this->appendDebug($this->varDump($attrs));
01209 if (!isset($attrs['form'])) {
01210 $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
01211 }
01212 if (isset($attrs['http:
01213 $v = $attrs['http:
01214 if (!strpos($v, ':')) {
01215
01216 if ($this->defaultNamespace[$pos]) {
01217
01218 $attrs['http:
01219 }
01220 }
01221 }
01222 if(isset($attrs['name'])){
01223 $this->attributes[$attrs['name']] = $attrs;
01224 $aname = $attrs['name'];
01225 } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http:
01226 if (isset($attrs['http:
01227 $aname = $attrs['http:
01228 } else {
01229 $aname = '';
01230 }
01231 } elseif(isset($attrs['ref'])){
01232 $aname = $attrs['ref'];
01233 $this->attributes[$attrs['ref']] = $attrs;
01234 }
01235
01236 if($this->currentComplexType){
01237 $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
01238 }
01239
01240 if(isset($attrs['http:
01241 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01242 $prefix = $this->getPrefix($aname);
01243 if(isset($attrs['http:
01244 $v = $attrs['http:
01245 } else {
01246 $v = '';
01247 }
01248 if(strpos($v,'[,]')){
01249 $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
01250 }
01251 $v = substr($v,0,strpos($v,'['));
01252 if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
01253 $v = $this->XMLSchemaVersion.':'.$v;
01254 }
01255 $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
01256 }
01257 break;
01258 case 'complexContent':
01259 break;
01260 case 'complexType':
01261 array_push($this->complexTypeStack, $this->currentComplexType);
01262 if(isset($attrs['name'])){
01263 $this->xdebug('processing named complexType '.$attrs['name']);
01264
01265 $this->currentComplexType = $attrs['name'];
01266 $this->complexTypes[$this->currentComplexType] = $attrs;
01267 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
01268
01269
01270
01271
01272
01273
01274
01275 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
01276 $this->xdebug('complexType is unusual array');
01277 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01278 } else {
01279 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
01280 }
01281 }else{
01282 $this->xdebug('processing unnamed complexType for element '.$this->currentElement);
01283 $this->currentComplexType = $this->currentElement . '_ContainedType';
01284
01285 $this->complexTypes[$this->currentComplexType] = $attrs;
01286 $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
01287
01288
01289
01290
01291
01292
01293
01294 if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
01295 $this->xdebug('complexType is unusual array');
01296 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01297 } else {
01298 $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
01299 }
01300 }
01301 break;
01302 case 'element':
01303 array_push($this->elementStack, $this->currentElement);
01304
01305
01306
01307 if (!isset($attrs['form'])) {
01308 $attrs['form'] = $this->schemaInfo['elementFormDefault'];
01309 }
01310 if(isset($attrs['type'])){
01311 $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
01312 if (! $this->getPrefix($attrs['type'])) {
01313 if ($this->defaultNamespace[$pos]) {
01314 $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
01315 $this->xdebug('used default namespace to make type ' . $attrs['type']);
01316 }
01317 }
01318
01319
01320
01321
01322
01323
01324
01325 if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
01326 $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
01327 $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
01328 }
01329 $this->currentElement = $attrs['name'];
01330 $this->elements[ $attrs['name'] ] = $attrs;
01331 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
01332 $ename = $attrs['name'];
01333 } elseif(isset($attrs['ref'])){
01334 $this->xdebug("processing element as ref to ".$attrs['ref']);
01335 $this->currentElement = "ref to ".$attrs['ref'];
01336 $ename = $this->getLocalPart($attrs['ref']);
01337 } else {
01338 $this->xdebug("processing untyped element ".$attrs['name']);
01339 $this->currentElement = $attrs['name'];
01340 $this->elements[ $attrs['name'] ] = $attrs;
01341 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
01342 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
01343 $this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
01344 $ename = $attrs['name'];
01345 }
01346 if(isset($ename) && $this->currentComplexType){
01347 $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
01348 }
01349 break;
01350 case 'enumeration':
01351 $this->xdebug('enumeration ' . $attrs['value']);
01352 if ($this->currentSimpleType) {
01353 $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
01354 } elseif ($this->currentComplexType) {
01355 $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
01356 }
01357 break;
01358 case 'extension':
01359 $this->xdebug('extension ' . $attrs['base']);
01360 if ($this->currentComplexType) {
01361 $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
01362 }
01363 break;
01364 case 'import':
01365 if (isset($attrs['schemaLocation'])) {
01366
01367 $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
01368 } else {
01369
01370 $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
01371 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
01372 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
01373 }
01374 }
01375 break;
01376 case 'list':
01377 break;
01378 case 'restriction':
01379 $this->xdebug('restriction ' . $attrs['base']);
01380 if($this->currentSimpleType){
01381 $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
01382 } elseif($this->currentComplexType){
01383 $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
01384 if(strstr($attrs['base'],':') == ':Array'){
01385 $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
01386 }
01387 }
01388 break;
01389 case 'schema':
01390 $this->schemaInfo = $attrs;
01391 $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
01392 if (isset($attrs['targetNamespace'])) {
01393 $this->schemaTargetNamespace = $attrs['targetNamespace'];
01394 }
01395 if (!isset($attrs['elementFormDefault'])) {
01396 $this->schemaInfo['elementFormDefault'] = 'unqualified';
01397 }
01398 if (!isset($attrs['attributeFormDefault'])) {
01399 $this->schemaInfo['attributeFormDefault'] = 'unqualified';
01400 }
01401 break;
01402 case 'simpleContent':
01403 break;
01404 case 'simpleType':
01405 array_push($this->simpleTypeStack, $this->currentSimpleType);
01406 if(isset($attrs['name'])){
01407 $this->xdebug("processing simpleType for name " . $attrs['name']);
01408 $this->currentSimpleType = $attrs['name'];
01409 $this->simpleTypes[ $attrs['name'] ] = $attrs;
01410 $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
01411 $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
01412 } else {
01413 $this->xdebug('processing unnamed simpleType for element '.$this->currentElement);
01414 $this->currentSimpleType = $this->currentElement . '_ContainedType';
01415
01416 $this->simpleTypes[$this->currentSimpleType] = $attrs;
01417 $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
01418 }
01419 break;
01420 case 'union':
01421 break;
01422 default:
01423
01424 }
01425 }
01426
01434 function schemaEndElement($parser, $name) {
01435
01436 $this->depth--;
01437
01438 if(isset($this->depth_array[$this->depth])){
01439 $pos = $this->depth_array[$this->depth];
01440 }
01441
01442 if ($prefix = $this->getPrefix($name)){
01443
01444 $name = $this->getLocalPart($name);
01445 } else {
01446 $prefix = '';
01447 }
01448
01449 if($name == 'complexType'){
01450 $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
01451 $this->currentComplexType = array_pop($this->complexTypeStack);
01452
01453 }
01454 if($name == 'element'){
01455 $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
01456 $this->currentElement = array_pop($this->elementStack);
01457 }
01458 if($name == 'simpleType'){
01459 $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
01460 $this->currentSimpleType = array_pop($this->simpleTypeStack);
01461 }
01462 }
01463
01471 function schemaCharacterData($parser, $data){
01472 $pos = $this->depth_array[$this->depth - 1];
01473 $this->message[$pos]['cdata'] .= $data;
01474 }
01475
01481 function serializeSchema(){
01482
01483 $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
01484 $xml = '';
01485
01486 if (sizeof($this->imports) > 0) {
01487 foreach($this->imports as $ns => $list) {
01488 foreach ($list as $ii) {
01489 if ($ii['location'] != '') {
01490 $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
01491 } else {
01492 $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
01493 }
01494 }
01495 }
01496 }
01497
01498 foreach($this->complexTypes as $typeName => $attrs){
01499 $contentStr = '';
01500
01501 if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
01502 foreach($attrs['elements'] as $element => $eParts){
01503 if(isset($eParts['ref'])){
01504 $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
01505 } else {
01506 $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
01507 foreach ($eParts as $aName => $aValue) {
01508
01509 if ($aName != 'name' && $aName != 'type') {
01510 $contentStr .= " $aName=\"$aValue\"";
01511 }
01512 }
01513 $contentStr .= "/>\n";
01514 }
01515 }
01516
01517 if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
01518 $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
01519 }
01520 }
01521
01522 if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
01523 foreach($attrs['attrs'] as $attr => $aParts){
01524 $contentStr .= " <$schemaPrefix:attribute";
01525 foreach ($aParts as $a => $v) {
01526 if ($a == 'ref' || $a == 'type') {
01527 $contentStr .= " $a=\"".$this->contractQName($v).'"';
01528 } elseif ($a == 'http:
01529 $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
01530 $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
01531 } else {
01532 $contentStr .= " $a=\"$v\"";
01533 }
01534 }
01535 $contentStr .= "/>\n";
01536 }
01537 }
01538
01539 if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
01540 $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
01541
01542 if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
01543 $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
01544 }
01545 }
01546
01547 if($contentStr != ''){
01548 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
01549 } else {
01550 $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
01551 }
01552 $xml .= $contentStr;
01553 }
01554
01555 if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
01556 foreach($this->simpleTypes as $typeName => $eParts){
01557 $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\"/>\n";
01558 if (isset($eParts['enumeration'])) {
01559 foreach ($eParts['enumeration'] as $e) {
01560 $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
01561 }
01562 }
01563 $xml .= " </$schemaPrefix:simpleType>";
01564 }
01565 }
01566
01567 if(isset($this->elements) && count($this->elements) > 0){
01568 foreach($this->elements as $element => $eParts){
01569 $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
01570 }
01571 }
01572
01573 if(isset($this->attributes) && count($this->attributes) > 0){
01574 foreach($this->attributes as $attr => $aParts){
01575 $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
01576 }
01577 }
01578
01579 $el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
01580 foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
01581 $el .= " xmlns:$nsp=\"$ns\"\n";
01582 }
01583 $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
01584 return $xml;
01585 }
01586
01593 function xdebug($string){
01594 $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
01595 }
01596
01609 function getPHPType($type,$ns){
01610 if(isset($this->typemap[$ns][$type])){
01611
01612 return $this->typemap[$ns][$type];
01613 } elseif(isset($this->complexTypes[$type])){
01614
01615 return $this->complexTypes[$type]['phpType'];
01616 }
01617 return false;
01618 }
01619
01642 function getTypeDef($type){
01643
01644 if(isset($this->complexTypes[$type])){
01645 $this->xdebug("in getTypeDef, found complexType $type");
01646 return $this->complexTypes[$type];
01647 } elseif(isset($this->simpleTypes[$type])){
01648 $this->xdebug("in getTypeDef, found simpleType $type");
01649 if (!isset($this->simpleTypes[$type]['phpType'])) {
01650
01651
01652 $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
01653 $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
01654 $etype = $this->getTypeDef($uqType);
01655 if ($etype) {
01656 $this->xdebug("in getTypeDef, found type for simpleType $type:");
01657 $this->xdebug($this->varDump($etype));
01658 if (isset($etype['phpType'])) {
01659 $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
01660 }
01661 if (isset($etype['elements'])) {
01662 $this->simpleTypes[$type]['elements'] = $etype['elements'];
01663 }
01664 }
01665 }
01666 return $this->simpleTypes[$type];
01667 } elseif(isset($this->elements[$type])){
01668 $this->xdebug("in getTypeDef, found element $type");
01669 if (!isset($this->elements[$type]['phpType'])) {
01670
01671 $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
01672 $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
01673 $etype = $this->getTypeDef($uqType);
01674 if ($etype) {
01675 $this->xdebug("in getTypeDef, found type for element $type:");
01676 $this->xdebug($this->varDump($etype));
01677 if (isset($etype['phpType'])) {
01678 $this->elements[$type]['phpType'] = $etype['phpType'];
01679 }
01680 if (isset($etype['elements'])) {
01681 $this->elements[$type]['elements'] = $etype['elements'];
01682 }
01683 } elseif ($ns == 'http:
01684 $this->xdebug("in getTypeDef, element $type is an XSD type");
01685 $this->elements[$type]['phpType'] = 'scalar';
01686 }
01687 }
01688 return $this->elements[$type];
01689 } elseif(isset($this->attributes[$type])){
01690 $this->xdebug("in getTypeDef, found attribute $type");
01691 return $this->attributes[$type];
01692 } elseif (ereg('_ContainedType$', $type)) {
01693 $this->xdebug("in getTypeDef, have an untyped element $type");
01694 $typeDef['typeClass'] = 'simpleType';
01695 $typeDef['phpType'] = 'scalar';
01696 $typeDef['type'] = 'http:
01697 return $typeDef;
01698 }
01699 $this->xdebug("in getTypeDef, did not find $type");
01700 return false;
01701 }
01702
01711 function serializeTypeDef($type){
01712
01713 if($typeDef = $this->getTypeDef($type)){
01714 $str .= '<'.$type;
01715 if(is_array($typeDef['attrs'])){
01716 foreach($attrs as $attName => $data){
01717 $str .= " $attName=\"{type = ".$data['type']."}\"";
01718 }
01719 }
01720 $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
01721 if(count($typeDef['elements']) > 0){
01722 $str .= ">";
01723 foreach($typeDef['elements'] as $element => $eData){
01724 $str .= $this->serializeTypeDef($element);
01725 }
01726 $str .= "</$type>";
01727 } elseif($typeDef['typeClass'] == 'element') {
01728 $str .= "></$type>";
01729 } else {
01730 $str .= "/>";
01731 }
01732 return $str;
01733 }
01734 return false;
01735 }
01736
01747 function typeToForm($name,$type){
01748
01749 if($typeDef = $this->getTypeDef($type)){
01750
01751 if($typeDef['phpType'] == 'struct'){
01752 $buffer .= '<table>';
01753 foreach($typeDef['elements'] as $child => $childDef){
01754 $buffer .= "
01755 <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
01756 <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
01757 }
01758 $buffer .= '</table>';
01759
01760 } elseif($typeDef['phpType'] == 'array'){
01761 $buffer .= '<table>';
01762 for($i=0;$i < 3; $i++){
01763 $buffer .= "
01764 <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
01765 <td><input type='text' name='parameters[".$name."][]'></td></tr>";
01766 }
01767 $buffer .= '</table>';
01768
01769 } else {
01770 $buffer .= "<input type='text' name='parameters[$name]'>";
01771 }
01772 } else {
01773 $buffer .= "<input type='text' name='parameters[$name]'>";
01774 }
01775 return $buffer;
01776 }
01777
01819 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
01820 $this->complexTypes[$name] = array(
01821 'name' => $name,
01822 'typeClass' => $typeClass,
01823 'phpType' => $phpType,
01824 'compositor'=> $compositor,
01825 'restrictionBase' => $restrictionBase,
01826 'elements' => $elements,
01827 'attrs' => $attrs,
01828 'arrayType' => $arrayType
01829 );
01830
01831 $this->xdebug("addComplexType $name:");
01832 $this->appendDebug($this->varDump($this->complexTypes[$name]));
01833 }
01834
01847 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
01848 $this->simpleTypes[$name] = array(
01849 'name' => $name,
01850 'typeClass' => $typeClass,
01851 'phpType' => $phpType,
01852 'type' => $restrictionBase,
01853 'enumeration' => $enumeration
01854 );
01855
01856 $this->xdebug("addSimpleType $name:");
01857 $this->appendDebug($this->varDump($this->simpleTypes[$name]));
01858 }
01859
01867 function addElement($attrs) {
01868 if (! $this->getPrefix($attrs['type'])) {
01869 $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
01870 }
01871 $this->elements[ $attrs['name'] ] = $attrs;
01872 $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
01873
01874 $this->xdebug("addElement " . $attrs['name']);
01875 $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
01876 }
01877 }
01878
01879
01880
01892 class soapval extends nusoap_base {
01899 var $name;
01906 var $type;
01913 var $value;
01920 var $element_ns;
01927 var $type_ns;
01934 var $attributes;
01935
01947 function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
01948 parent::nusoap_base();
01949 $this->name = $name;
01950 $this->type = $type;
01951 $this->value = $value;
01952 $this->element_ns = $element_ns;
01953 $this->type_ns = $type_ns;
01954 $this->attributes = $attributes;
01955 }
01956
01964 function serialize($use='encoded') {
01965 return $this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
01966 }
01967
01974 function decode(){
01975 return $this->value;
01976 }
01977 }
01978
01979
01980
01989 class soap_transport_http extends nusoap_base {
01990
01991 var $url = '';
01992 var $uri = '';
01993 var $digest_uri = '';
01994 var $scheme = '';
01995 var $host = '';
01996 var $port = '';
01997 var $path = '';
01998 var $request_method = 'POST';
01999 var $protocol_version = '1.0';
02000 var $encoding = '';
02001 var $outgoing_headers = array();
02002 var $incoming_headers = array();
02003 var $incoming_cookies = array();
02004 var $outgoing_payload = '';
02005 var $incoming_payload = '';
02006 var $useSOAPAction = true;
02007 var $persistentConnection = false;
02008 var $ch = false;
02009 var $username = '';
02010 var $password = '';
02011 var $authtype = '';
02012 var $digestRequest = array();
02013 var $certRequest = array();
02014
02015
02016
02017
02018
02019
02020
02024 function soap_transport_http($url){
02025 parent::nusoap_base();
02026 $this->setURL($url);
02027 ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
02028 $this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')';
02029 $this->debug('set User-Agent: ' . $this->outgoing_headers['User-Agent']);
02030 }
02031
02032 function setURL($url) {
02033 $this->url = $url;
02034
02035 $u = parse_url($url);
02036 foreach($u as $k => $v){
02037 $this->debug("$k = $v");
02038 $this->$k = $v;
02039 }
02040
02041
02042 if(isset($u['query']) && $u['query'] != ''){
02043 $this->path .= '?' . $u['query'];
02044 }
02045
02046
02047 if(!isset($u['port'])){
02048 if($u['scheme'] == 'https'){
02049 $this->port = 443;
02050 } else {
02051 $this->port = 80;
02052 }
02053 }
02054
02055 $this->uri = $this->path;
02056 $this->digest_uri = $this->uri;
02057
02058
02059 if (!isset($u['port'])) {
02060 $this->outgoing_headers['Host'] = $this->host;
02061 } else {
02062 $this->outgoing_headers['Host'] = $this->host.':'.$this->port;
02063 }
02064 $this->debug('set Host: ' . $this->outgoing_headers['Host']);
02065
02066 if (isset($u['user']) && $u['user'] != '') {
02067 $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
02068 }
02069 }
02070
02071 function connect($connection_timeout=0,$response_timeout=30){
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084 $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
02085 if ($this->scheme == 'http' || $this->scheme == 'ssl') {
02086
02087 if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
02088 if (!feof($this->fp)) {
02089 $this->debug('Re-use persistent connection');
02090 return true;
02091 }
02092 fclose($this->fp);
02093 $this->debug('Closed persistent connection at EOF');
02094 }
02095
02096
02097 if ($this->scheme == 'ssl') {
02098 $host = 'ssl:
02099 } else {
02100 $host = $this->host;
02101 }
02102 $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
02103
02104
02105 if($connection_timeout > 0){
02106 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
02107 } else {
02108 $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
02109 }
02110
02111
02112 if(!$this->fp) {
02113 $msg = 'Couldn\'t open socket connection to server ' . $this->url;
02114 if ($this->errno) {
02115 $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
02116 } else {
02117 $msg .= ' prior to connect(). This is often a problem looking up the host name.';
02118 }
02119 $this->debug($msg);
02120 $this->setError($msg);
02121 return false;
02122 }
02123
02124
02125 $this->debug('set response timeout to ' . $response_timeout);
02126 socket_set_timeout( $this->fp, $response_timeout);
02127
02128 $this->debug('socket connected');
02129 return true;
02130 } else if ($this->scheme == 'https') {
02131 if (!extension_loaded('curl')) {
02132 $this->setError('CURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
02133 return false;
02134 }
02135 $this->debug('connect using https');
02136
02137 $this->ch = curl_init();
02138
02139 $hostURL = ($this->port != '') ? "https://$this->host:$this->port" : "https://$this->host";
02140
02141 $hostURL .= $this->path;
02142 curl_setopt($this->ch, CURLOPT_URL, $hostURL);
02143
02144 curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
02145
02146 curl_setopt($this->ch, CURLOPT_HEADER, 1);
02147
02148 curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
02149
02150
02151
02152
02153
02154
02155 if ($this->persistentConnection) {
02156
02157
02158
02159 $this->persistentConnection = false;
02160 $this->outgoing_headers['Connection'] = 'close';
02161 $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
02162 }
02163
02164 if ($connection_timeout != 0) {
02165 curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_timeout);
02166 }
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179 curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
02180 curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
02181
02182
02183 if ($this->authtype == 'certificate') {
02184 if (isset($this->certRequest['cainfofile'])) {
02185 curl_setopt($this->ch, CURLOPT_CAINFO, $this->certRequest['cainfofile']);
02186 }
02187 if (isset($this->certRequest['verifypeer'])) {
02188 curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
02189 } else {
02190 curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1);
02191 }
02192 if (isset($this->certRequest['verifyhost'])) {
02193 curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
02194 } else {
02195 curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1);
02196 }
02197 if (isset($this->certRequest['sslcertfile'])) {
02198 curl_setopt($this->ch, CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
02199 }
02200 if (isset($this->certRequest['sslkeyfile'])) {
02201 curl_setopt($this->ch, CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
02202 }
02203 if (isset($this->certRequest['passphrase'])) {
02204 curl_setopt($this->ch, CURLOPT_SSLKEYPASSWD , $this->certRequest['passphrase']);
02205 }
02206 }
02207 $this->debug('cURL connection set up');
02208 return true;
02209 } else {
02210 $this->setError('Unknown scheme ' . $this->scheme);
02211 $this->debug('Unknown scheme ' . $this->scheme);
02212 return false;
02213 }
02214 }
02215
02226 function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
02227
02228 $this->debug('entered send() with data of length: '.strlen($data));
02229
02230 $this->tryagain = true;
02231 $tries = 0;
02232 while ($this->tryagain) {
02233 $this->tryagain = false;
02234 if ($tries++ < 2) {
02235
02236 if (!$this->connect($timeout, $response_timeout)){
02237 return false;
02238 }
02239
02240
02241 if (!$this->sendRequest($data, $cookies)){
02242 return false;
02243 }
02244
02245
02246 $respdata = $this->getResponse();
02247 } else {
02248 $this->setError('Too many tries to get an OK response');
02249 }
02250 }
02251 $this->debug('end of send()');
02252 return $respdata;
02253 }
02254
02255
02266 function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
02267 return $this->send($data, $timeout, $response_timeout, $cookies);
02268 }
02269
02280 function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
02281 $this->debug("Set credentials for authtype $authtype");
02282
02283 if ($authtype == 'basic') {
02284 $this->outgoing_headers['Authorization'] = 'Basic '.base64_encode(str_replace(':','',$username).':'.$password);
02285 } elseif ($authtype == 'digest') {
02286 if (isset($digestRequest['nonce'])) {
02287 $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
02288
02289
02290
02291
02292 $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
02293
02294
02295 $HA1 = md5($A1);
02296
02297
02298 $A2 = 'POST:' . $this->digest_uri;
02299
02300
02301 $HA2 = md5($A2);
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314 $unhashedDigest = '';
02315 $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
02316 $cnonce = $nonce;
02317 if ($digestRequest['qop'] != '') {
02318 $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
02319 } else {
02320 $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
02321 }
02322
02323 $hashedDigest = md5($unhashedDigest);
02324
02325 $this->outgoing_headers['Authorization'] = 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"';
02326 }
02327 } elseif ($authtype == 'certificate') {
02328 $this->certRequest = $certRequest;
02329 }
02330 $this->username = $username;
02331 $this->password = $password;
02332 $this->authtype = $authtype;
02333 $this->digestRequest = $digestRequest;
02334
02335 if (isset($this->outgoing_headers['Authorization'])) {
02336 $this->debug('set Authorization: ' . substr($this->outgoing_headers['Authorization'], 0, 12) . '...');
02337 } else {
02338 $this->debug('Authorization header not set');
02339 }
02340 }
02341
02348 function setSOAPAction($soapaction) {
02349 $this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"';
02350 $this->debug('set SOAPAction: ' . $this->outgoing_headers['SOAPAction']);
02351 }
02352
02359 function setEncoding($enc='gzip, deflate') {
02360 if (function_exists('gzdeflate')) {
02361 $this->protocol_version = '1.1';
02362 $this->outgoing_headers['Accept-Encoding'] = $enc;
02363 $this->debug('set Accept-Encoding: ' . $this->outgoing_headers['Accept-Encoding']);
02364 if (!isset($this->outgoing_headers['Connection'])) {
02365 $this->outgoing_headers['Connection'] = 'close';
02366 $this->persistentConnection = false;
02367 $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
02368 }
02369 set_magic_quotes_runtime(0);
02370
02371 $this->encoding = $enc;
02372 }
02373 }
02374
02384 function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
02385 $this->uri = $this->url;
02386 $this->host = $proxyhost;
02387 $this->port = $proxyport;
02388 if ($proxyusername != '' && $proxypassword != '') {
02389 $this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword);
02390 $this->debug('set Proxy-Authorization: ' . $this->outgoing_headers['Proxy-Authorization']);
02391 }
02392 }
02393
02404 function decodeChunked($buffer, $lb){
02405
02406 $length = 0;
02407 $new = '';
02408
02409
02410
02411 $chunkend = strpos($buffer, $lb);
02412 if ($chunkend == FALSE) {
02413 $this->debug('no linebreak found in decodeChunked');
02414 return $new;
02415 }
02416 $temp = substr($buffer,0,$chunkend);
02417 $chunk_size = hexdec( trim($temp) );
02418 $chunkstart = $chunkend + strlen($lb);
02419
02420 while ($chunk_size > 0) {
02421 $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
02422 $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
02423
02424
02425 if ($chunkend == FALSE) {
02426 $chunk = substr($buffer,$chunkstart);
02427
02428 $new .= $chunk;
02429 $length += strlen($chunk);
02430 break;
02431 }
02432
02433
02434 $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
02435
02436 $new .= $chunk;
02437
02438 $length += strlen($chunk);
02439
02440 $chunkstart = $chunkend + strlen($lb);
02441
02442 $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
02443 if ($chunkend == FALSE) {
02444 break;
02445 }
02446 $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
02447 $chunk_size = hexdec( trim($temp) );
02448 $chunkstart = $chunkend;
02449 }
02450 return $new;
02451 }
02452
02453
02454
02455
02456 function buildPayload($data, $cookie_str = '') {
02457
02458 $this->outgoing_headers['Content-Length'] = strlen($data);
02459 $this->debug('set Content-Length: ' . $this->outgoing_headers['Content-Length']);
02460
02461
02462 $req = "$this->request_method $this->uri HTTP/$this->protocol_version";
02463 $this->debug("HTTP request: $req");
02464 $this->outgoing_payload = "$req\r\n";
02465
02466
02467 foreach($this->outgoing_headers as $k => $v){
02468 $hdr = $k.': '.$v;
02469 $this->debug("HTTP header: $hdr");
02470 $this->outgoing_payload .= "$hdr\r\n";
02471 }
02472
02473
02474 if ($cookie_str != '') {
02475 $hdr = 'Cookie: '.$cookie_str;
02476 $this->debug("HTTP header: $hdr");
02477 $this->outgoing_payload .= "$hdr\r\n";
02478 }
02479
02480
02481 $this->outgoing_payload .= "\r\n";
02482
02483
02484 $this->outgoing_payload .= $data;
02485 }
02486
02487 function sendRequest($data, $cookies = NULL) {
02488
02489 $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
02490
02491
02492 $this->buildPayload($data, $cookie_str);
02493
02494 if ($this->scheme == 'http' || $this->scheme == 'ssl') {
02495
02496 if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
02497 $this->setError('couldn\'t write message data to socket');
02498 $this->debug('couldn\'t write message data to socket');
02499 return false;
02500 }
02501 $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
02502 return true;
02503 } else if ($this->scheme == 'https') {
02504
02505
02506
02507
02508
02509 foreach($this->outgoing_headers as $k => $v){
02510 $curl_headers[] = "$k: $v";
02511 }
02512 if ($cookie_str != '') {
02513 $curl_headers[] = 'Cookie: ' . $cookie_str;
02514 }
02515 curl_setopt($this->ch, CURLOPT_HTTPHEADER, $curl_headers);
02516 if ($this->request_method == "POST") {
02517 curl_setopt($this->ch, CURLOPT_POST, 1);
02518 curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
02519 } else {
02520 }
02521 $this->debug('set cURL payload');
02522 return true;
02523 }
02524 }
02525
02526 function getResponse(){
02527 $this->incoming_payload = '';
02528
02529 if ($this->scheme == 'http' || $this->scheme == 'ssl') {
02530
02531 $data = '';
02532 while (!isset($lb)){
02533
02534
02535 if(feof($this->fp)) {
02536 $this->incoming_payload = $data;
02537 $this->debug('found no headers before EOF after length ' . strlen($data));
02538 $this->debug("received before EOF:\n" . $data);
02539 $this->setError('server failed to send headers');
02540 return false;
02541 }
02542
02543 $tmp = fgets($this->fp, 256);
02544 $tmplen = strlen($tmp);
02545 $this->debug("read line of $tmplen bytes: " . trim($tmp));
02546
02547 if ($tmplen == 0) {
02548 $this->incoming_payload = $data;
02549 $this->debug('socket read of headers timed out after length ' . strlen($data));
02550 $this->debug("read before timeout: " . $data);
02551 $this->setError('socket read of headers timed out');
02552 return false;
02553 }
02554
02555 $data .= $tmp;
02556 $pos = strpos($data,"\r\n\r\n");
02557 if($pos > 1){
02558 $lb = "\r\n";
02559 } else {
02560 $pos = strpos($data,"\n\n");
02561 if($pos > 1){
02562 $lb = "\n";
02563 }
02564 }
02565
02566 if(isset($lb) && ereg('^HTTP/1.1 100',$data)){
02567 unset($lb);
02568 $data = '';
02569 }
02570 }
02571
02572 $this->incoming_payload .= $data;
02573 $this->debug('found end of headers after length ' . strlen($data));
02574
02575 $header_data = trim(substr($data,0,$pos));
02576 $header_array = explode($lb,$header_data);
02577 $this->incoming_headers = array();
02578 $this->incoming_cookies = array();
02579 foreach($header_array as $header_line){
02580 $arr = explode(':',$header_line, 2);
02581 if(count($arr) > 1){
02582 $header_name = strtolower(trim($arr[0]));
02583 $this->incoming_headers[$header_name] = trim($arr[1]);
02584 if ($header_name == 'set-cookie') {
02585
02586 $cookie = $this->parseCookie(trim($arr[1]));
02587 if ($cookie) {
02588 $this->incoming_cookies[] = $cookie;
02589 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
02590 } else {
02591 $this->debug('did not find cookie in ' . trim($arr[1]));
02592 }
02593 }
02594 } else if (isset($header_name)) {
02595
02596 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
02597 }
02598 }
02599
02600
02601 if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
02602 $content_length = 2147483647;
02603 $chunked = true;
02604 $this->debug("want to read chunked content");
02605 } elseif (isset($this->incoming_headers['content-length'])) {
02606 $content_length = $this->incoming_headers['content-length'];
02607 $chunked = false;
02608 $this->debug("want to read content of length $content_length");
02609 } else {
02610 $content_length = 2147483647;
02611 $chunked = false;
02612 $this->debug("want to read content to EOF");
02613 }
02614 $data = '';
02615 do {
02616 if ($chunked) {
02617 $tmp = fgets($this->fp, 256);
02618 $tmplen = strlen($tmp);
02619 $this->debug("read chunk line of $tmplen bytes");
02620 if ($tmplen == 0) {
02621 $this->incoming_payload = $data;
02622 $this->debug('socket read of chunk length timed out after length ' . strlen($data));
02623 $this->debug("read before timeout:\n" . $data);
02624 $this->setError('socket read of chunk length timed out');
02625 return false;
02626 }
02627 $content_length = hexdec(trim($tmp));
02628 $this->debug("chunk length $content_length");
02629 }
02630 $strlen = 0;
02631 while (($strlen < $content_length) && (!feof($this->fp))) {
02632 $readlen = min(8192, $content_length - $strlen);
02633 $tmp = fread($this->fp, $readlen);
02634 $tmplen = strlen($tmp);
02635 $this->debug("read buffer of $tmplen bytes");
02636 if (($tmplen == 0) && (!feof($this->fp))) {
02637 $this->incoming_payload = $data;
02638 $this->debug('socket read of body timed out after length ' . strlen($data));
02639 $this->debug("read before timeout:\n" . $data);
02640 $this->setError('socket read of body timed out');
02641 return false;
02642 }
02643 $strlen += $tmplen;
02644 $data .= $tmp;
02645 }
02646 if ($chunked && ($content_length > 0)) {
02647 $tmp = fgets($this->fp, 256);
02648 $tmplen = strlen($tmp);
02649 $this->debug("read chunk terminator of $tmplen bytes");
02650 if ($tmplen == 0) {
02651 $this->incoming_payload = $data;
02652 $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
02653 $this->debug("read before timeout:\n" . $data);
02654 $this->setError('socket read of chunk terminator timed out');
02655 return false;
02656 }
02657 }
02658 } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
02659 if (feof($this->fp)) {
02660 $this->debug('read to EOF');
02661 }
02662 $this->debug('read body of length ' . strlen($data));
02663 $this->incoming_payload .= $data;
02664 $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
02665
02666
02667 if(
02668 (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
02669 (! $this->persistentConnection) || feof($this->fp)){
02670 fclose($this->fp);
02671 $this->fp = false;
02672 $this->debug('closed socket');
02673 }
02674
02675
02676 if($this->incoming_payload == ''){
02677 $this->setError('no response from server');
02678 return false;
02679 }
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692 } else if ($this->scheme == 'https') {
02693
02694 $this->debug('send and receive with cURL');
02695 $this->incoming_payload = curl_exec($this->ch);
02696 $data = $this->incoming_payload;
02697
02698 $cErr = curl_error($this->ch);
02699 if ($cErr != '') {
02700 $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
02701
02702 foreach(curl_getinfo($this->ch) as $k => $v){
02703 $err .= "$k: $v<br>";
02704 }
02705 $this->debug($err);
02706 $this->setError($err);
02707 curl_close($this->ch);
02708 return false;
02709 } else {
02710
02711
02712
02713 }
02714
02715 $this->debug('No cURL error, closing cURL');
02716 curl_close($this->ch);
02717
02718
02719 while (ereg('^HTTP/1.1 100',$data)) {
02720 if ($pos = strpos($data,"\r\n\r\n")) {
02721 $data = ltrim(substr($data,$pos));
02722 } elseif($pos = strpos($data,"\n\n") ) {
02723 $data = ltrim(substr($data,$pos));
02724 }
02725 }
02726
02727
02728 if ($pos = strpos($data,"\r\n\r\n")) {
02729 $lb = "\r\n";
02730 } elseif( $pos = strpos($data,"\n\n")) {
02731 $lb = "\n";
02732 } else {
02733 $this->debug('no proper separation of headers and document');
02734 $this->setError('no proper separation of headers and document');
02735 return false;
02736 }
02737 $header_data = trim(substr($data,0,$pos));
02738 $header_array = explode($lb,$header_data);
02739 $data = ltrim(substr($data,$pos));
02740 $this->debug('found proper separation of headers and document');
02741 $this->debug('cleaned data, stringlen: '.strlen($data));
02742
02743 foreach ($header_array as $header_line) {
02744 $arr = explode(':',$header_line,2);
02745 if(count($arr) > 1){
02746 $header_name = strtolower(trim($arr[0]));
02747 $this->incoming_headers[$header_name] = trim($arr[1]);
02748 if ($header_name == 'set-cookie') {
02749
02750 $cookie = $this->parseCookie(trim($arr[1]));
02751 if ($cookie) {
02752 $this->incoming_cookies[] = $cookie;
02753 $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
02754 } else {
02755 $this->debug('did not find cookie in ' . trim($arr[1]));
02756 }
02757 }
02758 } else if (isset($header_name)) {
02759
02760 $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
02761 }
02762 }
02763 }
02764
02765 $arr = explode(' ', $header_array[0], 3);
02766 $http_version = $arr[0];
02767 $http_status = intval($arr[1]);
02768 $http_reason = count($arr) > 2 ? $arr[2] : '';
02769
02770
02771 if (isset($this->incoming_headers['location']) && $http_status == 301) {
02772 $this->debug("Got 301 $http_reason with Location: " . $this->incoming_headers['location']);
02773 $this->setURL($this->incoming_headers['location']);
02774 $this->tryagain = true;
02775 return false;
02776 }
02777
02778
02779 if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
02780 $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
02781 if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
02782 $this->debug('Server wants digest authentication');
02783
02784 $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
02785
02786
02787 $digestElements = explode(',', $digestString);
02788 foreach ($digestElements as $val) {
02789 $tempElement = explode('=', trim($val), 2);
02790 $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
02791 }
02792
02793
02794 if (isset($digestRequest['nonce'])) {
02795 $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
02796 $this->tryagain = true;
02797 return false;
02798 }
02799 }
02800 $this->debug('HTTP authentication failed');
02801 $this->setError('HTTP authentication failed');
02802 return false;
02803 }
02804
02805 if (
02806 ($http_status >= 300 && $http_status <= 307) ||
02807 ($http_status >= 400 && $http_status <= 417) ||
02808 ($http_status >= 501 && $http_status <= 505)
02809 ) {
02810 $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
02811 return false;
02812 }
02813
02814
02815 if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
02816 if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
02817
02818 if(function_exists('gzinflate')){
02819
02820
02821
02822 $this->debug('The gzinflate function exists');
02823 $datalen = strlen($data);
02824 if ($this->incoming_headers['content-encoding'] == 'deflate') {
02825 if ($degzdata = @gzinflate($data)) {
02826 $data = $degzdata;
02827 $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
02828 if (strlen($data) < $datalen) {
02829
02830 $this->debug('The inflated payload is smaller than the gzipped one; try again');
02831 if ($degzdata = @gzinflate($data)) {
02832 $data = $degzdata;
02833 $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
02834 }
02835 }
02836 } else {
02837 $this->debug('Error using gzinflate to inflate the payload');
02838 $this->setError('Error using gzinflate to inflate the payload');
02839 }
02840 } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
02841 if ($degzdata = @gzinflate(substr($data, 10))) {
02842 $data = $degzdata;
02843 $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
02844 if (strlen($data) < $datalen) {
02845
02846 $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
02847 if ($degzdata = @gzinflate(substr($data, 10))) {
02848 $data = $degzdata;
02849 $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
02850 }
02851 }
02852 } else {
02853 $this->debug('Error using gzinflate to un-gzip the payload');
02854 $this->setError('Error using gzinflate to un-gzip the payload');
02855 }
02856 }
02857
02858
02859
02860 $this->incoming_payload = $header_data.$lb.$lb.$data;
02861 } else {
02862 $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
02863 $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
02864 }
02865 } else {
02866 $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
02867 $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
02868 }
02869 } else {
02870 $this->debug('No Content-Encoding header');
02871 }
02872
02873 if(strlen($data) == 0){
02874 $this->debug('no data after headers!');
02875 $this->setError('no data present after HTTP headers');
02876 return false;
02877 }
02878
02879 return $data;
02880 }
02881
02882 function setContentType($type, $charset = false) {
02883 $this->outgoing_headers['Content-Type'] = $type . ($charset ? '; charset=' . $charset : '');
02884 $this->debug('set Content-Type: ' . $this->outgoing_headers['Content-Type']);
02885 }
02886
02887 function usePersistentConnection(){
02888 if (isset($this->outgoing_headers['Accept-Encoding'])) {
02889 return false;
02890 }
02891 $this->protocol_version = '1.1';
02892 $this->persistentConnection = true;
02893 $this->outgoing_headers['Connection'] = 'Keep-Alive';
02894 $this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
02895 return true;
02896 }
02897
02905
02906
02907
02908 function parseCookie($cookie_str) {
02909 $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
02910 $data = split(';', $cookie_str);
02911 $value_str = $data[0];
02912
02913 $cookie_param = 'domain=';
02914 $start = strpos($cookie_str, $cookie_param);
02915 if ($start > 0) {
02916 $domain = substr($cookie_str, $start + strlen($cookie_param));
02917 $domain = substr($domain, 0, strpos($domain, ';'));
02918 } else {
02919 $domain = '';
02920 }
02921
02922 $cookie_param = 'expires=';
02923 $start = strpos($cookie_str, $cookie_param);
02924 if ($start > 0) {
02925 $expires = substr($cookie_str, $start + strlen($cookie_param));
02926 $expires = substr($expires, 0, strpos($expires, ';'));
02927 } else {
02928 $expires = '';
02929 }
02930
02931 $cookie_param = 'path=';
02932 $start = strpos($cookie_str, $cookie_param);
02933 if ( $start > 0 ) {
02934 $path = substr($cookie_str, $start + strlen($cookie_param));
02935 $path = substr($path, 0, strpos($path, ';'));
02936 } else {
02937 $path = '/';
02938 }
02939
02940 $cookie_param = ';secure;';
02941 if (strpos($cookie_str, $cookie_param) !== FALSE) {
02942 $secure = true;
02943 } else {
02944 $secure = false;
02945 }
02946
02947 $sep_pos = strpos($value_str, '=');
02948
02949 if ($sep_pos) {
02950 $name = substr($value_str, 0, $sep_pos);
02951 $value = substr($value_str, $sep_pos + 1);
02952 $cookie= array( 'name' => $name,
02953 'value' => $value,
02954 'domain' => $domain,
02955 'path' => $path,
02956 'expires' => $expires,
02957 'secure' => $secure
02958 );
02959 return $cookie;
02960 }
02961 return false;
02962 }
02963
02972 function getCookiesForRequest($cookies, $secure=false) {
02973 $cookie_str = '';
02974 if ((! is_null($cookies)) && (is_array($cookies))) {
02975 foreach ($cookies as $cookie) {
02976 if (! is_array($cookie)) {
02977 continue;
02978 }
02979 $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
02980 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
02981 if (strtotime($cookie['expires']) <= time()) {
02982 $this->debug('cookie has expired');
02983 continue;
02984 }
02985 }
02986 if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
02987 $domain = preg_quote($cookie['domain']);
02988 if (! preg_match("'.*$domain$'i", $this->host)) {
02989 $this->debug('cookie has different domain');
02990 continue;
02991 }
02992 }
02993 if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
02994 $path = preg_quote($cookie['path']);
02995 if (! preg_match("'^$path.*'i", $this->path)) {
02996 $this->debug('cookie is for a different path');
02997 continue;
02998 }
02999 }
03000 if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
03001 $this->debug('cookie is secure, transport is not');
03002 continue;
03003 }
03004 $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
03005 $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
03006 }
03007 }
03008 return $cookie_str;
03009 }
03010 }
03011
03012
03013
03021 class wsdl extends nusoap_base {
03022
03023 var $wsdl;
03024
03025 var $schemas = array();
03026 var $currentSchema;
03027 var $message = array();
03028 var $complexTypes = array();
03029 var $messages = array();
03030 var $currentMessage;
03031 var $currentOperation;
03032 var $portTypes = array();
03033 var $currentPortType;
03034 var $bindings = array();
03035 var $currentBinding;
03036 var $ports = array();
03037 var $currentPort;
03038 var $opData = array();
03039 var $status = '';
03040 var $documentation = false;
03041 var $endpoint = '';
03042
03043 var $import = array();
03044
03045 var $parser;
03046 var $position = 0;
03047 var $depth = 0;
03048 var $depth_array = array();
03049
03050 var $proxyhost = '';
03051 var $proxyport = '';
03052 var $proxyusername = '';
03053 var $proxypassword = '';
03054 var $timeout = 0;
03055 var $response_timeout = 30;
03056
03069 function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30){
03070 parent::nusoap_base();
03071 $this->wsdl = $wsdl;
03072 $this->proxyhost = $proxyhost;
03073 $this->proxyport = $proxyport;
03074 $this->proxyusername = $proxyusername;
03075 $this->proxypassword = $proxypassword;
03076 $this->timeout = $timeout;
03077 $this->response_timeout = $response_timeout;
03078
03079
03080 if ($wsdl != "") {
03081 $this->debug('initial wsdl URL: ' . $wsdl);
03082 $this->parseWSDL($wsdl);
03083 }
03084
03085
03086 $imported_urls = array();
03087 $imported = 1;
03088 while ($imported > 0) {
03089 $imported = 0;
03090
03091 foreach ($this->schemas as $ns => $list) {
03092 foreach ($list as $xs) {
03093 $wsdlparts = parse_url($this->wsdl);
03094 foreach ($xs->imports as $ns2 => $list2) {
03095 for ($ii = 0; $ii < count($list2); $ii++) {
03096 if (! $list2[$ii]['loaded']) {
03097 $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
03098 $url = $list2[$ii]['location'];
03099 if ($url != '') {
03100 $urlparts = parse_url($url);
03101 if (!isset($urlparts['host'])) {
03102 $url = $wsdlparts['scheme'] . ':
03103 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
03104 }
03105 if (! in_array($url, $imported_urls)) {
03106 $this->parseWSDL($url);
03107 $imported++;
03108 $imported_urls[] = $url;
03109 }
03110 } else {
03111 $this->debug("Unexpected scenario: empty URL for unloaded import");
03112 }
03113 }
03114 }
03115 }
03116 }
03117 }
03118
03119 $wsdlparts = parse_url($this->wsdl);
03120 foreach ($this->import as $ns => $list) {
03121 for ($ii = 0; $ii < count($list); $ii++) {
03122 if (! $list[$ii]['loaded']) {
03123 $this->import[$ns][$ii]['loaded'] = true;
03124 $url = $list[$ii]['location'];
03125 if ($url != '') {
03126 $urlparts = parse_url($url);
03127 if (!isset($urlparts['host'])) {
03128 $url = $wsdlparts['scheme'] . ':
03129 substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
03130 }
03131 if (! in_array($url, $imported_urls)) {
03132 $this->parseWSDL($url);
03133 $imported++;
03134 $imported_urls[] = $url;
03135 }
03136 } else {
03137 $this->debug("Unexpected scenario: empty URL for unloaded import");
03138 }
03139 }
03140 }
03141 }
03142 }
03143
03144 foreach($this->bindings as $binding => $bindingData) {
03145 if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
03146 foreach($bindingData['operations'] as $operation => $data) {
03147 $this->debug('post-parse data gathering for ' . $operation);
03148 $this->bindings[$binding]['operations'][$operation]['input'] =
03149 isset($this->bindings[$binding]['operations'][$operation]['input']) ?
03150 array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
03151 $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
03152 $this->bindings[$binding]['operations'][$operation]['output'] =
03153 isset($this->bindings[$binding]['operations'][$operation]['output']) ?
03154 array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
03155 $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
03156 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
03157 $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
03158 }
03159 if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
03160 $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
03161 }
03162 if (isset($bindingData['style'])) {
03163 $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
03164 }
03165 $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
03166 $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
03167 $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
03168 }
03169 }
03170 }
03171 }
03172
03179 function parseWSDL($wsdl = '')
03180 {
03181 if ($wsdl == '') {
03182 $this->debug('no wsdl passed to parseWSDL()!!');
03183 $this->setError('no wsdl passed to parseWSDL()!!');
03184 return false;
03185 }
03186
03187
03188 $wsdl_props = parse_url($wsdl);
03189
03190 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
03191 $this->debug('getting WSDL http(s) URL ' . $wsdl);
03192
03193 $tr = new soap_transport_http($wsdl);
03194 $tr->request_method = 'GET';
03195 $tr->useSOAPAction = false;
03196 if($this->proxyhost && $this->proxyport){
03197 $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
03198 }
03199 $tr->setEncoding('gzip, deflate');
03200 $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
03201
03202
03203 $this->appendDebug($tr->getDebug());
03204
03205 if($err = $tr->getError() ){
03206 $errstr = 'HTTP ERROR: '.$err;
03207 $this->debug($errstr);
03208 $this->setError($errstr);
03209 unset($tr);
03210 return false;
03211 }
03212 unset($tr);
03213 $this->debug("got WSDL URL");
03214 } else {
03215
03216 if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
03217 $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
03218 } else {
03219 $path = $wsdl;
03220 }
03221 $this->debug('getting WSDL file ' . $path);
03222 if ($fp = @fopen($path, 'r')) {
03223 $wsdl_string = '';
03224 while ($data = fread($fp, 32768)) {
03225 $wsdl_string .= $data;
03226 }
03227 fclose($fp);
03228 } else {
03229 $errstr = "Bad path to WSDL file $path";
03230 $this->debug($errstr);
03231 $this->setError($errstr);
03232 return false;
03233 }
03234 }
03235 $this->debug('Parse WSDL');
03236
03237
03238 $this->parser = xml_parser_create();
03239
03240
03241 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
03242
03243 xml_set_object($this->parser, $this);
03244
03245 xml_set_element_handler($this->parser, 'start_element', 'end_element');
03246 xml_set_character_data_handler($this->parser, 'character_data');
03247
03248 if (!xml_parse($this->parser, $wsdl_string, true)) {
03249
03250 $errstr = sprintf(
03251 'XML error parsing WSDL from %s on line %d: %s',
03252 $wsdl,
03253 xml_get_current_line_number($this->parser),
03254 xml_error_string(xml_get_error_code($this->parser))
03255 );
03256 $this->debug($errstr);
03257 $this->debug("XML payload:\n" . $wsdl_string);
03258 $this->setError($errstr);
03259 return false;
03260 }
03261
03262 xml_parser_free($this->parser);
03263 $this->debug('Parsing WSDL done');
03264
03265 if($this->getError()){
03266 return false;
03267 }
03268 return true;
03269 }
03270
03279 function start_element($parser, $name, $attrs)
03280 {
03281 if ($this->status == 'schema') {
03282 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
03283 $this->appendDebug($this->currentSchema->getDebug());
03284 $this->currentSchema->clearDebug();
03285 } elseif (ereg('schema$', $name)) {
03286 $this->debug('Parsing WSDL schema');
03287
03288 $this->status = 'schema';
03289 $this->currentSchema = new xmlschema('', '', $this->namespaces);
03290 $this->currentSchema->schemaStartElement($parser, $name, $attrs);
03291 $this->appendDebug($this->currentSchema->getDebug());
03292 $this->currentSchema->clearDebug();
03293 } else {
03294
03295 $pos = $this->position++;
03296 $depth = $this->depth++;
03297
03298 $this->depth_array[$depth] = $pos;
03299 $this->message[$pos] = array('cdata' => '');
03300
03301 if (count($attrs) > 0) {
03302
03303 foreach($attrs as $k => $v) {
03304 if (ereg("^xmlns", $k)) {
03305 if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
03306 $this->namespaces[$ns_prefix] = $v;
03307 } else {
03308 $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
03309 }
03310 if ($v == 'http:
03311 $this->XMLSchemaVersion = $v;
03312 $this->namespaces['xsi'] = $v . '-instance';
03313 }
03314 }
03315 }
03316
03317 foreach($attrs as $k => $v) {
03318 $k = strpos($k, ':') ? $this->expandQname($k) : $k;
03319 if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
03320 $v = strpos($v, ':') ? $this->expandQname($v) : $v;
03321 }
03322 $eAttrs[$k] = $v;
03323 }
03324 $attrs = $eAttrs;
03325 } else {
03326 $attrs = array();
03327 }
03328
03329 if (ereg(':', $name)) {
03330
03331 $prefix = substr($name, 0, strpos($name, ':'));
03332
03333 $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
03334
03335 $name = substr(strstr($name, ':'), 1);
03336 }
03337
03338
03339 switch ($this->status) {
03340 case 'message':
03341 if ($name == 'part') {
03342 if (isset($attrs['type'])) {
03343 $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
03344 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
03345 }
03346 if (isset($attrs['element'])) {
03347 $this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
03348 $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'];
03349 }
03350 }
03351 break;
03352 case 'portType':
03353 switch ($name) {
03354 case 'operation':
03355 $this->currentPortOperation = $attrs['name'];
03356 $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
03357 if (isset($attrs['parameterOrder'])) {
03358 $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
03359 }
03360 break;
03361 case 'documentation':
03362 $this->documentation = true;
03363 break;
03364
03365 default:
03366 $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
03367 $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
03368 break;
03369 }
03370 break;
03371 case 'binding':
03372 switch ($name) {
03373 case 'binding':
03374
03375 if (isset($attrs['style'])) {
03376 $this->bindings[$this->currentBinding]['prefix'] = $prefix;
03377 }
03378 $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
03379 break;
03380 case 'header':
03381 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
03382 break;
03383 case 'operation':
03384 if (isset($attrs['soapAction'])) {
03385 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
03386 }
03387 if (isset($attrs['style'])) {
03388 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
03389 }
03390 if (isset($attrs['name'])) {
03391 $this->currentOperation = $attrs['name'];
03392 $this->debug("current binding operation: $this->currentOperation");
03393 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
03394 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
03395 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
03396 }
03397 break;
03398 case 'input':
03399 $this->opStatus = 'input';
03400 break;
03401 case 'output':
03402 $this->opStatus = 'output';
03403 break;
03404 case 'body':
03405 if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
03406 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
03407 } else {
03408 $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
03409 }
03410 break;
03411 }
03412 break;
03413 case 'service':
03414 switch ($name) {
03415 case 'port':
03416 $this->currentPort = $attrs['name'];
03417 $this->debug('current port: ' . $this->currentPort);
03418 $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
03419
03420 break;
03421 case 'address':
03422 $this->ports[$this->currentPort]['location'] = $attrs['location'];
03423 $this->ports[$this->currentPort]['bindingType'] = $namespace;
03424 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
03425 $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
03426 break;
03427 }
03428 break;
03429 }
03430
03431 switch ($name) {
03432 case 'import':
03433 if (isset($attrs['location'])) {
03434 $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
03435 $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
03436 } else {
03437 $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
03438 if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
03439 $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
03440 }
03441 $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
03442 }
03443 break;
03444
03445
03446
03447
03448 case 'message':
03449 $this->status = 'message';
03450 $this->messages[$attrs['name']] = array();
03451 $this->currentMessage = $attrs['name'];
03452 break;
03453 case 'portType':
03454 $this->status = 'portType';
03455 $this->portTypes[$attrs['name']] = array();
03456 $this->currentPortType = $attrs['name'];
03457 break;
03458 case "binding":
03459 if (isset($attrs['name'])) {
03460
03461 if (strpos($attrs['name'], ':')) {
03462 $this->currentBinding = $this->getLocalPart($attrs['name']);
03463 } else {
03464 $this->currentBinding = $attrs['name'];
03465 }
03466 $this->status = 'binding';
03467 $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
03468 $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
03469 }
03470 break;
03471 case 'service':
03472 $this->serviceName = $attrs['name'];
03473 $this->status = 'service';
03474 $this->debug('current service: ' . $this->serviceName);
03475 break;
03476 case 'definitions':
03477 foreach ($attrs as $name => $value) {
03478 $this->wsdl_info[$name] = $value;
03479 }
03480 break;
03481 }
03482 }
03483 }
03484
03492 function end_element($parser, $name){
03493
03494 if ( ereg('schema$', $name)) {
03495 $this->status = "";
03496 $this->appendDebug($this->currentSchema->getDebug());
03497 $this->currentSchema->clearDebug();
03498 $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
03499 $this->debug('Parsing WSDL schema done');
03500 }
03501 if ($this->status == 'schema') {
03502 $this->currentSchema->schemaEndElement($parser, $name);
03503 } else {
03504
03505 $this->depth--;
03506 }
03507
03508 if ($this->documentation) {
03509
03510
03511 $this->documentation = false;
03512 }
03513 }
03514
03522 function character_data($parser, $data)
03523 {
03524 $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
03525 if (isset($this->message[$pos]['cdata'])) {
03526 $this->message[$pos]['cdata'] .= $data;
03527 }
03528 if ($this->documentation) {
03529 $this->documentation .= $data;
03530 }
03531 }
03532
03533 function getBindingData($binding)
03534 {
03535 if (is_array($this->bindings[$binding])) {
03536 return $this->bindings[$binding];
03537 }
03538 }
03539
03547 function getOperations($bindingType = 'soap')
03548 {
03549 $ops = array();
03550 if ($bindingType == 'soap') {
03551 $bindingType = 'http:
03552 }
03553
03554 foreach($this->ports as $port => $portData) {
03555
03556 if ($portData['bindingType'] == $bindingType) {
03557
03558
03559
03560
03561 if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
03562 $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
03563 }
03564 }
03565 }
03566 return $ops;
03567 }
03568
03577 function getOperationData($operation, $bindingType = 'soap')
03578 {
03579 if ($bindingType == 'soap') {
03580 $bindingType = 'http:
03581 }
03582
03583 foreach($this->ports as $port => $portData) {
03584
03585 if ($portData['bindingType'] == $bindingType) {
03586
03587
03588 foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
03589
03590 if ($operation == $bOperation) {
03591 $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
03592 return $opData;
03593 }
03594 }
03595 }
03596 }
03597 }
03598
03607 function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
03608 if ($bindingType == 'soap') {
03609 $bindingType = 'http:
03610 }
03611
03612 foreach($this->ports as $port => $portData) {
03613
03614 if ($portData['bindingType'] == $bindingType) {
03615
03616 foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
03617 if ($opData['soapAction'] == $soapAction) {
03618 return $opData;
03619 }
03620 }
03621 }
03622 }
03623 }
03624
03643 function getTypeDef($type, $ns) {
03644 $this->debug("in getTypeDef: type=$type, ns=$ns");
03645 if ((! $ns) && isset($this->namespaces['tns'])) {
03646 $ns = $this->namespaces['tns'];
03647 $this->debug("in getTypeDef: type namespace forced to $ns");
03648 }
03649 if (isset($this->schemas[$ns])) {
03650 $this->debug("in getTypeDef: have schema for namespace $ns");
03651 for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
03652 $xs = &$this->schemas[$ns][$i];
03653 $t = $xs->getTypeDef($type);
03654 $this->appendDebug($xs->getDebug());
03655 $xs->clearDebug();
03656 if ($t) {
03657 if (!isset($t['phpType'])) {
03658
03659 $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
03660 $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
03661 $etype = $this->getTypeDef($uqType, $ns);
03662 if ($etype) {
03663 $this->debug("found type for [element] $type:");
03664 $this->debug($this->varDump($etype));
03665 if (isset($etype['phpType'])) {
03666 $t['phpType'] = $etype['phpType'];
03667 }
03668 if (isset($etype['elements'])) {
03669 $t['elements'] = $etype['elements'];
03670 }
03671 if (isset($etype['attrs'])) {
03672 $t['attrs'] = $etype['attrs'];
03673 }
03674 }
03675 }
03676 return $t;
03677 }
03678 }
03679 } else {
03680 $this->debug("in getTypeDef: do not have schema for namespace $ns");
03681 }
03682 return false;
03683 }
03684
03690 function webDescription(){
03691 global $HTTP_SERVER_VARS;
03692
03693 if (isset($_SERVER)) {
03694 $PHP_SELF = $_SERVER['PHP_SELF'];
03695 } elseif (isset($HTTP_SERVER_VARS)) {
03696 $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
03697 } else {
03698 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
03699 }
03700
03701 $b = '
03702 <html><head><title>NuSOAP: '.$this->serviceName.'</title>
03703 <style type="text/css">
03704 body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
03705 p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
03706 pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
03707 ul { margin-top: 10px; margin-left: 20px; }
03708 li { list-style-type: none; margin-top: 10px; color: #000000; }
03709 .content{
03710 margin-left: 0px; padding-bottom: 2em; }
03711 .nav {
03712 padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
03713 margin-top: 10px; margin-left: 0px; color: #000000;
03714 background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
03715 .title {
03716 font-family: arial; font-size: 26px; color: #ffffff;
03717 background-color: #999999; width: 105%; margin-left: 0px;
03718 padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
03719 .hidden {
03720 position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
03721 font-family: arial; overflow: hidden; width: 600;
03722 padding: 20px; font-size: 10px; background-color: #999999;
03723 layer-background-color:#FFFFFF; }
03724 a,a:active { color: charcoal; font-weight: bold; }
03725 a:visited { color: #666666; font-weight: bold; }
03726 a:hover { color: cc3300; font-weight: bold; }
03727 </style>
03728 <script language="JavaScript" type="text/javascript">
03729 <!--
03730
03731 function lib_bwcheck(){
03732 this.ver=navigator.appVersion
03733 this.agent=navigator.userAgent
03734 this.dom=document.getElementById?1:0
03735 this.opera5=this.agent.indexOf("Opera 5")>-1
03736 this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
03737 this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
03738 this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
03739 this.ie=this.ie4||this.ie5||this.ie6
03740 this.mac=this.agent.indexOf("Mac")>-1
03741 this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
03742 this.ns4=(document.layers && !this.dom)?1:0;
03743 this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
03744 return this
03745 }
03746 var bw = new lib_bwcheck()
03747
03748 function makeObj(obj){
03749 this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
03750 if(!this.evnt) return false
03751 this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
03752 this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
03753 this.writeIt=b_writeIt;
03754 return this
03755 }
03756
03757
03758 function b_writeIt(text){
03759 if (bw.ns4){this.wref.write(text);this.wref.close()}
03760 else this.wref.innerHTML = text
03761 }
03762
03763 var oDesc;
03764 function popup(divid){
03765 if(oDesc = new makeObj(divid)){
03766 oDesc.css.visibility = "visible"
03767 }
03768 }
03769 function popout(){
03770 if(oDesc) oDesc.css.visibility = "hidden"
03771 }
03772
03773 </script>
03774 </head>
03775 <body>
03776 <div class=content>
03777 <br><br>
03778 <div class=title>'.$this->serviceName.'</div>
03779 <div class=nav>
03780 <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
03781 Click on an operation name to view it's details.</p>
03782 <ul>';
03783 foreach($this->getOperations() as $op => $data){
03784 $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
03785
03786 $b .= "<div id='$op' class='hidden'>
03787 <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
03788 foreach($data as $donnie => $marie){
03789 if($donnie == 'input' || $donnie == 'output'){
03790 $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
03791 foreach($marie as $captain => $tenille){
03792 if($captain == 'parts'){
03793 $b .= " $captain:<br>";
03794
03795 foreach($tenille as $joanie => $chachi){
03796 $b .= " $joanie: $chachi<br>";
03797 }
03798
03799 } else {
03800 $b .= " $captain: $tenille<br>";
03801 }
03802 }
03803 } else {
03804 $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
03805 }
03806 }
03807 $b .= '</div>';
03808 }
03809 $b .= '
03810 <ul>
03811 </div>
03812 </div></body></html>';
03813 return $b;
03814 }
03815
03823 function serialize($debug = 0)
03824 {
03825 $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
03826 $xml .= "\n<definitions";
03827 foreach($this->namespaces as $k => $v) {
03828 $xml .= " xmlns:$k=\"$v\"";
03829 }
03830
03831 if (isset($this->namespaces['wsdl'])) {
03832 $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
03833 }
03834 if (isset($this->namespaces['tns'])) {
03835 $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
03836 }
03837 $xml .= '>';
03838
03839 if (sizeof($this->import) > 0) {
03840 foreach($this->import as $ns => $list) {
03841 foreach ($list as $ii) {
03842 if ($ii['location'] != '') {
03843 $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
03844 } else {
03845 $xml .= '<import namespace="' . $ns . '" />';
03846 }
03847 }
03848 }
03849 }
03850
03851 if (count($this->schemas)>=1) {
03852 $xml .= "\n<types>";
03853 foreach ($this->schemas as $ns => $list) {
03854 foreach ($list as $xs) {
03855 $xml .= $xs->serializeSchema();
03856 }
03857 }
03858 $xml .= '</types>';
03859 }
03860
03861 if (count($this->messages) >= 1) {
03862 foreach($this->messages as $msgName => $msgParts) {
03863 $xml .= "\n<message name=\"" . $msgName . '">';
03864 if(is_array($msgParts)){
03865 foreach($msgParts as $partName => $partType) {
03866 // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
03867 if (strpos($partType, ':')) {
03868 $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
03869 } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
03870 // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
03871 $typePrefix = 'xsd';
03872 } else {
03873 foreach($this->typemap as $ns => $types) {
03874 if (isset($types[$partType])) {
03875 $typePrefix = $this->getPrefixFromNamespace($ns);
03876 }
03877 }
03878 if (!isset($typePrefix)) {
03879 die("$partType has no namespace!");
03880 }
03881 }
03882 $ns = $this->getNamespaceFromPrefix($typePrefix);
03883 $typeDef = $this->getTypeDef($this->getLocalPart($partType), $ns);
03884 if ($typeDef['typeClass'] == 'element') {
03885 $elementortype = 'element';
03886 } else {
03887 $elementortype = 'type';
03888 }
03889 $xml .= '<part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />';
03890 }
03891 }
03892 $xml .= '</message>';
03893 }
03894 }
03895 // bindings & porttypes
03896 if (count($this->bindings) >= 1) {
03897 $binding_xml = '';
03898 $portType_xml = '';
03899 foreach($this->bindings as $bindingName => $attrs) {
03900 $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
03901 $binding_xml .= '<soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
03902 $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
03903 foreach($attrs['operations'] as $opName => $opParts) {
03904 $binding_xml .= '<operation name="' . $opName . '">';
03905 $binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
03906 if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
03907 $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
03908 } else {
03909 $enc_style = '';
03910 }
03911 $binding_xml .= '<input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
03912 if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
03913 $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
03914 } else {
03915 $enc_style = '';
03916 }
03917 $binding_xml .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
03918 $binding_xml .= '</operation>';
03919 $portType_xml .= '<operation name="' . $opParts['name'] . '"';
03920 if (isset($opParts['parameterOrder'])) {
03921 $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
03922 }
03923 $portType_xml .= '>';
03924 if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
03925 $portType_xml .= '<documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
03926 }
03927 $portType_xml .= '<input message="tns:' . $opParts['input']['message'] . '"/>';
03928 $portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>';
03929 $portType_xml .= '</operation>';
03930 }
03931 $portType_xml .= '</portType>';
03932 $binding_xml .= '</binding>';
03933 }
03934 $xml .= $portType_xml . $binding_xml;
03935 }
03936
03937 $xml .= "\n<service name=\"" . $this->serviceName . '">';
03938 if (count($this->ports) >= 1) {
03939 foreach($this->ports as $pName => $attrs) {
03940 $xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
03941 $xml .= '<soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
03942 $xml .= '</port>';
03943 }
03944 }
03945 $xml .= '</service>';
03946 return $xml . "\n</definitions>";
03947 }
03948
03962 function serializeRPCParameters($operation, $direction, $parameters)
03963 {
03964 $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
03965 $this->appendDebug('parameters=' . $this->varDump($parameters));
03966
03967 if ($direction != 'input' && $direction != 'output') {
03968 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
03969 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
03970 return false;
03971 }
03972 if (!$opData = $this->getOperationData($operation)) {
03973 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
03974 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
03975 return false;
03976 }
03977 $this->debug('opData:');
03978 $this->appendDebug($this->varDump($opData));
03979
03980 // Get encoding style for output and set to current
03981 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
03982 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
03983 $encodingStyle = $opData['output']['encodingStyle'];
03984 $enc_style = $encodingStyle;
03985 }
03986
03987 // set input params
03988 $xml = '';
03989 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
03990
03991 $use = $opData[$direction]['use'];
03992 $this->debug('have ' . count($opData[$direction]['parts']) . ' part(s) to serialize');
03993 if (is_array($parameters)) {
03994 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
03995 $this->debug('have ' . count($parameters) . ' parameter(s) provided as ' . $parametersArrayType . ' to serialize');
03996 foreach($opData[$direction]['parts'] as $name => $type) {
03997 $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
03998
03999 if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
04000 $encodingStyle = $opData[$direction]['encodingStyle'];
04001 $enc_style = $encodingStyle;
04002 } else {
04003 $enc_style = false;
04004 }
04005
04006
04007 if ($parametersArrayType == 'arraySimple') {
04008 $p = array_shift($parameters);
04009 $this->debug('calling serializeType w/indexed param');
04010 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
04011 } elseif (isset($parameters[$name])) {
04012 $this->debug('calling serializeType w/named param');
04013 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
04014 } else {
04015
04016 $this->debug('calling serializeType w/null param');
04017 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
04018 }
04019 }
04020 } else {
04021 $this->debug('no parameters passed.');
04022 }
04023 }
04024 $this->debug("serializeRPCParameters returning: $xml");
04025 return $xml;
04026 }
04027
04041 function serializeParameters($operation, $direction, $parameters)
04042 {
04043 $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
04044 $this->appendDebug('parameters=' . $this->varDump($parameters));
04045
04046 if ($direction != 'input' && $direction != 'output') {
04047 $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
04048 $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
04049 return false;
04050 }
04051 if (!$opData = $this->getOperationData($operation)) {
04052 $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
04053 $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
04054 return false;
04055 }
04056 $this->debug('opData:');
04057 $this->appendDebug($this->varDump($opData));
04058
04059
04060 $encodingStyle = 'http:
04061 if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
04062 $encodingStyle = $opData['output']['encodingStyle'];
04063 $enc_style = $encodingStyle;
04064 }
04065
04066
04067 $xml = '';
04068 if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
04069
04070 $use = $opData[$direction]['use'];
04071 $this->debug("use=$use");
04072 $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
04073 if (is_array($parameters)) {
04074 $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
04075 $this->debug('have ' . $parametersArrayType . ' parameters');
04076 foreach($opData[$direction]['parts'] as $name => $type) {
04077 $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
04078
04079 if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
04080 $encodingStyle = $opData[$direction]['encodingStyle'];
04081 $enc_style = $encodingStyle;
04082 } else {
04083 $enc_style = false;
04084 }
04085
04086
04087 if ($parametersArrayType == 'arraySimple') {
04088 $p = array_shift($parameters);
04089 $this->debug('calling serializeType w/indexed param');
04090 $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
04091 } elseif (isset($parameters[$name])) {
04092 $this->debug('calling serializeType w/named param');
04093 $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
04094 } else {
04095
04096 $this->debug('calling serializeType w/null param');
04097 $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
04098 }
04099 }
04100 } else {
04101 $this->debug('no parameters passed.');
04102 }
04103 }
04104 $this->debug("serializeParameters returning: $xml");
04105 return $xml;
04106 }
04107
04120 function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
04121 {
04122 $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
04123 $this->appendDebug("value=" . $this->varDump($value));
04124 if($use == 'encoded' && $encodingStyle) {
04125 $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
04126 }
04127
04128
04129 if (is_object($value) && get_class($value) == 'soapval') {
04130 if ($value->type_ns) {
04131 $type = $value->type_ns . ':' . $value->type;
04132 $forceType = true;
04133 $this->debug("in serializeType: soapval overrides type to $type");
04134 } elseif ($value->type) {
04135 $type = $value->type;
04136 $forceType = true;
04137 $this->debug("in serializeType: soapval overrides type to $type");
04138 } else {
04139 $forceType = false;
04140 $this->debug("in serializeType: soapval does not override type");
04141 }
04142 $attrs = $value->attributes;
04143 $value = $value->value;
04144 $this->debug("in serializeType: soapval overrides value to $value");
04145 if ($attrs) {
04146 if (!is_array($value)) {
04147 $value['!'] = $value;
04148 }
04149 foreach ($attrs as $n => $v) {
04150 $value['!' . $n] = $v;
04151 }
04152 $this->debug("in serializeType: soapval provides attributes");
04153 }
04154 } else {
04155 $forceType = false;
04156 }
04157
04158 $xml = '';
04159 if (strpos($type, ':')) {
04160 $uqType = substr($type, strrpos($type, ':') + 1);
04161 $ns = substr($type, 0, strrpos($type, ':'));
04162 $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
04163 if ($this->getNamespaceFromPrefix($ns)) {
04164 $ns = $this->getNamespaceFromPrefix($ns);
04165 $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
04166 }
04167
04168 if($ns == $this->XMLSchemaVersion || $ns == 'http:
04169 $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
04170 if ($unqualified && $use == 'literal') {
04171 $elementNS = " xmlns=\"\"";
04172 } else {
04173 $elementNS = '';
04174 }
04175 if (is_null($value)) {
04176 if ($use == 'literal') {
04177
04178 $xml = "<$name$elementNS/>";
04179 } else {
04180
04181 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
04182 }
04183 $this->debug("in serializeType: returning: $xml");
04184 return $xml;
04185 }
04186 if ($uqType == 'boolean') {
04187 if ((is_string($value) && $value == 'false') || (! $value)) {
04188 $value = 'false';
04189 } else {
04190 $value = 'true';
04191 }
04192 }
04193 if ($uqType == 'string' && gettype($value) == 'string') {
04194 $value = $this->expandEntities($value);
04195 }
04196 if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
04197 $value = sprintf("%.0lf", $value);
04198 }
04199
04200
04201
04202 if (!$this->getTypeDef($uqType, $ns)) {
04203 if ($use == 'literal') {
04204 if ($forceType) {
04205 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
04206 } else {
04207 $xml = "<$name$elementNS>$value</$name>";
04208 }
04209 } else {
04210 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
04211 }
04212 $this->debug("in serializeType: returning: $xml");
04213 return $xml;
04214 }
04215 $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
04216 } else if ($ns == 'http:
04217 $this->debug('in serializeType: appears to be Apache SOAP type');
04218 if ($uqType == 'Map') {
04219 $tt_prefix = $this->getPrefixFromNamespace('http:
04220 if (! $tt_prefix) {
04221 $this->debug('in serializeType: Add namespace for Apache SOAP type');
04222 $tt_prefix = 'ns' . rand(1000, 9999);
04223 $this->namespaces[$tt_prefix] = 'http:
04224
04225 $tt_prefix = $this->getPrefixFromNamespace('http:
04226 }
04227 $contents = '';
04228 foreach($value as $k => $v) {
04229 $this->debug("serializing map element: key $k, value $v");
04230 $contents .= '<item>';
04231 $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
04232 $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
04233 $contents .= '</item>';
04234 }
04235 if ($use == 'literal') {
04236 if ($forceType) {
04237 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
04238 } else {
04239 $xml = "<$name>$contents</$name>";
04240 }
04241 } else {
04242 $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
04243 }
04244 $this->debug("in serializeType: returning: $xml");
04245 return $xml;
04246 }
04247 $this->debug('in serializeType: Apache SOAP type, but only support Map');
04248 }
04249 } else {
04250
04251
04252 $this->debug("in serializeType: No namespace for type $type");
04253 $ns = '';
04254 $uqType = $type;
04255 }
04256 if(!$typeDef = $this->getTypeDef($uqType, $ns)){
04257 $this->setError("$type ($uqType) is not a supported type.");
04258 $this->debug("in serializeType: $type ($uqType) is not a supported type.");
04259 return false;
04260 } else {
04261 $this->debug("in serializeType: found typeDef");
04262 $this->appendDebug('typeDef=' . $this->varDump($typeDef));
04263 }
04264 $phpType = $typeDef['phpType'];
04265 $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
04266
04267 if ($phpType == 'struct') {
04268 if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
04269 $elementName = $uqType;
04270 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
04271 $elementNS = " xmlns=\"$ns\"";
04272 } else {
04273 $elementNS = " xmlns=\"\"";
04274 }
04275 } else {
04276 $elementName = $name;
04277 if ($unqualified) {
04278 $elementNS = " xmlns=\"\"";
04279 } else {
04280 $elementNS = '';
04281 }
04282 }
04283 if (is_null($value)) {
04284 if ($use == 'literal') {
04285
04286 $xml = "<$elementName$elementNS/>";
04287 } else {
04288 $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
04289 }
04290 $this->debug("in serializeType: returning: $xml");
04291 return $xml;
04292 }
04293 if (is_object($value)) {
04294 $value = get_object_vars($value);
04295 }
04296 if (is_array($value)) {
04297 $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
04298 if ($use == 'literal') {
04299 if ($forceType) {
04300 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
04301 } else {
04302 $xml = "<$elementName$elementNS$elementAttrs>";
04303 }
04304 } else {
04305 $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
04306 }
04307
04308 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
04309 $xml .= "</$elementName>";
04310 } else {
04311 $this->debug("in serializeType: phpType is struct, but value is not an array");
04312 $this->setError("phpType is struct, but value is not an array: see debug output for details");
04313 $xml = '';
04314 }
04315 } elseif ($phpType == 'array') {
04316 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
04317 $elementNS = " xmlns=\"$ns\"";
04318 } else {
04319 if ($unqualified) {
04320 $elementNS = " xmlns=\"\"";
04321 } else {
04322 $elementNS = '';
04323 }
04324 }
04325 if (is_null($value)) {
04326 if ($use == 'literal') {
04327
04328 $xml = "<$name$elementNS/>";
04329 } else {
04330 $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
04331 $this->getPrefixFromNamespace('http:
04332 ":Array\" " .
04333 $this->getPrefixFromNamespace('http:
04334 ':arrayType="' .
04335 $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
04336 ':' .
04337 $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
04338 }
04339 $this->debug("in serializeType: returning: $xml");
04340 return $xml;
04341 }
04342 if (isset($typeDef['multidimensional'])) {
04343 $nv = array();
04344 foreach($value as $v) {
04345 $cols = ',' . sizeof($v);
04346 $nv = array_merge($nv, $v);
04347 }
04348 $value = $nv;
04349 } else {
04350 $cols = '';
04351 }
04352 if (is_array($value) && sizeof($value) >= 1) {
04353 $rows = sizeof($value);
04354 $contents = '';
04355 foreach($value as $k => $v) {
04356 $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
04357
04358 if (!in_array($typeDef['arrayType'],$this->typemap['http:
04359 $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
04360 } else {
04361 $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
04362 }
04363 }
04364 } else {
04365 $rows = 0;
04366 $contents = null;
04367 }
04368
04369
04370 if ($use == 'literal') {
04371 $xml = "<$name$elementNS>"
04372 .$contents
04373 ."</$name>";
04374 } else {
04375 $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http:
04376 $this->getPrefixFromNamespace('http:
04377 .':arrayType="'
04378 .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
04379 .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
04380 .$contents
04381 ."</$name>";
04382 }
04383 } elseif ($phpType == 'scalar') {
04384 if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
04385 $elementNS = " xmlns=\"$ns\"";
04386 } else {
04387 if ($unqualified) {
04388 $elementNS = " xmlns=\"\"";
04389 } else {
04390 $elementNS = '';
04391 }
04392 }
04393 if ($use == 'literal') {
04394 if ($forceType) {
04395 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
04396 } else {
04397 $xml = "<$name$elementNS>$value</$name>";
04398 }
04399 } else {
04400 $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
04401 }
04402 }
04403 $this->debug("in serializeType: returning: $xml");
04404 return $xml;
04405 }
04406
04417 function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
04418 $xml = '';
04419 if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
04420 $this->debug("serialize attributes for XML Schema type $ns:$uqType");
04421 if (is_array($value)) {
04422 $xvalue = $value;
04423 } elseif (is_object($value)) {
04424 $xvalue = get_object_vars($value);
04425 } else {
04426 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
04427 $xvalue = array();
04428 }
04429 foreach ($typeDef['attrs'] as $aName => $attrs) {
04430 if (isset($xvalue['!' . $aName])) {
04431 $xname = '!' . $aName;
04432 $this->debug("value provided for attribute $aName with key $xname");
04433 } elseif (isset($xvalue[$aName])) {
04434 $xname = $aName;
04435 $this->debug("value provided for attribute $aName with key $xname");
04436 } elseif (isset($attrs['default'])) {
04437 $xname = '!' . $aName;
04438 $xvalue[$xname] = $attrs['default'];
04439 $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
04440 } else {
04441 $xname = '';
04442 $this->debug("no value provided for attribute $aName");
04443 }
04444 if ($xname) {
04445 $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
04446 }
04447 }
04448 } else {
04449 $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
04450 }
04451 if (isset($typeDef['extensionBase'])) {
04452 $ns = $this->getPrefix($typeDef['extensionBase']);
04453 $uqType = $this->getLocalPart($typeDef['extensionBase']);
04454 if ($this->getNamespaceFromPrefix($ns)) {
04455 $ns = $this->getNamespaceFromPrefix($ns);
04456 }
04457 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
04458 $this->debug("serialize attributes for extension base $ns:$uqType");
04459 $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
04460 } else {
04461 $this->debug("extension base $ns:$uqType is not a supported type");
04462 }
04463 }
04464 return $xml;
04465 }
04466
04479 function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
04480 $xml = '';
04481 if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
04482 $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
04483 if (is_array($value)) {
04484 $xvalue = $value;
04485 } elseif (is_object($value)) {
04486 $xvalue = get_object_vars($value);
04487 } else {
04488 $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
04489 $xvalue = array();
04490 }
04491
04492 if (count($typeDef['elements']) != count($xvalue)){
04493 $optionals = true;
04494 }
04495 foreach ($typeDef['elements'] as $eName => $attrs) {
04496 if (!isset($xvalue[$eName])) {
04497 if (isset($attrs['default'])) {
04498 $xvalue[$eName] = $attrs['default'];
04499 $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
04500 }
04501 }
04502
04503 if (isset($optionals)
04504 && (!isset($xvalue[$eName]))
04505 && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
04506 ){
04507 if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
04508 $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
04509 }
04510
04511 $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
04512 } else {
04513
04514 if (isset($xvalue[$eName])) {
04515 $v = $xvalue[$eName];
04516 } else {
04517 $v = null;
04518 }
04519 if (isset($attrs['form'])) {
04520 $unqualified = ($attrs['form'] == 'unqualified');
04521 } else {
04522 $unqualified = false;
04523 }
04524 if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
04525 $vv = $v;
04526 foreach ($vv as $k => $v) {
04527 if (isset($attrs['type']) || isset($attrs['ref'])) {
04528
04529 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
04530 } else {
04531
04532 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
04533 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
04534 }
04535 }
04536 } else {
04537 if (isset($attrs['type']) || isset($attrs['ref'])) {
04538
04539 $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
04540 } else {
04541
04542 $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
04543 $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
04544 }
04545 }
04546 }
04547 }
04548 } else {
04549 $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
04550 }
04551 if (isset($typeDef['extensionBase'])) {
04552 $ns = $this->getPrefix($typeDef['extensionBase']);
04553 $uqType = $this->getLocalPart($typeDef['extensionBase']);
04554 if ($this->getNamespaceFromPrefix($ns)) {
04555 $ns = $this->getNamespaceFromPrefix($ns);
04556 }
04557 if ($typeDef = $this->getTypeDef($uqType, $ns)) {
04558 $this->debug("serialize elements for extension base $ns:$uqType");
04559 $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
04560 } else {
04561 $this->debug("extension base $ns:$uqType is not a supported type");
04562 }
04563 }
04564 return $xml;
04565 }
04566
04581 function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
04582 if (count($elements) > 0) {
04583 foreach($elements as $n => $e){
04584
04585 foreach ($e as $k => $v) {
04586 $k = strpos($k,':') ? $this->expandQname($k) : $k;
04587 $v = strpos($v,':') ? $this->expandQname($v) : $v;
04588 $ee[$k] = $v;
04589 }
04590 $eElements[$n] = $ee;
04591 }
04592 $elements = $eElements;
04593 }
04594
04595 if (count($attrs) > 0) {
04596 foreach($attrs as $n => $a){
04597
04598 foreach ($a as $k => $v) {
04599 $k = strpos($k,':') ? $this->expandQname($k) : $k;
04600 $v = strpos($v,':') ? $this->expandQname($v) : $v;
04601 $aa[$k] = $v;
04602 }
04603 $eAttrs[$n] = $aa;
04604 }
04605 $attrs = $eAttrs;
04606 }
04607
04608 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
04609 $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
04610
04611 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
04612 $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
04613 }
04614
04626 function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
04627 $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
04628
04629 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
04630 $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
04631 }
04632
04640 function addElement($attrs) {
04641 $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
04642 $this->schemas[$typens][0]->addElement($attrs);
04643 }
04644
04659 function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
04660 if ($use == 'encoded' && $encodingStyle == '') {
04661 $encodingStyle = 'http:
04662 }
04663
04664 if ($style == 'document') {
04665 $elements = array();
04666 foreach ($in as $n => $t) {
04667 $elements[$n] = array('name' => $n, 'type' => $t);
04668 }
04669 $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
04670 $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
04671 $in = array('parameters' => 'tns:' . $name);
04672
04673 $elements = array();
04674 foreach ($out as $n => $t) {
04675 $elements[$n] = array('name' => $n, 'type' => $t);
04676 }
04677 $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
04678 $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType'));
04679 $out = array('parameters' => 'tns:' . $name . 'Response');
04680 }
04681
04682
04683 $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
04684 array(
04685 'name' => $name,
04686 'binding' => $this->serviceName . 'Binding',
04687 'endpoint' => $this->endpoint,
04688 'soapAction' => $soapaction,
04689 'style' => $style,
04690 'input' => array(
04691 'use' => $use,
04692 'namespace' => $namespace,
04693 'encodingStyle' => $encodingStyle,
04694 'message' => $name . 'Request',
04695 'parts' => $in),
04696 'output' => array(
04697 'use' => $use,
04698 'namespace' => $namespace,
04699 'encodingStyle' => $encodingStyle,
04700 'message' => $name . 'Response',
04701 'parts' => $out),
04702 'namespace' => $namespace,
04703 'transport' => 'http:
04704 'documentation' => $documentation);
04705
04706
04707 if($in)
04708 {
04709 foreach($in as $pName => $pType)
04710 {
04711 if(strpos($pType,':')) {
04712 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
04713 }
04714 $this->messages[$name.'Request'][$pName] = $pType;
04715 }
04716 } else {
04717 $this->messages[$name.'Request']= '0';
04718 }
04719 if($out)
04720 {
04721 foreach($out as $pName => $pType)
04722 {
04723 if(strpos($pType,':')) {
04724 $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
04725 }
04726 $this->messages[$name.'Response'][$pName] = $pType;
04727 }
04728 } else {
04729 $this->messages[$name.'Response']= '0';
04730 }
04731 return true;
04732 }
04733 }
04734
04735
04736
04745 class soap_parser extends nusoap_base {
04746
04747 var $xml = '';
04748 var $xml_encoding = '';
04749 var $method = '';
04750 var $root_struct = '';
04751 var $root_struct_name = '';
04752 var $root_struct_namespace = '';
04753 var $root_header = '';
04754 var $document = '';
04755
04756 var $status = '';
04757 var $position = 0;
04758 var $depth = 0;
04759 var $default_namespace = '';
04760 var $namespaces = array();
04761 var $message = array();
04762 var $parent = '';
04763 var $fault = false;
04764 var $fault_code = '';
04765 var $fault_str = '';
04766 var $fault_detail = '';
04767 var $depth_array = array();
04768 var $debug_flag = true;
04769 var $soapresponse = NULL;
04770 var $responseHeaders = '';
04771 var $body_position = 0;
04772
04773
04774 var $ids = array();
04775
04776 var $multirefs = array();
04777
04778 var $decode_utf8 = true;
04779
04789 function soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
04790 parent::nusoap_base();
04791 $this->xml = $xml;
04792 $this->xml_encoding = $encoding;
04793 $this->method = $method;
04794 $this->decode_utf8 = $decode_utf8;
04795
04796
04797 if(!empty($xml)){
04798
04799 $pos_xml = strpos($xml, '<?xml');
04800 if ($pos_xml !== FALSE) {
04801 $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
04802 if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
04803 $xml_encoding = $res[1];
04804 if (strtoupper($xml_encoding) != $encoding) {
04805 $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
04806 $this->debug($err);
04807 if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
04808 $this->setError($err);
04809 return;
04810 }
04811
04812 } else {
04813 $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
04814 }
04815 } else {
04816 $this->debug('No encoding specified in XML declaration');
04817 }
04818 } else {
04819 $this->debug('No XML declaration');
04820 }
04821 $this->debug('Entering soap_parser(), length='.strlen($xml).', encoding='.$encoding);
04822
04823 $this->parser = xml_parser_create($this->xml_encoding);
04824
04825
04826 xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
04827 xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
04828
04829 xml_set_object($this->parser, $this);
04830
04831 xml_set_element_handler($this->parser, 'start_element','end_element');
04832 xml_set_character_data_handler($this->parser,'character_data');
04833
04834
04835 if(!xml_parse($this->parser,$xml,true)){
04836
04837 $err = sprintf('XML error parsing SOAP payload on line %d: %s',
04838 xml_get_current_line_number($this->parser),
04839 xml_error_string(xml_get_error_code($this->parser)));
04840 $this->debug($err);
04841 $this->debug("XML payload:\n" . $xml);
04842 $this->setError($err);
04843 } else {
04844 $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
04845
04846 $this->soapresponse = $this->message[$this->root_struct]['result'];
04847
04848
04849
04850
04851
04852 if(sizeof($this->multirefs) > 0){
04853 foreach($this->multirefs as $id => $hrefs){
04854 $this->debug('resolving multirefs for id: '.$id);
04855 $idVal = $this->buildVal($this->ids[$id]);
04856 if (is_array($idVal) && isset($idVal['!id'])) {
04857 unset($idVal['!id']);
04858 }
04859 foreach($hrefs as $refPos => $ref){
04860 $this->debug('resolving href at pos '.$refPos);
04861 $this->multirefs[$id][$refPos] = $idVal;
04862 }
04863 }
04864 }
04865 }
04866 xml_parser_free($this->parser);
04867 } else {
04868 $this->debug('xml was empty, didn\'t parse!');
04869 $this->setError('xml was empty, didn\'t parse!');
04870 }
04871 }
04872
04881 function start_element($parser, $name, $attrs) {
04882
04883
04884 $pos = $this->position++;
04885
04886 $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
04887
04888
04889 $this->message[$pos]['depth'] = $this->depth++;
04890
04891
04892 if($pos != 0){
04893 $this->message[$this->parent]['children'] .= '|'.$pos;
04894 }
04895
04896 $this->message[$pos]['parent'] = $this->parent;
04897
04898 $this->parent = $pos;
04899
04900 $this->depth_array[$this->depth] = $pos;
04901
04902 if(strpos($name,':')){
04903
04904 $prefix = substr($name,0,strpos($name,':'));
04905
04906 $name = substr(strstr($name,':'),1);
04907 }
04908
04909 if($name == 'Envelope'){
04910 $this->status = 'envelope';
04911 } elseif($name == 'Header'){
04912 $this->root_header = $pos;
04913 $this->status = 'header';
04914 } elseif($name == 'Body'){
04915 $this->status = 'body';
04916 $this->body_position = $pos;
04917
04918 } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
04919 $this->status = 'method';
04920 $this->root_struct_name = $name;
04921 $this->root_struct = $pos;
04922 $this->message[$pos]['type'] = 'struct';
04923 $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
04924 }
04925
04926 $this->message[$pos]['status'] = $this->status;
04927
04928 $this->message[$pos]['name'] = htmlspecialchars($name);
04929
04930 $this->message[$pos]['attrs'] = $attrs;
04931
04932
04933 $attstr = '';
04934 foreach($attrs as $key => $value){
04935 $key_prefix = $this->getPrefix($key);
04936 $key_localpart = $this->getLocalPart($key);
04937
04938 if($key_prefix == 'xmlns'){
04939 if(ereg('^http:
04940 $this->XMLSchemaVersion = $value;
04941 $this->namespaces['xsd'] = $this->XMLSchemaVersion;
04942 $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
04943 }
04944 $this->namespaces[$key_localpart] = $value;
04945
04946 if($name == $this->root_struct_name){
04947 $this->methodNamespace = $value;
04948 }
04949
04950 } elseif($key_localpart == 'type'){
04951 $value_prefix = $this->getPrefix($value);
04952 $value_localpart = $this->getLocalPart($value);
04953 $this->message[$pos]['type'] = $value_localpart;
04954 $this->message[$pos]['typePrefix'] = $value_prefix;
04955 if(isset($this->namespaces[$value_prefix])){
04956 $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
04957 } else if(isset($attrs['xmlns:'.$value_prefix])) {
04958 $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
04959 }
04960
04961 } elseif($key_localpart == 'arrayType'){
04962 $this->message[$pos]['type'] = 'array';
04963
04964
04965
04966
04967
04968
04969
04970
04971 $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
04972 if(ereg($expr,$value,$regs)){
04973 $this->message[$pos]['typePrefix'] = $regs[1];
04974 $this->message[$pos]['arrayTypePrefix'] = $regs[1];
04975 if (isset($this->namespaces[$regs[1]])) {
04976 $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
04977 } else if (isset($attrs['xmlns:'.$regs[1]])) {
04978 $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
04979 }
04980 $this->message[$pos]['arrayType'] = $regs[2];
04981 $this->message[$pos]['arraySize'] = $regs[3];
04982 $this->message[$pos]['arrayCols'] = $regs[4];
04983 }
04984
04985 } elseif ($key_localpart == 'nil'){
04986 $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
04987
04988 } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
04989 $this->message[$pos]['xattrs']['!' . $key] = $value;
04990 }
04991
04992 if ($key == 'xmlns') {
04993 $this->default_namespace = $value;
04994 }
04995
04996 if($key == 'id'){
04997 $this->ids[$value] = $pos;
04998 }
04999
05000 if($key_localpart == 'root' && $value == 1){
05001 $this->status = 'method';
05002 $this->root_struct_name = $name;
05003 $this->root_struct = $pos;
05004 $this->debug("found root struct $this->root_struct_name, pos $pos");
05005 }
05006
05007 $attstr .= " $key=\"$value\"";
05008 }
05009
05010 if(isset($prefix)){
05011 $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
05012 $this->default_namespace = $this->namespaces[$prefix];
05013 } else {
05014 $this->message[$pos]['namespace'] = $this->default_namespace;
05015 }
05016 if($this->status == 'header'){
05017 if ($this->root_header != $pos) {
05018 $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
05019 }
05020 } elseif($this->root_struct_name != ''){
05021 $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
05022 }
05023 }
05024
05032 function end_element($parser, $name) {
05033
05034 $pos = $this->depth_array[$this->depth--];
05035
05036
05037 if(strpos($name,':')){
05038
05039 $prefix = substr($name,0,strpos($name,':'));
05040
05041 $name = substr(strstr($name,':'),1);
05042 }
05043
05044
05045 if(isset($this->body_position) && $pos > $this->body_position){
05046
05047 if(isset($this->message[$pos]['attrs']['href'])){
05048
05049 $id = substr($this->message[$pos]['attrs']['href'],1);
05050
05051 $this->multirefs[$id][$pos] = 'placeholder';
05052
05053 $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
05054
05055 } elseif($this->message[$pos]['children'] != ''){
05056
05057 if(!isset($this->message[$pos]['result'])){
05058 $this->message[$pos]['result'] = $this->buildVal($pos);
05059 }
05060
05061 } elseif (isset($this->message[$pos]['xattrs'])) {
05062 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
05063 $this->message[$pos]['xattrs']['!'] = null;
05064 } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
05065 if (isset($this->message[$pos]['type'])) {
05066 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
05067 } else {
05068 $parent = $this->message[$pos]['parent'];
05069 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
05070 $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
05071 } else {
05072 $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
05073 }
05074 }
05075 }
05076 $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
05077
05078 } else {
05079
05080 if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
05081 $this->message[$pos]['xattrs']['!'] = null;
05082 } elseif (isset($this->message[$pos]['type'])) {
05083 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
05084 } else {
05085 $parent = $this->message[$pos]['parent'];
05086 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
05087 $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
05088 } else {
05089 $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
05090 }
05091 }
05092
05093
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103 }
05104 }
05105
05106
05107 if($this->status == 'header'){
05108 if ($this->root_header != $pos) {
05109 $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
05110 }
05111 } elseif($pos >= $this->root_struct){
05112 $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
05113 }
05114
05115 if($pos == $this->root_struct){
05116 $this->status = 'body';
05117 $this->root_struct_namespace = $this->message[$pos]['namespace'];
05118 } elseif($name == 'Body'){
05119 $this->status = 'envelope';
05120 } elseif($name == 'Header'){
05121 $this->status = 'envelope';
05122 } elseif($name == 'Envelope'){
05123
05124 }
05125
05126 $this->parent = $this->message[$pos]['parent'];
05127 }
05128
05136 function character_data($parser, $data){
05137 $pos = $this->depth_array[$this->depth];
05138 if ($this->xml_encoding=='UTF-8'){
05139
05140
05141
05142 if($this->decode_utf8){
05143 $data = utf8_decode($data);
05144 }
05145 }
05146 $this->message[$pos]['cdata'] .= $data;
05147
05148 if($this->status == 'header'){
05149 $this->responseHeaders .= $data;
05150 } else {
05151 $this->document .= $data;
05152 }
05153 }
05154
05161 function get_response(){
05162 return $this->soapresponse;
05163 }
05164
05171 function getHeaders(){
05172 return $this->responseHeaders;
05173 }
05174
05184 function decodeSimple($value, $type, $typens) {
05185
05186 if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
05187 return (string) $value;
05188 }
05189 if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
05190 return (int) $value;
05191 }
05192 if ($type == 'float' || $type == 'double' || $type == 'decimal') {
05193 return (double) $value;
05194 }
05195 if ($type == 'boolean') {
05196 if (strtolower($value) == 'false' || strtolower($value) == 'f') {
05197 return false;
05198 }
05199 return (boolean) $value;
05200 }
05201 if ($type == 'base64' || $type == 'base64Binary') {
05202 $this->debug('Decode base64 value');
05203 return base64_decode($value);
05204 }
05205
05206 if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
05207 || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
05208 || $type == 'unsignedInt'
05209 || $type == 'unsignedShort' || $type == 'unsignedByte') {
05210 return (int) $value;
05211 }
05212
05213 if ($type == 'array') {
05214 return array();
05215 }
05216
05217 return (string) $value;
05218 }
05219
05228 function buildVal($pos){
05229 if(!isset($this->message[$pos]['type'])){
05230 $this->message[$pos]['type'] = '';
05231 }
05232 $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
05233
05234 if($this->message[$pos]['children'] != ''){
05235 $this->debug('in buildVal, there are children');
05236 $children = explode('|',$this->message[$pos]['children']);
05237 array_shift($children);
05238
05239 if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
05240 $r=0;
05241 $c=0;
05242 foreach($children as $child_pos){
05243 $this->debug("in buildVal, got an MD array element: $r, $c");
05244 $params[$r][] = $this->message[$child_pos]['result'];
05245 $c++;
05246 if($c == $this->message[$pos]['arrayCols']){
05247 $c = 0;
05248 $r++;
05249 }
05250 }
05251
05252 } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
05253 $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
05254 foreach($children as $child_pos){
05255 $params[] = &$this->message[$child_pos]['result'];
05256 }
05257
05258 } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http:
05259 $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
05260 foreach($children as $child_pos){
05261 $kv = explode("|",$this->message[$child_pos]['children']);
05262 $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
05263 }
05264
05265
05266 } else {
05267
05268 $this->debug('in buildVal, adding Java Vector '.$this->message[$pos]['name']);
05269 if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http:
05270 $notstruct = 1;
05271 } else {
05272 $notstruct = 0;
05273 }
05274
05275 foreach($children as $child_pos){
05276 if($notstruct){
05277 $params[] = &$this->message[$child_pos]['result'];
05278 } else {
05279 if (isset($params[$this->message[$child_pos]['name']])) {
05280
05281 if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
05282 $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
05283 }
05284 $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
05285 } else {
05286 $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
05287 }
05288 }
05289 }
05290 }
05291 if (isset($this->message[$pos]['xattrs'])) {
05292 $this->debug('in buildVal, handling attributes');
05293 foreach ($this->message[$pos]['xattrs'] as $n => $v) {
05294 $params[$n] = $v;
05295 }
05296 }
05297
05298 if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
05299 $this->debug('in buildVal, handling simpleContent');
05300 if (isset($this->message[$pos]['type'])) {
05301 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
05302 } else {
05303 $parent = $this->message[$pos]['parent'];
05304 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
05305 $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
05306 } else {
05307 $params['!'] = $this->message[$pos]['cdata'];
05308 }
05309 }
05310 }
05311 return is_array($params) ? $params : array();
05312 } else {
05313 $this->debug('in buildVal, no children, building scalar');
05314 $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
05315 if (isset($this->message[$pos]['type'])) {
05316 return $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
05317 }
05318 $parent = $this->message[$pos]['parent'];
05319 if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
05320 return $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
05321 }
05322 return $this->message[$pos]['cdata'];
05323 }
05324 }
05325 }
05326
05327
05328
05348 class soapclient extends nusoap_base {
05349
05350 var $username = '';
05351 var $password = '';
05352 var $authtype = '';
05353 var $certRequest = array();
05354 var $requestHeaders = false;
05355 var $responseHeaders = '';
05356 var $document = '';
05357 var $endpoint;
05358 var $forceEndpoint = '';
05359 var $proxyhost = '';
05360 var $proxyport = '';
05361 var $proxyusername = '';
05362 var $proxypassword = '';
05363 var $xml_encoding = '';
05364 var $http_encoding = false;
05365 var $timeout = 0;
05366 var $response_timeout = 30;
05367 var $endpointType = '';
05368 var $persistentConnection = false;
05369 var $defaultRpcParams = false;
05370 var $request = '';
05371 var $response = '';
05372 var $responseData = '';
05373 var $cookies = array();
05374 var $decode_utf8 = true;
05375 var $operations = array();
05376
05377
05378
05379
05384 var $fault;
05389 var $faultcode;
05394 var $faultstring;
05399 var $faultdetail;
05400
05415 function soapclient($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
05416 parent::nusoap_base();
05417 $this->endpoint = $endpoint;
05418 $this->proxyhost = $proxyhost;
05419 $this->proxyport = $proxyport;
05420 $this->proxyusername = $proxyusername;
05421 $this->proxypassword = $proxypassword;
05422 $this->timeout = $timeout;
05423 $this->response_timeout = $response_timeout;
05424
05425
05426 if($wsdl){
05427 if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
05428 $this->wsdl = $endpoint;
05429 $this->endpoint = $this->wsdl->wsdl;
05430 $this->wsdlFile = $this->endpoint;
05431 $this->debug('existing wsdl instance created from ' . $this->endpoint);
05432 } else {
05433 $this->wsdlFile = $this->endpoint;
05434
05435
05436 $this->debug('instantiating wsdl class with doc: '.$endpoint);
05437 $this->wsdl =& new wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout);
05438 }
05439 $this->appendDebug($this->wsdl->getDebug());
05440 $this->wsdl->clearDebug();
05441
05442 if($errstr = $this->wsdl->getError()){
05443 $this->debug('got wsdl error: '.$errstr);
05444 $this->setError('wsdl error: '.$errstr);
05445 } elseif($this->operations = $this->wsdl->getOperations()){
05446 $this->debug( 'got '.count($this->operations).' operations from wsdl '.$this->wsdlFile);
05447 $this->endpointType = 'wsdl';
05448 } else {
05449 $this->debug( 'getOperations returned false');
05450 $this->setError('no operations defined in the WSDL document!');
05451 }
05452 } else {
05453 $this->debug("instantiate SOAP with endpoint at $endpoint");
05454 $this->endpointType = 'soap';
05455 }
05456 }
05457
05483 function call($operation,$params=array(),$namespace='http:
05484 $this->operation = $operation;
05485 $this->fault = false;
05486 $this->setError('');
05487 $this->request = '';
05488 $this->response = '';
05489 $this->responseData = '';
05490 $this->faultstring = '';
05491 $this->faultcode = '';
05492 $this->opData = array();
05493
05494 $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
05495 $this->appendDebug('params=' . $this->varDump($params));
05496 $this->appendDebug('headers=' . $this->varDump($headers));
05497 if ($headers) {
05498 $this->requestHeaders = $headers;
05499 }
05500
05501 if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
05502
05503 $this->opData = $opData;
05504 $this->debug("found operation");
05505 $this->appendDebug('opData=' . $this->varDump($opData));
05506 if (isset($opData['soapAction'])) {
05507 $soapAction = $opData['soapAction'];
05508 }
05509 if (! $this->forceEndpoint) {
05510 $this->endpoint = $opData['endpoint'];
05511 } else {
05512 $this->endpoint = $this->forceEndpoint;
05513 }
05514 $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
05515 $style = $opData['style'];
05516 $use = $opData['input']['use'];
05517
05518 if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
05519 $nsPrefix = 'ns' . rand(1000, 9999);
05520 $this->wsdl->namespaces[$nsPrefix] = $namespace;
05521 }
05522 $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
05523
05524 if (is_string($params)) {
05525 $this->debug("serializing param string for WSDL operation $operation");
05526 $payload = $params;
05527 } elseif (is_array($params)) {
05528 $this->debug("serializing param array for WSDL operation $operation");
05529 $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params);
05530 } else {
05531 $this->debug('params must be array or string');
05532 $this->setError('params must be array or string');
05533 return false;
05534 }
05535 $usedNamespaces = $this->wsdl->usedNamespaces;
05536 if (isset($opData['input']['encodingStyle'])) {
05537 $encodingStyle = $opData['input']['encodingStyle'];
05538 } else {
05539 $encodingStyle = '';
05540 }
05541 $this->appendDebug($this->wsdl->getDebug());
05542 $this->wsdl->clearDebug();
05543 if ($errstr = $this->wsdl->getError()) {
05544 $this->debug('got wsdl error: '.$errstr);
05545 $this->setError('wsdl error: '.$errstr);
05546 return false;
05547 }
05548 } elseif($this->endpointType == 'wsdl') {
05549
05550 $this->appendDebug($this->wsdl->getDebug());
05551 $this->wsdl->clearDebug();
05552 $this->setError( 'operation '.$operation.' not present.');
05553 $this->debug("operation '$operation' not present.");
05554 return false;
05555 } else {
05556
05557
05558 $nsPrefix = 'ns' . rand(1000, 9999);
05559
05560 $payload = '';
05561 if (is_string($params)) {
05562 $this->debug("serializing param string for operation $operation");
05563 $payload = $params;
05564 } elseif (is_array($params)) {
05565 $this->debug("serializing param array for operation $operation");
05566 foreach($params as $k => $v){
05567 $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
05568 }
05569 } else {
05570 $this->debug('params must be array or string');
05571 $this->setError('params must be array or string');
05572 return false;
05573 }
05574 $usedNamespaces = array();
05575 if ($use == 'encoded') {
05576 $encodingStyle = 'http:
05577 } else {
05578 $encodingStyle = '';
05579 }
05580 }
05581
05582 if ($style == 'rpc') {
05583 if ($use == 'literal') {
05584 $this->debug("wrapping RPC request with literal method element");
05585 if ($namespace) {
05586 $payload = "<$operation xmlns=\"$namespace\">" . $payload . "</$operation>";
05587 } else {
05588 $payload = "<$operation>" . $payload . "</$operation>";
05589 }
05590 } else {
05591 $this->debug("wrapping RPC request with encoded method element");
05592 if ($namespace) {
05593 $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
05594 $payload .
05595 "</$nsPrefix:$operation>";
05596 } else {
05597 $payload = "<$operation>" .
05598 $payload .
05599 "</$operation>";
05600 }
05601 }
05602 }
05603
05604 $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
05605 $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
05606 $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
05607
05608 $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
05609 if($errstr = $this->getError()){
05610 $this->debug('Error: '.$errstr);
05611 return false;
05612 } else {
05613 $this->return = $return;
05614 $this->debug('sent message successfully and got a(n) '.gettype($return));
05615 $this->appendDebug('return=' . $this->varDump($return));
05616
05617
05618 if(is_array($return) && isset($return['faultcode'])){
05619 $this->debug('got fault');
05620 $this->setError($return['faultcode'].': '.$return['faultstring']);
05621 $this->fault = true;
05622 foreach($return as $k => $v){
05623 $this->$k = $v;
05624 $this->debug("$k = $v<br>");
05625 }
05626 return $return;
05627 } elseif ($style == 'document') {
05628
05629
05630 return $return;
05631 } else {
05632
05633 if(is_array($return)){
05634
05635
05636 if(sizeof($return) > 1){
05637 return $return;
05638 }
05639
05640 $return = array_shift($return);
05641 $this->debug('return shifted value: ');
05642 $this->appendDebug($this->varDump($return));
05643 return $return;
05644
05645 } else {
05646 return "";
05647 }
05648 }
05649 }
05650 }
05651
05659 function getOperationData($operation){
05660 if(isset($this->operations[$operation])){
05661 return $this->operations[$operation];
05662 }
05663 $this->debug("No data for operation: $operation");
05664 }
05665
05680 function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
05681 $this->checkCookies();
05682
05683 switch(true){
05684
05685 case ereg('^http',$this->endpoint):
05686 $this->debug('transporting via HTTP');
05687 if($this->persistentConnection == true && is_object($this->persistentConnection)){
05688 $http =& $this->persistentConnection;
05689 } else {
05690 $http = new soap_transport_http($this->endpoint);
05691 if ($this->persistentConnection) {
05692 $http->usePersistentConnection();
05693 }
05694 }
05695 $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
05696 $http->setSOAPAction($soapaction);
05697 if($this->proxyhost && $this->proxyport){
05698 $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
05699 }
05700 if($this->authtype != '') {
05701 $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
05702 }
05703 if($this->http_encoding != ''){
05704 $http->setEncoding($this->http_encoding);
05705 }
05706 $this->debug('sending message, length='.strlen($msg));
05707 if(ereg('^http:',$this->endpoint)){
05708
05709 $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
05710 } elseif(ereg('^https',$this->endpoint)){
05711
05712
05713
05714
05715
05716
05717 $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
05718 } else {
05719 $this->setError('no http/s in endpoint url');
05720 }
05721 $this->request = $http->outgoing_payload;
05722 $this->response = $http->incoming_payload;
05723 $this->appendDebug($http->getDebug());
05724 $this->UpdateCookies($http->incoming_cookies);
05725
05726
05727 if ($this->persistentConnection) {
05728 $http->clearDebug();
05729 if (!is_object($this->persistentConnection)) {
05730 $this->persistentConnection = $http;
05731 }
05732 }
05733
05734 if($err = $http->getError()){
05735 $this->setError('HTTP Error: '.$err);
05736 return false;
05737 } elseif($this->getError()){
05738 return false;
05739 } else {
05740 $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
05741 return $this->parseResponse($http->incoming_headers, $this->responseData);
05742 }
05743 break;
05744 default:
05745 $this->setError('no transport found, or selected transport is not yet supported!');
05746 return false;
05747 break;
05748 }
05749 }
05750
05759 function parseResponse($headers, $data) {
05760 $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
05761 if (!strstr($headers['content-type'], 'text/xml')) {
05762 $this->setError('Response not of type text/xml');
05763 return false;
05764 }
05765 if (strpos($headers['content-type'], '=')) {
05766 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
05767 $this->debug('Got response encoding: ' . $enc);
05768 if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
05769 $this->xml_encoding = strtoupper($enc);
05770 } else {
05771 $this->xml_encoding = 'US-ASCII';
05772 }
05773 } else {
05774
05775 $this->xml_encoding = 'ISO-8859-1';
05776 }
05777 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
05778 $parser = new soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
05779
05780 $this->appendDebug($parser->getDebug());
05781
05782 if($errstr = $parser->getError()){
05783 $this->setError( $errstr);
05784
05785 unset($parser);
05786 return false;
05787 } else {
05788
05789 $this->responseHeaders = $parser->getHeaders();
05790
05791 $return = $parser->get_response();
05792
05793 $this->document = $parser->document;
05794
05795 unset($parser);
05796
05797 return $return;
05798 }
05799 }
05800
05807 function setEndpoint($endpoint) {
05808 $this->forceEndpoint = $endpoint;
05809 }
05810
05817 function setHeaders($headers){
05818 $this->requestHeaders = $headers;
05819 }
05820
05827 function getHeaders(){
05828 return $this->responseHeaders;
05829 }
05830
05840 function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
05841 $this->proxyhost = $proxyhost;
05842 $this->proxyport = $proxyport;
05843 $this->proxyusername = $proxyusername;
05844 $this->proxypassword = $proxypassword;
05845 }
05846
05856 function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
05857 $this->username = $username;
05858 $this->password = $password;
05859 $this->authtype = $authtype;
05860 $this->certRequest = $certRequest;
05861 }
05862
05869 function setHTTPEncoding($enc='gzip, deflate'){
05870 $this->http_encoding = $enc;
05871 }
05872
05878 function useHTTPPersistentConnection(){
05879 $this->persistentConnection = true;
05880 }
05881
05893 function getDefaultRpcParams() {
05894 return $this->defaultRpcParams;
05895 }
05896
05908 function setDefaultRpcParams($rpcParams) {
05909 $this->defaultRpcParams = $rpcParams;
05910 }
05911
05919 function getProxy(){
05920 $r = rand();
05921 $evalStr = $this->_getProxyClassCode($r);
05922
05923
05924 eval($evalStr);
05925
05926 eval("\$proxy = new soap_proxy_$r('');");
05927
05928 $proxy->endpointType = 'wsdl';
05929 $proxy->wsdlFile = $this->wsdlFile;
05930 $proxy->wsdl = $this->wsdl;
05931 $proxy->operations = $this->operations;
05932 $proxy->defaultRpcParams = $this->defaultRpcParams;
05933
05934 $proxy->username = $this->username;
05935 $proxy->password = $this->password;
05936 $proxy->authtype = $this->authtype;
05937 $proxy->proxyhost = $this->proxyhost;
05938 $proxy->proxyport = $this->proxyport;
05939 $proxy->proxyusername = $this->proxyusername;
05940 $proxy->proxypassword = $this->proxypassword;
05941 $proxy->timeout = $this->timeout;
05942 $proxy->response_timeout = $this->response_timeout;
05943 $proxy->http_encoding = $this->http_encoding;
05944 $proxy->persistentConnection = $this->persistentConnection;
05945 $proxy->requestHeaders = $this->requestHeaders;
05946 $proxy->soap_defencoding = $this->soap_defencoding;
05947 $proxy->endpoint = $this->endpoint;
05948 $proxy->forceEndpoint = $this->forceEndpoint;
05949 return $proxy;
05950 }
05951
05958 function _getProxyClassCode($r) {
05959 if ($this->endpointType != 'wsdl') {
05960 $evalStr = 'A proxy can only be created for a WSDL client';
05961 $this->setError($evalStr);
05962 return $evalStr;
05963 }
05964 $evalStr = '';
05965 foreach ($this->operations as $operation => $opData) {
05966 if ($operation != '') {
05967
05968 if (sizeof($opData['input']['parts']) > 0) {
05969 $paramStr = '';
05970 $paramArrayStr = '';
05971 $paramCommentStr = '';
05972 foreach ($opData['input']['parts'] as $name => $type) {
05973 $paramStr .= "\$$name, ";
05974 $paramArrayStr .= "'$name' => \$$name, ";
05975 $paramCommentStr .= "$type \$$name, ";
05976 }
05977 $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
05978 $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
05979 $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
05980 } else {
05981 $paramStr = '';
05982 $paramCommentStr = 'void';
05983 }
05984 $opData['namespace'] = !isset($opData['namespace']) ? 'http:
05985 $evalStr .= "// $paramCommentStr
05986 function " . str_replace('.', '__', $operation) . "($paramStr) {
05987 \$params = array($paramArrayStr);
05988 return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
05989 }
05990 ";
05991 unset($paramStr);
05992 unset($paramCommentStr);
05993 }
05994 }
05995 $evalStr = 'class soap_proxy_'.$r.' extends soapclient {
05996 '.$evalStr.'
05997 }';
05998 return $evalStr;
05999 }
06000
06007 function getProxyClassCode() {
06008 $r = rand();
06009 return $this->_getProxyClassCode($r);
06010 }
06011
06019 function getHTTPBody($soapmsg) {
06020 return $soapmsg;
06021 }
06022
06031 function getHTTPContentType() {
06032 return 'text/xml';
06033 }
06034
06044 function getHTTPContentTypeCharset() {
06045 return $this->soap_defencoding;
06046 }
06047
06048
06049
06050
06051
06052
06053
06054 function decodeUTF8($bool){
06055 $this->decode_utf8 = $bool;
06056 return true;
06057 }
06058
06067 function setCookie($name, $value) {
06068 if (strlen($name) == 0) {
06069 return false;
06070 }
06071 $this->cookies[] = array('name' => $name, 'value' => $value);
06072 return true;
06073 }
06074
06081 function getCookies() {
06082 return $this->cookies;
06083 }
06084
06091 function checkCookies() {
06092 if (sizeof($this->cookies) == 0) {
06093 return true;
06094 }
06095 $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
06096 $curr_cookies = $this->cookies;
06097 $this->cookies = array();
06098 foreach ($curr_cookies as $cookie) {
06099 if (! is_array($cookie)) {
06100 $this->debug('Remove cookie that is not an array');
06101 continue;
06102 }
06103 if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
06104 if (strtotime($cookie['expires']) > time()) {
06105 $this->cookies[] = $cookie;
06106 } else {
06107 $this->debug('Remove expired cookie ' . $cookie['name']);
06108 }
06109 } else {
06110 $this->cookies[] = $cookie;
06111 }
06112 }
06113 $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
06114 return true;
06115 }
06116
06124 function UpdateCookies($cookies) {
06125 if (sizeof($this->cookies) == 0) {
06126
06127 if (sizeof($cookies) > 0) {
06128 $this->debug('Setting new cookie(s)');
06129 $this->cookies = $cookies;
06130 }
06131 return true;
06132 }
06133 if (sizeof($cookies) == 0) {
06134
06135 return true;
06136 }
06137
06138 foreach ($cookies as $newCookie) {
06139 if (!is_array($newCookie)) {
06140 continue;
06141 }
06142 if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
06143 continue;
06144 }
06145 $newName = $newCookie['name'];
06146
06147 $found = false;
06148 for ($i = 0; $i < count($this->cookies); $i++) {
06149 $cookie = $this->cookies[$i];
06150 if (!is_array($cookie)) {
06151 continue;
06152 }
06153 if (!isset($cookie['name'])) {
06154 continue;
06155 }
06156 if ($newName != $cookie['name']) {
06157 continue;
06158 }
06159 $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
06160 $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
06161 if ($newDomain != $domain) {
06162 continue;
06163 }
06164 $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
06165 $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
06166 if ($newPath != $path) {
06167 continue;
06168 }
06169 $this->cookies[$i] = $newCookie;
06170 $found = true;
06171 $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
06172 break;
06173 }
06174 if (! $found) {
06175 $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
06176 $this->cookies[] = $newCookie;
06177 }
06178 }
06179 return true;
06180 }
06181 }
06182 ?>