logo       


mantisbt/api/soap/nusoap changelog, NONE, 1.1 class.nusoap_base.php, NONE, : msg#00078

Subject: mantisbt/api/soap/nusoap changelog, NONE, 1.1 class.nusoap_base.php, NONE, 1.1 class.soap_fault.php, NONE, 1.1 class.soap_parser.php, NONE, 1.1 class.soap_server.php, NONE, 1.1 class.soap_transport_http.php, NONE, 1.1 class.soap_val.php, NONE, 1.1 class.soapclient.php, NONE, 1.1 class.wsdl.php, NONE, 1.1 class.wsdlcache.php, NONE, 1.1 class.xmlschema.php, NONE, 1.1 nusoap.php, NONE, 1.1 nusoapmime.php, NONE, 1.1
Update of /cvsroot/mantisbt/mantisbt/api/soap/nusoap
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv19753/nusoap

Added Files:
        changelog class.nusoap_base.php class.soap_fault.php 
        class.soap_parser.php class.soap_server.php 
        class.soap_transport_http.php class.soap_val.php 
        class.soapclient.php class.wsdl.php class.wsdlcache.php 
        class.xmlschema.php nusoap.php nusoapmime.php 
Log Message:
Fixed #8159: Provide MantisConnect webservice out of the box as the Mantis SOAP 
API.

--- NEW FILE: class.soap_parser.php ---
<?php




/**
*
* soap_parser class parses SOAP XML messages into native PHP values
*
* @author   Dietrich Ayala <dietrich-QnEadSwVb5QAvxtiuMwx3w@xxxxxxxxxxxxxxxx>
* @version  $Id: class.soap_parser.php,v 1.1 2007/07/18 06:53:00 vboctor Exp $
* @access   public
*/
class soap_parser extends nusoap_base {

        var $xml = '';
        var $xml_encoding = '';
        var $method = '';
        var $root_struct = '';
        var $root_struct_name = '';
        var $root_struct_namespace = '';
        var $root_header = '';
    var $document = '';                 // incoming SOAP body (text)
        // determines where in the message we are (envelope,header,body,method)
        var $status = '';
        var $position = 0;
        var $depth = 0;
        var $default_namespace = '';
        var $namespaces = array();
        var $message = array();
    var $parent = '';
        var $fault = false;
        var $fault_code = '';
        var $fault_str = '';
        var $fault_detail = '';
        var $depth_array = array();
        var $debug_flag = true;
        var $soapresponse = NULL;
        var $responseHeaders = '';      // incoming SOAP headers (text)
        var $body_position = 0;
        // for multiref parsing:
        // array of id => pos
        var $ids = array();
        // array of id => hrefs => pos
        var $multirefs = array();
        // toggle for auto-decoding element content
        var $decode_utf8 = true;

        /**
        * constructor that actually does the parsing
        *
        * @param    string $xml SOAP message
        * @param    string $encoding character encoding scheme of message
        * @param    string $method method for which XML is parsed (unused?)
        * @param    string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
        * @access   public
        */
        function 
soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
                parent::nusoap_base();
                $this->xml = $xml;
                $this->xml_encoding = $encoding;
                $this->method = $method;
                $this->decode_utf8 = $decode_utf8;

                // Check whether content has been read.
                if(!empty($xml)){
                        // Check XML encoding
                        $pos_xml = strpos($xml, '<?xml');
                        if ($pos_xml !== FALSE) {
                                $xml_decl = substr($xml, $pos_xml, strpos($xml, 
'?>', $pos_xml + 2) - $pos_xml + 1);
                                if 
(preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
                                        $xml_encoding = $res[1];
                                        if (strtoupper($xml_encoding) != 
$encoding) {
                                                $err = "Charset from HTTP 
Content-Type '" . $encoding . "' does not match encoding from XML declaration 
'" . $xml_encoding . "'";
                                                $this->debug($err);
                                                if ($encoding != 'ISO-8859-1' 
|| strtoupper($xml_encoding) != 'UTF-8') {
                                                        $this->setError($err);
                                                        return;
                                                }
                                                // when HTTP says ISO-8859-1 
(the default) and XML says UTF-8 (the typical), assume the other endpoint is 
just sloppy and proceed
                                        } else {
                                                $this->debug('Charset from HTTP 
Content-Type matches encoding from XML declaration');
                                        }
                                } else {
                                        $this->debug('No encoding specified in 
XML declaration');
                                }
                        } else {
                                $this->debug('No XML declaration');
                        }
                        $this->debug('Entering soap_parser(), 
length='.strlen($xml).', encoding='.$encoding);
                        // Create an XML parser - why not xml_parser_create_ns?
                        $this->parser = xml_parser_create($this->xml_encoding);
                        // Set the options for parsing the XML data.
                        //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 
1);
                        xml_parser_set_option($this->parser, 
XML_OPTION_CASE_FOLDING, 0);
                        xml_parser_set_option($this->parser, 
XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
                        // Set the object for the parser.
                        xml_set_object($this->parser, $this);
                        // Set the element handlers for the parser.
                        xml_set_element_handler($this->parser, 
'start_element','end_element');
                        
xml_set_character_data_handler($this->parser,'character_data');

                        // Parse the XML file.
                        if(!xml_parse($this->parser,$xml,true)){
                            // Display an error message.
                            $err = sprintf('XML error parsing SOAP payload on 
line %d: %s',
                            xml_get_current_line_number($this->parser),
                            
xml_error_string(xml_get_error_code($this->parser)));
                                $this->debug($err);
                                $this->debug("XML payload:\n" . $xml);
                                $this->setError($err);
                        } else {
                                $this->debug('parsed successfully, found root 
struct: '.$this->root_struct.' of name '.$this->root_struct_name);
                                // get final value
                                $this->soapresponse = 
$this->message[$this->root_struct]['result'];
                                // get header value: no, because this is 
documented as XML string
//                              if($this->root_header != '' && 
isset($this->message[$this->root_header]['result'])){
//                                      $this->responseHeaders = 
$this->message[$this->root_header]['result'];
//                              }
                                // resolve hrefs/ids
                                if(sizeof($this->multirefs) > 0){
                                        foreach($this->multirefs as $id => 
$hrefs){
                                                $this->debug('resolving 
multirefs for id: '.$id);
                                                $idVal = 
$this->buildVal($this->ids[$id]);
                                                if (is_array($idVal) && 
isset($idVal['!id'])) {
                                                        unset($idVal['!id']);
                                                }
                                                foreach($hrefs as $refPos => 
$ref){
                                                        $this->debug('resolving 
href at pos '.$refPos);
                                                        
$this->multirefs[$id][$refPos] = $idVal;
                                                }
                                        }
                                }
                        }
                        xml_parser_free($this->parser);
                } else {
                        $this->debug('xml was empty, didn\'t parse!');
                        $this->setError('xml was empty, didn\'t parse!');
                }
        }

        /**
        * start-element handler
        *
        * @param    resource $parser XML parser object
        * @param    string $name element name
        * @param    array $attrs associative array of attributes
        * @access   private
        */
        function start_element($parser, $name, $attrs) {
                // position in a total number of elements, starting from 0
                // update class level pos
                $pos = $this->position++;
                // and set mine
                $this->message[$pos] = array('pos' => 
$pos,'children'=>'','cdata'=>'');
                // depth = how many levels removed from root?
                // set mine as current global depth and increment global depth 
value
                $this->message[$pos]['depth'] = $this->depth++;

                // else add self as child to whoever the current parent is
                if($pos != 0){
                        $this->message[$this->parent]['children'] .= '|'.$pos;
                }
                // set my parent
                $this->message[$pos]['parent'] = $this->parent;
                // set self as current parent
                $this->parent = $pos;
                // set self as current value for this depth
                $this->depth_array[$this->depth] = $pos;
                // get element prefix
                if(strpos($name,':')){
                        // get ns prefix
                        $prefix = substr($name,0,strpos($name,':'));
                        // get unqualified name
                        $name = substr(strstr($name,':'),1);
                }
                // set status
                if($name == 'Envelope'){
                        $this->status = 'envelope';
                } elseif($name == 'Header'){
                        $this->root_header = $pos;
                        $this->status = 'header';
                } elseif($name == 'Body'){
                        $this->status = 'body';
                        $this->body_position = $pos;
                // set method
                } elseif($this->status == 'body' && $pos == 
($this->body_position+1)){
                        $this->status = 'method';
                        $this->root_struct_name = $name;
                        $this->root_struct = $pos;
                        $this->message[$pos]['type'] = 'struct';
                        $this->debug("found root struct 
$this->root_struct_name, pos $this->root_struct");
                }
                // set my status
                $this->message[$pos]['status'] = $this->status;
                // set name
                $this->message[$pos]['name'] = htmlspecialchars($name);
                // set attrs
                $this->message[$pos]['attrs'] = $attrs;

                // loop through atts, logging ns and type declarations
        $attstr = '';
                foreach($attrs as $key => $value){
                $key_prefix = $this->getPrefix($key);
                        $key_localpart = $this->getLocalPart($key);
                        // if ns declarations, add to class level array of 
valid namespaces
            if($key_prefix == 'xmlns'){
                                
if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
                                        $this->XMLSchemaVersion = $value;
                                        $this->namespaces['xsd'] = 
$this->XMLSchemaVersion;
                                        $this->namespaces['xsi'] = 
$this->XMLSchemaVersion.'-instance';
                                }
                $this->namespaces[$key_localpart] = $value;
                                // set method namespace
                                if($name == $this->root_struct_name){
                                        $this->methodNamespace = $value;
                                }
                        // if it's a type declaration, set type
            } elseif($key_localpart == 'type'){
                $value_prefix = $this->getPrefix($value);
                $value_localpart = $this->getLocalPart($value);
                                $this->message[$pos]['type'] = $value_localpart;
                                $this->message[$pos]['typePrefix'] = 
$value_prefix;
                if(isset($this->namespaces[$value_prefix])){
                        $this->message[$pos]['type_namespace'] = 
$this->namespaces[$value_prefix];
                } else if(isset($attrs['xmlns:'.$value_prefix])) {
                                        $this->message[$pos]['type_namespace'] 
= $attrs['xmlns:'.$value_prefix];
                }
                                // should do something here with the namespace 
of specified type?
                        } elseif($key_localpart == 'arrayType'){
                                $this->message[$pos]['type'] = 'array';
                                /* do arrayType ereg here
                                [1]    arrayTypeValue    ::=    atype asize
                                [2]    atype    ::=    QName rank*
                                [3]    rank    ::=    '[' (',')* ']'
                                [4]    asize    ::=    '[' length~ ']'
                                [5]    length    ::=    nextDimension* Digit+
                                [6]    nextDimension    ::=    Digit+ ','
                                */
                                $expr = 
'([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
                                if(ereg($expr,$value,$regs)){
                                        $this->message[$pos]['typePrefix'] = 
$regs[1];
                                        $this->message[$pos]['arrayTypePrefix'] 
= $regs[1];
                        if (isset($this->namespaces[$regs[1]])) {
                                $this->message[$pos]['arrayTypeNamespace'] = 
$this->namespaces[$regs[1]];
                        } else if (isset($attrs['xmlns:'.$regs[1]])) {
                                                
$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
                        }
                                        $this->message[$pos]['arrayType'] = 
$regs[2];
                                        $this->message[$pos]['arraySize'] = 
$regs[3];
                                        $this->message[$pos]['arrayCols'] = 
$regs[4];
                                }
                        // specifies nil value (or not)
                        } elseif ($key_localpart == 'nil'){
                                $this->message[$pos]['nil'] = ($value == 'true' 
|| $value == '1');
                        // some other attribute
                        } elseif ($key != 'href' && $key != 'xmlns' && 
$key_localpart != 'encodingStyle' && $key_localpart != 'root') {
                                $this->message[$pos]['xattrs']['!' . $key] = 
$value;
                        }

                        if ($key == 'xmlns') {
                                $this->default_namespace = $value;
                        }
                        // log id
                        if($key == 'id'){
                                $this->ids[$value] = $pos;
                        }
                        // root
                        if($key_localpart == 'root' && $value == 1){
                                $this->status = 'method';
                                $this->root_struct_name = $name;
                                $this->root_struct = $pos;
                                $this->debug("found root struct 
$this->root_struct_name, pos $pos");
                        }
            // for doclit
            $attstr .= " $key=\"$value\"";
                }
        // get namespace - must be done after namespace atts are processed
                if(isset($prefix)){
                        $this->message[$pos]['namespace'] = 
$this->namespaces[$prefix];
                        $this->default_namespace = $this->namespaces[$prefix];
                } else {
                        $this->message[$pos]['namespace'] = 
$this->default_namespace;
                }
        if($this->status == 'header'){
                if ($this->root_header != $pos) {
                        $this->responseHeaders .= "<" . (isset($prefix) ? 
$prefix . ':' : '') . "$name$attstr>";
                }
        } elseif($this->root_struct_name != ''){
                $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') 
. "$name$attstr>";
        }
        }

        /**
        * end-element handler
        *
        * @param    resource $parser XML parser object
        * @param    string $name element name
        * @access   private
        */
        function end_element($parser, $name) {
                // position of current element is equal to the last value left 
in depth_array for my depth
                $pos = $this->depth_array[$this->depth--];

        // get element prefix
                if(strpos($name,':')){
                        // get ns prefix
                        $prefix = substr($name,0,strpos($name,':'));
                        // get unqualified name
                        $name = substr(strstr($name,':'),1);
                }
                
                // build to native type
                if(isset($this->body_position) && $pos > $this->body_position){
                        // deal w/ multirefs
                        if(isset($this->message[$pos]['attrs']['href'])){
                                // get id
                                $id = 
substr($this->message[$pos]['attrs']['href'],1);
                                // add placeholder to href array
                                $this->multirefs[$id][$pos] = 'placeholder';
                                // add set a reference to it as the result value
                                $this->message[$pos]['result'] =& 
$this->multirefs[$id][$pos];
            // build complexType values
                        } elseif($this->message[$pos]['children'] != ''){
                                // if result has already been generated 
(struct/array)
                                if(!isset($this->message[$pos]['result'])){
                                        $this->message[$pos]['result'] = 
$this->buildVal($pos);
                                }
                        // build complexType values of attributes and possibly 
simpleContent
                        } elseif (isset($this->message[$pos]['xattrs'])) {
                                if (isset($this->message[$pos]['nil']) && 
$this->message[$pos]['nil']) {
                                        $this->message[$pos]['xattrs']['!'] = 
null;
                                } elseif (isset($this->message[$pos]['cdata']) 
&& trim($this->message[$pos]['cdata']) != '') {
                        if (isset($this->message[$pos]['type'])) {
                                                
$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'] : '');
                                        } else {
                                                $parent = 
$this->message[$pos]['parent'];
                                                if 
(isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 
'array') && isset($this->message[$parent]['arrayType'])) {
                                                        
$this->message[$pos]['xattrs']['!'] = 
$this->decodeSimple($this->message[$pos]['cdata'], 
$this->message[$parent]['arrayType'], 
isset($this->message[$parent]['arrayTypeNamespace']) ? 
$this->message[$parent]['arrayTypeNamespace'] : '');
                                                } else {
                                                        
$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
                                                }
                                        }
                                }
                                $this->message[$pos]['result'] = 
$this->message[$pos]['xattrs'];
                        // set value of simpleType (or nil complexType)
                        } else {
                //$this->debug('adding data for scalar value 
'.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
                                if (isset($this->message[$pos]['nil']) && 
$this->message[$pos]['nil']) {
                                        $this->message[$pos]['xattrs']['!'] = 
null;
                                } elseif (isset($this->message[$pos]['type'])) {
                                        $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'] : '');
                                } else {
                                        $parent = 
$this->message[$pos]['parent'];
                                        if 
(isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 
'array') && isset($this->message[$parent]['arrayType'])) {
                                                $this->message[$pos]['result'] 
= $this->decodeSimple($this->message[$pos]['cdata'], 
$this->message[$parent]['arrayType'], 
isset($this->message[$parent]['arrayTypeNamespace']) ? 
$this->message[$parent]['arrayTypeNamespace'] : '');
                                        } else {
                                                $this->message[$pos]['result'] 
= $this->message[$pos]['cdata'];
                                        }
                                }

                                /* add value to parent's result, if parent is 
struct/array
                                $parent = $this->message[$pos]['parent'];
                                if($this->message[$parent]['type'] != 'map'){
                                        
if(strtolower($this->message[$parent]['type']) == 'array'){
                                                
$this->message[$parent]['result'][] = $this->message[$pos]['result'];
                                        } else {
                                                
$this->message[$parent]['result'][$this->message[$pos]['name']] = 
$this->message[$pos]['result'];
                                        }
                                }
                                */
                        }
                }
                
        // for doclit
        if($this->status == 'header'){
                if ($this->root_header != $pos) {
                        $this->responseHeaders .= "</" . (isset($prefix) ? 
$prefix . ':' : '') . "$name>";
                }
        } elseif($pos >= $this->root_struct){
                $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') 
. "$name>";
        }
                // switch status
                if($pos == $this->root_struct){
                        $this->status = 'body';
                        $this->root_struct_namespace = 
$this->message[$pos]['namespace'];
                } elseif($name == 'Body'){
                        $this->status = 'envelope';
                 } elseif($name == 'Header'){
                        $this->status = 'envelope';
                } elseif($name == 'Envelope'){
                        //
                }
                // set parent back to my parent
                $this->parent = $this->message[$pos]['parent'];
        }

        /**
        * element content handler
        *
        * @param    resource $parser XML parser object
        * @param    string $data element content
        * @access   private
        */
        function character_data($parser, $data){
                $pos = $this->depth_array[$this->depth];
                if ($this->xml_encoding=='UTF-8'){
                        // TODO: add an option to disable this for folks who 
want
                        // raw UTF-8 that, e.g., might not map to iso-8859-1
                        // TODO: this can also be handled with 
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
                        if($this->decode_utf8){
                                $data = utf8_decode($data);
                        }
                }
        $this->message[$pos]['cdata'] .= $data;
        // for doclit
        if($this->status == 'header'){
                $this->responseHeaders .= $data;
        } else {
                $this->document .= $data;
        }
        }

        /**
        * get the parsed message
        *
        * @return       mixed
        * @access   public
        */
        function get_response(){
                return $this->soapresponse;
        }

        /**
        * get the parsed headers
        *
        * @return       string XML or empty if no headers
        * @access   public
        */
        function getHeaders(){
            return $this->responseHeaders;
        }

        /**
        * decodes simple types into PHP variables
        *
        * @param    string $value value to decode
        * @param    string $type XML type to decode
        * @param    string $typens XML type namespace to decode
        * @return       mixed PHP value
        * @access   private
        */
        function decodeSimple($value, $type, $typens) {
                // TODO: use the namespace!
                if ((!isset($type)) || $type == 'string' || $type == 'long' || 
$type == 'unsignedLong') {
                        return (string) $value;
                }
                if ($type == 'int' || $type == 'integer' || $type == 'short' || 
$type == 'byte') {
                        return (int) $value;
                }
                if ($type == 'float' || $type == 'double' || $type == 
'decimal') {
                        return (double) $value;
                }
                if ($type == 'boolean') {
                        if (strtolower($value) == 'false' || strtolower($value) 
== 'f') {
                                return false;
                        }
                        return (boolean) $value;
                }
                if ($type == 'base64' || $type == 'base64Binary') {
                        $this->debug('Decode base64 value');
                        return base64_decode($value);
                }
                // obscure numeric types
                if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
                        || $type == 'nonNegativeInteger' || $type == 
'positiveInteger'
                        || $type == 'unsignedInt'
                        || $type == 'unsignedShort' || $type == 'unsignedByte') 
{
                        return (int) $value;
                }
                // bogus: parser treats array with no elements as a simple type
                if ($type == 'array') {
                        return array();
                }
                // everything else
                return (string) $value;
        }

        /**
        * builds response structures for compound values (arrays/structs)
        * and scalars
        *
        * @param    integer $pos position in node tree
        * @return       mixed   PHP value
        * @access   private
        */
        function buildVal($pos){
                if(!isset($this->message[$pos]['type'])){
                        $this->message[$pos]['type'] = '';
                }
                $this->debug('in buildVal() for 
'.$this->message[$pos]['name']."(pos $pos) of type 
".$this->message[$pos]['type']);
                // if there are children...
                if($this->message[$pos]['children'] != ''){
                        $this->debug('in buildVal, there are children');
                        $children = 
explode('|',$this->message[$pos]['children']);
                        array_shift($children); // knock off empty
                        // md array
                        if(isset($this->message[$pos]['arrayCols']) && 
$this->message[$pos]['arrayCols'] != ''){
                $r=0; // rowcount
                $c=0; // colcount
                foreach($children as $child_pos){
                                        $this->debug("in buildVal, got an MD 
array element: $r, $c");
                                        $params[$r][] = 
$this->message[$child_pos]['result'];
                                    $c++;
                                    if($c == $this->message[$pos]['arrayCols']){
                                        $c = 0;
                                                $r++;
                                    }
                }
            // array
                        } elseif($this->message[$pos]['type'] == 'array' || 
$this->message[$pos]['type'] == 'Array'){
                $this->debug('in buildVal, adding array 
'.$this->message[$pos]['name']);
                foreach($children as $child_pos){
                        $params[] = &$this->message[$child_pos]['result'];
                }
            // apache Map type: java hashtable
            } elseif($this->message[$pos]['type'] == 'Map' && 
$this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
                $this->debug('in buildVal, Java Map 
'.$this->message[$pos]['name']);
                foreach($children as $child_pos){
                        $kv = 
explode("|",$this->message[$child_pos]['children']);
                        $params[$this->message[$kv[1]]['result']] = 
&$this->message[$kv[2]]['result'];
                }
            // generic compound type
            //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || 
$this->message[$pos]['type'] == 'struct') {
                    } else {
                        // Apache Vector type: treat as an array
                $this->debug('in buildVal, adding Java Vector 
'.$this->message[$pos]['name']);
                                if ($this->message[$pos]['type'] == 'Vector' && 
$this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
                                        $notstruct = 1;
                                } else {
                                        $notstruct = 0;
                    }
                //
                foreach($children as $child_pos){
                        if($notstruct){
                                $params[] = 
&$this->message[$child_pos]['result'];
                        } else {
                                if 
(isset($params[$this->message[$child_pos]['name']])) {
                                        // de-serialize repeated element name 
into an array
                                        if 
((!is_array($params[$this->message[$child_pos]['name']])) || 
(!isset($params[$this->message[$child_pos]['name']][0]))) {
                                                
$params[$this->message[$child_pos]['name']] = 
array($params[$this->message[$child_pos]['name']]);
                                        }
                                        
$params[$this->message[$child_pos]['name']][] = 
&$this->message[$child_pos]['result'];
                                } else {
                                                
$params[$this->message[$child_pos]['name']] = 
&$this->message[$child_pos]['result'];
                                            }
                        }
                }
                        }
                        if (isset($this->message[$pos]['xattrs'])) {
                $this->debug('in buildVal, handling attributes');
                                foreach ($this->message[$pos]['xattrs'] as $n 
=> $v) {
                                        $params[$n] = $v;
                                }
                        }
                        // handle simpleContent
                        if (isset($this->message[$pos]['cdata']) && 
trim($this->message[$pos]['cdata']) != '') {
                $this->debug('in buildVal, handling simpleContent');
                if (isset($this->message[$pos]['type'])) {
                                        $params['!'] = 
$this->decodeSimple($this->message[$pos]['cdata'], 
$this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? 
$this->message[$pos]['type_namespace'] : '');
                                } else {
                                        $parent = 
$this->message[$pos]['parent'];
                                        if 
(isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 
'array') && isset($this->message[$parent]['arrayType'])) {
                                                $params['!'] = 
$this->decodeSimple($this->message[$pos]['cdata'], 
$this->message[$parent]['arrayType'], 
isset($this->message[$parent]['arrayTypeNamespace']) ? 
$this->message[$parent]['arrayTypeNamespace'] : '');
                                        } else {
                                                $params['!'] = 
$this->message[$pos]['cdata'];
                                        }
                                }
                        }
                        return is_array($params) ? $params : array();
                } else {
                $this->debug('in buildVal, no children, building scalar');
                        $cdata = isset($this->message[$pos]['cdata']) ? 
$this->message[$pos]['cdata'] : '';
                if (isset($this->message[$pos]['type'])) {
                                return $this->decodeSimple($cdata, 
$this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? 
$this->message[$pos]['type_namespace'] : '');
                        }
                        $parent = $this->message[$pos]['parent'];
                        if (isset($this->message[$parent]['type']) && 
($this->message[$parent]['type'] == 'array') && 
isset($this->message[$parent]['arrayType'])) {
                                return $this->decodeSimple($cdata, 
$this->message[$parent]['arrayType'], 
isset($this->message[$parent]['arrayTypeNamespace']) ? 
$this->message[$parent]['arrayTypeNamespace'] : '');
                        }
                return $this->message[$pos]['cdata'];
                }
        }
}




?>
--- NEW FILE: class.xmlschema.php ---
<?php




/**
* parses an XML Schema, allows access to it's data, other utility methods
* no validation... yet.
* very experimental and limited. As is discussed on XML-DEV, I'm one of the 
people
* that just doesn't have time to read the spec(s) thoroughly, and just have a 
couple of trusty
* tutorials I refer to :)
*
* @author   Dietrich Ayala <dietrich-QnEadSwVb5QAvxtiuMwx3w@xxxxxxxxxxxxxxxx>
* @version  $Id: class.xmlschema.php,v 1.1 2007/07/18 06:53:09 vboctor Exp $
* @access   public
*/
class XMLSchema extends nusoap_base  {
        
        // files
        var $schema = '';
        var $xml = '';
        // namespaces
        var $enclosingNamespaces;
        // schema info
        var $schemaInfo = array();
        var $schemaTargetNamespace = '';
        // types, elements, attributes defined by the schema
        var $attributes = array();
        var $complexTypes = array();
        var $complexTypeStack = array();
        var $currentComplexType = null;
        var $elements = array();
        var $elementStack = array();
        var $currentElement = null;
        var $simpleTypes = array();
        var $simpleTypeStack = array();
        var $currentSimpleType = null;
        // imports
        var $imports = array();
        // parser vars
        var $parser;
        var $position = 0;
        var $depth = 0;
        var $depth_array = array();
        var $message = array();
        var $defaultNamespace = array();
    
        /**
        * constructor
        *
        * @param    string $schema schema document URI
        * @param    string $xml xml document URI
        * @param        string $namespaces namespaces defined in enclosing XML
        * @access   public
        */
        function XMLSchema($schema='',$xml='',$namespaces=array()){
                parent::nusoap_base();
                $this->debug('xmlschema class instantiated, inside 
constructor');
                // files
                $this->schema = $schema;
                $this->xml = $xml;

                // namespaces
                $this->enclosingNamespaces = $namespaces;
                $this->namespaces = array_merge($this->namespaces, $namespaces);

                // parse schema file
                if($schema != ''){
                        $this->debug('initial schema file: '.$schema);
                        $this->parseFile($schema, 'schema');
                }

                // parse xml file
                if($xml != ''){
                        $this->debug('initial xml file: '.$xml);
                        $this->parseFile($xml, 'xml');
                }

        }

    /**
    * parse an XML file
    *
    * @param string $xml, path/URL to XML file
    * @param string $type, (schema | xml)
        * @return boolean
    * @access public
    */
        function parseFile($xml,$type){
                // parse xml file
                if($xml != ""){
                        $xmlStr = @join("",@file($xml));
                        if($xmlStr == ""){
                                $msg = 'Error reading XML from '.$xml;
                                $this->setError($msg);
                                $this->debug($msg);
                        return false;
                        } else {
                                $this->debug("parsing $xml");
                                $this->parseString($xmlStr,$type);
                                $this->debug("done parsing $xml");
                        return true;
                        }
                }
                return false;
        }

        /**
        * parse an XML string
        *
        * @param    string $xml path or URL
    * @param string $type, (schema|xml)
        * @access   private
        */
        function parseString($xml,$type){
                // parse xml string
                if($xml != ""){

                // Create an XML parser.
                $this->parser = xml_parser_create();
                // Set the options for parsing the XML data.
                xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 
0);

                // Set the object for the parser.
                xml_set_object($this->parser, $this);

                // Set the element handlers for the parser.
                        if($type == "schema"){
                        xml_set_element_handler($this->parser, 
'schemaStartElement','schemaEndElement');
                        
xml_set_character_data_handler($this->parser,'schemaCharacterData');
                        } elseif($type == "xml"){
                                xml_set_element_handler($this->parser, 
'xmlStartElement','xmlEndElement');
                        
xml_set_character_data_handler($this->parser,'xmlCharacterData');
                        }

                    // Parse the XML file.
                    if(!xml_parse($this->parser,$xml,true)){
                        // Display an error message.
                                $errstr = sprintf('XML error parsing XML schema 
on line %d: %s',
                                xml_get_current_line_number($this->parser),
                                
xml_error_string(xml_get_error_code($this->parser))
                                );
                                $this->debug($errstr);
                                $this->debug("XML payload:\n" . $xml);
                                $this->setError($errstr);
                }
            
                        xml_parser_free($this->parser);
                } else{
                        $this->debug('no xml passed to parseString()!!');
                        $this->setError('no xml passed to parseString()!!');
                }
        }

        /**
        * start-element handler
        *
        * @param    string $parser XML parser object
        * @param    string $name element name
        * @param    string $attrs associative array of attributes
        * @access   private
        */
        function schemaStartElement($parser, $name, $attrs) {
                
                // position in the total number of elements, starting from 0
                $pos = $this->position++;
                $depth = $this->depth++;
                // set self as current value for this depth
                $this->depth_array[$depth] = $pos;
                $this->message[$pos] = array('cdata' => ''); 
                if ($depth > 0) {
                        $this->defaultNamespace[$pos] = 
$this->defaultNamespace[$this->depth_array[$depth - 1]];
                } else {
                        $this->defaultNamespace[$pos] = false;
                }

                // get element prefix
                if($prefix = $this->getPrefix($name)){
                        // get unqualified name
                        $name = $this->getLocalPart($name);
                } else {
                $prefix = '';
        }
                
        // loop thru attributes, expanding, and registering namespace 
declarations
        if(count($attrs) > 0){
                foreach($attrs as $k => $v){
                // if ns declarations, add to class level array of valid 
namespaces
                                if(ereg("^xmlns",$k)){
                        //$this->xdebug("$k: $v");
                        //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
                        if($ns_prefix = substr(strrchr($k,':'),1)){
                                //$this->xdebug("Add namespace[$ns_prefix] = 
$v");
                                                $this->namespaces[$ns_prefix] = 
$v;
                                        } else {
                                                $this->defaultNamespace[$pos] = 
$v;
                                                if (! 
$this->getPrefixFromNamespace($v)) {
                                                        
$this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
                                                }
                                        }
                                        if($v == 
'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' 
|| $v == 'http://www.w3.org/2000/10/XMLSchema'){
                                                $this->XMLSchemaVersion = $v;
                                                $this->namespaces['xsi'] = 
$v.'-instance';
                                        }
                                }
                }
                foreach($attrs as $k => $v){
                // expand each attribute
                $k = strpos($k,':') ? $this->expandQname($k) : $k;
                $v = strpos($v,':') ? $this->expandQname($v) : $v;
                        $eAttrs[$k] = $v;
                }
                $attrs = $eAttrs;
        } else {
                $attrs = array();
        }
                // find status, register data
                switch($name){
                        case 'all':                     // (optional) 
compositor content for a complexType
                        case 'choice':
                        case 'group':
                        case 'sequence':
                                //$this->xdebug("compositor $name for 
currentComplexType: $this->currentComplexType and currentElement: 
$this->currentElement");
                                
$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
                                //if($name == 'all' || $name == 'sequence'){
                                //      
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
                                //}
                        break;
                        case 'attribute':       // complexType attribute
                //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of 
value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
                $this->xdebug("parsing attribute:");
                $this->appendDebug($this->varDump($attrs));
                                if (!isset($attrs['form'])) {
                                        $attrs['form'] = 
$this->schemaInfo['attributeFormDefault'];
                                }
                if 
(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
                                        $v = 
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
                                        if (!strpos($v, ':')) {
                                                // no namespace in arrayType 
attribute value...
                                                if 
($this->defaultNamespace[$pos]) {
                                                        // ...so use the default
                                                        
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = 
$this->defaultNamespace[$pos] . ':' . 
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
                                                }
                                        }
                }
                if(isset($attrs['name'])){
                                        $this->attributes[$attrs['name']] = 
$attrs;
                                        $aname = $attrs['name'];
                                } elseif(isset($attrs['ref']) && $attrs['ref'] 
== 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
                                        if 
(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
                                $aname = 
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
                        } else {
                                $aname = '';
                        }
                                } elseif(isset($attrs['ref'])){
                                        $aname = $attrs['ref'];
                    $this->attributes[$attrs['ref']] = $attrs;
                                }
                
                                if($this->currentComplexType){  // This should 
*always* be
                                        
$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
                                }
                                // arrayType attribute
                                
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || 
$this->getLocalPart($aname) == 'arrayType'){
                                        
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
                        $prefix = $this->getPrefix($aname);
                                        
if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
                                                $v = 
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
                                        } else {
                                                $v = '';
                                        }
                    if(strpos($v,'[,]')){
                        
$this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
                    }
                    $v = substr($v,0,strpos($v,'[')); // clip the []
                    if(!strpos($v,':') && 
isset($this->typemap[$this->XMLSchemaVersion][$v])){
                        $v = $this->XMLSchemaVersion.':'.$v;
                    }
                    $this->complexTypes[$this->currentComplexType]['arrayType'] 
= $v;
                                }
                        break;
                        case 'complexContent':  // (optional) content for a 
complexType
                        break;
                        case 'complexType':
                                array_push($this->complexTypeStack, 
$this->currentComplexType);
                                if(isset($attrs['name'])){
                                        $this->xdebug('processing named 
complexType '.$attrs['name']);
                                        //$this->currentElement = false;
                                        $this->currentComplexType = 
$attrs['name'];
                                        
$this->complexTypes[$this->currentComplexType] = $attrs;
                                        
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
                                        // This is for constructs like
                                        //           <complexType 
name="ListOfString" base="soap:Array">
                                        //                <sequence>
                                        //                    <element 
name="string" type="xsd:string"
                                        //                        minOccurs="0" 
maxOccurs="unbounded" />
                                        //                </sequence>
                                        //            </complexType>
                                        if(isset($attrs['base']) && 
ereg(':Array$',$attrs['base'])){
                                                $this->xdebug('complexType is 
unusual array');
                                                
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
                                        } else {
                                                
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
                                        }
                                }else{
                                        $this->xdebug('processing unnamed 
complexType for element '.$this->currentElement);
                                        $this->currentComplexType = 
$this->currentElement . '_ContainedType';
                                        //$this->currentElement = false;
                                        
$this->complexTypes[$this->currentComplexType] = $attrs;
                                        
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
                                        // This is for constructs like
                                        //           <complexType 
name="ListOfString" base="soap:Array">
                                        //                <sequence>
                                        //                    <element 
name="string" type="xsd:string"
                                        //                        minOccurs="0" 
maxOccurs="unbounded" />
                                        //                </sequence>
                                        //            </complexType>
                                        if(isset($attrs['base']) && 
ereg(':Array$',$attrs['base'])){
                                                $this->xdebug('complexType is 
unusual array');
                                                
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
                                        } else {
                                                
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
                                        }
                                }
                        break;
                        case 'element':
                                array_push($this->elementStack, 
$this->currentElement);
                                // elements defined as part of a complex type 
should
                                // not really be added to $this->elements, but 
for some
                                // reason, they are
                                if (!isset($attrs['form'])) {
                                        $attrs['form'] = 
$this->schemaInfo['elementFormDefault'];
                                }
                                if(isset($attrs['type'])){
                                        $this->xdebug("processing typed element 
".$attrs['name']." of type ".$attrs['type']);
                                        if (! $this->getPrefix($attrs['type'])) 
{
                                                if 
($this->defaultNamespace[$pos]) {
                                                        $attrs['type'] = 
$this->defaultNamespace[$pos] . ':' . $attrs['type'];
                                                        $this->xdebug('used 
default namespace to make type ' . $attrs['type']);
                                                }
                                        }
                                        // This is for constructs like
                                        //           <complexType 
name="ListOfString" base="soap:Array">
                                        //                <sequence>
                                        //                    <element 
name="string" type="xsd:string"
                                        //                        minOccurs="0" 
maxOccurs="unbounded" />
                                        //                </sequence>
                                        //            </complexType>
                                        if ($this->currentComplexType && 
$this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
                                                $this->xdebug('arrayType for 
unusual array is ' . $attrs['type']);
                                                
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
                                        }
                                        $this->currentElement = $attrs['name'];
                                        $this->elements[ $attrs['name'] ] = 
$attrs;
                                        $this->elements[ $attrs['name'] 
]['typeClass'] = 'element';
                                        $ename = $attrs['name'];
                                } elseif(isset($attrs['ref'])){
                                        $this->xdebug("processing element as 
ref to ".$attrs['ref']);
                                        $this->currentElement = "ref to 
".$attrs['ref'];
                                        $ename = 
$this->getLocalPart($attrs['ref']);
                                } else {
                                        $this->xdebug("processing untyped 
element ".$attrs['name']);
                                        $this->currentElement = $attrs['name'];
                                        $this->elements[ $attrs['name'] ] = 
$attrs;
                                        $this->elements[ $attrs['name'] 
]['typeClass'] = 'element';
                                        $attrs['type'] = 
$this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
                                        $this->elements[ $attrs['name'] 
]['type'] = $attrs['type'];
                                        $ename = $attrs['name'];
                                }
                                if(isset($ename) && $this->currentComplexType){
                                        
$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
                                }
                        break;
                        case 'enumeration':     //      restriction value list 
member
                                $this->xdebug('enumeration ' . $attrs['value']);
                                if ($this->currentSimpleType) {
                                        
$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
                                } elseif ($this->currentComplexType) {
                                        
$this->complexTypes[$this->currentComplexType]['enumeration'][] = 
$attrs['value'];
                                }
                        break;
                        case 'extension':       // simpleContent or 
complexContent type extension
                                $this->xdebug('extension ' . $attrs['base']);
                                if ($this->currentComplexType) {
                                        
$this->complexTypes[$this->currentComplexType]['extensionBase'] = 
$attrs['base'];
                                }
                        break;
                        case 'import':
                            if (isset($attrs['schemaLocation'])) {
                                        //$this->xdebug('import namespace ' . 
$attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
                    $this->imports[$attrs['namespace']][] = array('location' => 
$attrs['schemaLocation'], 'loaded' => false);
                                } else {
                                        //$this->xdebug('import namespace ' . 
$attrs['namespace']);
                    $this->imports[$attrs['namespace']][] = array('location' => 
'', 'loaded' => true);
                                        if (! 
$this->getPrefixFromNamespace($attrs['namespace'])) {
                                                
$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
                                        }
                                }
                        break;
                        case 'list':    // simpleType value list
                        break;
                        case 'restriction':     // simpleType, simpleContent or 
complexContent value restriction
                                $this->xdebug('restriction ' . $attrs['base']);
                                if($this->currentSimpleType){
                                        
$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
                                } elseif($this->currentComplexType){
                                        
$this->complexTypes[$this->currentComplexType]['restrictionBase'] = 
$attrs['base'];
                                        if(strstr($attrs['base'],':') == 
':Array'){
                                                
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
                                        }
                                }
                        break;
                        case 'schema':
                                $this->schemaInfo = $attrs;
                                $this->schemaInfo['schemaVersion'] = 
$this->getNamespaceFromPrefix($prefix);
                                if (isset($attrs['targetNamespace'])) {
                                        $this->schemaTargetNamespace = 
$attrs['targetNamespace'];
                                }
                                if (!isset($attrs['elementFormDefault'])) {
                                        $this->schemaInfo['elementFormDefault'] 
= 'unqualified';
                                }
                                if (!isset($attrs['attributeFormDefault'])) {
                                        
$this->schemaInfo['attributeFormDefault'] = 'unqualified';
                                }
                        break;
                        case 'simpleContent':   // (optional) content for a 
complexType
                        break;
                        case 'simpleType':
                                array_push($this->simpleTypeStack, 
$this->currentSimpleType);
                                if(isset($attrs['name'])){
                                        $this->xdebug("processing simpleType 
for name " . $attrs['name']);
                                        $this->currentSimpleType = 
$attrs['name'];
                                        $this->simpleTypes[ $attrs['name'] ] = 
$attrs;
                                        $this->simpleTypes[ $attrs['name'] 
]['typeClass'] = 'simpleType';
                                        $this->simpleTypes[ $attrs['name'] 
]['phpType'] = 'scalar';
                                } else {
                                        $this->xdebug('processing unnamed 
simpleType for element '.$this->currentElement);
                                        $this->currentSimpleType = 
$this->currentElement . '_ContainedType';
                                        //$this->currentElement = false;
                                        
$this->simpleTypes[$this->currentSimpleType] = $attrs;
                                        
$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
                                }
                        break;
                        case 'union':   // simpleType type list
                        break;
                        default:
                                //$this->xdebug("do not have anything to do for 
element $name");
                }
        }

        /**
        * end-element handler
        *
        * @param    string $parser XML parser object
        * @param    string $name element name
        * @access   private
        */
        function schemaEndElement($parser, $name) {
                // bring depth down a notch
                $this->depth--;
                // position of current element is equal to the last value left 
in depth_array for my depth
                if(isset($this->depth_array[$this->depth])){
                $pos = $this->depth_array[$this->depth];
        }
                // get element prefix
                if ($prefix = $this->getPrefix($name)){
                        // get unqualified name
                        $name = $this->getLocalPart($name);
                } else {
                $prefix = '';
        }
                // move on...
                if($name == 'complexType'){
                        $this->xdebug('done processing complexType ' . 
($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
                        $this->currentComplexType = 
array_pop($this->complexTypeStack);
                        //$this->currentElement = false;
                }
                if($name == 'element'){
                        $this->xdebug('done processing element ' . 
($this->currentElement ? $this->currentElement : '(unknown)'));
                        $this->currentElement = array_pop($this->elementStack);
                }
                if($name == 'simpleType'){
                        $this->xdebug('done processing simpleType ' . 
($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
                        $this->currentSimpleType = 
array_pop($this->simpleTypeStack);
                }
        }

        /**
        * element content handler
        *
        * @param    string $parser XML parser object
        * @param    string $data element content
        * @access   private
        */
        function schemaCharacterData($parser, $data){
                $pos = $this->depth_array[$this->depth - 1];
                $this->message[$pos]['cdata'] .= $data;
        }

        /**
        * serialize the schema
        *
        * @access   public
        */
        function serializeSchema(){

                $schemaPrefix = 
$this->getPrefixFromNamespace($this->XMLSchemaVersion);
                $xml = '';
                // imports
                if (sizeof($this->imports) > 0) {
                        foreach($this->imports as $ns => $list) {
                                foreach ($list as $ii) {
                                        if ($ii['location'] != '') {
                                                $xml .= " <$schemaPrefix:import 
location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
                                        } else {
                                                $xml .= " <$schemaPrefix:import 
namespace=\"" . $ns . "\" />\n";
                                        }
                                }
                        } 
                } 
                // complex types
                foreach($this->complexTypes as $typeName => $attrs){
                        $contentStr = '';
                        // serialize child elements
                        if(isset($attrs['elements']) && 
(count($attrs['elements']) > 0)){
                                foreach($attrs['elements'] as $element => 
$eParts){
                                        if(isset($eParts['ref'])){
                                                $contentStr .= "   
<$schemaPrefix:element ref=\"$element\"/>\n";
                                        } else {
                                                $contentStr .= "   
<$schemaPrefix:element name=\"$element\" type=\"" . 
$this->contractQName($eParts['type']) . "\"";
                                                foreach ($eParts as $aName => 
$aValue) {
                                                        // handle, e.g., 
abstract, default, form, minOccurs, maxOccurs, nillable
                                                        if ($aName != 'name' && 
$aName != 'type') {
                                                                $contentStr .= 
" $aName=\"$aValue\"";
                                                        }
                                                }
                                                $contentStr .= "/>\n";
                                        }
                                }
                                // compositor wraps elements
                                if (isset($attrs['compositor']) && 
($attrs['compositor'] != '')) {
                                        $contentStr = "  
<$schemaPrefix:$attrs[compositor]>\n".$contentStr."  
</$schemaPrefix:$attrs[compositor]>\n";
                                }
                        }
                        // attributes
                        if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 
1)){
                                foreach($attrs['attrs'] as $attr => $aParts){
                                        $contentStr .= "    
<$schemaPrefix:attribute";
                                        foreach ($aParts as $a => $v) {
                                                if ($a == 'ref' || $a == 
'type') {
                                                        $contentStr .= " 
$a=\"".$this->contractQName($v).'"';
                                                } elseif ($a == 
'http://schemas.xmlsoap.org/wsdl/:arrayType') {
                                                        
$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
                                                        $contentStr .= ' 
wsdl:arrayType="'.$this->contractQName($v).'"';
                                                } else {
                                                        $contentStr .= " 
$a=\"$v\"";
                                                }
                                        }
                                        $contentStr .= "/>\n";
                                }
                        }
                        // if restriction
                        if (isset($attrs['restrictionBase']) && 
$attrs['restrictionBase'] != ''){
                                $contentStr = "   <$schemaPrefix:restriction 
base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr."  
 </$schemaPrefix:restriction>\n";
                                // complex or simple content
                                if ((isset($attrs['elements']) && 
count($attrs['elements']) > 0) || (isset($attrs['attrs']) && 
count($attrs['attrs']) > 0)){
                                        $contentStr = "  
<$schemaPrefix:complexContent>\n".$contentStr."  
</$schemaPrefix:complexContent>\n";
                                }
                        }
                        // finalize complex type
                        if($contentStr != ''){
                                $contentStr = " <$schemaPrefix:complexType 
name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
                        } else {
                                $contentStr = " <$schemaPrefix:complexType 
name=\"$typeName\"/>\n";
                        }
                        $xml .= $contentStr;
                }
                // simple types
                if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
                        foreach($this->simpleTypes as $typeName => $eParts){
                                $xml .= " <$schemaPrefix:simpleType 
name=\"$typeName\">\n  <$schemaPrefix:restriction 
base=\"".$this->contractQName($eParts['type'])."\"/>\n";
                                if (isset($eParts['enumeration'])) {
                                        foreach ($eParts['enumeration'] as $e) {
                                                $xml .= "  
<$schemaPrefix:enumeration value=\"$e\"/>\n";
                                        }
                                }
                                $xml .= " </$schemaPrefix:simpleType>";
                        }
                }
                // elements
                if(isset($this->elements) && count($this->elements) > 0){
                        foreach($this->elements as $element => $eParts){
                                $xml .= " <$schemaPrefix:element 
name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
                        }
                }
                // attributes
                if(isset($this->attributes) && count($this->attributes) > 0){
                        foreach($this->attributes as $attr => $aParts){
                                $xml .= " <$schemaPrefix:attribute 
name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
                        }
                }
                // finish 'er up
                $el = "<$schemaPrefix:schema 
targetNamespace=\"$this->schemaTargetNamespace\"\n";
                foreach (array_diff($this->usedNamespaces, 
$this->enclosingNamespaces) as $nsp => $ns) {
                        $el .= " xmlns:$nsp=\"$ns\"\n";
                }
                $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
                return $xml;
        }

        /**
        * adds debug data to the clas level debug string
        *
        * @param    string $string debug data
        * @access   private
        */
        function xdebug($string){
                $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
        }

    /**
    * get the PHP type of a user defined type in the schema
    * PHP type is kind of a misnomer since it actually returns 'struct' for 
assoc. arrays
    * returns false if no type exists, or not w/ the given namespace
    * else returns a string that is either a native php type, or 'struct'
    *
    * @param string $type, name of defined type
    * @param string $ns, namespace of type
    * @return mixed
    * @access public
    * @deprecated
    */
        function getPHPType($type,$ns){
                if(isset($this->typemap[$ns][$type])){
                        //print "found type '$type' and ns $ns in typemap<br>";
                        return $this->typemap[$ns][$type];
                } elseif(isset($this->complexTypes[$type])){
                        //print "getting type '$type' and ns $ns from 
complexTypes array<br>";
                        return $this->complexTypes[$type]['phpType'];
                }
                return false;
        }

        /**
    * returns an associative array of information about a given type
    * returns false if no type exists by the given name
    *
        *       For a complexType typeDef = array(
        *       'restrictionBase' => '',
        *       'phpType' => '',
        *       'compositor' => '(sequence|all)',
        *       'elements' => array(), // refs to elements array
        *       'attrs' => array() // refs to attributes array
        *       ... and so on (see addComplexType)
        *       )
        *
        *   For simpleType or element, the array has different keys.
    *
    * @param string
    * @return mixed
    * @access public
    * @see addComplexType
    * @see addSimpleType
    * @see addElement
    */
        function getTypeDef($type){
                //$this->debug("in getTypeDef for type $type");
                if(isset($this->complexTypes[$type])){
                        $this->xdebug("in getTypeDef, found complexType $type");
                        return $this->complexTypes[$type];
                } elseif(isset($this->simpleTypes[$type])){
                        $this->xdebug("in getTypeDef, found simpleType $type");
                        if (!isset($this->simpleTypes[$type]['phpType'])) {
                                // get info for type to tack onto the simple 
type
                                // TODO: can this ever really apply (i.e. what 
is a simpleType really?)
                                $uqType = 
substr($this->simpleTypes[$type]['type'], 
strrpos($this->simpleTypes[$type]['type'], ':') + 1);
                                $ns = substr($this->simpleTypes[$type]['type'], 
0, strrpos($this->simpleTypes[$type]['type'], ':'));
                                $etype = $this->getTypeDef($uqType);
                                if ($etype) {
                                        $this->xdebug("in getTypeDef, found 
type for simpleType $type:");
                                        $this->xdebug($this->varDump($etype));
                                        if (isset($etype['phpType'])) {
                                                
$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
                                        }
                                        if (isset($etype['elements'])) {
                                                
$this->simpleTypes[$type]['elements'] = $etype['elements'];
                                        }
                                }
                        }
                        return $this->simpleTypes[$type];
                } elseif(isset($this->elements[$type])){
                        $this->xdebug("in getTypeDef, found element $type");
                        if (!isset($this->elements[$type]['phpType'])) {
                                // get info for type to tack onto the element
                                $uqType = 
substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], 
':') + 1);
                                $ns = substr($this->elements[$type]['type'], 0, 
strrpos($this->elements[$type]['type'], ':'));
                                $etype = $this->getTypeDef($uqType);
                                if ($etype) {
                                        $this->xdebug("in getTypeDef, found 
type for element $type:");
                                        $this->xdebug($this->varDump($etype));
                                        if (isset($etype['phpType'])) {
                                                
$this->elements[$type]['phpType'] = $etype['phpType'];
                                        }
                                        if (isset($etype['elements'])) {
                                                
$this->elements[$type]['elements'] = $etype['elements'];
                                        }
                                } elseif ($ns == 
'http://www.w3.org/2001/XMLSchema') {
                                        $this->xdebug("in getTypeDef, element 
$type is an XSD type");
                                        $this->elements[$type]['phpType'] = 
'scalar';
                                }
                        }
                        return $this->elements[$type];
                } elseif(isset($this->attributes[$type])){
                        $this->xdebug("in getTypeDef, found attribute $type");
                        return $this->attributes[$type];
                } elseif (ereg('_ContainedType$', $type)) {
                        $this->xdebug("in getTypeDef, have an untyped element 
$type");
                        $typeDef['typeClass'] = 'simpleType';
                        $typeDef['phpType'] = 'scalar';
                        $typeDef['type'] = 
'http://www.w3.org/2001/XMLSchema:string';
                        return $typeDef;
                }
                $this->xdebug("in getTypeDef, did not find $type");
                return false;
        }

        /**
    * returns a sample serialization of a given type, or false if no type by 
the given name
    *
    * @param string $type, name of type
    * @return mixed
    * @access public
    * @deprecated
    */
    function serializeTypeDef($type){
        //print "in sTD() for type $type<br>";
        if($typeDef = $this->getTypeDef($type)){
                $str .= '<'.$type;
            if(is_array($typeDef['attrs'])){
                foreach($attrs as $attName => $data){
                    $str .= " $attName=\"{type = ".$data['type']."}\"";
                }
            }
            $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
            if(count($typeDef['elements']) > 0){
                $str .= ">";
                foreach($typeDef['elements'] as $element => $eData){
                    $str .= $this->serializeTypeDef($element);
                }
                $str .= "</$type>";
            } elseif($typeDef['typeClass'] == 'element') {
                $str .= "></$type>";
            } else {
                $str .= "/>";
            }
                        return $str;
        }
        return false;
    }

    /**
    * returns HTML form elements that allow a user
    * to enter values for creating an instance of the given type.
    *
    * @param string $name, name for type instance
    * @param string $type, name of type
    * @return string
    * @access public
    * @deprecated
        */
        function typeToForm($name,$type){
                // get typedef
                if($typeDef = $this->getTypeDef($type)){
                        // if struct
                        if($typeDef['phpType'] == 'struct'){
                                $buffer .= '<table>';
                                foreach($typeDef['elements'] as $child => 
$childDef){
                                        $buffer .= "
                                        <tr><td align='right'>$childDef[name] 
(type: ".$this->getLocalPart($childDef['type'])."):</td>
                                        <td><input type='text' 
name='parameters[".$name."][$childDef[name]]'></td></tr>";
                                }
                                $buffer .= '</table>';
                        // if array
                        } elseif($typeDef['phpType'] == 'array'){
                                $buffer .= '<table>';
                                for($i=0;$i < 3; $i++){
                                        $buffer .= "
                                        <tr><td align='right'>array item (type: 
$typeDef[arrayType]):</td>
                                        <td><input type='text' 
name='parameters[".$name."][]'></td></tr>";
                                }
                                $buffer .= '</table>';
                        // if scalar
                        } else {
                                $buffer .= "<input type='text' 
name='parameters[$name]'>";
                        }
                } else {
                        $buffer .= "<input type='text' 
name='parameters[$name]'>";
                }
                return $buffer;
        }
        
        /**
        * adds a complex type to the schema
        * 
        * example: array
        * 
        * addType(
        *       'ArrayOfstring',
        *       'complexType',
        *       'array',
        *       '',
        *       'SOAP-ENC:Array',
        *       array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
        *       'xsd:string'
        * );
        * 
        * example: PHP associative array ( SOAP Struct )
        * 
        * addType(
        *       'SOAPStruct',
        *       'complexType',
        *       'struct',
        *       'all',
        *       array('myVar'=> array('name'=>'myVar','type'=>'string')
        * );
        * 
        * @param name
        * @param typeClass (complexType|simpleType|attribute)
        * @param phpType: currently supported are array and struct (php assoc 
array)
        * @param compositor (all|sequence|choice)
        * @param restrictionBase namespace:name 
(http://schemas.xmlsoap.org/soap/encoding/:Array)
        * @param elements = array ( name = array(name=>'',type=>'') )
        * @param attrs = array(
        *       array(
        *               'ref' => 
"http://schemas.xmlsoap.org/soap/encoding/:arrayType";,
        *               "http://schemas.xmlsoap.org/wsdl/:arrayType"; => 
"string[]"
        *       )
        * )
        * @param arrayType: namespace:name 
(http://www.w3.org/2001/XMLSchema:string)
        * @access public
        * @see getTypeDef
        */
        function 
addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
                $this->complexTypes[$name] = array(
            'name'              => $name,
            'typeClass' => $typeClass,
            'phpType'   => $phpType,
                'compositor'=> $compositor,
            'restrictionBase' => $restrictionBase,
                'elements'      => $elements,
            'attrs'             => $attrs,
            'arrayType' => $arrayType
                );
                
                $this->xdebug("addComplexType $name:");
                $this->appendDebug($this->varDump($this->complexTypes[$name]));
        }
        
        /**
        * adds a simple type to the schema
        *
        * @param string $name
        * @param string $restrictionBase namespace:name 
(http://schemas.xmlsoap.org/soap/encoding/:Array)
        * @param string $typeClass (should always be simpleType)
        * @param string $phpType (should always be scalar)
        * @param array $enumeration array of values
        * @access public
        * @see xmlschema
        * @see getTypeDef
        */
        function addSimpleType($name, $restrictionBase='', 
$typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
                $this->simpleTypes[$name] = array(
            'name'                      => $name,
            'typeClass'         => $typeClass,
            'phpType'           => $phpType,
            'type'                      => $restrictionBase,
            'enumeration'       => $enumeration
                );
                
                $this->xdebug("addSimpleType $name:");
                $this->appendDebug($this->varDump($this->simpleTypes[$name]));
        }

        /**
        * adds an element to the schema
        *
        * @param array $attrs attributes that must include name and type
        * @see xmlschema
        * @access public
        */
        function addElement($attrs) {
                if (! $this->getPrefix($attrs['type'])) {
                        $attrs['type'] = $this->schemaTargetNamespace . ':' . 
$attrs['type'];
                }
                $this->elements[ $attrs['name'] ] = $attrs;
                $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
                
                $this->xdebug("addElement " . $attrs['name']);
                $this->appendDebug($this->varDump($this->elements[ 
$attrs['name'] ]));
        }
}




?>
--- NEW FILE: class.soap_val.php ---
<?php




/**
* For creating serializable abstractions of native PHP types.  This class
* allows element name/namespace, XSD type, and XML attributes to be
* associated with a value.  This is extremely useful when WSDL is not
* used, but is also useful when WSDL is used with polymorphic types, including
* xsd:anyType and user-defined types.
*
* @author   Dietrich Ayala <dietrich-QnEadSwVb5QAvxtiuMwx3w@xxxxxxxxxxxxxxxx>
* @version  $Id: class.soap_val.php,v 1.1 2007/07/18 06:53:06 vboctor Exp $
* @access   public
*/
class soapval extends nusoap_base {
        /**
         * The XML element name
         *
         * @var string
         * @access private
         */
        var $name;
        /**
         * The XML type name (string or false)
         *
         * @var mixed
         * @access private
         */
        var $type;
        /**
         * The PHP value
         *
         * @var mixed
         * @access private
         */
        var $value;
        /**
         * The XML element namespace (string or false)
         *
         * @var mixed
         * @access private
         */
        var $element_ns;
        /**
         * The XML type namespace (string or false)
         *
         * @var mixed
         * @access private
         */
        var $type_ns;
        /**
         * The XML element attributes (array or false)
         *
         * @var mixed
         * @access private
         */
        var $attributes;

        /**
        * constructor
        *
        * @param    string $name optional name
        * @param    mixed $type optional type name
        * @param        mixed $value optional value
        * @param        mixed $element_ns optional namespace of value
        * @param        mixed $type_ns optional namespace of type
        * @param        mixed $attributes associative array of attributes to 
add to element serialization
        * @access   public
        */
        function 
soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false)
 {
                parent::nusoap_base();
                $this->name = $name;
                $this->type = $type;
                $this->value = $value;
                $this->element_ns = $element_ns;
                $this->type_ns = $type_ns;
                $this->attributes = $attributes;
    }

        /**
        * return serialized value
        *
        * @param        string $use The WSDL use value (encoded|literal)
        * @return       string XML data
        * @access   public
        */
        function serialize($use='encoded') {
                return 
$this->serialize_val($this->value,$this->name,$this->type,$this->element_ns,$this->type_ns,$this->attributes,$use);
    }

        /**
        * decodes a soapval object into a PHP native type
        *
        * @return       mixed
        * @access   public
        */
        function decode(){
                return $this->value;
        }
}




?>
--- NEW FILE: class.soapclient.php ---
<?php




/**
*
* soapclient higher level class for easy usage.
*
* usage:
*
* // instantiate client with server info
* $soapclient = new soapclient( string path [ ,boolean wsdl] );
*
* // call method, get results
* echo $soapclient->call( string methodname [ ,array parameters] );
*
* // bye bye client
* unset($soapclient);
*
* @author   Dietrich Ayala <dietrich-QnEadSwVb5QAvxtiuMwx3w@xxxxxxxxxxxxxxxx>
* @version  $Id: class.soapclient.php,v 1.1 2007/07/18 06:53:07 vboctor Exp $
* @access   public
*/
class soapclient extends nusoap_base  {

        var $username = '';
        var $password = '';
        var $authtype = '';
        var $certRequest = array();
        var $requestHeaders = false;    // SOAP headers in request (text)
        var $responseHeaders = '';              // SOAP headers from response 
(incomplete namespace resolution) (text)
        var $document = '';                             // SOAP body response 
portion (incomplete namespace resolution) (text)
        var $endpoint;
        var $forceEndpoint = '';                // overrides WSDL endpoint
    var $proxyhost = '';
    var $proxyport = '';
        var $proxyusername = '';
        var $proxypassword = '';
    var $xml_encoding = '';                     // character set encoding of 
incoming (response) messages
        var $http_encoding = false;
        var $timeout = 0;                               // HTTP connection 
timeout
        var $response_timeout = 30;             // HTTP response timeout
        var $endpointType = '';                 // soap|wsdl, empty for WSDL 
initialization error
        var $persistentConnection = false;
        var $defaultRpcParams = false;  // This is no longer used
        var $request = '';                              // HTTP request
        var $response = '';                             // HTTP response
        var $responseData = '';                 // SOAP payload of response
        var $cookies = array();                 // Cookies from response or for 
request
    var $decode_utf8 = true;            // toggles whether the parser decodes 
element content w/ utf8_decode()
        var $operations = array();              // WSDL operations, empty for 
WSDL initialization error
        
        /*
         * fault related variables
         */
        /**
         * @var      fault
         * @access   public
         */
        var $fault;
        /**
         * @var      faultcode
         * @access   public
         */
        var $faultcode;
        /**
         * @var      faultstring
         * @access   public
         */
        var $faultstring;
        /**
         * @var      faultdetail
         * @access   public
         */
        var $faultdetail;

        /**
        * constructor
        *
        * @param    mixed $endpoint SOAP server or WSDL URL (string), or wsdl 
instance (object)
        * @param    bool $wsdl optional, set to true if using WSDL
        * @param        int $portName optional portName in WSDL document
        * @param    string $proxyhost
        * @param    string $proxyport
        * @param        string $proxyusername
        * @param        string $proxypassword
        * @param        integer $timeout set the connection timeout
        * @param        integer $response_timeout set the response timeout
        * @access   public
        */
        function soapclient($endpoint,$wsdl = false,$proxyhost = 
false,$proxyport = false,$proxyusername = false, $proxypassword = false, 
$timeout = 0, $response_timeout = 30){
                parent::nusoap_base();
                $this->endpoint = $endpoint;
                $this->proxyhost = $proxyhost;
                $this->proxyport = $proxyport;
                $this->proxyusername = $proxyusername;
                $this->proxypassword = $proxypassword;
                $this->timeout = $timeout;
                $this->response_timeout = $response_timeout;

                // make values
                if($wsdl){
                        if (is_object($endpoint) && (get_class($endpoint) == 
'wsdl')) {
                                $this->wsdl = $endpoint;
                                $this->endpoint = $this->wsdl->wsdl;
                                $this->wsdlFile = $this->endpoint;
                                $this->debug('existing wsdl instance created 
from ' . $this->endpoint);
                        } else {
                                $this->wsdlFile = $this->endpoint;
                                
                                // instantiate wsdl object and parse wsdl file
                                $this->debug('instantiating wsdl class with 
doc: '.$endpoint);
                                $this->wsdl =& new 
wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout);
                        }
                        $this->appendDebug($this->wsdl->getDebug());
                        $this->wsdl->clearDebug();
                        // catch errors
                        if($errstr = $this->wsdl->getError()){
                                $this->debug('got wsdl error: '.$errstr);
                                $this->setError('wsdl error: '.$errstr);
                        } elseif($this->operations = 
$this->wsdl->getOperations()){
                                $this->debug( 'got '.count($this->operations).' 
operations from wsdl '.$this->wsdlFile);
                                $this->endpointType = 'wsdl';
                        } else {
                                $this->debug( 'getOperations returned false');
                                $this->setError('no operations defined in the 
WSDL document!');
                        }
                } else {
                        $this->debug("instantiate SOAP with endpoint at 
$endpoint");
                        $this->endpointType = 'soap';
                }
        }

        /**
        * calls method, returns PHP native type
        *
        * @param    string $method SOAP server URL or path
        * @param    mixed $params An array, associative or simple, of the 
parameters
        *                                     for the method call, or a string 
that is the XML
        *                                     for the call.  For rpc style, 
this call will
        *                                     wrap the XML in a tag named after 
the method, as
        *                                     well as the SOAP Envelope and 
Body.  For document
        *                                     style, this will only wrap with 
the Envelope and Body.
        *                                     IMPORTANT: when using an array 
with document style,
        *                                     in which case there
        *                         is really one parameter, the root of the 
fragment
        *                         used in the call, which encloses what 
programmers
        *                         normally think of parameters.  A parameter 
array
        *                         *must* include the wrapper.
        * @param        string $namespace optional method namespace (WSDL can 
override)
        * @param        string $soapAction optional SOAPAction value (WSDL can 
override)
        * @param        mixed $headers optional string of XML with SOAP header 
content, or array of soapval objects for SOAP headers
        * @param        boolean $rpcParams optional (no longer used)
        * @param        string  $style optional (rpc|document) the style to use 
when serializing parameters (WSDL can override)
        * @param        string  $use optional (encoded|literal) the use when 
serializing parameters (WSDL can override)
        * @return       mixed   response from SOAP call
        * @access   public
        */
        function 
call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
                $this->operation = $operation;
                $this->fault = false;
                $this->setError('');
                $this->request = '';
                $this->response = '';
                $this->responseData = '';
                $this->faultstring = '';
                $this->faultcode = '';
                $this->opData = array();
                
                $this->debug("call: operation=$operation, namespace=$namespace, 
soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, 
endpointType=$this->endpointType");
                $this->appendDebug('params=' . $this->varDump($params));
                $this->appendDebug('headers=' . $this->varDump($headers));
                if ($headers) {
                        $this->requestHeaders = $headers;
                }
                // serialize parameters
                if($this->endpointType == 'wsdl' && $opData = 
$this->getOperationData($operation)){
                        // use WSDL for operation
                        $this->opData = $opData;
                        $this->debug("found operation");
                        $this->appendDebug('opData=' . $this->varDump($opData));
                        if (isset($opData['soapAction'])) {
                                $soapAction = $opData['soapAction'];
                        }
                        if (! $this->forceEndpoint) {
                                $this->endpoint = $opData['endpoint'];
                        } else {
                                $this->endpoint = $this->forceEndpoint;
                        }
                        $namespace = isset($opData['input']['namespace']) ? 
$opData['input']['namespace'] :     $namespace;
                        $style = $opData['style'];
                        $use = $opData['input']['use'];
                        // add ns to ns array
                        if($namespace != '' && 
!isset($this->wsdl->namespaces[$namespace])){
                                $nsPrefix = 'ns' . rand(1000, 9999);
                                $this->wsdl->namespaces[$nsPrefix] = $namespace;
                        }
            $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
                        // serialize payload
                        if (is_string($params)) {
                                $this->debug("serializing param string for WSDL 
operation $operation");
                                $payload = $params;
                        } elseif (is_array($params)) {
                                $this->debug("serializing param array for WSDL 
operation $operation");
                                $payload = 
$this->wsdl->serializeRPCParameters($operation,'input',$params);
                        } else {
                                $this->debug('params must be array or string');
                                $this->setError('params must be array or 
string');
                                return false;
                        }
            $usedNamespaces = $this->wsdl->usedNamespaces;
                        if (isset($opData['input']['encodingStyle'])) {
                                $encodingStyle = 
$opData['input']['encodingStyle'];
                        } else {
                                $encodingStyle = '';
                        }
                        $this->appendDebug($this->wsdl->getDebug());
                        $this->wsdl->clearDebug();
                        if ($errstr = $this->wsdl->getError()) {
                                $this->debug('got wsdl error: '.$errstr);
                                $this->setError('wsdl error: '.$errstr);
                                return false;
                        }
                } elseif($this->endpointType == 'wsdl') {
                        // operation not in WSDL
                        $this->appendDebug($this->wsdl->getDebug());
                        $this->wsdl->clearDebug();
                        $this->setError( 'operation '.$operation.' not 
present.');
                        $this->debug("operation '$operation' not present.");
                        return false;
                } else {
                        // no WSDL
                        //$this->namespaces['ns1'] = $namespace;
                        $nsPrefix = 'ns' . rand(1000, 9999);
                        // serialize 
                        $payload = '';
                        if (is_string($params)) {
                                $this->debug("serializing param string for 
operation $operation");
                                $payload = $params;
                        } elseif (is_array($params)) {
                                $this->debug("serializing param array for 
operation $operation");
                                foreach($params as $k => $v){
                                        $payload .= 
$this->serialize_val($v,$k,false,false,false,false,$use);
                                }
                        } else {
                                $this->debug('params must be array or string');
                                $this->setError('params must be array or 
string');
                                return false;
                        }
                        $usedNamespaces = array();
                        if ($use == 'encoded') {
                                $encodingStyle = 
'http://schemas.xmlsoap.org/soap/encoding/';
                        } else {
                                $encodingStyle = '';
                        }
                }
                // wrap RPC calls with method element
                if ($style == 'rpc') {
                        if ($use == 'literal') {
                                $this->debug("wrapping RPC request with literal 
method element");
                                if ($namespace) {
                                        $payload = "<$operation 
xmlns=\"$namespace\">" . $payload . "</$operation>";
                                } else {
                                        $payload = "<$operation>" . $payload . 
"</$operation>";
                                }
                        } else {
                                $this->debug("wrapping RPC request with encoded 
method element");
                                if ($namespace) {
                                        $payload = "<$nsPrefix:$operation 
xmlns:$nsPrefix=\"$namespace\">" .
                                                                $payload .
                                                                
"</$nsPrefix:$operation>";
                                } else {
                                        $payload = "<$operation>" .
                                                                $payload .
                                                                "</$operation>";
                                }
                        }
                }
                // serialize envelope
                $soapmsg = 
$this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
                $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, 
namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
                $this->debug('SOAP message length=' . strlen($soapmsg) . ' 
contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
                // send
                $return = 
$this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
                if($errstr = $this->getError()){
                        $this->debug('Error: '.$errstr);
                        return false;
                } else {
                        $this->return = $return;
                        $this->debug('sent message successfully and got a(n) 
'.gettype($return));
                $this->appendDebug('return=' . $this->varDump($return));
                        
                        // fault?
                        if(is_array($return) && isset($return['faultcode'])){
                                $this->debug('got fault');
                                $this->setError($return['faultcode'].': 
'.$return['faultstring']);
                                $this->fault = true;
                                foreach($return as $k => $v){
                                        $this->$k = $v;
                                        $this->debug("$k = $v<br>");
                                }
                                return $return;
                        } elseif ($style == 'document') {
                                // NOTE: if the response is defined to have 
multiple parts (i.e. unwrapped),
                                // we are only going to return the first part 
here...sorry about that
                                return $return;
                        } else {
                                // array of return values
                                if(is_array($return)){
                                        // multiple 'out' parameters, which we 
return wrapped up
                                        // in the array
                                        if(sizeof($return) > 1){
                                                return $return;
                                        }
                                        // single 'out' parameter (normally the 
return value)
                                        $return = array_shift($return);
                                        $this->debug('return shifted value: ');
                                        
$this->appendDebug($this->varDump($return));
                                return $return;
                                // nothing returned (ie, echoVoid)
                                } else {
                                        return "";
                                }
                        }
                }
        }

        /**
        * get available data pertaining to an operation
        *
        * @param    string $operation operation name
        * @return       array array of data pertaining to the operation
        * @access   public
        */
        function getOperationData($operation){
                if(isset($this->operations[$operation])){
                        return $this->operations[$operation];
                }
                $this->debug("No data for operation: $operation");
        }

    /**
    * send the SOAP message
    *
    * Note: if the operation has multiple return values
    * the return value of this method will be an array
    * of those values.
    *
        * @param    string $msg a SOAPx4 soapmsg object
        * @param    string $soapaction SOAPAction value
        * @param    integer $timeout set connection timeout in seconds
        * @param        integer $response_timeout set response timeout in 
seconds
        * @return       mixed native PHP types.
        * @access   private
        */
        function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) 
{
                $this->checkCookies();
                // detect transport
                switch(true){
                        // http(s)
                        case ereg('^http',$this->endpoint):
                                $this->debug('transporting via HTTP');
                                if($this->persistentConnection == true && 
is_object($this->persistentConnection)){
                                        $http =& $this->persistentConnection;
                                } else {
                                        $http = new 
soap_transport_http($this->endpoint);
                                        if ($this->persistentConnection) {
                                                
$http->usePersistentConnection();
                                        }
                                }
                                
$http->setContentType($this->getHTTPContentType(), 
$this->getHTTPContentTypeCharset());
                                $http->setSOAPAction($soapaction);
                                if($this->proxyhost && $this->proxyport){
                                        
$http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
                                }
                if($this->authtype != '') {
                                        $http->setCredentials($this->username, 
$this->password, $this->authtype, array(), $this->certRequest);
                                }
                                if($this->http_encoding != ''){
                                        
$http->setEncoding($this->http_encoding);
                                }
                                $this->debug('sending message, 
length='.strlen($msg));
                                if(ereg('^http:',$this->endpoint)){
                                //if(strpos($this->endpoint,'http:')){
                                        $this->responseData = 
$http->send($msg,$timeout,$response_timeout,$this->cookies);
                                } elseif(ereg('^https',$this->endpoint)){
                                //} elseif(strpos($this->endpoint,'https:')){
                                        //if(phpversion() == '4.3.0-dev'){
                                                //$response = 
$http->send($msg,$timeout,$response_timeout);
                                //$this->request = $http->outgoing_payload;
                                                //$this->response = 
$http->incoming_payload;
                                        //} else
                                        $this->responseData = 
$http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
                                } else {
                                        $this->setError('no http/s in endpoint 
url');
                                }
                                $this->request = $http->outgoing_payload;
                                $this->response = $http->incoming_payload;
                                $this->appendDebug($http->getDebug());
                                $this->UpdateCookies($http->incoming_cookies);

                                // save transport object if using persistent 
connections
                                if ($this->persistentConnection) {
                                        $http->clearDebug();
                                        if 
(!is_object($this->persistentConnection)) {
                                                $this->persistentConnection = 
$http;
                                        }
                                }
                                
                                if($err = $http->getError()){
                                        $this->setError('HTTP Error: '.$err);
                                        return false;
                                } elseif($this->getError()){
                                        return false;
                                } else {
                                        $this->debug('got response, length='. 
strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
                                        return 
$this->parseResponse($http->incoming_headers, $this->responseData);
                                }
                        break;
                        default:
                                $this->setError('no transport found, or 
selected transport is not yet supported!');
                        return false;
                        break;
                }
        }

        /**
        * processes SOAP message returned from server
        *
        * @param        array   $headers        The HTTP headers
        * @param        string  $data           unprocessed response data from 
server
        * @return       mixed   value of the message, decoded into a PHP type
        * @access   private
        */
    function parseResponse($headers, $data) {
                $this->debug('Entering parseResponse() for data of length ' . 
strlen($data) . ' and type ' . $headers['content-type']);
                if (!strstr($headers['content-type'], 'text/xml')) {
                        $this->setError('Response not of type text/xml');
                        return false;
                }
                if (strpos($headers['content-type'], '=')) {
                        $enc = str_replace('"', '', 
substr(strstr($headers["content-type"], '='), 1));
                        $this->debug('Got response encoding: ' . $enc);
                        if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
                                $this->xml_encoding = strtoupper($enc);
                        } else {
                                $this->xml_encoding = 'US-ASCII';
                        }
                } else {
                        // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for 
HTTP 1.1
                        $this->xml_encoding = 'ISO-8859-1';
                }
                $this->debug('Use encoding: ' . $this->xml_encoding . ' when 
creating soap_parser');
                $parser = new 
soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
                // add parser debug data to our debug
                $this->appendDebug($parser->getDebug());
                // if parse errors
                if($errstr = $parser->getError()){
                        $this->setError( $errstr);
                        // destroy the parser object
                        unset($parser);
                        return false;
                } else {
                        // get SOAP headers
                        $this->responseHeaders = $parser->getHeaders();
                        // get decoded message
                        $return = $parser->get_response();
            // add document for doclit support
            $this->document = $parser->document;
                        // destroy the parser object
                        unset($parser);
                        // return decode message
                        return $return;
                }
         }

        /**
        * sets the SOAP endpoint, which can override WSDL
        *
        * @param        $endpoint string The endpoint URL to use, or empty 
string or false to prevent override
        * @access   public
        */
        function setEndpoint($endpoint) {
                $this->forceEndpoint = $endpoint;
        }

        /**
        * set the SOAP headers
        *
        * @param        $headers mixed String of XML with SOAP header content, 
or array of soapval objects for SOAP headers
        * @access   public
        */
        function setHeaders($headers){
                $this->requestHeaders = $headers;
        }

        /**
        * get the SOAP response headers (namespace resolution incomplete)
        *
        * @return       string
        * @access   public
        */
        function getHeaders(){
                return $this->responseHeaders;
        }

        /**
        * set proxy info here
        *
        * @param    string $proxyhost
        * @param    string $proxyport
        * @param        string $proxyusername
        * @param        string $proxypassword
        * @access   public
        */
        function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', 
$proxypassword = '') {
                $this->proxyhost = $proxyhost;
                $this->proxyport = $proxyport;
                $this->proxyusername = $proxyusername;
                $this->proxypassword = $proxypassword;
        }

        /**
        * if authenticating, set user credentials here
        *
        * @param    string $username
        * @param    string $password
        * @param        string $authtype (basic|digest|certificate)
        * @param        array $certRequest (keys must be cainfofile (optional), 
sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost 
(optional): see corresponding options in cURL docs)
        * @access   public
        */
        function setCredentials($username, $password, $authtype = 'basic', 
$certRequest = array()) {
                $this->username = $username;
                $this->password = $password;
                $this->authtype = $authtype;
                $this->certRequest = $certRequest;
        }
        
        /**
        * use HTTP encoding
        *
        * @param    string $enc
        * @access   public
        */
        function setHTTPEncoding($enc='gzip, deflate'){
                $this->http_encoding = $enc;
        }
        
        /**
        * use HTTP persistent connections if possible
        *
        * @access   public
        */
        function useHTTPPersistentConnection(){
                $this->persistentConnection = true;
        }
        
        /**
        * gets the default RPC parameter setting.
        * If true, default is that call params are like RPC even for document 
style.
        * Each call() can override this value.
        *
        * This is no longer used.
        *
        * @return boolean
        * @access public
        * @deprecated
        */
        function getDefaultRpcParams() {
                return $this->defaultRpcParams;
        }

        /**
        * sets the default RPC parameter setting.
        * If true, default is that call params are like RPC even for document 
style
        * Each call() can override this value.
        *
        * This is no longer used.
        *
        * @param    boolean $rpcParams
        * @access public
        * @deprecated
        */
        function setDefaultRpcParams($rpcParams) {
                $this->defaultRpcParams = $rpcParams;
        }
        
        /**
        * dynamically creates an instance of a proxy class,
        * allowing user to directly call methods from wsdl
        *
        * @return   object soap_proxy object
        * @access   public
        */
        function getProxy(){
                $r = rand();
                $evalStr = $this->_getProxyClassCode($r);
                //$this->debug("proxy class: $evalStr"