2023-06-05 11:23:16 +00:00
< ? php
/*
$Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
NuSOAP - Web Services Toolkit for PHP
Copyright ( c ) 2002 NuSphere Corporation
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 2.1 of the License , or ( at your option ) any later version .
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
The NuSOAP project home is :
http :// sourceforge . net / projects / nusoap /
The primary support for NuSOAP is the Help forum on the project home page .
If you have any questions or comments , please email :
Dietrich Ayala
dietrich @ ganx4 . com
http :// dietrich . ganx4 . com / nusoap
NuSphere Corporation
http :// www . nusphere . com
*/
/*
* Some of the standards implmented in whole or part by NuSOAP :
*
* SOAP 1.1 ( http :// www . w3 . org / TR / 2000 / NOTE - SOAP - 20000508 / )
* WSDL 1.1 ( http :// www . w3 . org / TR / 2001 / NOTE - wsdl - 20010315 )
* SOAP Messages With Attachments ( http :// www . w3 . org / TR / SOAP - attachments )
* XML 1.0 ( http :// www . w3 . org / TR / 2006 / REC - xml - 20060816 / )
* Namespaces in XML 1.0 ( http :// www . w3 . org / TR / 2006 / REC - xml - names - 20060816 / )
* XML Schema 1.0 ( http :// www . w3 . org / TR / xmlschema - 0 / )
* RFC 2045 Multipurpose Internet Mail Extensions ( MIME ) Part One : Format of Internet Message Bodies
* RFC 2068 Hypertext Transfer Protocol -- HTTP / 1.1
* RFC 2617 HTTP Authentication : Basic and Digest Access Authentication
*/
/* load classes
// necessary classes
require_once ( 'class.soapclient.php' );
require_once ( 'class.soap_val.php' );
require_once ( 'class.soap_parser.php' );
require_once ( 'class.soap_fault.php' );
// transport classes
require_once ( 'class.soap_transport_http.php' );
// optional add-on classes
require_once ( 'class.xmlschema.php' );
require_once ( 'class.wsdl.php' );
// server class
require_once ( 'class.soap_server.php' ); */
// class variable emulation
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
$GLOBALS [ '_transient' ][ 'static' ][ 'nusoap_base' ][ 'globalDebugLevel' ] = 9 ;
/**
*
* nusoap_base
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_base {
/**
* Identification for HTTP headers .
*
* @ var string
* @ access private
*/
var $title = 'NuSOAP' ;
/**
* Version for HTTP headers .
*
* @ var string
* @ access private
*/
var $version = '0.9.5' ;
/**
* CVS revision for HTTP headers .
*
* @ var string
* @ access private
*/
var $revision = '$Revision: 1.123 $' ;
/**
* Current error string ( manipulated by getError / setError )
*
* @ var string
* @ access private
*/
var $error_str = '' ;
/**
* Current debug string ( manipulated by debug / appendDebug / clearDebug / getDebug / getDebugAsXMLComment )
*
* @ var string
* @ access private
*/
var $debug_str = '' ;
/**
* toggles automatic encoding of special characters as entities
* ( should always be true , I think )
*
* @ var boolean
* @ access private
*/
var $charencoding = true ;
/**
* the debug level for this instance
*
* @ var integer
* @ access private
*/
var $debugLevel ;
/**
* set schema version
*
* @ var string
* @ access public
*/
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema' ;
/**
* charset encoding for outgoing messages
*
* @ var string
* @ access public
*/
var $soap_defencoding = 'ISO-8859-1' ;
//var $soap_defencoding = 'UTF-8';
/**
* namespaces in an array of prefix => uri
*
* this is " seeded " by a set of constants , but it may be altered by code
*
* @ var array
* @ access public
*/
var $namespaces = array (
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/' ,
'xsd' => 'http://www.w3.org/2001/XMLSchema' ,
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance' ,
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
);
/**
* namespaces used in the current context , e . g . during serialization
*
* @ var array
* @ access private
*/
var $usedNamespaces = array ();
/**
* XML Schema types in an array of uri => ( array of xml type => php type )
* is this legacy yet ?
* no , this is used by the nusoap_xmlschema class to verify type => namespace mappings .
* @ var array
* @ access public
*/
var $typemap = array (
'http://www.w3.org/2001/XMLSchema' => array (
'string' => 'string' , 'boolean' => 'boolean' , 'float' => 'double' , 'double' => 'double' , 'decimal' => 'double' ,
'duration' => '' , 'dateTime' => 'string' , 'time' => 'string' , 'date' => 'string' , 'gYearMonth' => '' ,
'gYear' => '' , 'gMonthDay' => '' , 'gDay' => '' , 'gMonth' => '' , 'hexBinary' => 'string' , 'base64Binary' => 'string' ,
// abstract "any" types
'anyType' => 'string' , 'anySimpleType' => 'string' ,
// derived datatypes
'normalizedString' => 'string' , 'token' => 'string' , 'language' => '' , 'NMTOKEN' => '' , 'NMTOKENS' => '' , 'Name' => '' , 'NCName' => '' , 'ID' => '' ,
'IDREF' => '' , 'IDREFS' => '' , 'ENTITY' => '' , 'ENTITIES' => '' , 'integer' => 'integer' , 'nonPositiveInteger' => 'integer' ,
'negativeInteger' => 'integer' , 'long' => 'integer' , 'int' => 'integer' , 'short' => 'integer' , 'byte' => 'integer' , 'nonNegativeInteger' => 'integer' ,
'unsignedLong' => '' , 'unsignedInt' => '' , 'unsignedShort' => '' , 'unsignedByte' => '' , 'positiveInteger' => '' ),
'http://www.w3.org/2000/10/XMLSchema' => array (
'i4' => '' , 'int' => 'integer' , 'boolean' => 'boolean' , 'string' => 'string' , 'double' => 'double' ,
'float' => 'double' , 'dateTime' => 'string' ,
'timeInstant' => 'string' , 'base64Binary' => 'string' , 'base64' => 'string' , 'ur-type' => 'array' ),
'http://www.w3.org/1999/XMLSchema' => array (
'i4' => '' , 'int' => 'integer' , 'boolean' => 'boolean' , 'string' => 'string' , 'double' => 'double' ,
'float' => 'double' , 'dateTime' => 'string' ,
'timeInstant' => 'string' , 'base64Binary' => 'string' , 'base64' => 'string' , 'ur-type' => 'array' ),
'http://soapinterop.org/xsd' => array ( 'SOAPStruct' => 'struct' ),
'http://schemas.xmlsoap.org/soap/encoding/' => array ( 'base64' => 'string' , 'array' => 'array' , 'Array' => 'array' ),
'http://xml.apache.org/xml-soap' => array ( 'Map' )
);
/**
* XML entities to convert
*
* @ var array
* @ access public
* @ deprecated
* @ see expandEntities
*/
var $xmlEntities = array ( 'quot' => '"' , 'amp' => '&' ,
'lt' => '<' , 'gt' => '>' , 'apos' => " ' " );
/**
* constructor
*
* @ access public
*/
function __construct () {
$this -> debugLevel = $GLOBALS [ '_transient' ][ 'static' ][ 'nusoap_base' ][ 'globalDebugLevel' ];
}
/**
* gets the global debug level , which applies to future instances
*
* @ return integer Debug level 0 - 9 , where 0 turns off
* @ access public
*/
function getGlobalDebugLevel () {
return $GLOBALS [ '_transient' ][ 'static' ][ 'nusoap_base' ][ 'globalDebugLevel' ];
}
/**
* sets the global debug level , which applies to future instances
*
* @ param int $level Debug level 0 - 9 , where 0 turns off
* @ access public
*/
function setGlobalDebugLevel ( $level ) {
$GLOBALS [ '_transient' ][ 'static' ][ 'nusoap_base' ][ 'globalDebugLevel' ] = $level ;
}
/**
* gets the debug level for this instance
*
* @ return int Debug level 0 - 9 , where 0 turns off
* @ access public
*/
function getDebugLevel () {
return $this -> debugLevel ;
}
/**
* sets the debug level for this instance
*
* @ param int $level Debug level 0 - 9 , where 0 turns off
* @ access public
*/
function setDebugLevel ( $level ) {
$this -> debugLevel = $level ;
}
/**
* adds debug data to the instance debug string with formatting
*
* @ param string $string debug data
* @ access private
*/
function debug ( $string ){
if ( $this -> debugLevel > 0 ) {
$this -> appendDebug ( $this -> getmicrotime () . ' ' . get_class ( $this ) . " : $string\n " );
}
}
/**
* adds debug data to the instance debug string without formatting
*
* @ param string $string debug data
* @ access public
*/
function appendDebug ( $string ){
if ( $this -> debugLevel > 0 ) {
// it would be nice to use a memory stream here to use
// memory more efficiently
$this -> debug_str .= $string ;
}
}
/**
* clears the current debug data for this instance
*
* @ access public
*/
function clearDebug () {
// it would be nice to use a memory stream here to use
// memory more efficiently
$this -> debug_str = '' ;
}
/**
* gets the current debug data for this instance
*
* @ return debug data
* @ access public
*/
function & getDebug () {
// it would be nice to use a memory stream here to use
// memory more efficiently
return $this -> debug_str ;
}
/**
* gets the current debug data for this instance as an XML comment
* this may change the contents of the debug data
*
* @ return debug data as an XML comment
* @ access public
*/
function & getDebugAsXMLComment () {
// it would be nice to use a memory stream here to use
// memory more efficiently
while ( strpos ( $this -> debug_str , '--' )) {
$this -> debug_str = str_replace ( '--' , '- -' , $this -> debug_str );
}
$ret = " <!-- \n " . $this -> debug_str . " \n --> " ;
return $ret ;
}
/**
* expands entities , e . g . changes '<' to '<' .
*
* @ param string $val The string in which to expand entities .
* @ access private
*/
function expandEntities ( $val ) {
if ( $this -> charencoding ) {
$val = str_replace ( '&' , '&' , $val );
$val = str_replace ( " ' " , ''' , $val );
$val = str_replace ( '"' , '"' , $val );
$val = str_replace ( '<' , '<' , $val );
$val = str_replace ( '>' , '>' , $val );
}
return $val ;
}
/**
* returns error string if present
*
* @ return mixed error string or false
* @ access public
*/
function getError (){
if ( $this -> error_str != '' ){
return $this -> error_str ;
}
return false ;
}
/**
* sets error string
*
* @ return boolean $string error string
* @ access private
*/
function setError ( $str ){
$this -> error_str = $str ;
}
/**
* detect if array is a simple array or a struct ( associative array )
*
* @ param mixed $val The PHP array
* @ return string ( arraySimple | arrayStruct )
* @ access private
*/
function isArraySimpleOrStruct ( $val ) {
$keyList = array_keys ( $val );
foreach ( $keyList as $keyListValue ) {
if ( ! is_int ( $keyListValue )) {
return 'arrayStruct' ;
}
}
return 'arraySimple' ;
}
/**
* serializes PHP values in accordance w / section 5. Type information is
* not serialized if $use == 'literal' .
*
* @ param mixed $val The value to serialize
* @ param string $name The name ( local part ) of the XML element
* @ param string $type The XML schema type ( local part ) for the element
* @ param string $name_ns The namespace for the name of the XML element
* @ param string $type_ns The namespace for the type of the element
* @ param array $attributes The attributes to serialize as name => value pairs
* @ param string $use The WSDL " use " ( encoded | literal )
* @ param boolean $soapval Whether this is called from soapval .
* @ return string The serialized element , possibly with child elements
* @ access public
*/
function serialize_val ( $val , $name = false , $type = false , $name_ns = false , $type_ns = false , $attributes = false , $use = 'encoded' , $soapval = false ) {
$this -> debug ( " in serialize_val: name= $name , type= $type , name_ns= $name_ns , type_ns= $type_ns , use= $use , soapval= $soapval " );
$this -> appendDebug ( 'value=' . $this -> varDump ( $val ));
$this -> appendDebug ( 'attributes=' . $this -> varDump ( $attributes ));
if ( is_object ( $val ) && get_class ( $val ) == 'soapval' && ( ! $soapval )) {
$this -> debug ( " serialize_val: serialize soapval " );
$xml = $val -> serialize ( $use );
$this -> appendDebug ( $val -> getDebug ());
$val -> clearDebug ();
$this -> debug ( " serialize_val of soapval returning $xml " );
return $xml ;
}
// force valid name if necessary
if ( is_numeric ( $name )) {
$name = '__numeric_' . $name ;
} elseif ( ! $name ) {
$name = 'noname' ;
}
// if name has ns, add ns prefix to name
$xmlns = '' ;
if ( $name_ns ){
$prefix = 'nu' . rand ( 1000 , 9999 );
$name = $prefix . ':' . $name ;
$xmlns .= " xmlns: $prefix = \" $name_ns\ " " ;
}
// if type is prefixed, create type prefix
if ( $type_ns != '' && $type_ns == $this -> namespaces [ 'xsd' ]){
// need to fix this. shouldn't default to xsd if no ns specified
// w/o checking against typemap
$type_prefix = 'xsd' ;
} elseif ( $type_ns ){
$type_prefix = 'ns' . rand ( 1000 , 9999 );
$xmlns .= " xmlns: $type_prefix = \" $type_ns\ " " ;
}
// serialize attributes if present
$atts = '' ;
if ( $attributes ){
foreach ( $attributes as $k => $v ){
$atts .= " $k = \" " . $this -> expandEntities ( $v ) . '"' ;
}
}
// serialize null value
if ( is_null ( $val )) {
$this -> debug ( " serialize_val: serialize null " );
if ( $use == 'literal' ) {
// TODO: depends on minOccurs
$xml = " < $name $xmlns $atts /> " ;
$this -> debug ( " serialize_val returning $xml " );
return $xml ;
} else {
if ( isset ( $type ) && isset ( $type_prefix )) {
$type_str = " xsi:type= \" $type_prefix : $type\ " " ;
} else {
$type_str = '' ;
}
$xml = " < $name $xmlns $type_str $atts xsi:nil= \" true \" /> " ;
$this -> debug ( " serialize_val returning $xml " );
return $xml ;
}
}
// serialize if an xsd built-in primitive type
if ( $type != '' && isset ( $this -> typemap [ $this -> XMLSchemaVersion ][ $type ])){
$this -> debug ( " serialize_val: serialize xsd built-in primitive type " );
if ( is_bool ( $val )) {
if ( $type == 'boolean' ) {
$val = $val ? 'true' : 'false' ;
} elseif ( ! $val ) {
$val = 0 ;
}
} else if ( is_string ( $val )) {
$val = $this -> expandEntities ( $val );
}
if ( $use == 'literal' ) {
$xml = " < $name $xmlns $atts > $val </ $name > " ;
$this -> debug ( " serialize_val returning $xml " );
return $xml ;
} else {
$xml = " < $name $xmlns xsi:type= \" xsd: $type\ " $atts > $val </ $name > " ;
$this -> debug ( " serialize_val returning $xml " );
return $xml ;
}
}
// detect type and serialize
$xml = '' ;
switch ( true ) {
case ( is_bool ( $val ) || $type == 'boolean' ) :
$this -> debug ( " serialize_val: serialize boolean " );
if ( $type == 'boolean' ) {
$val = $val ? 'true' : 'false' ;
} elseif ( ! $val ) {
$val = 0 ;
}
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > $val </ $name > " ;
} else {
$xml .= " < $name $xmlns xsi:type= \" xsd:boolean \" $atts > $val </ $name > " ;
}
break ;
case ( is_int ( $val ) || is_long ( $val ) || $type == 'int' ) :
$this -> debug ( " serialize_val: serialize int " );
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > $val </ $name > " ;
} else {
$xml .= " < $name $xmlns xsi:type= \" xsd:int \" $atts > $val </ $name > " ;
}
break ;
case ( is_float ( $val ) || is_double ( $val ) || $type == 'float' ) :
$this -> debug ( " serialize_val: serialize float " );
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > $val </ $name > " ;
} else {
$xml .= " < $name $xmlns xsi:type= \" xsd:float \" $atts > $val </ $name > " ;
}
break ;
case ( is_string ( $val ) || $type == 'string' ) :
$this -> debug ( " serialize_val: serialize string " );
$val = $this -> expandEntities ( $val );
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > $val </ $name > " ;
} else {
$xml .= " < $name $xmlns xsi:type= \" xsd:string \" $atts > $val </ $name > " ;
}
break ;
case is_object ( $val ) :
$this -> debug ( " serialize_val: serialize object " );
if ( get_class ( $val ) == 'soapval' ) {
$this -> debug ( " serialize_val: serialize soapval object " );
$pXml = $val -> serialize ( $use );
$this -> appendDebug ( $val -> getDebug ());
$val -> clearDebug ();
} else {
if ( ! $name ) {
$name = get_class ( $val );
$this -> debug ( " In serialize_val, used class name $name as element name " );
} else {
$this -> debug ( " In serialize_val, do not override name $name for element name for class " . get_class ( $val ));
}
foreach ( get_object_vars ( $val ) as $k => $v ){
$pXml = isset ( $pXml ) ? $pXml . $this -> serialize_val ( $v , $k , false , false , false , false , $use ) : $this -> serialize_val ( $v , $k , false , false , false , false , $use );
}
}
if ( isset ( $type ) && isset ( $type_prefix )){
$type_str = " xsi:type= \" $type_prefix : $type\ " " ;
} else {
$type_str = '' ;
}
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > $pXml </ $name > " ;
} else {
$xml .= " < $name $xmlns $type_str $atts > $pXml </ $name > " ;
}
break ;
break ;
case ( is_array ( $val ) || $type ) :
// detect if struct or array
$valueType = $this -> isArraySimpleOrStruct ( $val );
if ( $valueType == 'arraySimple' || preg_match ( '/^ArrayOf/' , $type )){
$this -> debug ( " serialize_val: serialize array " );
$i = 0 ;
if ( is_array ( $val ) && count ( $val ) > 0 ){
foreach ( $val as $v ){
if ( is_object ( $v ) && get_class ( $v ) == 'soapval' ){
$tt_ns = $v -> type_ns ;
$tt = $v -> type ;
} elseif ( is_array ( $v )) {
$tt = $this -> isArraySimpleOrStruct ( $v );
} else {
$tt = gettype ( $v );
}
$array_types [ $tt ] = 1 ;
// TODO: for literal, the name should be $name
$xml .= $this -> serialize_val ( $v , 'item' , false , false , false , false , $use );
++ $i ;
}
if ( count ( $array_types ) > 1 ){
$array_typename = 'xsd:anyType' ;
} elseif ( isset ( $tt ) && isset ( $this -> typemap [ $this -> XMLSchemaVersion ][ $tt ])) {
if ( $tt == 'integer' ) {
$tt = 'int' ;
}
$array_typename = 'xsd:' . $tt ;
} elseif ( isset ( $tt ) && $tt == 'arraySimple' ){
$array_typename = 'SOAP-ENC:Array' ;
} elseif ( isset ( $tt ) && $tt == 'arrayStruct' ){
$array_typename = 'unnamed_struct_use_soapval' ;
} else {
// if type is prefixed, create type prefix
if ( $tt_ns != '' && $tt_ns == $this -> namespaces [ 'xsd' ]){
$array_typename = 'xsd:' . $tt ;
} elseif ( $tt_ns ) {
$tt_prefix = 'ns' . rand ( 1000 , 9999 );
$array_typename = " $tt_prefix : $tt " ;
$xmlns .= " xmlns: $tt_prefix = \" $tt_ns\ " " ;
} else {
$array_typename = $tt ;
}
}
$array_type = $i ;
if ( $use == 'literal' ) {
$type_str = '' ;
} else if ( isset ( $type ) && isset ( $type_prefix )) {
$type_str = " xsi:type= \" $type_prefix : $type\ " " ;
} else {
$type_str = " xsi:type= \" SOAP-ENC:Array \" SOAP-ENC:arrayType= \" " . $array_typename . " [ $array_type ] \" " ;
}
// empty array
} else {
if ( $use == 'literal' ) {
$type_str = '' ;
} else if ( isset ( $type ) && isset ( $type_prefix )) {
$type_str = " xsi:type= \" $type_prefix : $type\ " " ;
} else {
$type_str = " xsi:type= \" SOAP-ENC:Array \" SOAP-ENC:arrayType= \" xsd:anyType[0] \" " ;
}
}
// TODO: for array in literal, there is no wrapper here
$xml = " < $name $xmlns $type_str $atts > " . $xml . " </ $name > " ;
} else {
// got a struct
$this -> debug ( " serialize_val: serialize struct " );
if ( isset ( $type ) && isset ( $type_prefix )){
$type_str = " xsi:type= \" $type_prefix : $type\ " " ;
} else {
$type_str = '' ;
}
if ( $use == 'literal' ) {
$xml .= " < $name $xmlns $atts > " ;
} else {
$xml .= " < $name $xmlns $type_str $atts > " ;
}
foreach ( $val as $k => $v ){
// Apache Map
if ( $type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap' ) {
$xml .= '<item>' ;
$xml .= $this -> serialize_val ( $k , 'key' , false , false , false , false , $use );
$xml .= $this -> serialize_val ( $v , 'value' , false , false , false , false , $use );
$xml .= '</item>' ;
} else {
$xml .= $this -> serialize_val ( $v , $k , false , false , false , false , $use );
}
}
$xml .= " </ $name > " ;
}
break ;
default :
$this -> debug ( " serialize_val: serialize unknown " );
$xml .= 'not detected, got ' . gettype ( $val ) . ' for ' . $val ;
break ;
}
$this -> debug ( " serialize_val returning $xml " );
return $xml ;
}
/**
* serializes a message
*
* @ param string $body the XML of the SOAP body
* @ param mixed $headers optional string of XML with SOAP header content , or array of soapval objects for SOAP headers , or associative array
* @ param array $namespaces optional the namespaces used in generating the body and headers
* @ param string $style optional ( rpc | document )
* @ param string $use optional ( encoded | literal )
* @ param string $encodingStyle optional ( usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded )
* @ return string the message
* @ access public
*/
function serializeEnvelope ( $body , $headers = false , $namespaces = array (), $style = 'rpc' , $use = 'encoded' , $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ){
// TODO: add an option to automatically run utf8_encode on $body and $headers
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
// one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
$this -> debug ( " In serializeEnvelope length= " . strlen ( $body ) . " body (max 1000 characters)= " . substr ( $body , 0 , 1000 ) . " style= $style use= $use encodingStyle= $encodingStyle " );
$this -> debug ( " headers: " );
$this -> appendDebug ( $this -> varDump ( $headers ));
$this -> debug ( " namespaces: " );
$this -> appendDebug ( $this -> varDump ( $namespaces ));
// serialize namespaces
$ns_string = '' ;
foreach ( array_merge ( $this -> namespaces , $namespaces ) as $k => $v ){
$ns_string .= " xmlns: $k = \" $v\ " " ;
}
if ( $encodingStyle ) {
$ns_string = " SOAP-ENV:encodingStyle= \" $encodingStyle\ " $ns_string " ;
}
// serialize headers
if ( $headers ){
if ( is_array ( $headers )) {
$xml = '' ;
foreach ( $headers as $k => $v ) {
if ( is_object ( $v ) && get_class ( $v ) == 'soapval' ) {
$xml .= $this -> serialize_val ( $v , false , false , false , false , false , $use );
} else {
$xml .= $this -> serialize_val ( $v , $k , false , false , false , false , $use );
}
}
$headers = $xml ;
$this -> debug ( " In serializeEnvelope, serialized array of headers to $headers " );
}
$headers = " <SOAP-ENV:Header> " . $headers . " </SOAP-ENV:Header> " ;
}
// serialize envelope
return
'<?xml version="1.0" encoding="' . $this -> soap_defencoding . '"?' . " > " .
'<SOAP-ENV:Envelope' . $ns_string . " > " .
$headers .
" <SOAP-ENV:Body> " .
$body .
" </SOAP-ENV:Body> " .
" </SOAP-ENV:Envelope> " ;
}
/**
* formats a string to be inserted into an HTML stream
*
* @ param string $str The string to format
* @ return string The formatted string
* @ access public
* @ deprecated
*/
function formatDump ( $str ){
$str = htmlspecialchars ( $str );
return nl2br ( $str );
}
/**
* contracts ( changes namespace to prefix ) a qualified name
*
* @ param string $qname qname
* @ return string contracted qname
* @ access private
*/
function contractQname ( $qname ){
// get element namespace
//$this->xdebug("Contract $qname");
if ( strrpos ( $qname , ':' )) {
// get unqualified name
$name = substr ( $qname , strrpos ( $qname , ':' ) + 1 );
// get ns
$ns = substr ( $qname , 0 , strrpos ( $qname , ':' ));
$p = $this -> getPrefixFromNamespace ( $ns );
if ( $p ) {
return $p . ':' . $name ;
}
return $qname ;
} else {
return $qname ;
}
}
/**
* expands ( changes prefix to namespace ) a qualified name
*
* @ param string $qname qname
* @ return string expanded qname
* @ access private
*/
function expandQname ( $qname ){
// get element prefix
if ( strpos ( $qname , ':' ) && ! preg_match ( '/^http:\/\//' , $qname )){
// get unqualified name
$name = substr ( strstr ( $qname , ':' ), 1 );
// get ns prefix
$prefix = substr ( $qname , 0 , strpos ( $qname , ':' ));
if ( isset ( $this -> namespaces [ $prefix ])){
return $this -> namespaces [ $prefix ] . ':' . $name ;
} else {
return $qname ;
}
} else {
return $qname ;
}
}
/**
* returns the local part of a prefixed string
* returns the original string , if not prefixed
*
* @ param string $str The prefixed string
* @ return string The local part
* @ access public
*/
function getLocalPart ( $str ){
if ( $sstr = strrchr ( $str , ':' )){
// get unqualified name
return substr ( $sstr , 1 );
} else {
return $str ;
}
}
/**
* returns the prefix part of a prefixed string
* returns false , if not prefixed
*
* @ param string $str The prefixed string
* @ return mixed The prefix or false if there is no prefix
* @ access public
*/
function getPrefix ( $str ){
if ( $pos = strrpos ( $str , ':' )){
// get prefix
return substr ( $str , 0 , $pos );
}
return false ;
}
/**
* pass it a prefix , it returns a namespace
*
* @ param string $prefix The prefix
* @ return mixed The namespace , false if no namespace has the specified prefix
* @ access public
*/
function getNamespaceFromPrefix ( $prefix ){
if ( isset ( $this -> namespaces [ $prefix ])) {
return $this -> namespaces [ $prefix ];
}
//$this->setError("No namespace registered for prefix '$prefix'");
return false ;
}
/**
* returns the prefix for a given namespace ( or prefix )
* or false if no prefixes registered for the given namespace
*
* @ param string $ns The namespace
* @ return mixed The prefix , false if the namespace has no prefixes
* @ access public
*/
function getPrefixFromNamespace ( $ns ) {
foreach ( $this -> namespaces as $p => $n ) {
if ( $ns == $n || $ns == $p ) {
$this -> usedNamespaces [ $p ] = $n ;
return $p ;
}
}
return false ;
}
/**
* returns the time in ODBC canonical form with microseconds
*
* @ return string The time in ODBC canonical form with microseconds
* @ access public
*/
function getmicrotime () {
if ( function_exists ( 'gettimeofday' )) {
$tod = gettimeofday ();
$sec = $tod [ 'sec' ];
$usec = $tod [ 'usec' ];
} else {
$sec = time ();
$usec = 0 ;
}
return strftime ( '%Y-%m-%d %H:%M:%S' , $sec ) . '.' . sprintf ( '%06d' , $usec );
}
/**
* Returns a string with the output of var_dump
*
* @ param mixed $data The variable to var_dump
* @ return string The output of var_dump
* @ access public
*/
function varDump ( $data ) {
ob_start ();
var_dump ( $data );
$ret_val = ob_get_contents ();
ob_end_clean ();
return $ret_val ;
}
/**
* represents the object as a string
*
* @ return string
* @ access public
*/
function __toString () {
return $this -> varDump ( $this );
}
}
// XML Schema Datatype Helper Functions
//xsd:dateTime helpers
/**
* convert unix timestamp to ISO 8601 compliant date string
*
* @ param int $timestamp Unix time stamp
* @ param boolean $utc Whether the time stamp is UTC or local
* @ return mixed ISO 8601 date string or false
* @ access public
*/
function timestamp_to_iso8601 ( $timestamp , $utc = true ){
$datestr = date ( 'Y-m-d\TH:i:sO' , $timestamp );
$pos = strrpos ( $datestr , " + " );
if ( $pos === FALSE ) {
$pos = strrpos ( $datestr , " - " );
}
if ( $pos !== FALSE ) {
if ( strlen ( $datestr ) == $pos + 5 ) {
$datestr = substr ( $datestr , 0 , $pos + 3 ) . ':' . substr ( $datestr , - 2 );
}
}
if ( $utc ){
$pattern = '/' .
'([0-9]{4})-' . // centuries & years CCYY-
'([0-9]{2})-' . // months MM-
'([0-9]{2})' . // days DD
'T' . // separator T
'([0-9]{2}):' . // hours hh:
'([0-9]{2}):' . // minutes mm:
'([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
'/' ;
if ( preg_match ( $pattern , $datestr , $regs )){
return sprintf ( '%04d-%02d-%02dT%02d:%02d:%02dZ' , $regs [ 1 ], $regs [ 2 ], $regs [ 3 ], $regs [ 4 ], $regs [ 5 ], $regs [ 6 ]);
}
return false ;
} else {
return $datestr ;
}
}
/**
* convert ISO 8601 compliant date string to unix timestamp
*
* @ param string $datestr ISO 8601 compliant date string
* @ return mixed Unix timestamp ( int ) or false
* @ access public
*/
function iso8601_to_timestamp ( $datestr ){
$pattern = '/' .
'([0-9]{4})-' . // centuries & years CCYY-
'([0-9]{2})-' . // months MM-
'([0-9]{2})' . // days DD
'T' . // separator T
'([0-9]{2}):' . // hours hh:
'([0-9]{2}):' . // minutes mm:
'([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
'/' ;
if ( preg_match ( $pattern , $datestr , $regs )){
// not utc
if ( $regs [ 8 ] != 'Z' ){
$op = substr ( $regs [ 8 ], 0 , 1 );
$h = substr ( $regs [ 8 ], 1 , 2 );
$m = substr ( $regs [ 8 ], strlen ( $regs [ 8 ]) - 2 , 2 );
if ( $op == '-' ){
$regs [ 4 ] = $regs [ 4 ] + $h ;
$regs [ 5 ] = $regs [ 5 ] + $m ;
} elseif ( $op == '+' ){
$regs [ 4 ] = $regs [ 4 ] - $h ;
$regs [ 5 ] = $regs [ 5 ] - $m ;
}
}
return gmmktime ( $regs [ 4 ], $regs [ 5 ], $regs [ 6 ], $regs [ 2 ], $regs [ 3 ], $regs [ 1 ]);
// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
} else {
return false ;
}
}
/**
* sleeps some number of microseconds
*
* @ param string $usec the number of microseconds to sleep
* @ access public
* @ deprecated
*/
function usleepWindows ( $usec )
{
$start = gettimeofday ();
do
{
$stop = gettimeofday ();
$timePassed = 1000000 * ( $stop [ 'sec' ] - $start [ 'sec' ])
+ $stop [ 'usec' ] - $start [ 'usec' ];
}
while ( $timePassed < $usec );
}
?> <?php
/**
* Contains information for a SOAP fault .
* Mainly used for returning faults from deployed functions
* in a server instance .
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_fault extends nusoap_base {
/**
* The fault code ( client | server )
* @ var string
* @ access private
*/
var $faultcode ;
/**
* The fault actor
* @ var string
* @ access private
*/
var $faultactor ;
/**
* The fault string , a description of the fault
* @ var string
* @ access private
*/
var $faultstring ;
/**
* The fault detail , typically a string or array of string
* @ var mixed
* @ access private
*/
var $faultdetail ;
/**
* constructor
*
* @ param string $faultcode ( SOAP - ENV : Client | SOAP - ENV : Server )
* @ param string $faultactor only used when msg routed between multiple actors
* @ param string $faultstring human readable error message
* @ param mixed $faultdetail detail , typically a string or array of string
*/
function __construct ( $faultcode , $faultactor = '' , $faultstring = '' , $faultdetail = '' ){
parent :: nusoap_base ();
$this -> faultcode = $faultcode ;
$this -> faultactor = $faultactor ;
$this -> faultstring = $faultstring ;
$this -> faultdetail = $faultdetail ;
}
/**
* serialize a fault
*
* @ return string The serialization of the fault instance .
* @ access public
*/
function serialize (){
$ns_string = '' ;
foreach ( $this -> namespaces as $k => $v ){
$ns_string .= " \n xmlns: $k = \" $v\ " " ;
}
$return_msg =
'<?xml version="1.0" encoding="' . $this -> soap_defencoding . '"?>' .
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . " > \n " .
'<SOAP-ENV:Body>' .
'<SOAP-ENV:Fault>' .
$this -> serialize_val ( $this -> faultcode , 'faultcode' ) .
$this -> serialize_val ( $this -> faultactor , 'faultactor' ) .
$this -> serialize_val ( $this -> faultstring , 'faultstring' ) .
$this -> serialize_val ( $this -> faultdetail , 'detail' ) .
'</SOAP-ENV:Fault>' .
'</SOAP-ENV:Body>' .
'</SOAP-ENV:Envelope>' ;
return $return_msg ;
}
}
/**
* Backward compatibility
*/
class soap_fault extends nusoap_fault {
}
?> <?php
/**
* parses an XML Schema , allows access to it ' s data , other utility methods .
* imperfect , no validation ... yet , but quite functional .
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_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 __construct ( $schema = '' , $xml = '' , $namespaces = array ()){
parent :: nusoap_base ();
$this -> debug ( 'nusoap_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()!!' );
}
}
/**
* gets a type name for an unnamed type
*
* @ param string Element name
* @ return string A type name for an unnamed type
* @ access private
*/
function CreateTypeName ( $ename ) {
$scope = '' ;
for ( $i = 0 ; $i < count ( $this -> complexTypeStack ); $i ++ ) {
$scope .= $this -> complexTypeStack [ $i ] . '_' ;
}
return $scope . $ename . '_ContainedType' ;
}
/**
* 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 ( preg_match ( '/^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' ])) {
// TODO: handle globals
$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
$this -> xdebug ( " do nothing for element $name " );
break ;
case 'complexType' :
array_push ( $this -> complexTypeStack , $this -> currentComplexType );
if ( isset ( $attrs [ 'name' ])){
// TODO: what is the scope of named complexTypes that appear
// nested within other c complexTypes?
$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' ]) && preg_match ( '/:Array$/' , $attrs [ 'base' ])){
$this -> xdebug ( 'complexType is unusual array' );
$this -> complexTypes [ $this -> currentComplexType ][ 'phpType' ] = 'array' ;
} else {
$this -> complexTypes [ $this -> currentComplexType ][ 'phpType' ] = 'struct' ;
}
} else {
$name = $this -> CreateTypeName ( $this -> currentElement );
$this -> xdebug ( 'processing unnamed complexType for element ' . $this -> currentElement . ' named ' . $name );
$this -> currentComplexType = $name ;
//$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' ]) && preg_match ( '/:Array$/' , $attrs [ 'base' ])){
$this -> xdebug ( 'complexType is unusual array' );
$this -> complexTypes [ $this -> currentComplexType ][ 'phpType' ] = 'array' ;
} else {
$this -> complexTypes [ $this -> currentComplexType ][ 'phpType' ] = 'struct' ;
}
}
$this -> complexTypes [ $this -> currentComplexType ][ 'simpleContent' ] = 'false' ;
break ;
case 'element' :
array_push ( $this -> elementStack , $this -> currentElement );
if ( ! isset ( $attrs [ 'form' ])) {
if ( $this -> currentComplexType ) {
$attrs [ 'form' ] = $this -> schemaInfo [ 'elementFormDefault' ];
} else {
// global
$attrs [ 'form' ] = 'qualified' ;
}
}
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' ];
$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 {
$type = $this -> CreateTypeName ( $this -> currentComplexType . '_' . $attrs [ 'name' ]);
$this -> xdebug ( " processing untyped element " . $attrs [ 'name' ] . ' type ' . $type );
$this -> currentElement = $attrs [ 'name' ];
$attrs [ 'type' ] = $this -> schemaTargetNamespace . ':' . $type ;
$ename = $attrs [ 'name' ];
}
if ( isset ( $ename ) && $this -> currentComplexType ) {
$this -> xdebug ( " add element $ename to complexType $this->currentComplexType " );
$this -> complexTypes [ $this -> currentComplexType ][ 'elements' ][ $ename ] = $attrs ;
} elseif ( ! isset ( $attrs [ 'ref' ])) {
$this -> xdebug ( " add element $ename to elements array " );
$this -> elements [ $attrs [ 'name' ] ] = $attrs ;
$this -> elements [ $attrs [ 'name' ] ][ 'typeClass' ] = 'element' ;
}
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 ) {
$ns = $this -> getPrefix ( $attrs [ 'base' ]);
if ( $ns == '' ) {
$this -> complexTypes [ $this -> currentComplexType ][ 'extensionBase' ] = $this -> schemaTargetNamespace . ':' . $attrs [ 'base' ];
} else {
$this -> complexTypes [ $this -> currentComplexType ][ 'extensionBase' ] = $attrs [ 'base' ];
}
} else {
$this -> xdebug ( 'no current complexType to set extensionBase' );
}
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 'include' :
if ( isset ( $attrs [ 'schemaLocation' ])) {
$this -> xdebug ( 'include into namespace ' . $this -> schemaTargetNamespace . ' from ' . $attrs [ 'schemaLocation' ]);
$this -> imports [ $this -> schemaTargetNamespace ][] = array ( 'location' => $attrs [ 'schemaLocation' ], 'loaded' => false );
} else {
$this -> xdebug ( 'ignoring invalid XML Schema construct: include without schemaLocation attribute' );
}
break ;
case 'list' : // simpleType value list
$this -> xdebug ( " do nothing for element $name " );
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
if ( $this -> currentComplexType ) { // This should *always* be
$this -> complexTypes [ $this -> currentComplexType ][ 'simpleContent' ] = 'true' ;
} else {
$this -> xdebug ( " do nothing for element $name because there is no current 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 {
$name = $this -> CreateTypeName ( $this -> currentComplexType . '_' . $this -> currentElement );
$this -> xdebug ( 'processing unnamed simpleType for element ' . $this -> currentElement . ' named ' . $name );
$this -> currentSimpleType = $name ;
//$this->currentElement = false;
$this -> simpleTypes [ $this -> currentSimpleType ] = $attrs ;
$this -> simpleTypes [ $this -> currentSimpleType ][ 'phpType' ] = 'scalar' ;
}
break ;
case 'union' : // simpleType type list
$this -> xdebug ( " do nothing for element $name " );
break ;
default :
$this -> xdebug ( " do not have any logic to process 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 -> xdebug ( $this -> varDump ( $this -> complexTypes [ $this -> currentComplexType ]));
$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 -> xdebug ( $this -> varDump ( $this -> simpleTypes [ $this -> currentSimpleType ]));
$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 :restriction> \n </ $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
$attr = '' ;
foreach ( $this -> schemaInfo as $k => $v ) {
if ( $k == 'elementFormDefault' || $k == 'attributeFormDefault' ) {
$attr .= " $k = \" $v\ " " ;
}
}
$el = " < $schemaPrefix :schema $attr targetNamespace= \" $this->schemaTargetNamespace\ " \n " ;
foreach ( array_diff ( $this -> usedNamespaces , $this -> enclosingNamespaces ) as $nsp => $ns ) {
$el .= " xmlns: $nsp = \" $ns\ " " ;
}
$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 $type
* @ return mixed
* @ access public
* @ see addComplexType
* @ see addSimpleType
* @ see addElement
*/
function getTypeDef ( $type ){
//$this->debug("in getTypeDef for type $type");
if ( substr ( $type , - 1 ) == '^' ) {
$is_element = 1 ;
$type = substr ( $type , 0 , - 1 );
} else {
$is_element = 0 ;
}
if (( ! $is_element ) && isset ( $this -> complexTypes [ $type ])){
$this -> xdebug ( " in getTypeDef, found complexType $type " );
return $this -> complexTypes [ $type ];
} elseif (( ! $is_element ) && 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' ];
}
if ( isset ( $etype [ 'extensionBase' ])) {
$this -> elements [ $type ][ 'extensionBase' ] = $etype [ 'extensionBase' ];
}
} 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 ( preg_match ( '/_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 ( $typeDef [ '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 nusoap_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 nusoap_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' ] ]));
}
}
/**
* Backward compatibility
*/
class XMLSchema extends nusoap_xmlschema {
}
?> <?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 @ ganx4 . com >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol 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 __construct ( $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 , true );
}
/**
* decodes a soapval object into a PHP native type
*
* @ return mixed
* @ access public
*/
function decode (){
return $this -> value ;
}
}
?> <?php
/**
* transport class for sending / receiving data via HTTP and HTTPS
* NOTE : PHP must be compiled with the CURL extension for HTTPS support
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class soap_transport_http extends nusoap_base {
var $url = '' ;
var $uri = '' ;
var $digest_uri = '' ;
var $scheme = '' ;
var $host = '' ;
var $port = '' ;
var $path = '' ;
var $request_method = 'POST' ;
var $protocol_version = '1.0' ;
var $encoding = '' ;
var $outgoing_headers = array ();
var $incoming_headers = array ();
var $incoming_cookies = array ();
var $outgoing_payload = '' ;
var $incoming_payload = '' ;
var $response_status_line ; // HTTP response status line
var $useSOAPAction = true ;
var $persistentConnection = false ;
var $ch = false ; // cURL handle
var $ch_options = array (); // cURL custom options
var $use_curl = false ; // force cURL use
var $proxy = null ; // proxy information (associative array)
var $username = '' ;
var $password = '' ;
var $authtype = '' ;
var $digestRequest = array ();
var $certRequest = array (); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
// passphrase: SSL key password/passphrase
// certpassword: SSL certificate password
// verifypeer: default is 1
// verifyhost: default is 1
/**
* constructor
*
* @ param string $url The URL to which to connect
* @ param array $curl_options User - specified cURL options
* @ param boolean $use_curl Whether to try to force cURL use
* @ access public
*/
function __construct ( $url , $curl_options = NULL , $use_curl = false ){
parent :: nusoap_base ();
$this -> debug ( " ctor url= $url use_curl= $use_curl curl_options: " );
$this -> appendDebug ( $this -> varDump ( $curl_options ));
$this -> setURL ( $url );
if ( is_array ( $curl_options )) {
$this -> ch_options = $curl_options ;
}
$this -> use_curl = $use_curl ;
preg_match ( '/\$Revisio' . 'n: ([^ ]+)/' , $this -> revision , $rev );
$this -> setHeader ( 'User-Agent' , $this -> title . '/' . $this -> version . ' (' . $rev [ 1 ] . ')' );
}
/**
* sets a cURL option
*
* @ param mixed $option The cURL option ( always integer ? )
* @ param mixed $value The cURL option value
* @ access private
*/
function setCurlOption ( $option , $value ) {
$this -> debug ( " setCurlOption option= $option , value= " );
$this -> appendDebug ( $this -> varDump ( $value ));
curl_setopt ( $this -> ch , $option , $value );
}
/**
* sets an HTTP header
*
* @ param string $name The name of the header
* @ param string $value The value of the header
* @ access private
*/
function setHeader ( $name , $value ) {
$this -> outgoing_headers [ $name ] = $value ;
$this -> debug ( " set header $name : $value " );
}
/**
* unsets an HTTP header
*
* @ param string $name The name of the header
* @ access private
*/
function unsetHeader ( $name ) {
if ( isset ( $this -> outgoing_headers [ $name ])) {
$this -> debug ( " unset header $name " );
unset ( $this -> outgoing_headers [ $name ]);
}
}
/**
* sets the URL to which to connect
*
* @ param string $url The URL to which to connect
* @ access private
*/
function setURL ( $url ) {
$this -> url = $url ;
$u = parse_url ( $url );
foreach ( $u as $k => $v ){
$this -> debug ( " parsed URL $k = $v " );
$this -> $k = $v ;
}
// add any GET params to path
if ( isset ( $u [ 'query' ]) && $u [ 'query' ] != '' ){
$this -> path .= '?' . $u [ 'query' ];
}
// set default port
if ( ! isset ( $u [ 'port' ])){
if ( $u [ 'scheme' ] == 'https' ){
$this -> port = 443 ;
} else {
$this -> port = 80 ;
}
}
$this -> uri = $this -> path ;
$this -> digest_uri = $this -> uri ;
// build headers
if ( ! isset ( $u [ 'port' ])) {
$this -> setHeader ( 'Host' , $this -> host );
} else {
$this -> setHeader ( 'Host' , $this -> host . ':' . $this -> port );
}
if ( isset ( $u [ 'user' ]) && $u [ 'user' ] != '' ) {
$this -> setCredentials ( urldecode ( $u [ 'user' ]), isset ( $u [ 'pass' ]) ? urldecode ( $u [ 'pass' ]) : '' );
}
}
/**
* gets the I / O method to use
*
* @ return string I / O method to use ( socket | curl | unknown )
* @ access private
*/
function io_method () {
if ( $this -> use_curl || ( $this -> scheme == 'https' ) || ( $this -> scheme == 'http' && $this -> authtype == 'ntlm' ) || ( $this -> scheme == 'http' && is_array ( $this -> proxy ) && $this -> proxy [ 'authtype' ] == 'ntlm' ))
return 'curl' ;
if (( $this -> scheme == 'http' || $this -> scheme == 'ssl' ) && $this -> authtype != 'ntlm' && ( ! is_array ( $this -> proxy ) || $this -> proxy [ 'authtype' ] != 'ntlm' ))
return 'socket' ;
return 'unknown' ;
}
/**
* establish an HTTP connection
*
* @ param integer $timeout set connection timeout in seconds
* @ param integer $response_timeout set response timeout in seconds
* @ return boolean true if connected , false if not
* @ access private
*/
function connect ( $connection_timeout = 0 , $response_timeout = 30 ){
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
// "regular" socket.
// TODO: disabled for now because OpenSSL must be *compiled* in (not just
// loaded), and until PHP5 stream_get_wrappers is not available.
// if ($this->scheme == 'https') {
// if (version_compare(phpversion(), '4.3.0') >= 0) {
// if (extension_loaded('openssl')) {
// $this->scheme = 'ssl';
// $this->debug('Using SSL over OpenSSL');
// }
// }
// }
$this -> debug ( " connect connection_timeout $connection_timeout , response_timeout $response_timeout , scheme $this->scheme , host $this->host , port $this->port " );
if ( $this -> io_method () == 'socket' ) {
if ( ! is_array ( $this -> proxy )) {
$host = $this -> host ;
$port = $this -> port ;
} else {
$host = $this -> proxy [ 'host' ];
$port = $this -> proxy [ 'port' ];
}
// use persistent connection
if ( $this -> persistentConnection && isset ( $this -> fp ) && is_resource ( $this -> fp )){
if ( ! feof ( $this -> fp )) {
$this -> debug ( 'Re-use persistent connection' );
return true ;
}
fclose ( $this -> fp );
$this -> debug ( 'Closed persistent connection at EOF' );
}
// munge host if using OpenSSL
if ( $this -> scheme == 'ssl' ) {
$host = 'ssl://' . $host ;
}
$this -> debug ( 'calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout );
// open socket
if ( $connection_timeout > 0 ){
$this -> fp = @ fsockopen ( $host , $this -> port , $this -> errno , $this -> error_str , $connection_timeout );
} else {
$this -> fp = @ fsockopen ( $host , $this -> port , $this -> errno , $this -> error_str );
}
// test pointer
if ( ! $this -> fp ) {
$msg = 'Couldn\'t open socket connection to server ' . $this -> url ;
if ( $this -> errno ) {
$msg .= ', Error (' . $this -> errno . '): ' . $this -> error_str ;
} else {
$msg .= ' prior to connect(). This is often a problem looking up the host name.' ;
}
$this -> debug ( $msg );
$this -> setError ( $msg );
return false ;
}
// set response timeout
$this -> debug ( 'set response timeout to ' . $response_timeout );
socket_set_timeout ( $this -> fp , $response_timeout );
$this -> debug ( 'socket connected' );
return true ;
} else if ( $this -> io_method () == 'curl' ) {
if ( ! extension_loaded ( 'curl' )) {
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
$this -> setError ( 'The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.' );
return false ;
}
// Avoid warnings when PHP does not have these options
if ( defined ( 'CURLOPT_CONNECTIONTIMEOUT' ))
$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT ;
else
$CURLOPT_CONNECTIONTIMEOUT = 78 ;
if ( defined ( 'CURLOPT_HTTPAUTH' ))
$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH ;
else
$CURLOPT_HTTPAUTH = 107 ;
if ( defined ( 'CURLOPT_PROXYAUTH' ))
$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH ;
else
$CURLOPT_PROXYAUTH = 111 ;
if ( defined ( 'CURLAUTH_BASIC' ))
$CURLAUTH_BASIC = CURLAUTH_BASIC ;
else
$CURLAUTH_BASIC = 1 ;
if ( defined ( 'CURLAUTH_DIGEST' ))
$CURLAUTH_DIGEST = CURLAUTH_DIGEST ;
else
$CURLAUTH_DIGEST = 2 ;
if ( defined ( 'CURLAUTH_NTLM' ))
$CURLAUTH_NTLM = CURLAUTH_NTLM ;
else
$CURLAUTH_NTLM = 8 ;
$this -> debug ( 'connect using cURL' );
// init CURL
$this -> ch = curl_init ();
// set url
$hostURL = ( $this -> port != '' ) ? " $this->scheme :// $this->host : $this->port " : " $this->scheme :// $this->host " ;
// add path
$hostURL .= $this -> path ;
$this -> setCurlOption ( CURLOPT_URL , $hostURL );
// follow location headers (re-directs)
if ( ini_get ( 'open_basedir' )) {
$this -> debug ( 'open_basedir set, so do not set CURLOPT_FOLLOWLOCATION' );
$this -> debug ( 'open_basedir = ' );
$this -> appendDebug ( $this -> varDump ( ini_get ( 'open_basedir' )));
} else {
$this -> setCurlOption ( CURLOPT_FOLLOWLOCATION , 1 );
}
// ask for headers in the response output
$this -> setCurlOption ( CURLOPT_HEADER , 1 );
// ask for the response output as the return value
$this -> setCurlOption ( CURLOPT_RETURNTRANSFER , 1 );
// encode
// We manage this ourselves through headers and encoding
// if(function_exists('gzuncompress')){
// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
// }
// persistent connection
if ( $this -> persistentConnection ) {
// I believe the following comment is now bogus, having applied to
// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
// The way we send data, we cannot use persistent connections, since
// there will be some "junk" at the end of our request.
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
$this -> persistentConnection = false ;
$this -> setHeader ( 'Connection' , 'close' );
}
// set timeouts
if ( $connection_timeout != 0 ) {
$this -> setCurlOption ( $CURLOPT_CONNECTIONTIMEOUT , $connection_timeout );
}
if ( $response_timeout != 0 ) {
$this -> setCurlOption ( CURLOPT_TIMEOUT , $response_timeout );
}
if ( $this -> scheme == 'https' ) {
$this -> debug ( 'set cURL SSL verify options' );
// recent versions of cURL turn on peer/host checking by default,
// while PHP binaries are not compiled with a default location for the
// CA cert bundle, so disable peer/host checking.
//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
$this -> setCurlOption ( CURLOPT_SSL_VERIFYPEER , 0 );
$this -> setCurlOption ( CURLOPT_SSL_VERIFYHOST , 0 );
// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
if ( $this -> authtype == 'certificate' ) {
$this -> debug ( 'set cURL certificate options' );
if ( isset ( $this -> certRequest [ 'cainfofile' ])) {
$this -> setCurlOption ( CURLOPT_CAINFO , $this -> certRequest [ 'cainfofile' ]);
}
if ( isset ( $this -> certRequest [ 'verifypeer' ])) {
$this -> setCurlOption ( CURLOPT_SSL_VERIFYPEER , $this -> certRequest [ 'verifypeer' ]);
} else {
$this -> setCurlOption ( CURLOPT_SSL_VERIFYPEER , 1 );
}
if ( isset ( $this -> certRequest [ 'verifyhost' ])) {
$this -> setCurlOption ( CURLOPT_SSL_VERIFYHOST , $this -> certRequest [ 'verifyhost' ]);
} else {
$this -> setCurlOption ( CURLOPT_SSL_VERIFYHOST , 1 );
}
if ( isset ( $this -> certRequest [ 'sslcertfile' ])) {
$this -> setCurlOption ( CURLOPT_SSLCERT , $this -> certRequest [ 'sslcertfile' ]);
}
if ( isset ( $this -> certRequest [ 'sslkeyfile' ])) {
$this -> setCurlOption ( CURLOPT_SSLKEY , $this -> certRequest [ 'sslkeyfile' ]);
}
if ( isset ( $this -> certRequest [ 'passphrase' ])) {
$this -> setCurlOption ( CURLOPT_SSLKEYPASSWD , $this -> certRequest [ 'passphrase' ]);
}
if ( isset ( $this -> certRequest [ 'certpassword' ])) {
$this -> setCurlOption ( CURLOPT_SSLCERTPASSWD , $this -> certRequest [ 'certpassword' ]);
}
}
}
if ( $this -> authtype && ( $this -> authtype != 'certificate' )) {
if ( $this -> username ) {
$this -> debug ( 'set cURL username/password' );
$this -> setCurlOption ( CURLOPT_USERPWD , " $this->username : $this->password " );
}
if ( $this -> authtype == 'basic' ) {
$this -> debug ( 'set cURL for Basic authentication' );
$this -> setCurlOption ( $CURLOPT_HTTPAUTH , $CURLAUTH_BASIC );
}
if ( $this -> authtype == 'digest' ) {
$this -> debug ( 'set cURL for digest authentication' );
$this -> setCurlOption ( $CURLOPT_HTTPAUTH , $CURLAUTH_DIGEST );
}
if ( $this -> authtype == 'ntlm' ) {
$this -> debug ( 'set cURL for NTLM authentication' );
$this -> setCurlOption ( $CURLOPT_HTTPAUTH , $CURLAUTH_NTLM );
}
}
if ( is_array ( $this -> proxy )) {
$this -> debug ( 'set cURL proxy options' );
if ( $this -> proxy [ 'port' ] != '' ) {
$this -> setCurlOption ( CURLOPT_PROXY , $this -> proxy [ 'host' ] . ':' . $this -> proxy [ 'port' ]);
} else {
$this -> setCurlOption ( CURLOPT_PROXY , $this -> proxy [ 'host' ]);
}
if ( $this -> proxy [ 'username' ] || $this -> proxy [ 'password' ]) {
$this -> debug ( 'set cURL proxy authentication options' );
$this -> setCurlOption ( CURLOPT_PROXYUSERPWD , $this -> proxy [ 'username' ] . ':' . $this -> proxy [ 'password' ]);
if ( $this -> proxy [ 'authtype' ] == 'basic' ) {
$this -> setCurlOption ( $CURLOPT_PROXYAUTH , $CURLAUTH_BASIC );
}
if ( $this -> proxy [ 'authtype' ] == 'ntlm' ) {
$this -> setCurlOption ( $CURLOPT_PROXYAUTH , $CURLAUTH_NTLM );
}
}
}
$this -> debug ( 'cURL connection set up' );
return true ;
} else {
$this -> setError ( 'Unknown scheme ' . $this -> scheme );
$this -> debug ( 'Unknown scheme ' . $this -> scheme );
return false ;
}
}
/**
* sends the SOAP request and gets the SOAP response via HTTP [ S ]
*
* @ param string $data message data
* @ param integer $timeout set connection timeout in seconds
* @ param integer $response_timeout set response timeout in seconds
* @ param array $cookies cookies to send
* @ return string data
* @ access public
*/
function send ( $data , $timeout = 0 , $response_timeout = 30 , $cookies = NULL ) {
$this -> debug ( 'entered send() with data of length: ' . strlen ( $data ));
$this -> tryagain = true ;
$tries = 0 ;
while ( $this -> tryagain ) {
$this -> tryagain = false ;
if ( $tries ++ < 2 ) {
// make connnection
if ( ! $this -> connect ( $timeout , $response_timeout )){
return false ;
}
// send request
if ( ! $this -> sendRequest ( $data , $cookies )){
return false ;
}
// get response
$respdata = $this -> getResponse ();
} else {
$this -> setError ( " Too many tries to get an OK response ( $this->response_status_line ) " );
}
}
$this -> debug ( 'end of send()' );
return $respdata ;
}
/**
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
*
* @ param string $data message data
* @ param integer $timeout set connection timeout in seconds
* @ param integer $response_timeout set response timeout in seconds
2023-06-28 12:45:56 +00:00
* @ param array $cookies cookies to send ( 6 / 12 / 2023 Made not required to prevent PHP error / warning for required following optional )
2023-06-05 11:23:16 +00:00
* @ return string data
* @ access public
* @ deprecated
*/
2023-06-28 12:45:56 +00:00
function sendHTTPS ( $data , $timeout = 0 , $response_timeout = 30 , $cookies = array ()) {
2023-06-05 11:23:16 +00:00
return $this -> send ( $data , $timeout , $response_timeout , $cookies );
}
/**
* if authenticating , set user credentials here
*
* @ param string $username
* @ param string $password
* @ param string $authtype ( basic | digest | certificate | ntlm )
* @ param array $digestRequest ( keys must be nonce , nc , realm , qop )
* @ param array $certRequest ( keys must be cainfofile ( optional ), sslcertfile , sslkeyfile , passphrase , certpassword ( optional ), verifypeer ( optional ), verifyhost ( optional ) : see corresponding options in cURL docs )
* @ access public
*/
function setCredentials ( $username , $password , $authtype = 'basic' , $digestRequest = array (), $certRequest = array ()) {
$this -> debug ( " setCredentials username= $username authtype= $authtype digestRequest= " );
$this -> appendDebug ( $this -> varDump ( $digestRequest ));
$this -> debug ( " certRequest= " );
$this -> appendDebug ( $this -> varDump ( $certRequest ));
// cf. RFC 2617
if ( $authtype == 'basic' ) {
$this -> setHeader ( 'Authorization' , 'Basic ' . base64_encode ( str_replace ( ':' , '' , $username ) . ':' . $password ));
} elseif ( $authtype == 'digest' ) {
if ( isset ( $digestRequest [ 'nonce' ])) {
$digestRequest [ 'nc' ] = isset ( $digestRequest [ 'nc' ]) ? $digestRequest [ 'nc' ] ++ : 1 ;
// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
$A1 = $username . ':' . ( isset ( $digestRequest [ 'realm' ]) ? $digestRequest [ 'realm' ] : '' ) . ':' . $password ;
// H(A1) = MD5(A1)
$HA1 = md5 ( $A1 );
// A2 = Method ":" digest-uri-value
$A2 = $this -> request_method . ':' . $this -> digest_uri ;
// H(A2)
$HA2 = md5 ( $A2 );
// KD(secret, data) = H(concat(secret, ":", data))
// if qop == auth:
// request-digest = <"> < KD ( H(A1), unq(nonce-value)
// ":" nc-value
// ":" unq(cnonce-value)
// ":" unq(qop-value)
// ":" H(A2)
// ) <">
// if qop is missing,
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
$unhashedDigest = '' ;
$nonce = isset ( $digestRequest [ 'nonce' ]) ? $digestRequest [ 'nonce' ] : '' ;
$cnonce = $nonce ;
if ( $digestRequest [ 'qop' ] != '' ) {
$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf ( " %08d " , $digestRequest [ 'nc' ]) . ':' . $cnonce . ':' . $digestRequest [ 'qop' ] . ':' . $HA2 ;
} else {
$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2 ;
}
$hashedDigest = md5 ( $unhashedDigest );
$opaque = '' ;
if ( isset ( $digestRequest [ 'opaque' ])) {
$opaque = ', opaque="' . $digestRequest [ 'opaque' ] . '"' ;
}
$this -> setHeader ( 'Authorization' , 'Digest username="' . $username . '", realm="' . $digestRequest [ 'realm' ] . '", nonce="' . $nonce . '", uri="' . $this -> digest_uri . $opaque . '", cnonce="' . $cnonce . '", nc=' . sprintf ( " %08x " , $digestRequest [ 'nc' ]) . ', qop="' . $digestRequest [ 'qop' ] . '", response="' . $hashedDigest . '"' );
}
} elseif ( $authtype == 'certificate' ) {
$this -> certRequest = $certRequest ;
$this -> debug ( 'Authorization header not set for certificate' );
} elseif ( $authtype == 'ntlm' ) {
// do nothing
$this -> debug ( 'Authorization header not set for ntlm' );
}
$this -> username = $username ;
$this -> password = $password ;
$this -> authtype = $authtype ;
$this -> digestRequest = $digestRequest ;
}
/**
* set the soapaction value
*
* @ param string $soapaction
* @ access public
*/
function setSOAPAction ( $soapaction ) {
$this -> setHeader ( 'SOAPAction' , '"' . $soapaction . '"' );
}
/**
* use http encoding
*
* @ param string $enc encoding style . supported values : gzip , deflate , or both
* @ access public
*/
function setEncoding ( $enc = 'gzip, deflate' ) {
if ( function_exists ( 'gzdeflate' )) {
$this -> protocol_version = '1.1' ;
$this -> setHeader ( 'Accept-Encoding' , $enc );
if ( ! isset ( $this -> outgoing_headers [ 'Connection' ])) {
$this -> setHeader ( 'Connection' , 'close' );
$this -> persistentConnection = false ;
}
// deprecated as of PHP 5.3.0
//set_magic_quotes_runtime(0);
$this -> encoding = $enc ;
}
}
/**
* set proxy info here
*
* @ param string $proxyhost use an empty string to remove proxy
* @ param string $proxyport
* @ param string $proxyusername
* @ param string $proxypassword
* @ param string $proxyauthtype ( basic | ntlm )
* @ access public
*/
function setProxy ( $proxyhost , $proxyport , $proxyusername = '' , $proxypassword = '' , $proxyauthtype = 'basic' ) {
if ( $proxyhost ) {
$this -> proxy = array (
'host' => $proxyhost ,
'port' => $proxyport ,
'username' => $proxyusername ,
'password' => $proxypassword ,
'authtype' => $proxyauthtype
);
if ( $proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic' ) {
$this -> setHeader ( 'Proxy-Authorization' , ' Basic ' . base64_encode ( $proxyusername . ':' . $proxypassword ));
}
} else {
$this -> debug ( 'remove proxy' );
$proxy = null ;
unsetHeader ( 'Proxy-Authorization' );
}
}
/**
* Test if the given string starts with a header that is to be skipped .
* Skippable headers result from chunked transfer and proxy requests .
*
* @ param string $data The string to check .
* @ returns boolean Whether a skippable header was found .
* @ access private
*/
function isSkippableCurlHeader ( & $data ) {
$skipHeaders = array ( 'HTTP/1.1 100' ,
'HTTP/1.0 301' ,
'HTTP/1.1 301' ,
'HTTP/1.0 302' ,
'HTTP/1.1 302' ,
'HTTP/1.0 401' ,
'HTTP/1.1 401' ,
'HTTP/1.0 200 Connection established' );
foreach ( $skipHeaders as $hd ) {
$prefix = substr ( $data , 0 , strlen ( $hd ));
if ( $prefix == $hd ) return true ;
}
return false ;
}
/**
* decode a string that is encoded w / " chunked' transfer encoding
* as defined in RFC2068 19.4 . 6
*
* @ param string $buffer
* @ param string $lb
* @ returns string
* @ access public
* @ deprecated
*/
function decodeChunked ( $buffer , $lb ){
// length := 0
$length = 0 ;
$new = '' ;
// read chunk-size, chunk-extension (if any) and CRLF
// get the position of the linebreak
$chunkend = strpos ( $buffer , $lb );
if ( $chunkend == FALSE ) {
$this -> debug ( 'no linebreak found in decodeChunked' );
return $new ;
}
$temp = substr ( $buffer , 0 , $chunkend );
$chunk_size = hexdec ( trim ( $temp ) );
$chunkstart = $chunkend + strlen ( $lb );
// while (chunk-size > 0) {
while ( $chunk_size > 0 ) {
$this -> debug ( " chunkstart: $chunkstart chunk_size: $chunk_size " );
$chunkend = strpos ( $buffer , $lb , $chunkstart + $chunk_size );
// Just in case we got a broken connection
if ( $chunkend == FALSE ) {
$chunk = substr ( $buffer , $chunkstart );
// append chunk-data to entity-body
$new .= $chunk ;
$length += strlen ( $chunk );
break ;
}
// read chunk-data and CRLF
$chunk = substr ( $buffer , $chunkstart , $chunkend - $chunkstart );
// append chunk-data to entity-body
$new .= $chunk ;
// length := length + chunk-size
$length += strlen ( $chunk );
// read chunk-size and CRLF
$chunkstart = $chunkend + strlen ( $lb );
$chunkend = strpos ( $buffer , $lb , $chunkstart ) + strlen ( $lb );
if ( $chunkend == FALSE ) {
break ; //Just in case we got a broken connection
}
$temp = substr ( $buffer , $chunkstart , $chunkend - $chunkstart );
$chunk_size = hexdec ( trim ( $temp ) );
$chunkstart = $chunkend ;
}
return $new ;
}
/**
* Writes the payload , including HTTP headers , to $this -> outgoing_payload .
*
* @ param string $data HTTP body
* @ param string $cookie_str data for HTTP Cookie header
* @ return void
* @ access private
*/
function buildPayload ( $data , $cookie_str = '' ) {
// Note: for cURL connections, $this->outgoing_payload is ignored,
// as is the Content-Length header, but these are still created as
// debugging guides.
// add content-length header
if ( $this -> request_method != 'GET' ) {
$this -> setHeader ( 'Content-Length' , strlen ( $data ));
}
// start building outgoing payload:
if ( $this -> proxy ) {
$uri = $this -> url ;
} else {
$uri = $this -> uri ;
}
$req = " $this->request_method $uri HTTP/ $this->protocol_version " ;
$this -> debug ( " HTTP request: $req " );
$this -> outgoing_payload = " $req\r\n " ;
// loop thru headers, serializing
foreach ( $this -> outgoing_headers as $k => $v ){
$hdr = $k . ': ' . $v ;
$this -> debug ( " HTTP header: $hdr " );
$this -> outgoing_payload .= " $hdr\r\n " ;
}
// add any cookies
if ( $cookie_str != '' ) {
$hdr = 'Cookie: ' . $cookie_str ;
$this -> debug ( " HTTP header: $hdr " );
$this -> outgoing_payload .= " $hdr\r\n " ;
}
// header/body separator
$this -> outgoing_payload .= " \r \n " ;
// add data
$this -> outgoing_payload .= $data ;
}
/**
* sends the SOAP request via HTTP [ S ]
*
* @ param string $data message data
* @ param array $cookies cookies to send
* @ return boolean true if OK , false if problem
* @ access private
*/
function sendRequest ( $data , $cookies = NULL ) {
// build cookie string
$cookie_str = $this -> getCookiesForRequest ( $cookies , (( $this -> scheme == 'ssl' ) || ( $this -> scheme == 'https' )));
// build payload
$this -> buildPayload ( $data , $cookie_str );
if ( $this -> io_method () == 'socket' ) {
// send payload
if ( ! fputs ( $this -> fp , $this -> outgoing_payload , strlen ( $this -> outgoing_payload ))) {
$this -> setError ( 'couldn\'t write message data to socket' );
$this -> debug ( 'couldn\'t write message data to socket' );
return false ;
}
$this -> debug ( 'wrote data to socket, length = ' . strlen ( $this -> outgoing_payload ));
return true ;
} else if ( $this -> io_method () == 'curl' ) {
// set payload
// cURL does say this should only be the verb, and in fact it
// turns out that the URI and HTTP version are appended to this, which
// some servers refuse to work with (so we no longer use this method!)
//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
$curl_headers = array ();
foreach ( $this -> outgoing_headers as $k => $v ){
if ( $k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization' ) {
$this -> debug ( " Skip cURL header $k : $v " );
} else {
$curl_headers [] = " $k : $v " ;
}
}
if ( $cookie_str != '' ) {
$curl_headers [] = 'Cookie: ' . $cookie_str ;
}
$this -> setCurlOption ( CURLOPT_HTTPHEADER , $curl_headers );
$this -> debug ( 'set cURL HTTP headers' );
if ( $this -> request_method == " POST " ) {
$this -> setCurlOption ( CURLOPT_POST , 1 );
$this -> setCurlOption ( CURLOPT_POSTFIELDS , $data );
$this -> debug ( 'set cURL POST data' );
} else {
}
// insert custom user-set cURL options
foreach ( $this -> ch_options as $key => $val ) {
$this -> setCurlOption ( $key , $val );
}
$this -> debug ( 'set cURL payload' );
return true ;
}
}
/**
* gets the SOAP response via HTTP [ S ]
*
* @ return string the response ( also sets member variables like incoming_payload )
* @ access private
*/
function getResponse (){
$this -> incoming_payload = '' ;
if ( $this -> io_method () == 'socket' ) {
// loop until headers have been retrieved
$data = '' ;
while ( ! isset ( $lb )){
// We might EOF during header read.
if ( feof ( $this -> fp )) {
$this -> incoming_payload = $data ;
$this -> debug ( 'found no headers before EOF after length ' . strlen ( $data ));
$this -> debug ( " received before EOF: \n " . $data );
$this -> setError ( 'server failed to send headers' );
return false ;
}
$tmp = fgets ( $this -> fp , 256 );
$tmplen = strlen ( $tmp );
$this -> debug ( " read line of $tmplen bytes: " . trim ( $tmp ));
if ( $tmplen == 0 ) {
$this -> incoming_payload = $data ;
$this -> debug ( 'socket read of headers timed out after length ' . strlen ( $data ));
$this -> debug ( " read before timeout: " . $data );
$this -> setError ( 'socket read of headers timed out' );
return false ;
}
$data .= $tmp ;
$pos = strpos ( $data , " \r \n \r \n " );
if ( $pos > 1 ){
$lb = " \r \n " ;
} else {
$pos = strpos ( $data , " \n \n " );
if ( $pos > 1 ){
$lb = " \n " ;
}
}
// remove 100 headers
if ( isset ( $lb ) && preg_match ( '/^HTTP\/1.1 100/' , $data )) {
unset ( $lb );
$data = '' ;
} //
}
// store header data
$this -> incoming_payload .= $data ;
$this -> debug ( 'found end of headers after length ' . strlen ( $data ));
// process headers
$header_data = trim ( substr ( $data , 0 , $pos ));
$header_array = explode ( $lb , $header_data );
$this -> incoming_headers = array ();
$this -> incoming_cookies = array ();
foreach ( $header_array as $header_line ){
$arr = explode ( ':' , $header_line , 2 );
if ( count ( $arr ) > 1 ){
$header_name = strtolower ( trim ( $arr [ 0 ]));
$this -> incoming_headers [ $header_name ] = trim ( $arr [ 1 ]);
if ( $header_name == 'set-cookie' ) {
// TODO: allow multiple cookies from parseCookie
$cookie = $this -> parseCookie ( trim ( $arr [ 1 ]));
if ( $cookie ) {
$this -> incoming_cookies [] = $cookie ;
$this -> debug ( 'found cookie: ' . $cookie [ 'name' ] . ' = ' . $cookie [ 'value' ]);
} else {
$this -> debug ( 'did not find cookie in ' . trim ( $arr [ 1 ]));
}
}
} else if ( isset ( $header_name )) {
// append continuation line to previous header
$this -> incoming_headers [ $header_name ] .= $lb . ' ' . $header_line ;
}
}
// loop until msg has been received
if ( isset ( $this -> incoming_headers [ 'transfer-encoding' ]) && strtolower ( $this -> incoming_headers [ 'transfer-encoding' ]) == 'chunked' ) {
$content_length = 2147483647 ; // ignore any content-length header
$chunked = true ;
$this -> debug ( " want to read chunked content " );
} elseif ( isset ( $this -> incoming_headers [ 'content-length' ])) {
$content_length = $this -> incoming_headers [ 'content-length' ];
$chunked = false ;
$this -> debug ( " want to read content of length $content_length " );
} else {
$content_length = 2147483647 ;
$chunked = false ;
$this -> debug ( " want to read content to EOF " );
}
$data = '' ;
do {
if ( $chunked ) {
$tmp = fgets ( $this -> fp , 256 );
$tmplen = strlen ( $tmp );
$this -> debug ( " read chunk line of $tmplen bytes " );
if ( $tmplen == 0 ) {
$this -> incoming_payload = $data ;
$this -> debug ( 'socket read of chunk length timed out after length ' . strlen ( $data ));
$this -> debug ( " read before timeout: \n " . $data );
$this -> setError ( 'socket read of chunk length timed out' );
return false ;
}
$content_length = hexdec ( trim ( $tmp ));
$this -> debug ( " chunk length $content_length " );
}
$strlen = 0 ;
while (( $strlen < $content_length ) && ( ! feof ( $this -> fp ))) {
$readlen = min ( 8192 , $content_length - $strlen );
$tmp = fread ( $this -> fp , $readlen );
$tmplen = strlen ( $tmp );
$this -> debug ( " read buffer of $tmplen bytes " );
if (( $tmplen == 0 ) && ( ! feof ( $this -> fp ))) {
$this -> incoming_payload = $data ;
$this -> debug ( 'socket read of body timed out after length ' . strlen ( $data ));
$this -> debug ( " read before timeout: \n " . $data );
$this -> setError ( 'socket read of body timed out' );
return false ;
}
$strlen += $tmplen ;
$data .= $tmp ;
}
if ( $chunked && ( $content_length > 0 )) {
$tmp = fgets ( $this -> fp , 256 );
$tmplen = strlen ( $tmp );
$this -> debug ( " read chunk terminator of $tmplen bytes " );
if ( $tmplen == 0 ) {
$this -> incoming_payload = $data ;
$this -> debug ( 'socket read of chunk terminator timed out after length ' . strlen ( $data ));
$this -> debug ( " read before timeout: \n " . $data );
$this -> setError ( 'socket read of chunk terminator timed out' );
return false ;
}
}
} while ( $chunked && ( $content_length > 0 ) && ( ! feof ( $this -> fp )));
if ( feof ( $this -> fp )) {
$this -> debug ( 'read to EOF' );
}
$this -> debug ( 'read body of length ' . strlen ( $data ));
$this -> incoming_payload .= $data ;
$this -> debug ( 'received a total of ' . strlen ( $this -> incoming_payload ) . ' bytes of data from server' );
// close filepointer
if (
( isset ( $this -> incoming_headers [ 'connection' ]) && strtolower ( $this -> incoming_headers [ 'connection' ]) == 'close' ) ||
( ! $this -> persistentConnection ) || feof ( $this -> fp )){
fclose ( $this -> fp );
$this -> fp = false ;
$this -> debug ( 'closed socket' );
}
// connection was closed unexpectedly
if ( $this -> incoming_payload == '' ){
$this -> setError ( 'no response from server' );
return false ;
}
// decode transfer-encoding
// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
// if(!$data = $this->decodeChunked($data, $lb)){
// $this->setError('Decoding of chunked data failed');
// return false;
// }
//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
// set decoded payload
// $this->incoming_payload = $header_data.$lb.$lb.$data;
// }
} else if ( $this -> io_method () == 'curl' ) {
// send and receive
$this -> debug ( 'send and receive with cURL' );
$this -> incoming_payload = curl_exec ( $this -> ch );
$data = $this -> incoming_payload ;
$cErr = curl_error ( $this -> ch );
if ( $cErr != '' ) {
$err = 'cURL ERROR: ' . curl_errno ( $this -> ch ) . ': ' . $cErr . '<br>' ;
// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
foreach ( curl_getinfo ( $this -> ch ) as $k => $v ){
$err .= " $k : $v <br> " ;
}
$this -> debug ( $err );
$this -> setError ( $err );
curl_close ( $this -> ch );
return false ;
} else {
//echo '<pre>';
//var_dump(curl_getinfo($this->ch));
//echo '</pre>';
}
// close curl
$this -> debug ( 'No cURL error, closing cURL' );
curl_close ( $this -> ch );
// try removing skippable headers
$savedata = $data ;
while ( $this -> isSkippableCurlHeader ( $data )) {
$this -> debug ( " Found HTTP header to skip " );
if ( $pos = strpos ( $data , " \r \n \r \n " )) {
$data = ltrim ( substr ( $data , $pos ));
} elseif ( $pos = strpos ( $data , " \n \n " ) ) {
$data = ltrim ( substr ( $data , $pos ));
}
}
if ( $data == '' ) {
// have nothing left; just remove 100 header(s)
$data = $savedata ;
while ( preg_match ( '/^HTTP\/1.1 100/' , $data )) {
if ( $pos = strpos ( $data , " \r \n \r \n " )) {
$data = ltrim ( substr ( $data , $pos ));
} elseif ( $pos = strpos ( $data , " \n \n " ) ) {
$data = ltrim ( substr ( $data , $pos ));
}
}
}
// separate content from HTTP headers
if ( $pos = strpos ( $data , " \r \n \r \n " )) {
$lb = " \r \n " ;
} elseif ( $pos = strpos ( $data , " \n \n " )) {
$lb = " \n " ;
} else {
$this -> debug ( 'no proper separation of headers and document' );
$this -> setError ( 'no proper separation of headers and document' );
return false ;
}
$header_data = trim ( substr ( $data , 0 , $pos ));
$header_array = explode ( $lb , $header_data );
$data = ltrim ( substr ( $data , $pos ));
$this -> debug ( 'found proper separation of headers and document' );
$this -> debug ( 'cleaned data, stringlen: ' . strlen ( $data ));
// clean headers
foreach ( $header_array as $header_line ) {
$arr = explode ( ':' , $header_line , 2 );
if ( count ( $arr ) > 1 ){
$header_name = strtolower ( trim ( $arr [ 0 ]));
$this -> incoming_headers [ $header_name ] = trim ( $arr [ 1 ]);
if ( $header_name == 'set-cookie' ) {
// TODO: allow multiple cookies from parseCookie
$cookie = $this -> parseCookie ( trim ( $arr [ 1 ]));
if ( $cookie ) {
$this -> incoming_cookies [] = $cookie ;
$this -> debug ( 'found cookie: ' . $cookie [ 'name' ] . ' = ' . $cookie [ 'value' ]);
} else {
$this -> debug ( 'did not find cookie in ' . trim ( $arr [ 1 ]));
}
}
} else if ( isset ( $header_name )) {
// append continuation line to previous header
$this -> incoming_headers [ $header_name ] .= $lb . ' ' . $header_line ;
}
}
}
$this -> response_status_line = $header_array [ 0 ];
$arr = explode ( ' ' , $this -> response_status_line , 3 );
$http_version = $arr [ 0 ];
$http_status = intval ( $arr [ 1 ]);
$http_reason = count ( $arr ) > 2 ? $arr [ 2 ] : '' ;
// see if we need to resend the request with http digest authentication
if ( isset ( $this -> incoming_headers [ 'location' ]) && ( $http_status == 301 || $http_status == 302 )) {
$this -> debug ( " Got $http_status $http_reason with Location: " . $this -> incoming_headers [ 'location' ]);
$this -> setURL ( $this -> incoming_headers [ 'location' ]);
$this -> tryagain = true ;
return false ;
}
// see if we need to resend the request with http digest authentication
if ( isset ( $this -> incoming_headers [ 'www-authenticate' ]) && $http_status == 401 ) {
$this -> debug ( " Got 401 $http_reason with WWW-Authenticate: " . $this -> incoming_headers [ 'www-authenticate' ]);
if ( strstr ( $this -> incoming_headers [ 'www-authenticate' ], " Digest " )) {
$this -> debug ( 'Server wants digest authentication' );
// remove "Digest " from our elements
$digestString = str_replace ( 'Digest ' , '' , $this -> incoming_headers [ 'www-authenticate' ]);
// parse elements into array
$digestElements = explode ( ',' , $digestString );
foreach ( $digestElements as $val ) {
$tempElement = explode ( '=' , trim ( $val ), 2 );
$digestRequest [ $tempElement [ 0 ]] = str_replace ( " \" " , '' , $tempElement [ 1 ]);
}
// should have (at least) qop, realm, nonce
if ( isset ( $digestRequest [ 'nonce' ])) {
$this -> setCredentials ( $this -> username , $this -> password , 'digest' , $digestRequest );
$this -> tryagain = true ;
return false ;
}
}
$this -> debug ( 'HTTP authentication failed' );
$this -> setError ( 'HTTP authentication failed' );
return false ;
}
if (
( $http_status >= 300 && $http_status <= 307 ) ||
( $http_status >= 400 && $http_status <= 417 ) ||
( $http_status >= 501 && $http_status <= 505 )
) {
$this -> setError ( " Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response) " );
return false ;
}
// decode content-encoding
if ( isset ( $this -> incoming_headers [ 'content-encoding' ]) && $this -> incoming_headers [ 'content-encoding' ] != '' ){
if ( strtolower ( $this -> incoming_headers [ 'content-encoding' ]) == 'deflate' || strtolower ( $this -> incoming_headers [ 'content-encoding' ]) == 'gzip' ){
// if decoding works, use it. else assume data wasn't gzencoded
if ( function_exists ( 'gzinflate' )){
//$timer->setMarker('starting decoding of gzip/deflated content');
// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
// this means there are no Zlib headers, although there should be
$this -> debug ( 'The gzinflate function exists' );
$datalen = strlen ( $data );
if ( $this -> incoming_headers [ 'content-encoding' ] == 'deflate' ) {
if ( $degzdata = @ gzinflate ( $data )) {
$data = $degzdata ;
$this -> debug ( 'The payload has been inflated to ' . strlen ( $data ) . ' bytes' );
if ( strlen ( $data ) < $datalen ) {
// test for the case that the payload has been compressed twice
$this -> debug ( 'The inflated payload is smaller than the gzipped one; try again' );
if ( $degzdata = @ gzinflate ( $data )) {
$data = $degzdata ;
$this -> debug ( 'The payload has been inflated again to ' . strlen ( $data ) . ' bytes' );
}
}
} else {
$this -> debug ( 'Error using gzinflate to inflate the payload' );
$this -> setError ( 'Error using gzinflate to inflate the payload' );
}
} elseif ( $this -> incoming_headers [ 'content-encoding' ] == 'gzip' ) {
if ( $degzdata = @ gzinflate ( substr ( $data , 10 ))) { // do our best
$data = $degzdata ;
$this -> debug ( 'The payload has been un-gzipped to ' . strlen ( $data ) . ' bytes' );
if ( strlen ( $data ) < $datalen ) {
// test for the case that the payload has been compressed twice
$this -> debug ( 'The un-gzipped payload is smaller than the gzipped one; try again' );
if ( $degzdata = @ gzinflate ( substr ( $data , 10 ))) {
$data = $degzdata ;
$this -> debug ( 'The payload has been un-gzipped again to ' . strlen ( $data ) . ' bytes' );
}
}
} else {
$this -> debug ( 'Error using gzinflate to un-gzip the payload' );
$this -> setError ( 'Error using gzinflate to un-gzip the payload' );
}
}
//$timer->setMarker('finished decoding of gzip/deflated content');
//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
// set decoded payload
$this -> incoming_payload = $header_data . $lb . $lb . $data ;
} else {
$this -> debug ( 'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.' );
$this -> setError ( 'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.' );
}
} else {
$this -> debug ( 'Unsupported Content-Encoding ' . $this -> incoming_headers [ 'content-encoding' ]);
$this -> setError ( 'Unsupported Content-Encoding ' . $this -> incoming_headers [ 'content-encoding' ]);
}
} else {
$this -> debug ( 'No Content-Encoding header' );
}
if ( strlen ( $data ) == 0 ){
$this -> debug ( 'no data after headers!' );
$this -> setError ( 'no data present after HTTP headers' );
return false ;
}
return $data ;
}
/**
* sets the content - type for the SOAP message to be sent
*
* @ param string $type the content type , MIME style
* @ param mixed $charset character set used for encoding ( or false )
* @ access public
*/
function setContentType ( $type , $charset = false ) {
$this -> setHeader ( 'Content-Type' , $type . ( $charset ? '; charset=' . $charset : '' ));
}
/**
* specifies that an HTTP persistent connection should be used
*
* @ return boolean whether the request was honored by this method .
* @ access public
*/
function usePersistentConnection (){
if ( isset ( $this -> outgoing_headers [ 'Accept-Encoding' ])) {
return false ;
}
$this -> protocol_version = '1.1' ;
$this -> persistentConnection = true ;
$this -> setHeader ( 'Connection' , 'Keep-Alive' );
return true ;
}
/**
* parse an incoming Cookie into it ' s parts
*
* @ param string $cookie_str content of cookie
* @ return array with data of that cookie
* @ access private
*/
/*
* TODO : allow a Set - Cookie string to be parsed into multiple cookies
*/
function parseCookie ( $cookie_str ) {
$cookie_str = str_replace ( '; ' , ';' , $cookie_str ) . ';' ;
$data = preg_split ( '/;/' , $cookie_str );
$value_str = $data [ 0 ];
$cookie_param = 'domain=' ;
$start = strpos ( $cookie_str , $cookie_param );
if ( $start > 0 ) {
$domain = substr ( $cookie_str , $start + strlen ( $cookie_param ));
$domain = substr ( $domain , 0 , strpos ( $domain , ';' ));
} else {
$domain = '' ;
}
$cookie_param = 'expires=' ;
$start = strpos ( $cookie_str , $cookie_param );
if ( $start > 0 ) {
$expires = substr ( $cookie_str , $start + strlen ( $cookie_param ));
$expires = substr ( $expires , 0 , strpos ( $expires , ';' ));
} else {
$expires = '' ;
}
$cookie_param = 'path=' ;
$start = strpos ( $cookie_str , $cookie_param );
if ( $start > 0 ) {
$path = substr ( $cookie_str , $start + strlen ( $cookie_param ));
$path = substr ( $path , 0 , strpos ( $path , ';' ));
} else {
$path = '/' ;
}
$cookie_param = ';secure;' ;
if ( strpos ( $cookie_str , $cookie_param ) !== FALSE ) {
$secure = true ;
} else {
$secure = false ;
}
$sep_pos = strpos ( $value_str , '=' );
if ( $sep_pos ) {
$name = substr ( $value_str , 0 , $sep_pos );
$value = substr ( $value_str , $sep_pos + 1 );
$cookie = array ( 'name' => $name ,
'value' => $value ,
'domain' => $domain ,
'path' => $path ,
'expires' => $expires ,
'secure' => $secure
);
return $cookie ;
}
return false ;
}
/**
* sort out cookies for the current request
*
* @ param array $cookies array with all cookies
* @ param boolean $secure is the send - content secure or not ?
* @ return string for Cookie - HTTP - Header
* @ access private
*/
function getCookiesForRequest ( $cookies , $secure = false ) {
$cookie_str = '' ;
if (( ! is_null ( $cookies )) && ( is_array ( $cookies ))) {
foreach ( $cookies as $cookie ) {
if ( ! is_array ( $cookie )) {
continue ;
}
$this -> debug ( " check cookie for validity: " . $cookie [ 'name' ] . '=' . $cookie [ 'value' ]);
if (( isset ( $cookie [ 'expires' ])) && ( ! empty ( $cookie [ 'expires' ]))) {
if ( strtotime ( $cookie [ 'expires' ]) <= time ()) {
$this -> debug ( 'cookie has expired' );
continue ;
}
}
if (( isset ( $cookie [ 'domain' ])) && ( ! empty ( $cookie [ 'domain' ]))) {
$domain = preg_quote ( $cookie [ 'domain' ]);
if ( ! preg_match ( " '.* $domain $ 'i " , $this -> host )) {
$this -> debug ( 'cookie has different domain' );
continue ;
}
}
if (( isset ( $cookie [ 'path' ])) && ( ! empty ( $cookie [ 'path' ]))) {
$path = preg_quote ( $cookie [ 'path' ]);
if ( ! preg_match ( " '^ $path .*'i " , $this -> path )) {
$this -> debug ( 'cookie is for a different path' );
continue ;
}
}
if (( ! $secure ) && ( isset ( $cookie [ 'secure' ])) && ( $cookie [ 'secure' ])) {
$this -> debug ( 'cookie is secure, transport is not' );
continue ;
}
$cookie_str .= $cookie [ 'name' ] . '=' . $cookie [ 'value' ] . '; ' ;
$this -> debug ( 'add cookie to Cookie-String: ' . $cookie [ 'name' ] . '=' . $cookie [ 'value' ]);
}
}
return $cookie_str ;
}
}
?> <?php
/**
*
* nusoap_server allows the user to create a SOAP server
* that is capable of receiving messages and returning responses
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_server extends nusoap_base {
/**
* HTTP headers of request
* @ var array
* @ access private
*/
var $headers = array ();
/**
* HTTP request
* @ var string
* @ access private
*/
var $request = '' ;
/**
* SOAP headers from request ( incomplete namespace resolution ; special characters not escaped ) ( text )
* @ var string
* @ access public
*/
var $requestHeaders = '' ;
/**
* SOAP Headers from request ( parsed )
* @ var mixed
* @ access public
*/
var $requestHeader = NULL ;
/**
* SOAP body request portion ( incomplete namespace resolution ; special characters not escaped ) ( text )
* @ var string
* @ access public
*/
var $document = '' ;
/**
* SOAP payload for request ( text )
* @ var string
* @ access public
*/
var $requestSOAP = '' ;
/**
* requested method namespace URI
* @ var string
* @ access private
*/
var $methodURI = '' ;
/**
* name of method requested
* @ var string
* @ access private
*/
var $methodname = '' ;
/**
* method parameters from request
* @ var array
* @ access private
*/
var $methodparams = array ();
/**
* SOAP Action from request
* @ var string
* @ access private
*/
var $SOAPAction = '' ;
/**
* character set encoding of incoming ( request ) messages
* @ var string
* @ access public
*/
var $xml_encoding = '' ;
/**
* toggles whether the parser decodes element content w / utf8_decode ()
* @ var boolean
* @ access public
*/
var $decode_utf8 = true ;
/**
* HTTP headers of response
* @ var array
* @ access public
*/
var $outgoing_headers = array ();
/**
* HTTP response
* @ var string
* @ access private
*/
var $response = '' ;
/**
* SOAP headers for response ( text or array of soapval or associative array )
* @ var mixed
* @ access public
*/
var $responseHeaders = '' ;
/**
* SOAP payload for response ( text )
* @ var string
* @ access private
*/
var $responseSOAP = '' ;
/**
* method return value to place in response
* @ var mixed
* @ access private
*/
var $methodreturn = false ;
/**
* whether $methodreturn is a string of literal XML
* @ var boolean
* @ access public
*/
var $methodreturnisliteralxml = false ;
/**
* SOAP fault for response ( or false )
* @ var mixed
* @ access private
*/
var $fault = false ;
/**
* text indication of result ( for debugging )
* @ var string
* @ access private
*/
var $result = 'successful' ;
/**
* assoc array of operations => opData ; operations are added by the register ()
* method or by parsing an external WSDL definition
* @ var array
* @ access private
*/
var $operations = array ();
/**
* wsdl instance ( if one )
* @ var mixed
* @ access private
*/
var $wsdl = false ;
/**
* URL for WSDL ( if one )
* @ var mixed
* @ access private
*/
var $externalWSDLURL = false ;
/**
* whether to append debug to response as XML comment
* @ var boolean
* @ access public
*/
var $debug_flag = false ;
/**
* constructor
* the optional parameter is a path to a WSDL file that you ' d like to bind the server instance to .
*
* @ param mixed $wsdl file path or URL ( string ), or wsdl instance ( object )
* @ access public
*/
function __construct ( $wsdl = false ){
parent :: nusoap_base ();
// turn on debugging?
global $debug ;
if ( isset ( $_SERVER )) {
$this -> debug ( " _SERVER is defined: " );
$this -> appendDebug ( $this -> varDump ( $_SERVER ));
} else {
$this -> debug ( " _SERVER not defined. " );
}
if ( isset ( $debug )) {
$this -> debug ( " In nusoap_server, set debug_flag= $debug based on global flag " );
$this -> debug_flag = $debug ;
} elseif ( isset ( $_SERVER [ 'QUERY_STRING' ])) {
$qs = explode ( '&' , sanitize_text_field ( wp_unslash ( $_SERVER [ 'QUERY_STRING' ] ) ) );
foreach ( $qs as $v ) {
if ( substr ( $v , 0 , 6 ) == 'debug=' ) {
$this -> debug ( " In nusoap_server, set debug_flag= " . substr ( $v , 6 ) . " based on query string #1 " );
$this -> debug_flag = substr ( $v , 6 );
}
}
}
// wsdl
if ( $wsdl ){
$this -> debug ( " In nusoap_server, WSDL is specified " );
if ( is_object ( $wsdl ) && ( get_class ( $wsdl ) == 'wsdl' )) {
$this -> wsdl = $wsdl ;
$this -> externalWSDLURL = $this -> wsdl -> wsdl ;
$this -> debug ( 'Use existing wsdl instance from ' . $this -> externalWSDLURL );
} else {
$this -> debug ( 'Create wsdl from ' . $wsdl );
$this -> wsdl = new wsdl ( $wsdl );
$this -> externalWSDLURL = $wsdl ;
}
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
if ( $err = $this -> wsdl -> getError ()){
die ( 'WSDL ERROR: ' . esc_html ( $err ) );
}
}
}
/**
* processes request and returns response
*
* @ param string $data usually is the value of $HTTP_RAW_POST_DATA
* @ access public
*/
function service ( $data ){
if ( isset ( $_SERVER [ 'REQUEST_METHOD' ])) {
$rm = sanitize_text_field ( wp_unslash ( $_SERVER [ 'REQUEST_METHOD' ] ) );
} else {
$rm = '' ;
}
if ( isset ( $_SERVER [ 'QUERY_STRING' ])) {
$qs = sanitize_text_field ( wp_unslash ( $_SERVER [ 'QUERY_STRING' ] ) );
} else {
$qs = '' ;
}
$this -> debug ( " In service, request method= $rm query string= $qs strlen( \$ data)= " . strlen ( $data ));
if ( $rm == 'POST' ) {
$this -> debug ( " In service, invoke the request " );
$this -> parse_request ( $data );
if ( ! $this -> fault ) {
$this -> invoke_method ();
}
if ( ! $this -> fault ) {
$this -> serialize_return ();
}
$this -> send_response ();
} elseif ( preg_match ( '/wsdl/' , $qs ) ){
$this -> debug ( " In service, this is a request for WSDL " );
if ( $this -> externalWSDLURL ){
if ( strpos ( $this -> externalWSDLURL , " http:// " ) !== false ) { // assume URL
$this -> debug ( " In service, re-direct for WSDL " );
header ( 'Location: ' . $this -> externalWSDLURL );
} else { // assume file
$this -> debug ( " In service, use file passthru for WSDL " );
header ( " Content-Type: text/xml \r \n " );
$pos = strpos ( $this -> externalWSDLURL , " file:// " );
if ( $pos === false ) {
$filename = $this -> externalWSDLURL ;
} else {
$filename = substr ( $this -> externalWSDLURL , $pos + 7 );
}
$fp = fopen ( $this -> externalWSDLURL , 'r' );
fpassthru ( $fp );
}
} elseif ( $this -> wsdl ) {
$this -> debug ( " In service, serialize WSDL " );
header ( " Content-Type: text/xml; charset=ISO-8859-1 \r \n " );
print esc_html ( $this -> wsdl -> serialize ( $this -> debug_flag ) );
if ( $this -> debug_flag ) {
$this -> debug ( 'wsdl:' );
$this -> appendDebug ( $this -> varDump ( $this -> wsdl ));
print esc_html ( $this -> getDebugAsXMLComment () );
}
} else {
$this -> debug ( " In service, there is no WSDL " );
header ( " Content-Type: text/html; charset=ISO-8859-1 \r \n " );
print " This service does not provide WSDL " ;
}
} elseif ( $this -> wsdl ) {
$this -> debug ( " In service, return Web description " );
print esc_html ( $this -> wsdl -> webDescription () );
} else {
$this -> debug ( " In service, no Web description " );
header ( " Content-Type: text/html; charset=ISO-8859-1 \r \n " );
print " This service does not provide a Web description " ;
}
}
/**
* parses HTTP request headers .
*
* The following fields are set by this function ( when successful )
*
* headers
* request
* xml_encoding
* SOAPAction
*
* @ access private
*/
function parse_http_headers () {
$this -> request = '' ;
$this -> SOAPAction = '' ;
if ( function_exists ( 'getallheaders' )){
$this -> debug ( " In parse_http_headers, use getallheaders " );
$headers = getallheaders ();
foreach ( $headers as $k => $v ){
$k = strtolower ( $k );
$this -> headers [ $k ] = $v ;
$this -> request .= " $k : $v\r\n " ;
$this -> debug ( " $k : $v " );
}
// get SOAPAction header
if ( isset ( $this -> headers [ 'soapaction' ])){
$this -> SOAPAction = str_replace ( '"' , '' , $this -> headers [ 'soapaction' ]);
}
// get the character encoding of the incoming request
if ( isset ( $this -> headers [ 'content-type' ]) && strpos ( $this -> headers [ 'content-type' ], '=' )){
$enc = str_replace ( '"' , '' , substr ( strstr ( $this -> headers [ " content-type " ], '=' ), 1 ));
if ( preg_match ( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i' , $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' ;
}
} elseif ( isset ( $_SERVER ) && is_array ( $_SERVER )){
$this -> debug ( " In parse_http_headers, use _SERVER " );
foreach ( $_SERVER as $k => $v ) {
if ( substr ( $k , 0 , 5 ) == 'HTTP_' ) {
$k = str_replace ( ' ' , '-' , strtolower ( str_replace ( '_' , ' ' , substr ( $k , 5 ))));
} else {
$k = str_replace ( ' ' , '-' , strtolower ( str_replace ( '_' , ' ' , $k )));
}
if ( $k == 'soapaction' ) {
// get SOAPAction header
$k = 'SOAPAction' ;
$v = str_replace ( '"' , '' , $v );
$v = str_replace ( '\\' , '' , $v );
$this -> SOAPAction = $v ;
} else if ( $k == 'content-type' ) {
// get the character encoding of the incoming request
if ( strpos ( $v , '=' )) {
$enc = substr ( strstr ( $v , '=' ), 1 );
$enc = str_replace ( '"' , '' , $enc );
$enc = str_replace ( '\\' , '' , $enc );
if ( preg_match ( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i' , $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 -> headers [ $k ] = $v ;
$this -> request .= " $k : $v\r\n " ;
$this -> debug ( " $k : $v " );
}
} else {
$this -> debug ( " In parse_http_headers, HTTP headers not accessible " );
$this -> setError ( " HTTP headers not accessible " );
}
}
/**
* parses a request
*
* The following fields are set by this function ( when successful )
*
* headers
* request
* xml_encoding
* SOAPAction
* request
* requestSOAP
* methodURI
* methodname
* methodparams
* requestHeaders
* document
*
* This sets the fault field on error
*
* @ param string $data XML string
* @ access private
*/
function parse_request ( $data = '' ) {
$this -> debug ( 'entering parse_request()' );
$this -> parse_http_headers ();
$this -> debug ( 'got character encoding: ' . $this -> xml_encoding );
// uncompress if necessary
if ( isset ( $this -> headers [ 'content-encoding' ]) && $this -> headers [ 'content-encoding' ] != '' ) {
$this -> debug ( 'got content encoding: ' . $this -> headers [ 'content-encoding' ]);
if ( $this -> headers [ 'content-encoding' ] == 'br' ) {
// if decoding works, use it. else assume data wasn't brotli compressed
if ( function_exists ( 'brotli_uncompress' )) {
if ( $this -> headers [ 'content-encoding' ] == 'deflate' && $debrdata = @ brotli_uncompress ( $data )) {
$data = $debrdata ;
} else {
$this -> fault ( 'SOAP-ENV:Client' , 'Errors occurred when trying to decode the data' );
return ;
}
} else {
$this -> fault ( 'SOAP-ENV:Client' , 'This Server does not support compressed data' );
return ;
}
} elseif ( $this -> headers [ 'content-encoding' ] == 'deflate' || $this -> headers [ 'content-encoding' ] == 'gzip' ) {
// if decoding works, use it. else assume data wasn't gzencoded
if ( function_exists ( 'gzuncompress' )) {
if ( $this -> headers [ 'content-encoding' ] == 'deflate' && $degzdata = @ gzuncompress ( $data )) {
$data = $degzdata ;
} elseif ( $this -> headers [ 'content-encoding' ] == 'gzip' && $degzdata = gzinflate ( substr ( $data , 10 ))) {
$data = $degzdata ;
} else {
$this -> fault ( 'SOAP-ENV:Client' , 'Errors occurred when trying to decode the data' );
return ;
}
} else {
$this -> fault ( 'SOAP-ENV:Client' , 'This Server does not support compressed data' );
return ;
}
}
}
$this -> request .= " \r \n " . $data ;
$data = $this -> parseRequest ( $this -> headers , $data );
$this -> requestSOAP = $data ;
$this -> debug ( 'leaving parse_request' );
}
/**
* invokes a PHP function for the requested SOAP method
*
* The following fields are set by this function ( when successful )
*
* methodreturn
*
* Note that the PHP function that is called may also set the following
* fields to affect the response sent to the client
*
* responseHeaders
* outgoing_headers
*
* This sets the fault field on error
*
* @ access private
*/
function invoke_method () {
$this -> debug ( 'in invoke_method, methodname=' . $this -> methodname . ' methodURI=' . $this -> methodURI . ' SOAPAction=' . $this -> SOAPAction );
//
// if you are debugging in this area of the code, your service uses a class to implement methods,
// you use SOAP RPC, and the client is .NET, please be aware of the following...
// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
// method name. that is fine for naming the .NET methods. it is not fine for properly constructing
// the XML request and reading the XML response. you need to add the RequestElementName and
// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
// generates for the method. these parameters are used to specify the correct XML element names
// for .NET to use, i.e. the names with the '.' in them.
//
$orig_methodname = $this -> methodname ;
if ( $this -> wsdl ) {
if ( $this -> opData = $this -> wsdl -> getOperationData ( $this -> methodname )) {
$this -> debug ( 'in invoke_method, found WSDL operation=' . $this -> methodname );
$this -> appendDebug ( 'opData=' . $this -> varDump ( $this -> opData ));
} elseif ( $this -> opData = $this -> wsdl -> getOperationDataForSoapAction ( $this -> SOAPAction )) {
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
$this -> debug ( 'in invoke_method, found WSDL soapAction=' . $this -> SOAPAction . ' for operation=' . $this -> opData [ 'name' ]);
$this -> appendDebug ( 'opData=' . $this -> varDump ( $this -> opData ));
$this -> methodname = $this -> opData [ 'name' ];
} else {
$this -> debug ( 'in invoke_method, no WSDL for operation=' . $this -> methodname );
$this -> fault ( 'SOAP-ENV:Client' , " Operation ' " . $this -> methodname . " ' is not defined in the WSDL for this service " );
return ;
}
} else {
$this -> debug ( 'in invoke_method, no WSDL to validate method' );
}
// if a . is present in $this->methodname, we see if there is a class in scope,
// which could be referred to. We will also distinguish between two deliminators,
// to allow methods to be called a the class or an instance
if ( strpos ( $this -> methodname , '..' ) > 0 ) {
$delim = '..' ;
} else if ( strpos ( $this -> methodname , '.' ) > 0 ) {
$delim = '.' ;
} else {
$delim = '' ;
}
$this -> debug ( " in invoke_method, delim= $delim " );
$class = '' ;
$method = '' ;
if ( strlen ( $delim ) > 0 && substr_count ( $this -> methodname , $delim ) == 1 ) {
$try_class = substr ( $this -> methodname , 0 , strpos ( $this -> methodname , $delim ));
if ( class_exists ( $try_class )) {
// get the class and method name
$class = $try_class ;
$method = substr ( $this -> methodname , strpos ( $this -> methodname , $delim ) + strlen ( $delim ));
$this -> debug ( " in invoke_method, class= $class method= $method delim= $delim " );
} else {
$this -> debug ( " in invoke_method, class= $try_class not found " );
}
} else {
$try_class = '' ;
$this -> debug ( " in invoke_method, no class to try " );
}
// does method exist?
if ( $class == '' ) {
if ( ! function_exists ( $this -> methodname )) {
$this -> debug ( " in invoke_method, function ' $this->methodname ' not found! " );
$this -> result = 'fault: method not found' ;
$this -> fault ( 'SOAP-ENV:Client' , " method ' $this->methodname '(' $orig_methodname ') not defined in service(' $try_class ' ' $delim ') " );
return ;
}
} else {
$method_to_compare = ( substr ( phpversion (), 0 , 2 ) == '4.' ) ? strtolower ( $method ) : $method ;
if ( ! in_array ( $method_to_compare , get_class_methods ( $class ))) {
$this -> debug ( " in invoke_method, method ' $this->methodname ' not found in class ' $class '! " );
$this -> result = 'fault: method not found' ;
$this -> fault ( 'SOAP-ENV:Client' , " method ' $this->methodname '/' $method_to_compare '(' $orig_methodname ') not defined in service/' $class '(' $try_class ' ' $delim ') " );
return ;
}
}
// evaluate message, getting back parameters
// verify that request parameters match the method's signature
if ( ! $this -> verify_method ( $this -> methodname , $this -> methodparams )){
// debug
$this -> debug ( 'ERROR: request not verified against method signature' );
$this -> result = 'fault: request failed validation against method signature' ;
// return fault
$this -> fault ( 'SOAP-ENV:Client' , " Operation ' $this->methodname ' not defined in service. " );
return ;
}
// if there are parameters to pass
$this -> debug ( 'in invoke_method, params:' );
$this -> appendDebug ( $this -> varDump ( $this -> methodparams ));
$this -> debug ( " in invoke_method, calling ' $this->methodname ' " );
if ( ! function_exists ( 'call_user_func_array' )) {
if ( $class == '' ) {
$this -> debug ( 'in invoke_method, calling function using eval()' );
$funcCall = " \$ this->methodreturn = $this->methodname ( " ;
} else {
if ( $delim == '..' ) {
$this -> debug ( 'in invoke_method, calling class method using eval()' );
$funcCall = " \$ this->methodreturn = " . $class . " :: " . $method . " ( " ;
} else {
$this -> debug ( 'in invoke_method, calling instance method using eval()' );
// generate unique instance name
$instname = " \$ inst_ " . time ();
$funcCall = $instname . " = new " . $class . " (); " ;
$funcCall .= " \$ this->methodreturn = " . $instname . " -> " . $method . " ( " ;
}
}
if ( $this -> methodparams ) {
foreach ( $this -> methodparams as $param ) {
if ( is_array ( $param ) || is_object ( $param )) {
$this -> fault ( 'SOAP-ENV:Client' , 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available' );
return ;
}
$funcCall .= " \" $param\ " , " ;
}
$funcCall = substr ( $funcCall , 0 , - 1 );
}
$funcCall .= ');' ;
$this -> debug ( 'in invoke_method, function call: ' . $funcCall );
@ eval ( $funcCall );
} else {
if ( $class == '' ) {
$this -> debug ( 'in invoke_method, calling function using call_user_func_array()' );
$call_arg = " $this->methodname " ; // straight assignment changes $this->methodname to lower case after call_user_func_array()
} elseif ( $delim == '..' ) {
$this -> debug ( 'in invoke_method, calling class method using call_user_func_array()' );
$call_arg = array ( $class , $method );
} else {
$this -> debug ( 'in invoke_method, calling instance method using call_user_func_array()' );
$instance = new $class ();
$call_arg = array ( & $instance , $method );
}
if ( is_array ( $this -> methodparams )) {
$this -> methodreturn = call_user_func_array ( $call_arg , array_values ( $this -> methodparams ));
} else {
$this -> methodreturn = call_user_func_array ( $call_arg , array ());
}
}
$this -> debug ( 'in invoke_method, methodreturn:' );
$this -> appendDebug ( $this -> varDump ( $this -> methodreturn ));
$this -> debug ( " in invoke_method, called method $this->methodname , received data of type " . gettype ( $this -> methodreturn ));
}
/**
* serializes the return value from a PHP function into a full SOAP Envelope
*
* The following fields are set by this function ( when successful )
*
* responseSOAP
*
* This sets the fault field on error
*
* @ access private
*/
function serialize_return () {
$this -> debug ( 'Entering serialize_return methodname: ' . $this -> methodname . ' methodURI: ' . $this -> methodURI );
// if fault
if ( isset ( $this -> methodreturn ) && is_object ( $this -> methodreturn ) && (( get_class ( $this -> methodreturn ) == 'soap_fault' ) || ( get_class ( $this -> methodreturn ) == 'nusoap_fault' ))) {
$this -> debug ( 'got a fault object from method' );
$this -> fault = $this -> methodreturn ;
return ;
} elseif ( $this -> methodreturnisliteralxml ) {
$return_val = $this -> methodreturn ;
// returned value(s)
} else {
$this -> debug ( 'got a(n) ' . gettype ( $this -> methodreturn ) . ' from method' );
$this -> debug ( 'serializing return value' );
if ( $this -> wsdl ){
if ( sizeof ( $this -> opData [ 'output' ][ 'parts' ]) > 1 ) {
$this -> debug ( 'more than one output part, so use the method return unchanged' );
$opParams = $this -> methodreturn ;
} elseif ( sizeof ( $this -> opData [ 'output' ][ 'parts' ]) == 1 ) {
$this -> debug ( 'exactly one output part, so wrap the method return in a simple array' );
// TODO: verify that it is not already wrapped!
//foreach ($this->opData['output']['parts'] as $name => $type) {
// $this->debug('wrap in element named ' . $name);
//}
$opParams = array ( $this -> methodreturn );
}
$return_val = $this -> wsdl -> serializeRPCParameters ( $this -> methodname , 'output' , $opParams );
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
if ( $errstr = $this -> wsdl -> getError ()){
$this -> debug ( 'got wsdl error: ' . $errstr );
$this -> fault ( 'SOAP-ENV:Server' , 'unable to serialize result' );
return ;
}
} else {
if ( isset ( $this -> methodreturn )) {
$return_val = $this -> serialize_val ( $this -> methodreturn , 'return' );
} else {
$return_val = '' ;
$this -> debug ( 'in absence of WSDL, assume void return for backward compatibility' );
}
}
}
$this -> debug ( 'return value:' );
$this -> appendDebug ( $this -> varDump ( $return_val ));
$this -> debug ( 'serializing response' );
if ( $this -> wsdl ) {
$this -> debug ( 'have WSDL for serialization: style is ' . $this -> opData [ 'style' ]);
if ( $this -> opData [ 'style' ] == 'rpc' ) {
$this -> debug ( 'style is rpc for serialization: use is ' . $this -> opData [ 'output' ][ 'use' ]);
if ( $this -> opData [ 'output' ][ 'use' ] == 'literal' ) {
// http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
if ( $this -> methodURI ) {
$payload = '<ns1:' . $this -> methodname . 'Response xmlns:ns1="' . $this -> methodURI . '">' . $return_val . '</ns1:' . $this -> methodname . " Response> " ;
} else {
$payload = '<' . $this -> methodname . 'Response>' . $return_val . '</' . $this -> methodname . 'Response>' ;
}
} else {
if ( $this -> methodURI ) {
$payload = '<ns1:' . $this -> methodname . 'Response xmlns:ns1="' . $this -> methodURI . '">' . $return_val . '</ns1:' . $this -> methodname . " Response> " ;
} else {
$payload = '<' . $this -> methodname . 'Response>' . $return_val . '</' . $this -> methodname . 'Response>' ;
}
}
} else {
$this -> debug ( 'style is not rpc for serialization: assume document' );
$payload = $return_val ;
}
} else {
$this -> debug ( 'do not have WSDL for serialization: assume rpc/encoded' );
$payload = '<ns1:' . $this -> methodname . 'Response xmlns:ns1="' . $this -> methodURI . '">' . $return_val . '</ns1:' . $this -> methodname . " Response> " ;
}
$this -> result = 'successful' ;
if ( $this -> wsdl ){
//if($this->debug_flag){
$this -> appendDebug ( $this -> wsdl -> getDebug ());
// }
if ( isset ( $this -> opData [ 'output' ][ 'encodingStyle' ])) {
$encodingStyle = $this -> opData [ 'output' ][ 'encodingStyle' ];
} else {
$encodingStyle = '' ;
}
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
$this -> responseSOAP = $this -> serializeEnvelope ( $payload , $this -> responseHeaders , $this -> wsdl -> usedNamespaces , $this -> opData [ 'style' ], $this -> opData [ 'output' ][ 'use' ], $encodingStyle );
} else {
$this -> responseSOAP = $this -> serializeEnvelope ( $payload , $this -> responseHeaders );
}
$this -> debug ( " Leaving serialize_return " );
}
/**
* sends an HTTP response
*
* The following fields are set by this function ( when successful )
*
* outgoing_headers
* response
*
* @ access private
*/
function send_response () {
$this -> debug ( 'Enter send_response' );
if ( $this -> fault ) {
$payload = $this -> fault -> serialize ();
$this -> outgoing_headers [] = " HTTP/1.0 500 Internal Server Error " ;
$this -> outgoing_headers [] = " Status: 500 Internal Server Error " ;
} else {
$payload = $this -> responseSOAP ;
// Some combinations of PHP+Web server allow the Status
// to come through as a header. Since OK is the default
// just do nothing.
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
// $this->outgoing_headers[] = "Status: 200 OK";
}
// add debug data if in debug mode
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ){
$payload .= $this -> getDebugAsXMLComment ();
}
$this -> outgoing_headers [] = " Server: $this->title Server v $this->version " ;
preg_match ( '/\$Revisio' . 'n: ([^ ]+)/' , $this -> revision , $rev );
$this -> outgoing_headers [] = " X-SOAP-Server: $this->title / $this->version ( " . $rev [ 1 ] . " ) " ;
// Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n";
$payload = $this -> getHTTPBody ( $payload );
$type = $this -> getHTTPContentType ();
$charset = $this -> getHTTPContentTypeCharset ();
$this -> outgoing_headers [] = " Content-Type: $type " . ( $charset ? '; charset=' . $charset : '' );
//begin code to compress payload - by John
// NOTE: there is no way to know whether the Web server will also compress
// this data.
if ( strlen ( $payload ) > 1024 && isset ( $this -> headers ) && isset ( $this -> headers [ 'accept-encoding' ])) {
if ( strstr ( $this -> headers [ 'accept-encoding' ], 'br' )) {
if ( function_exists ( 'brotli_compress' )) {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content being brotli compressed --> " ;
}
$this -> outgoing_headers [] = " Content-Encoding: br " ;
$payload = brotli_compress ( $payload );
} else {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content will not be brotli compressed: no brotli_compress --> " ;
}
}
} elseif ( strstr ( $this -> headers [ 'accept-encoding' ], 'gzip' )) {
if ( function_exists ( 'gzencode' )) {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content being gzipped --> " ;
}
$this -> outgoing_headers [] = " Content-Encoding: gzip " ;
$payload = gzencode ( $payload );
} else {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content will not be gzipped: no gzencode --> " ;
}
}
} elseif ( strstr ( $this -> headers [ 'accept-encoding' ], 'deflate' )) {
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
// instead of gzcompress output,
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
if ( function_exists ( 'gzdeflate' )) {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content being deflated --> " ;
}
$this -> outgoing_headers [] = " Content-Encoding: deflate " ;
$payload = gzdeflate ( $payload );
} else {
if ( isset ( $this -> debug_flag ) && $this -> debug_flag ) {
$payload .= " <!-- Content will not be deflated: no gzcompress --> " ;
}
}
}
}
//end code
$this -> outgoing_headers [] = " Content-Length: " . strlen ( $payload );
reset ( $this -> outgoing_headers );
foreach ( $this -> outgoing_headers as $hdr ){
header ( $hdr , false );
}
print wp_kses ( $payload , Util_Ui :: get_allowed_html_for_wp_kses_from_content ( $payload ) );
$this -> response = join ( " \r \n " , $this -> outgoing_headers ) . " \r \n \r \n " . $payload ;
}
/**
* takes the value that was created by parsing the request
* and compares to the method ' s signature , if available .
*
* @ param string $operation The operation to be invoked
* @ param array $request The array of parameter values
* @ return boolean Whether the operation was found
* @ access private
*/
function verify_method ( $operation , $request ){
if ( isset ( $this -> wsdl ) && is_object ( $this -> wsdl )){
if ( $this -> wsdl -> getOperationData ( $operation )){
return true ;
}
} elseif ( isset ( $this -> operations [ $operation ])){
return true ;
}
return false ;
}
/**
* processes SOAP message received from client
*
* @ param array $headers The HTTP headers
* @ param string $data unprocessed request data from client
* @ return mixed value of the message , decoded into a PHP type
* @ access private
*/
function parseRequest ( $headers , $data ) {
$this -> debug ( 'Entering parseRequest() for data of length ' . strlen ( $data ) . ' headers:' );
$this -> appendDebug ( $this -> varDump ( $headers ));
if ( ! isset ( $headers [ 'content-type' ])) {
$this -> setError ( 'Request not of type text/xml (no content-type header)' );
return false ;
}
if ( ! strstr ( $headers [ 'content-type' ], 'text/xml' )) {
$this -> setError ( 'Request 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 ( preg_match ( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i' , $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 nusoap_parser' );
// parse response, get soap parser obj
$parser = new nusoap_parser ( $data , $this -> xml_encoding , '' , $this -> decode_utf8 );
// parser debug
$this -> debug ( " parser debug: \n " . $parser -> getDebug ());
// if fault occurred during message parsing
if ( $err = $parser -> getError ()){
$this -> result = 'fault: error in msg parsing: ' . $err ;
$this -> fault ( 'SOAP-ENV:Client' , " error in msg parsing: \n " . $err );
// else successfully parsed request into soapval object
} else {
// get/set methodname
$this -> methodURI = $parser -> root_struct_namespace ;
$this -> methodname = $parser -> root_struct_name ;
$this -> debug ( 'methodname: ' . $this -> methodname . ' methodURI: ' . $this -> methodURI );
$this -> debug ( 'calling parser->get_soapbody()' );
$this -> methodparams = $parser -> get_soapbody ();
// get SOAP headers
$this -> requestHeaders = $parser -> getHeaders ();
// get SOAP Header
$this -> requestHeader = $parser -> get_soapheader ();
// add document for doclit support
$this -> document = $parser -> document ;
}
}
/**
* gets the HTTP body for the current response .
*
* @ param string $soapmsg The SOAP payload
* @ return string The HTTP body , which includes the SOAP payload
* @ access private
*/
function getHTTPBody ( $soapmsg ) {
return $soapmsg ;
}
/**
* gets the HTTP content type for the current response .
*
* Note : getHTTPBody must be called before this .
*
* @ return string the HTTP content type for the current response .
* @ access private
*/
function getHTTPContentType () {
return 'text/xml' ;
}
/**
* gets the HTTP content type charset for the current response .
* returns false for non - text content types .
*
* Note : getHTTPBody must be called before this .
*
* @ return string the HTTP content type charset for the current response .
* @ access private
*/
function getHTTPContentTypeCharset () {
return $this -> soap_defencoding ;
}
/**
* add a method to the dispatch map ( this has been replaced by the register method )
*
* @ param string $methodname
* @ param string $in array of input values
* @ param string $out array of output values
* @ access public
* @ deprecated
*/
function add_to_map ( $methodname , $in , $out ){
$this -> operations [ $methodname ] = array ( 'name' => $methodname , 'in' => $in , 'out' => $out );
}
/**
* register a service function with the server
*
* @ param string $name the name of the PHP function , class . method or class .. method
* @ param array $in assoc array of input values : key = param name , value = param type
* @ param array $out assoc array of output values : key = param name , value = param type
* @ param mixed $namespace the element namespace for the method or false
* @ param mixed $soapaction the soapaction for the method or false
* @ param mixed $style optional ( rpc | document ) or false Note : when 'document' is specified , parameter and return wrappers are created for you automatically
* @ param mixed $use optional ( encoded | literal ) or false
* @ param string $documentation optional Description to include in WSDL
* @ param string $encodingStyle optional ( usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded )
* @ access public
*/
function register ( $name , $in = array (), $out = array (), $namespace = false , $soapaction = false , $style = false , $use = false , $documentation = '' , $encodingStyle = '' ){
if ( $this -> externalWSDLURL ){
die ( 'You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.' );
}
if ( ! $name ) {
die ( 'You must specify a name when you register an operation' );
}
if ( ! is_array ( $in )) {
die ( 'You must provide an array for operation inputs' );
}
if ( ! is_array ( $out )) {
die ( 'You must provide an array for operation outputs' );
}
if ( false == $namespace ) {
}
if ( false == $soapaction ) {
if ( isset ( $_SERVER )) {
$SERVER_NAME = isset ( $_SERVER [ 'SERVER_NAME' ] ) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'SERVER_NAME' ] ) ) : '' ;
$SCRIPT_NAME = '' ;
if ( isset ( $_SERVER [ 'PHP_SELF' ] ) ) {
$SCRIPT_NAME = sanitize_text_field ( wp_unslash ( $_SERVER [ 'PHP_SELF' ] ) );
} elseif ( isset ( $_SERVER [ 'SCRIPT_NAME' ] ) ) {
$SCRIPT_NAME = sanitize_text_field ( wp_unslash ( $_SERVER [ 'SCRIPT_NAME' ] ) );
}
$HTTPS = isset ( $_SERVER [ 'HTTPS' ]) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'HTTPS' ] ) ) : 'off' ;
} else {
$this -> setError ( " _SERVER not available " );
}
if ( $HTTPS == '1' || $HTTPS == 'on' ) {
$SCHEME = 'https' ;
} else {
$SCHEME = 'http' ;
}
$soapaction = " $SCHEME :// $SERVER_NAME $SCRIPT_NAME / $name " ;
}
if ( false == $style ) {
$style = " rpc " ;
}
if ( false == $use ) {
$use = " encoded " ;
}
if ( $use == 'encoded' && $encodingStyle == '' ) {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ;
}
$this -> operations [ $name ] = array (
'name' => $name ,
'in' => $in ,
'out' => $out ,
'namespace' => $namespace ,
'soapaction' => $soapaction ,
'style' => $style );
if ( $this -> wsdl ){
$this -> wsdl -> addOperation ( $name , $in , $out , $namespace , $soapaction , $style , $use , $documentation , $encodingStyle );
}
return true ;
}
/**
* Specify a fault to be returned to the client .
* This also acts as a flag to the server that a fault has occured .
*
* @ param string $faultcode
* @ param string $faultstring
* @ param string $faultactor
* @ param string $faultdetail
* @ access public
*/
function fault ( $faultcode , $faultstring , $faultactor = '' , $faultdetail = '' ){
if ( $faultdetail == '' && $this -> debug_flag ) {
$faultdetail = $this -> getDebug ();
}
$this -> fault = new nusoap_fault ( $faultcode , $faultactor , $faultstring , $faultdetail );
$this -> fault -> soap_defencoding = $this -> soap_defencoding ;
}
/**
* Sets up wsdl object .
* Acts as a flag to enable internal WSDL generation
*
* @ param string $serviceName , name of the service
* @ param mixed $namespace optional 'tns' service namespace or false
* @ param mixed $endpoint optional URL of service endpoint or false
* @ param string $style optional ( rpc | document ) WSDL style ( also specified by operation )
* @ param string $transport optional SOAP transport
* @ param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
*/
function configureWSDL ( $serviceName , $namespace = false , $endpoint = false , $style = 'rpc' , $transport = 'http://schemas.xmlsoap.org/soap/http' , $schemaTargetNamespace = false )
{
if ( isset ( $_SERVER )) {
$SERVER_NAME = isset ( $_SERVER [ 'SERVER_NAME' ] ) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'SERVER_NAME' ] ) ) : '' ;
$SERVER_PORT = isset ( $_SERVER [ 'SERVER_PORT' ] ) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'SERVER_PORT' ] ) ) : '' ;
$SCRIPT_NAME = '' ;
if ( isset ( $_SERVER [ 'PHP_SELF' ] ) ) {
$SCRIPT_NAME = sanitize_text_field ( wp_unslash ( $_SERVER [ 'PHP_SELF' ] ) );
} elseif ( isset ( $_SERVER [ 'SCRIPT_NAME' ] ) ) {
$SCRIPT_NAME = sanitize_text_field ( wp_unslash ( $_SERVER [ 'SCRIPT_NAME' ] ) );
}
$HTTPS = isset ( $_SERVER [ 'HTTPS' ] ) ? sanitize_text_field ( wp_unslash ( $_SERVER [ 'HTTPS' ] ) ) : 'off' ;
} else {
$this -> setError ( " _SERVER not available " );
}
// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
$colon = strpos ( $SERVER_NAME , " : " );
if ( $colon ) {
$SERVER_NAME = substr ( $SERVER_NAME , 0 , $colon );
}
if ( $SERVER_PORT == 80 ) {
$SERVER_PORT = '' ;
} else {
$SERVER_PORT = ':' . $SERVER_PORT ;
}
if ( false == $namespace ) {
$namespace = " http:// $SERVER_NAME /soap/ $serviceName " ;
}
if ( false == $endpoint ) {
if ( $HTTPS == '1' || $HTTPS == 'on' ) {
$SCHEME = 'https' ;
} else {
$SCHEME = 'http' ;
}
$endpoint = " $SCHEME :// $SERVER_NAME $SERVER_PORT $SCRIPT_NAME " ;
}
if ( false == $schemaTargetNamespace ) {
$schemaTargetNamespace = $namespace ;
}
$this -> wsdl = new wsdl ;
$this -> wsdl -> serviceName = $serviceName ;
$this -> wsdl -> endpoint = $endpoint ;
$this -> wsdl -> namespaces [ 'tns' ] = $namespace ;
$this -> wsdl -> namespaces [ 'soap' ] = 'http://schemas.xmlsoap.org/wsdl/soap/' ;
$this -> wsdl -> namespaces [ 'wsdl' ] = 'http://schemas.xmlsoap.org/wsdl/' ;
if ( $schemaTargetNamespace != $namespace ) {
$this -> wsdl -> namespaces [ 'types' ] = $schemaTargetNamespace ;
}
$this -> wsdl -> schemas [ $schemaTargetNamespace ][ 0 ] = new nusoap_xmlschema ( '' , '' , $this -> wsdl -> namespaces );
if ( $style == 'document' ) {
$this -> wsdl -> schemas [ $schemaTargetNamespace ][ 0 ] -> schemaInfo [ 'elementFormDefault' ] = 'qualified' ;
}
$this -> wsdl -> schemas [ $schemaTargetNamespace ][ 0 ] -> schemaTargetNamespace = $schemaTargetNamespace ;
$this -> wsdl -> schemas [ $schemaTargetNamespace ][ 0 ] -> imports [ 'http://schemas.xmlsoap.org/soap/encoding/' ][ 0 ] = array ( 'location' => '' , 'loaded' => true );
$this -> wsdl -> schemas [ $schemaTargetNamespace ][ 0 ] -> imports [ 'http://schemas.xmlsoap.org/wsdl/' ][ 0 ] = array ( 'location' => '' , 'loaded' => true );
$this -> wsdl -> bindings [ $serviceName . 'Binding' ] = array (
'name' => $serviceName . 'Binding' ,
'style' => $style ,
'transport' => $transport ,
'portType' => $serviceName . 'PortType' );
$this -> wsdl -> ports [ $serviceName . 'Port' ] = array (
'binding' => $serviceName . 'Binding' ,
'location' => $endpoint ,
'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/' );
}
}
/**
* Backward compatibility
*/
class soap_server extends nusoap_server {
}
?> <?php
/**
* parses a WSDL file , allows access to it ' s data , other utility methods .
* also builds WSDL structures programmatically .
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class wsdl extends nusoap_base {
// URL or filename of the root of this WSDL
var $wsdl ;
// define internal arrays of bindings, ports, operations, messages, etc.
var $schemas = array ();
var $currentSchema ;
var $message = array ();
var $complexTypes = array ();
var $messages = array ();
var $currentMessage ;
var $currentOperation ;
var $portTypes = array ();
var $currentPortType ;
var $bindings = array ();
var $currentBinding ;
var $ports = array ();
var $currentPort ;
var $opData = array ();
var $status = '' ;
var $documentation = false ;
var $endpoint = '' ;
// array of wsdl docs to import
var $import = array ();
// parser vars
var $parser ;
var $position = 0 ;
var $depth = 0 ;
var $depth_array = array ();
// for getting wsdl
var $proxyhost = '' ;
var $proxyport = '' ;
var $proxyusername = '' ;
var $proxypassword = '' ;
var $timeout = 0 ;
var $response_timeout = 30 ;
var $curl_options = array (); // User-specified cURL options
var $use_curl = false ; // whether to always try to use cURL
// for HTTP authentication
var $username = '' ; // Username for HTTP authentication
var $password = '' ; // Password for HTTP authentication
var $authtype = '' ; // Type of HTTP authentication
var $certRequest = array (); // Certificate for HTTP SSL authentication
/**
* constructor
*
* @ param string $wsdl WSDL document URL
* @ 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
* @ param array $curl_options user - specified cURL options
* @ param boolean $use_curl try to use cURL
* @ access public
*/
function __construct ( $wsdl = '' , $proxyhost = false , $proxyport = false , $proxyusername = false , $proxypassword = false , $timeout = 0 , $response_timeout = 30 , $curl_options = null , $use_curl = false ){
parent :: nusoap_base ();
$this -> debug ( " ctor wsdl= $wsdl timeout= $timeout response_timeout= $response_timeout " );
$this -> proxyhost = $proxyhost ;
$this -> proxyport = $proxyport ;
$this -> proxyusername = $proxyusername ;
$this -> proxypassword = $proxypassword ;
$this -> timeout = $timeout ;
$this -> response_timeout = $response_timeout ;
if ( is_array ( $curl_options ))
$this -> curl_options = $curl_options ;
$this -> use_curl = $use_curl ;
$this -> fetchWSDL ( $wsdl );
}
/**
* fetches the WSDL document and parses it
*
* @ access public
*/
function fetchWSDL ( $wsdl ) {
$this -> debug ( " parse and process WSDL path= $wsdl " );
$this -> wsdl = $wsdl ;
// parse wsdl file
if ( $this -> wsdl != " " ) {
$this -> parseWSDL ( $this -> wsdl );
}
// imports
// TODO: handle imports more properly, grabbing them in-line and nesting them
$imported_urls = array ();
$imported = 1 ;
while ( $imported > 0 ) {
$imported = 0 ;
// Schema imports
foreach ( $this -> schemas as $ns => $list ) {
foreach ( $list as $xs ) {
$wsdlparts = parse_url ( $this -> wsdl ); // this is bogusly simple!
foreach ( $xs -> imports as $ns2 => $list2 ) {
for ( $ii = 0 ; $ii < count ( $list2 ); $ii ++ ) {
if ( ! $list2 [ $ii ][ 'loaded' ]) {
$this -> schemas [ $ns ] -> imports [ $ns2 ][ $ii ][ 'loaded' ] = true ;
$url = $list2 [ $ii ][ 'location' ];
if ( $url != '' ) {
$urlparts = parse_url ( $url );
if ( ! isset ( $urlparts [ 'host' ])) {
$url = $wsdlparts [ 'scheme' ] . '://' . $wsdlparts [ 'host' ] . ( isset ( $wsdlparts [ 'port' ]) ? ':' . $wsdlparts [ 'port' ] : '' ) .
substr ( $wsdlparts [ 'path' ], 0 , strrpos ( $wsdlparts [ 'path' ], '/' ) + 1 ) . $urlparts [ 'path' ];
}
if ( ! in_array ( $url , $imported_urls )) {
$this -> parseWSDL ( $url );
$imported ++ ;
$imported_urls [] = $url ;
}
} else {
$this -> debug ( " Unexpected scenario: empty URL for unloaded import " );
}
}
}
}
}
}
// WSDL imports
$wsdlparts = parse_url ( $this -> wsdl ); // this is bogusly simple!
foreach ( $this -> import as $ns => $list ) {
for ( $ii = 0 ; $ii < count ( $list ); $ii ++ ) {
if ( ! $list [ $ii ][ 'loaded' ]) {
$this -> import [ $ns ][ $ii ][ 'loaded' ] = true ;
$url = $list [ $ii ][ 'location' ];
if ( $url != '' ) {
$urlparts = parse_url ( $url );
if ( ! isset ( $urlparts [ 'host' ])) {
$url = $wsdlparts [ 'scheme' ] . '://' . $wsdlparts [ 'host' ] . ( isset ( $wsdlparts [ 'port' ]) ? ':' . $wsdlparts [ 'port' ] : '' ) .
substr ( $wsdlparts [ 'path' ], 0 , strrpos ( $wsdlparts [ 'path' ], '/' ) + 1 ) . $urlparts [ 'path' ];
}
if ( ! in_array ( $url , $imported_urls )) {
$this -> parseWSDL ( $url );
$imported ++ ;
$imported_urls [] = $url ;
}
} else {
$this -> debug ( " Unexpected scenario: empty URL for unloaded import " );
}
}
}
}
}
// add new data to operation data
foreach ( $this -> bindings as $binding => $bindingData ) {
if ( isset ( $bindingData [ 'operations' ]) && is_array ( $bindingData [ 'operations' ])) {
foreach ( $bindingData [ 'operations' ] as $operation => $data ) {
$this -> debug ( 'post-parse data gathering for ' . $operation );
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ] =
isset ( $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ]) ?
array_merge ( $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ], $this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'input' ]) :
$this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'input' ];
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ] =
isset ( $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ]) ?
array_merge ( $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ], $this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'output' ]) :
$this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'output' ];
if ( isset ( $this -> messages [ $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ][ 'message' ] ])){
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ][ 'parts' ] = $this -> messages [ $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'input' ][ 'message' ] ];
}
if ( isset ( $this -> messages [ $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ][ 'message' ] ])){
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ][ 'parts' ] = $this -> messages [ $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'output' ][ 'message' ] ];
}
// Set operation style if necessary, but do not override one already provided
if ( isset ( $bindingData [ 'style' ]) && ! isset ( $this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'style' ])) {
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'style' ] = $bindingData [ 'style' ];
}
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'transport' ] = isset ( $bindingData [ 'transport' ]) ? $bindingData [ 'transport' ] : '' ;
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'documentation' ] = isset ( $this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'documentation' ]) ? $this -> portTypes [ $bindingData [ 'portType' ] ][ $operation ][ 'documentation' ] : '' ;
$this -> bindings [ $binding ][ 'operations' ][ $operation ][ 'endpoint' ] = isset ( $bindingData [ 'endpoint' ]) ? $bindingData [ 'endpoint' ] : '' ;
}
}
}
}
/**
* parses the wsdl document
*
* @ param string $wsdl path or URL
* @ access private
*/
function parseWSDL ( $wsdl = '' ) {
$this -> debug ( " parse WSDL at path= $wsdl " );
if ( $wsdl == '' ) {
$this -> debug ( 'no wsdl passed to parseWSDL()!!' );
$this -> setError ( 'no wsdl passed to parseWSDL()!!' );
return false ;
}
// parse $wsdl for url format
$wsdl_props = parse_url ( $wsdl );
if ( isset ( $wsdl_props [ 'scheme' ]) && ( $wsdl_props [ 'scheme' ] == 'http' || $wsdl_props [ 'scheme' ] == 'https' )) {
$this -> debug ( 'getting WSDL http(s) URL ' . $wsdl );
// get wsdl
$tr = new soap_transport_http ( $wsdl , $this -> curl_options , $this -> use_curl );
$tr -> request_method = 'GET' ;
$tr -> useSOAPAction = false ;
if ( $this -> proxyhost && $this -> proxyport ){
$tr -> setProxy ( $this -> proxyhost , $this -> proxyport , $this -> proxyusername , $this -> proxypassword );
}
if ( $this -> authtype != '' ) {
$tr -> setCredentials ( $this -> username , $this -> password , $this -> authtype , array (), $this -> certRequest );
}
$tr -> setEncoding ( 'gzip, deflate' );
$wsdl_string = $tr -> send ( '' , $this -> timeout , $this -> response_timeout );
//$this->debug("WSDL request\n" . $tr->outgoing_payload);
//$this->debug("WSDL response\n" . $tr->incoming_payload);
$this -> appendDebug ( $tr -> getDebug ());
// catch errors
if ( $err = $tr -> getError () ){
$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: ' . $err ;
$this -> debug ( $errstr );
$this -> setError ( $errstr );
unset ( $tr );
return false ;
}
unset ( $tr );
$this -> debug ( " got WSDL URL " );
} else {
// $wsdl is not http(s), so treat it as a file URL or plain file path
if ( isset ( $wsdl_props [ 'scheme' ]) && ( $wsdl_props [ 'scheme' ] == 'file' ) && isset ( $wsdl_props [ 'path' ])) {
$path = isset ( $wsdl_props [ 'host' ]) ? ( $wsdl_props [ 'host' ] . ':' . $wsdl_props [ 'path' ]) : $wsdl_props [ 'path' ];
} else {
$path = $wsdl ;
}
$this -> debug ( 'getting WSDL file ' . $path );
if ( $fp = @ fopen ( $path , 'r' )) {
$wsdl_string = '' ;
while ( $data = fread ( $fp , 32768 )) {
$wsdl_string .= $data ;
}
fclose ( $fp );
} else {
$errstr = " Bad path to WSDL file $path " ;
$this -> debug ( $errstr );
$this -> setError ( $errstr );
return false ;
}
}
$this -> debug ( 'Parse WSDL' );
// end new code added
// Create an XML parser.
$this -> parser = xml_parser_create ();
// 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 );
// 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 , $wsdl_string , true )) {
// Display an error message.
$errstr = sprintf (
'XML error parsing WSDL from %s on line %d: %s' ,
$wsdl ,
xml_get_current_line_number ( $this -> parser ),
xml_error_string ( xml_get_error_code ( $this -> parser ))
);
$this -> debug ( $errstr );
$this -> debug ( " XML payload: \n " . $wsdl_string );
$this -> setError ( $errstr );
return false ;
}
// free the parser
xml_parser_free ( $this -> parser );
$this -> debug ( 'Parsing WSDL done' );
// catch wsdl parse errors
if ( $this -> getError ()){
return false ;
}
return true ;
}
/**
* start - element handler
*
* @ param string $parser XML parser object
* @ param string $name element name
* @ param string $attrs associative array of attributes
* @ access private
*/
function start_element ( $parser , $name , $attrs )
{
if ( $this -> status == 'schema' ) {
$this -> currentSchema -> schemaStartElement ( $parser , $name , $attrs );
$this -> appendDebug ( $this -> currentSchema -> getDebug ());
$this -> currentSchema -> clearDebug ();
} elseif ( preg_match ( '/schema$/' , $name )) {
$this -> debug ( 'Parsing WSDL schema' );
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
$this -> status = 'schema' ;
$this -> currentSchema = new nusoap_xmlschema ( '' , '' , $this -> namespaces );
$this -> currentSchema -> schemaStartElement ( $parser , $name , $attrs );
$this -> appendDebug ( $this -> currentSchema -> getDebug ());
$this -> currentSchema -> clearDebug ();
} else {
// 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' => '' );
// process attributes
if ( count ( $attrs ) > 0 ) {
// register namespace declarations
foreach ( $attrs as $k => $v ) {
if ( preg_match ( '/^xmlns/' , $k )) {
if ( $ns_prefix = substr ( strrchr ( $k , ':' ), 1 )) {
$this -> namespaces [ $ns_prefix ] = $v ;
} else {
$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' ;
}
}
}
// expand each attribute prefix to its namespace
foreach ( $attrs as $k => $v ) {
$k = strpos ( $k , ':' ) ? $this -> expandQname ( $k ) : $k ;
if ( $k != 'location' && $k != 'soapAction' && $k != 'namespace' ) {
$v = strpos ( $v , ':' ) ? $this -> expandQname ( $v ) : $v ;
}
$eAttrs [ $k ] = $v ;
}
$attrs = $eAttrs ;
} else {
$attrs = array ();
}
// get element prefix, namespace and name
if ( preg_match ( '/:/' , $name )) {
// get ns prefix
$prefix = substr ( $name , 0 , strpos ( $name , ':' ));
// get ns
$namespace = isset ( $this -> namespaces [ $prefix ]) ? $this -> namespaces [ $prefix ] : '' ;
// get unqualified name
$name = substr ( strstr ( $name , ':' ), 1 );
}
// process attributes, expanding any prefixes to namespaces
// find status, register data
switch ( $this -> status ) {
case 'message' :
if ( $name == 'part' ) {
if ( isset ( $attrs [ 'type' ])) {
$this -> debug ( " msg " . $this -> currentMessage . " : found part (with type) $attrs[name] : " . implode ( ',' , $attrs ));
$this -> messages [ $this -> currentMessage ][ $attrs [ 'name' ]] = $attrs [ 'type' ];
}
if ( isset ( $attrs [ 'element' ])) {
$this -> debug ( " msg " . $this -> currentMessage . " : found part (with element) $attrs[name] : " . implode ( ',' , $attrs ));
$this -> messages [ $this -> currentMessage ][ $attrs [ 'name' ]] = $attrs [ 'element' ] . '^' ;
}
}
break ;
case 'portType' :
switch ( $name ) {
case 'operation' :
$this -> currentPortOperation = $attrs [ 'name' ];
$this -> debug ( " portType $this->currentPortType operation: $this->currentPortOperation " );
if ( isset ( $attrs [ 'parameterOrder' ])) {
$this -> portTypes [ $this -> currentPortType ][ $attrs [ 'name' ]][ 'parameterOrder' ] = $attrs [ 'parameterOrder' ];
}
break ;
case 'documentation' :
$this -> documentation = true ;
break ;
// merge input/output data
default :
$m = isset ( $attrs [ 'message' ]) ? $this -> getLocalPart ( $attrs [ 'message' ]) : '' ;
$this -> portTypes [ $this -> currentPortType ][ $this -> currentPortOperation ][ $name ][ 'message' ] = $m ;
break ;
}
break ;
case 'binding' :
switch ( $name ) {
case 'binding' :
// get ns prefix
if ( isset ( $attrs [ 'style' ])) {
$this -> bindings [ $this -> currentBinding ][ 'prefix' ] = $prefix ;
}
$this -> bindings [ $this -> currentBinding ] = array_merge ( $this -> bindings [ $this -> currentBinding ], $attrs );
break ;
case 'header' :
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ $this -> opStatus ][ 'headers' ][] = $attrs ;
break ;
case 'operation' :
if ( isset ( $attrs [ 'soapAction' ])) {
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ 'soapAction' ] = $attrs [ 'soapAction' ];
}
if ( isset ( $attrs [ 'style' ])) {
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ 'style' ] = $attrs [ 'style' ];
}
if ( isset ( $attrs [ 'name' ])) {
$this -> currentOperation = $attrs [ 'name' ];
$this -> debug ( " current binding operation: $this->currentOperation " );
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ 'name' ] = $attrs [ 'name' ];
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ 'binding' ] = $this -> currentBinding ;
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ 'endpoint' ] = isset ( $this -> bindings [ $this -> currentBinding ][ 'endpoint' ]) ? $this -> bindings [ $this -> currentBinding ][ 'endpoint' ] : '' ;
}
break ;
case 'input' :
$this -> opStatus = 'input' ;
break ;
case 'output' :
$this -> opStatus = 'output' ;
break ;
case 'body' :
if ( isset ( $this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ $this -> opStatus ])) {
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ $this -> opStatus ] = array_merge ( $this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ $this -> opStatus ], $attrs );
} else {
$this -> bindings [ $this -> currentBinding ][ 'operations' ][ $this -> currentOperation ][ $this -> opStatus ] = $attrs ;
}
break ;
}
break ;
case 'service' :
switch ( $name ) {
case 'port' :
$this -> currentPort = $attrs [ 'name' ];
$this -> debug ( 'current port: ' . $this -> currentPort );
$this -> ports [ $this -> currentPort ][ 'binding' ] = $this -> getLocalPart ( $attrs [ 'binding' ]);
break ;
case 'address' :
$this -> ports [ $this -> currentPort ][ 'location' ] = $attrs [ 'location' ];
$this -> ports [ $this -> currentPort ][ 'bindingType' ] = $namespace ;
$this -> bindings [ $this -> ports [ $this -> currentPort ][ 'binding' ] ][ 'bindingType' ] = $namespace ;
$this -> bindings [ $this -> ports [ $this -> currentPort ][ 'binding' ] ][ 'endpoint' ] = $attrs [ 'location' ];
break ;
}
break ;
}
// set status
switch ( $name ) {
case 'import' :
if ( isset ( $attrs [ 'location' ])) {
$this -> import [ $attrs [ 'namespace' ]][] = array ( 'location' => $attrs [ 'location' ], 'loaded' => false );
$this -> debug ( 'parsing import ' . $attrs [ 'namespace' ] . ' - ' . $attrs [ 'location' ] . ' (' . count ( $this -> import [ $attrs [ 'namespace' ]]) . ')' );
} else {
$this -> import [ $attrs [ 'namespace' ]][] = array ( 'location' => '' , 'loaded' => true );
if ( ! $this -> getPrefixFromNamespace ( $attrs [ 'namespace' ])) {
$this -> namespaces [ 'ns' . ( count ( $this -> namespaces ) + 1 )] = $attrs [ 'namespace' ];
}
$this -> debug ( 'parsing import ' . $attrs [ 'namespace' ] . ' - [no location] (' . count ( $this -> import [ $attrs [ 'namespace' ]]) . ')' );
}
break ;
//wait for schema
//case 'types':
// $this->status = 'schema';
// break;
case 'message' :
$this -> status = 'message' ;
$this -> messages [ $attrs [ 'name' ]] = array ();
$this -> currentMessage = $attrs [ 'name' ];
break ;
case 'portType' :
$this -> status = 'portType' ;
$this -> portTypes [ $attrs [ 'name' ]] = array ();
$this -> currentPortType = $attrs [ 'name' ];
break ;
case " binding " :
if ( isset ( $attrs [ 'name' ])) {
// get binding name
if ( strpos ( $attrs [ 'name' ], ':' )) {
$this -> currentBinding = $this -> getLocalPart ( $attrs [ 'name' ]);
} else {
$this -> currentBinding = $attrs [ 'name' ];
}
$this -> status = 'binding' ;
$this -> bindings [ $this -> currentBinding ][ 'portType' ] = $this -> getLocalPart ( $attrs [ 'type' ]);
$this -> debug ( " current binding: $this->currentBinding of portType: " . $attrs [ 'type' ]);
}
break ;
case 'service' :
$this -> serviceName = $attrs [ 'name' ];
$this -> status = 'service' ;
$this -> debug ( 'current service: ' . $this -> serviceName );
break ;
case 'definitions' :
foreach ( $attrs as $name => $value ) {
$this -> wsdl_info [ $name ] = $value ;
}
break ;
}
}
}
/**
* end - element handler
*
* @ param string $parser XML parser object
* @ param string $name element name
* @ access private
*/
function end_element ( $parser , $name ){
// unset schema status
if ( /*preg_match('/types$/', $name) ||*/ preg_match ( '/schema$/' , $name )) {
$this -> status = " " ;
$this -> appendDebug ( $this -> currentSchema -> getDebug ());
$this -> currentSchema -> clearDebug ();
$this -> schemas [ $this -> currentSchema -> schemaTargetNamespace ][] = $this -> currentSchema ;
$this -> debug ( 'Parsing WSDL schema done' );
}
if ( $this -> status == 'schema' ) {
$this -> currentSchema -> schemaEndElement ( $parser , $name );
} else {
// bring depth down a notch
$this -> depth -- ;
}
// end documentation
if ( $this -> documentation ) {
//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
$this -> documentation = false ;
}
}
/**
* element content handler
*
* @ param string $parser XML parser object
* @ param string $data element content
* @ access private
*/
function character_data ( $parser , $data )
{
$pos = isset ( $this -> depth_array [ $this -> depth ]) ? $this -> depth_array [ $this -> depth ] : 0 ;
if ( isset ( $this -> message [ $pos ][ 'cdata' ])) {
$this -> message [ $pos ][ 'cdata' ] .= $data ;
}
if ( $this -> documentation ) {
$this -> documentation .= $data ;
}
}
/**
* if authenticating , set user credentials here
*
* @ param string $username
* @ param string $password
* @ param string $authtype ( basic | digest | certificate | ntlm )
* @ param array $certRequest ( keys must be cainfofile ( optional ), sslcertfile , sslkeyfile , passphrase , certpassword ( optional ), verifypeer ( optional ), verifyhost ( optional ) : see corresponding options in cURL docs )
* @ access public
*/
function setCredentials ( $username , $password , $authtype = 'basic' , $certRequest = array ()) {
$this -> debug ( " setCredentials username= $username authtype= $authtype certRequest= " );
$this -> appendDebug ( $this -> varDump ( $certRequest ));
$this -> username = $username ;
$this -> password = $password ;
$this -> authtype = $authtype ;
$this -> certRequest = $certRequest ;
}
function getBindingData ( $binding )
{
if ( is_array ( $this -> bindings [ $binding ])) {
return $this -> bindings [ $binding ];
}
}
/**
* returns an assoc array of operation names => operation data
*
* @ param string $portName WSDL port name
* @ param string $bindingType eg : soap , smtp , dime ( only soap and soap12 are currently supported )
* @ return array
* @ access public
*/
function getOperations ( $portName = '' , $bindingType = 'soap' ) {
$ops = array ();
if ( $bindingType == 'soap' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/' ;
} elseif ( $bindingType == 'soap12' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/' ;
} else {
$this -> debug ( " getOperations bindingType $bindingType may not be supported " );
}
$this -> debug ( " getOperations for port ' $portName ' bindingType $bindingType " );
// loop thru ports
foreach ( $this -> ports as $port => $portData ) {
$this -> debug ( " getOperations checking port $port bindingType " . $portData [ 'bindingType' ]);
if ( $portName == '' || $port == $portName ) {
// binding type of port matches parameter
if ( $portData [ 'bindingType' ] == $bindingType ) {
$this -> debug ( " getOperations found port $port bindingType $bindingType " );
//$this->debug("port data: " . $this->varDump($portData));
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
// merge bindings
if ( isset ( $this -> bindings [ $portData [ 'binding' ] ][ 'operations' ])) {
$ops = array_merge ( $ops , $this -> bindings [ $portData [ 'binding' ] ][ 'operations' ]);
}
}
}
}
if ( count ( $ops ) == 0 ) {
$this -> debug ( " getOperations found no operations for port ' $portName ' bindingType $bindingType " );
}
return $ops ;
}
/**
* returns an associative array of data necessary for calling an operation
*
* @ param string $operation name of operation
* @ param string $bindingType type of binding eg : soap , soap12
* @ return array
* @ access public
*/
function getOperationData ( $operation , $bindingType = 'soap' )
{
if ( $bindingType == 'soap' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/' ;
} elseif ( $bindingType == 'soap12' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/' ;
}
// loop thru ports
foreach ( $this -> ports as $port => $portData ) {
// binding type of port matches parameter
if ( $portData [ 'bindingType' ] == $bindingType ) {
// get binding
//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
foreach ( array_keys ( $this -> bindings [ $portData [ 'binding' ] ][ 'operations' ]) as $bOperation ) {
// note that we could/should also check the namespace here
if ( $operation == $bOperation ) {
$opData = $this -> bindings [ $portData [ 'binding' ] ][ 'operations' ][ $operation ];
return $opData ;
}
}
}
}
}
/**
* returns an associative array of data necessary for calling an operation
*
* @ param string $soapAction soapAction for operation
* @ param string $bindingType type of binding eg : soap , soap12
* @ return array
* @ access public
*/
function getOperationDataForSoapAction ( $soapAction , $bindingType = 'soap' ) {
if ( $bindingType == 'soap' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/' ;
} elseif ( $bindingType == 'soap12' ) {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/' ;
}
// loop thru ports
foreach ( $this -> ports as $port => $portData ) {
// binding type of port matches parameter
if ( $portData [ 'bindingType' ] == $bindingType ) {
// loop through operations for the binding
foreach ( $this -> bindings [ $portData [ 'binding' ] ][ 'operations' ] as $bOperation => $opData ) {
if ( $opData [ 'soapAction' ] == $soapAction ) {
return $opData ;
}
}
}
}
}
/**
* returns an array of information about a given type
* returns false if no type exists by the given name
*
* typeDef = array (
* 'elements' => array (), // refs to elements array
* 'restrictionBase' => '' ,
* 'phpType' => '' ,
* 'order' => '(sequence|all)' ,
* 'attrs' => array () // refs to attributes array
* )
*
* @ param string $type the type
* @ param string $ns namespace ( not prefix ) of the type
* @ return mixed
* @ access public
* @ see nusoap_xmlschema
*/
function getTypeDef ( $type , $ns ) {
$this -> debug ( " in getTypeDef: type= $type , ns= $ns " );
if (( ! $ns ) && isset ( $this -> namespaces [ 'tns' ])) {
$ns = $this -> namespaces [ 'tns' ];
$this -> debug ( " in getTypeDef: type namespace forced to $ns " );
}
if ( ! isset ( $this -> schemas [ $ns ])) {
foreach ( $this -> schemas as $ns0 => $schema0 ) {
if ( strcasecmp ( $ns , $ns0 ) == 0 ) {
$this -> debug ( " in getTypeDef: replacing schema namespace $ns with $ns0 " );
$ns = $ns0 ;
break ;
}
}
}
if ( isset ( $this -> schemas [ $ns ])) {
$this -> debug ( " in getTypeDef: have schema for namespace $ns " );
for ( $i = 0 ; $i < count ( $this -> schemas [ $ns ]); $i ++ ) {
$xs = & $this -> schemas [ $ns ][ $i ];
$t = $xs -> getTypeDef ( $type );
$this -> appendDebug ( $xs -> getDebug ());
$xs -> clearDebug ();
if ( $t ) {
$this -> debug ( " in getTypeDef: found type $type " );
if ( ! isset ( $t [ 'phpType' ])) {
// get info for type to tack onto the element
$uqType = substr ( $t [ 'type' ], strrpos ( $t [ 'type' ], ':' ) + 1 );
$ns = substr ( $t [ 'type' ], 0 , strrpos ( $t [ 'type' ], ':' ));
$etype = $this -> getTypeDef ( $uqType , $ns );
if ( $etype ) {
$this -> debug ( " found type for [element] $type : " );
$this -> debug ( $this -> varDump ( $etype ));
if ( isset ( $etype [ 'phpType' ])) {
$t [ 'phpType' ] = $etype [ 'phpType' ];
}
if ( isset ( $etype [ 'elements' ])) {
$t [ 'elements' ] = $etype [ 'elements' ];
}
if ( isset ( $etype [ 'attrs' ])) {
$t [ 'attrs' ] = $etype [ 'attrs' ];
}
} else {
$this -> debug ( " did not find type for [element] $type " );
}
}
return $t ;
}
}
$this -> debug ( " in getTypeDef: did not find type $type " );
} else {
$this -> debug ( " in getTypeDef: do not have schema for namespace $ns " );
}
return false ;
}
/**
* prints html description of services
*
* @ access private
*/
function webDescription (){
if ( isset ( $_SERVER [ 'PHP_SELF' ] ) ) {
$PHP_SELF = sanitize_text_field ( wp_unslash ( $_SERVER [ 'PHP_SELF' ] ) );
} else {
$this -> setError ( " _SERVER not available " );
}
$b = '
< html >< head >< title > NuSOAP : '.$this->serviceName.' </ title >
< style type = " text/css " >
body { font - family : arial ; color : #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
p { font - family : arial ; color : #000000; margin-top: 0px; margin-bottom: 12px; }
pre { background - color : silver ; padding : 5 px ; font - family : Courier New ; font - size : x - small ; color : #000000;}
ul { margin - top : 10 px ; margin - left : 20 px ; }
li { list - style - type : none ; margin - top : 10 px ; color : #000000; }
. content {
margin - left : 0 px ; padding - bottom : 2 em ; }
. nav {
padding - top : 10 px ; padding - bottom : 10 px ; padding - left : 15 px ; font - size : . 70 em ;
margin - top : 10 px ; margin - left : 0 px ; color : #000000;
background - color : #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
. title {
font - family : arial ; font - size : 26 px ; color : #ffffff;
background - color : #999999; width: 100%;
margin - left : 0 px ; margin - right : 0 px ;
padding - top : 10 px ; padding - bottom : 10 px ;}
. hidden {
position : absolute ; visibility : hidden ; z - index : 200 ; left : 250 px ; top : 100 px ;
font - family : arial ; overflow : hidden ; width : 600 ;
padding : 20 px ; font - size : 10 px ; background - color : #999999;
layer - background - color : #FFFFFF; }
a , a : active { color : charcoal ; font - weight : bold ; }
a : visited { color : #666666; font-weight: bold; }
a : hover { color : cc3300 ; font - weight : bold ; }
</ style >
< script language = " JavaScript " type = " text/javascript " >
<!--
// POP-UP CAPTIONS...
function lib_bwcheck (){ //Browsercheck (needed)
this . ver = navigator . appVersion
this . agent = navigator . userAgent
this . dom = document . getElementById ? 1 : 0
this . opera5 = this . agent . indexOf ( " Opera 5 " ) >- 1
this . ie5 = ( this . ver . indexOf ( " MSIE 5 " ) >- 1 && this . dom && ! this . opera5 ) ? 1 : 0 ;
this . ie6 = ( this . ver . indexOf ( " MSIE 6 " ) >- 1 && this . dom && ! this . opera5 ) ? 1 : 0 ;
this . ie4 = ( document . all && ! this . dom && ! this . opera5 ) ? 1 : 0 ;
this . ie = this . ie4 || this . ie5 || this . ie6
this . mac = this . agent . indexOf ( " Mac " ) >- 1
this . ns6 = ( this . dom && parseInt ( this . ver ) >= 5 ) ? 1 : 0 ;
this . ns4 = ( document . layers && ! this . dom ) ? 1 : 0 ;
this . bw = ( this . ie6 || this . ie5 || this . ie4 || this . ns4 || this . ns6 || this . opera5 )
return this
}
var bw = new lib_bwcheck ()
//Makes crossbrowser object.
function makeObj ( obj ){
this . evnt = bw . dom ? document . getElementById ( obj ) : bw . ie4 ? document . all [ obj ] : bw . ns4 ? document . layers [ obj ] : 0 ;
if ( ! this . evnt ) return false
this . css = bw . dom || bw . ie4 ? this . evnt . style : bw . ns4 ? this . evnt : 0 ;
this . wref = bw . dom || bw . ie4 ? this . evnt : bw . ns4 ? this . css . document : 0 ;
this . writeIt = b_writeIt ;
return this
}
// A unit of measure that will be added when setting the position of a layer.
//var px = bw.ns4||window.opera?"":"px";
function b_writeIt ( text ){
if ( bw . ns4 ){ this . wref . write ( text ); this . wref . close ()}
else this . wref . innerHTML = text
}
//Shows the messages
var oDesc ;
function popup ( divid ){
if ( oDesc = new makeObj ( divid )){
oDesc . css . visibility = " visible "
}
}
function popout (){ // Hides message
if ( oDesc ) oDesc . css . visibility = " hidden "
}
//-->
</ script >
</ head >
< body >
< div class = content >
< br >< br >
< div class = title > '.$this->serviceName.' </ div >
< div class = nav >
< p > View the < a href = " '. $PHP_SELF .'?wsdl " > WSDL </ a > for the service .
Click on an operation name to view it & apos ; s details .</ p >
< ul > ' ;
foreach ( $this -> getOperations () as $op => $data ){
$b .= " <li><a href='#' onclick= \" popout();popup(' $op ') \" > $op </a></li> " ;
// create hidden div
$b .= " <div id=' $op ' class='hidden'>
< a href = '#' onclick = 'popout()' >< font color = '#ffffff' > Close </ font ></ a >< br >< br > " ;
foreach ( $data as $donnie => $marie ){ // loop through opdata
if ( $donnie == 'input' || $donnie == 'output' ){ // show input/output data
$b .= " <font color='white'> " . ucfirst ( $donnie ) . ':</font><br>' ;
foreach ( $marie as $captain => $tenille ){ // loop through data
if ( $captain == 'parts' ){ // loop thru parts
$b .= " $captain :<br> " ;
//if(is_array($tenille)){
foreach ( $tenille as $joanie => $chachi ){
$b .= " $joanie : $chachi <br> " ;
}
//}
} else {
$b .= " $captain : $tenille <br> " ;
}
}
} else {
$b .= " <font color='white'> " . ucfirst ( $donnie ) . " :</font> $marie <br> " ;
}
}
$b .= '</div>' ;
}
$b .= '
< ul >
</ div >
</ div ></ body ></ html > ' ;
return $b ;
}
/**
* serialize the parsed wsdl
*
* @ param mixed $debug whether to put debug = 1 in endpoint URL
* @ return string serialization of WSDL
* @ access public
*/
function serialize ( $debug = 0 )
{
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>' ;
$xml .= " \n <definitions " ;
foreach ( $this -> namespaces as $k => $v ) {
$xml .= " xmlns: $k = \" $v\ " " ;
}
// 10.9.02 - add poulter fix for wsdl and tns declarations
if ( isset ( $this -> namespaces [ 'wsdl' ])) {
$xml .= " xmlns= \" " . $this -> namespaces [ 'wsdl' ] . " \" " ;
}
if ( isset ( $this -> namespaces [ 'tns' ])) {
$xml .= " targetNamespace= \" " . $this -> namespaces [ 'tns' ] . " \" " ;
}
$xml .= '>' ;
// imports
if ( sizeof ( $this -> import ) > 0 ) {
foreach ( $this -> import as $ns => $list ) {
foreach ( $list as $ii ) {
if ( $ii [ 'location' ] != '' ) {
$xml .= '<import location="' . $ii [ 'location' ] . '" namespace="' . $ns . '" />' ;
} else {
$xml .= '<import namespace="' . $ns . '" />' ;
}
}
}
}
// types
if ( count ( $this -> schemas ) >= 1 ) {
$xml .= " \n <types> \n " ;
foreach ( $this -> schemas as $ns => $list ) {
foreach ( $list as $xs ) {
$xml .= $xs -> serializeSchema ();
}
}
$xml .= '</types>' ;
}
// messages
if ( count ( $this -> messages ) >= 1 ) {
foreach ( $this -> messages as $msgName => $msgParts ) {
$xml .= " \n <message name= \" " . $msgName . '">' ;
if ( is_array ( $msgParts )){
foreach ( $msgParts as $partName => $partType ) {
// print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
if ( strpos ( $partType , ':' )) {
$typePrefix = $this -> getPrefixFromNamespace ( $this -> getPrefix ( $partType ));
} elseif ( isset ( $this -> typemap [ $this -> namespaces [ 'xsd' ]][ $partType ])) {
// print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
$typePrefix = 'xsd' ;
} else {
foreach ( $this -> typemap as $ns => $types ) {
if ( isset ( $types [ $partType ])) {
$typePrefix = $this -> getPrefixFromNamespace ( $ns );
}
}
if ( ! isset ( $typePrefix )) {
die ( esc_html ( $partType ) . 'has no namespace!' );
}
}
$ns = $this -> getNamespaceFromPrefix ( $typePrefix );
$localPart = $this -> getLocalPart ( $partType );
$typeDef = $this -> getTypeDef ( $localPart , $ns );
if ( $typeDef [ 'typeClass' ] == 'element' ) {
$elementortype = 'element' ;
if ( substr ( $localPart , - 1 ) == '^' ) {
$localPart = substr ( $localPart , 0 , - 1 );
}
} else {
$elementortype = 'type' ;
}
$xml .= " \n " . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />' ;
}
}
$xml .= '</message>' ;
}
}
// bindings & porttypes
if ( count ( $this -> bindings ) >= 1 ) {
$binding_xml = '' ;
$portType_xml = '' ;
foreach ( $this -> bindings as $bindingName => $attrs ) {
$binding_xml .= " \n <binding name= \" " . $bindingName . '" type="tns:' . $attrs [ 'portType' ] . '">' ;
$binding_xml .= " \n " . ' <soap:binding style="' . $attrs [ 'style' ] . '" transport="' . $attrs [ 'transport' ] . '"/>' ;
$portType_xml .= " \n <portType name= \" " . $attrs [ 'portType' ] . '">' ;
foreach ( $attrs [ 'operations' ] as $opName => $opParts ) {
$binding_xml .= " \n " . ' <operation name="' . $opName . '">' ;
$binding_xml .= " \n " . ' <soap:operation soapAction="' . $opParts [ 'soapAction' ] . '" style="' . $opParts [ 'style' ] . '"/>' ;
if ( isset ( $opParts [ 'input' ][ 'encodingStyle' ]) && $opParts [ 'input' ][ 'encodingStyle' ] != '' ) {
$enc_style = ' encodingStyle="' . $opParts [ 'input' ][ 'encodingStyle' ] . '"' ;
} else {
$enc_style = '' ;
}
$binding_xml .= " \n " . ' <input><soap:body use="' . $opParts [ 'input' ][ 'use' ] . '" namespace="' . $opParts [ 'input' ][ 'namespace' ] . '"' . $enc_style . '/></input>' ;
if ( isset ( $opParts [ 'output' ][ 'encodingStyle' ]) && $opParts [ 'output' ][ 'encodingStyle' ] != '' ) {
$enc_style = ' encodingStyle="' . $opParts [ 'output' ][ 'encodingStyle' ] . '"' ;
} else {
$enc_style = '' ;
}
$binding_xml .= " \n " . ' <output><soap:body use="' . $opParts [ 'output' ][ 'use' ] . '" namespace="' . $opParts [ 'output' ][ 'namespace' ] . '"' . $enc_style . '/></output>' ;
$binding_xml .= " \n " . ' </operation>' ;
$portType_xml .= " \n " . ' <operation name="' . $opParts [ 'name' ] . '"' ;
if ( isset ( $opParts [ 'parameterOrder' ])) {
$portType_xml .= ' parameterOrder="' . $opParts [ 'parameterOrder' ] . '"' ;
}
$portType_xml .= '>' ;
if ( isset ( $opParts [ 'documentation' ]) && $opParts [ 'documentation' ] != '' ) {
$portType_xml .= " \n " . ' <documentation>' . htmlspecialchars ( $opParts [ 'documentation' ]) . '</documentation>' ;
}
$portType_xml .= " \n " . ' <input message="tns:' . $opParts [ 'input' ][ 'message' ] . '"/>' ;
$portType_xml .= " \n " . ' <output message="tns:' . $opParts [ 'output' ][ 'message' ] . '"/>' ;
$portType_xml .= " \n " . ' </operation>' ;
}
$portType_xml .= " \n " . '</portType>' ;
$binding_xml .= " \n " . '</binding>' ;
}
$xml .= $portType_xml . $binding_xml ;
}
// services
$xml .= " \n <service name= \" " . $this -> serviceName . '">' ;
if ( count ( $this -> ports ) >= 1 ) {
foreach ( $this -> ports as $pName => $attrs ) {
$xml .= " \n " . ' <port name="' . $pName . '" binding="tns:' . $attrs [ 'binding' ] . '">' ;
$xml .= " \n " . ' <soap:address location="' . $attrs [ 'location' ] . ( $debug ? '?debug=1' : '' ) . '"/>' ;
$xml .= " \n " . ' </port>' ;
}
}
$xml .= " \n " . '</service>' ;
return $xml . " \n </definitions> " ;
}
/**
* determine whether a set of parameters are unwrapped
* when they are expect to be wrapped , Microsoft - style .
*
* @ param string $type the type ( element name ) of the wrapper
* @ param array $parameters the parameter values for the SOAP call
* @ return boolean whether they parameters are unwrapped ( and should be wrapped )
* @ access private
*/
function parametersMatchWrapped ( $type , & $parameters ) {
$this -> debug ( " in parametersMatchWrapped type= $type , parameters= " );
$this -> appendDebug ( $this -> varDump ( $parameters ));
// split type into namespace:unqualified-type
if ( strpos ( $type , ':' )) {
$uqType = substr ( $type , strrpos ( $type , ':' ) + 1 );
$ns = substr ( $type , 0 , strrpos ( $type , ':' ));
$this -> debug ( " in parametersMatchWrapped: got a prefixed type: $uqType , $ns " );
if ( $this -> getNamespaceFromPrefix ( $ns )) {
$ns = $this -> getNamespaceFromPrefix ( $ns );
$this -> debug ( " in parametersMatchWrapped: expanded prefixed type: $uqType , $ns " );
}
} else {
// TODO: should the type be compared to types in XSD, and the namespace
// set to XSD if the type matches?
$this -> debug ( " in parametersMatchWrapped: No namespace for type $type " );
$ns = '' ;
$uqType = $type ;
}
// get the type information
if ( ! $typeDef = $this -> getTypeDef ( $uqType , $ns )) {
$this -> debug ( " in parametersMatchWrapped: $type ( $uqType ) is not a supported type. " );
return false ;
}
$this -> debug ( " in parametersMatchWrapped: found typeDef= " );
$this -> appendDebug ( $this -> varDump ( $typeDef ));
if ( substr ( $uqType , - 1 ) == '^' ) {
$uqType = substr ( $uqType , 0 , - 1 );
}
$phpType = $typeDef [ 'phpType' ];
$arrayType = ( isset ( $typeDef [ 'arrayType' ]) ? $typeDef [ 'arrayType' ] : '' );
$this -> debug ( " in parametersMatchWrapped: uqType: $uqType , ns: $ns , phptype: $phpType , arrayType: $arrayType " );
// we expect a complexType or element of complexType
if ( $phpType != 'struct' ) {
$this -> debug ( " in parametersMatchWrapped: not a struct " );
return false ;
}
// see whether the parameter names match the elements
if ( isset ( $typeDef [ 'elements' ]) && is_array ( $typeDef [ 'elements' ])) {
$elements = 0 ;
$matches = 0 ;
foreach ( $typeDef [ 'elements' ] as $name => $attrs ) {
if ( isset ( $parameters [ $name ])) {
$this -> debug ( " in parametersMatchWrapped: have parameter named $name " );
$matches ++ ;
} else {
$this -> debug ( " in parametersMatchWrapped: do not have parameter named $name " );
}
$elements ++ ;
}
$this -> debug ( " in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names " );
if ( $matches == 0 ) {
return false ;
}
return true ;
}
// since there are no elements for the type, if the user passed no
// parameters, the parameters match wrapped.
$this -> debug ( " in parametersMatchWrapped: no elements type $ns : $uqType " );
return count ( $parameters ) == 0 ;
}
/**
* serialize PHP values according to a WSDL message definition
* contrary to the method name , this is not limited to RPC
*
* TODO
* - multi - ref serialization
* - validate PHP values against type definitions , return errors if invalid
*
* @ param string $operation operation name
* @ param string $direction ( input | output )
* @ param mixed $parameters parameter value ( s )
* @ param string $bindingType ( soap | soap12 )
* @ return mixed parameters serialized as XML or false on error ( e . g . operation not found )
* @ access public
*/
function serializeRPCParameters ( $operation , $direction , $parameters , $bindingType = 'soap' ) {
$this -> debug ( " in serializeRPCParameters: operation= $operation , direction= $direction , XMLSchemaVersion= $this->XMLSchemaVersion , bindingType= $bindingType " );
$this -> appendDebug ( 'parameters=' . $this -> varDump ( $parameters ));
if ( $direction != 'input' && $direction != 'output' ) {
$this -> debug ( 'The value of the \$direction argument needs to be either "input" or "output"' );
$this -> setError ( 'The value of the \$direction argument needs to be either "input" or "output"' );
return false ;
}
if ( ! $opData = $this -> getOperationData ( $operation , $bindingType )) {
$this -> debug ( 'Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType );
$this -> setError ( 'Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType );
return false ;
}
$this -> debug ( 'in serializeRPCParameters: opData:' );
$this -> appendDebug ( $this -> varDump ( $opData ));
// Get encoding style for output and set to current
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ;
if (( $direction == 'input' ) && isset ( $opData [ 'output' ][ 'encodingStyle' ]) && ( $opData [ 'output' ][ 'encodingStyle' ] != $encodingStyle )) {
$encodingStyle = $opData [ 'output' ][ 'encodingStyle' ];
$enc_style = $encodingStyle ;
}
// set input params
$xml = '' ;
if ( isset ( $opData [ $direction ][ 'parts' ]) && sizeof ( $opData [ $direction ][ 'parts' ]) > 0 ) {
$parts = & $opData [ $direction ][ 'parts' ];
$part_count = sizeof ( $parts );
$style = $opData [ 'style' ];
$use = $opData [ $direction ][ 'use' ];
$this -> debug ( " have $part_count part(s) to serialize using $style / $use " );
if ( is_array ( $parameters )) {
$parametersArrayType = $this -> isArraySimpleOrStruct ( $parameters );
$parameter_count = count ( $parameters );
$this -> debug ( " have $parameter_count parameter(s) provided as $parametersArrayType to serialize " );
// check for Microsoft-style wrapped parameters
if ( $style == 'document' && $use == 'literal' && $part_count == 1 && isset ( $parts [ 'parameters' ])) {
$this -> debug ( 'check whether the caller has wrapped the parameters' );
if ( $direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1 ) {
// TODO: consider checking here for double-wrapping, when
// service function wraps, then NuSOAP wraps again
$this -> debug ( " change simple array to associative with 'parameters' element " );
$parameters [ 'parameters' ] = $parameters [ 0 ];
unset ( $parameters [ 0 ]);
}
if (( $parametersArrayType == 'arrayStruct' || $parameter_count == 0 ) && ! isset ( $parameters [ 'parameters' ])) {
$this -> debug ( 'check whether caller\'s parameters match the wrapped ones' );
if ( $this -> parametersMatchWrapped ( $parts [ 'parameters' ], $parameters )) {
$this -> debug ( 'wrap the parameters for the caller' );
$parameters = array ( 'parameters' => $parameters );
$parameter_count = 1 ;
}
}
}
foreach ( $parts as $name => $type ) {
$this -> debug ( " serializing part $name of type $type " );
// Track encoding style
if ( isset ( $opData [ $direction ][ 'encodingStyle' ]) && $encodingStyle != $opData [ $direction ][ 'encodingStyle' ]) {
$encodingStyle = $opData [ $direction ][ 'encodingStyle' ];
$enc_style = $encodingStyle ;
} else {
$enc_style = false ;
}
// NOTE: add error handling here
// if serializeType returns false, then catch global error and fault
if ( $parametersArrayType == 'arraySimple' ) {
$p = array_shift ( $parameters );
$this -> debug ( 'calling serializeType w/indexed param' );
$xml .= $this -> serializeType ( $name , $type , $p , $use , $enc_style );
} elseif ( isset ( $parameters [ $name ])) {
$this -> debug ( 'calling serializeType w/named param' );
$xml .= $this -> serializeType ( $name , $type , $parameters [ $name ], $use , $enc_style );
} else {
// TODO: only send nillable
$this -> debug ( 'calling serializeType w/null param' );
$xml .= $this -> serializeType ( $name , $type , null , $use , $enc_style );
}
}
} else {
$this -> debug ( 'no parameters passed.' );
}
}
$this -> debug ( " serializeRPCParameters returning: $xml " );
return $xml ;
}
/**
* serialize a PHP value according to a WSDL message definition
*
* TODO
* - multi - ref serialization
* - validate PHP values against type definitions , return errors if invalid
*
* @ param string $operation operation name
* @ param string $direction ( input | output )
* @ param mixed $parameters parameter value ( s )
* @ return mixed parameters serialized as XML or false on error ( e . g . operation not found )
* @ access public
* @ deprecated
*/
function serializeParameters ( $operation , $direction , $parameters )
{
$this -> debug ( " in serializeParameters: operation= $operation , direction= $direction , XMLSchemaVersion= $this->XMLSchemaVersion " );
$this -> appendDebug ( 'parameters=' . $this -> varDump ( $parameters ));
if ( $direction != 'input' && $direction != 'output' ) {
$this -> debug ( 'The value of the \$direction argument needs to be either "input" or "output"' );
$this -> setError ( 'The value of the \$direction argument needs to be either "input" or "output"' );
return false ;
}
if ( ! $opData = $this -> getOperationData ( $operation )) {
$this -> debug ( 'Unable to retrieve WSDL data for operation: ' . $operation );
$this -> setError ( 'Unable to retrieve WSDL data for operation: ' . $operation );
return false ;
}
$this -> debug ( 'opData:' );
$this -> appendDebug ( $this -> varDump ( $opData ));
// Get encoding style for output and set to current
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ;
if (( $direction == 'input' ) && isset ( $opData [ 'output' ][ 'encodingStyle' ]) && ( $opData [ 'output' ][ 'encodingStyle' ] != $encodingStyle )) {
$encodingStyle = $opData [ 'output' ][ 'encodingStyle' ];
$enc_style = $encodingStyle ;
}
// set input params
$xml = '' ;
if ( isset ( $opData [ $direction ][ 'parts' ]) && sizeof ( $opData [ $direction ][ 'parts' ]) > 0 ) {
$use = $opData [ $direction ][ 'use' ];
$this -> debug ( " use= $use " );
$this -> debug ( 'got ' . count ( $opData [ $direction ][ 'parts' ]) . ' part(s)' );
if ( is_array ( $parameters )) {
$parametersArrayType = $this -> isArraySimpleOrStruct ( $parameters );
$this -> debug ( 'have ' . $parametersArrayType . ' parameters' );
foreach ( $opData [ $direction ][ 'parts' ] as $name => $type ) {
$this -> debug ( 'serializing part "' . $name . '" of type "' . $type . '"' );
// Track encoding style
if ( isset ( $opData [ $direction ][ 'encodingStyle' ]) && $encodingStyle != $opData [ $direction ][ 'encodingStyle' ]) {
$encodingStyle = $opData [ $direction ][ 'encodingStyle' ];
$enc_style = $encodingStyle ;
} else {
$enc_style = false ;
}
// NOTE: add error handling here
// if serializeType returns false, then catch global error and fault
if ( $parametersArrayType == 'arraySimple' ) {
$p = array_shift ( $parameters );
$this -> debug ( 'calling serializeType w/indexed param' );
$xml .= $this -> serializeType ( $name , $type , $p , $use , $enc_style );
} elseif ( isset ( $parameters [ $name ])) {
$this -> debug ( 'calling serializeType w/named param' );
$xml .= $this -> serializeType ( $name , $type , $parameters [ $name ], $use , $enc_style );
} else {
// TODO: only send nillable
$this -> debug ( 'calling serializeType w/null param' );
$xml .= $this -> serializeType ( $name , $type , null , $use , $enc_style );
}
}
} else {
$this -> debug ( 'no parameters passed.' );
}
}
$this -> debug ( " serializeParameters returning: $xml " );
return $xml ;
}
/**
* serializes a PHP value according a given type definition
*
* @ param string $name name of value ( part or element )
* @ param string $type XML schema type of value ( type or element )
* @ param mixed $value a native PHP value ( parameter value )
* @ param string $use use for part ( encoded | literal )
* @ param string $encodingStyle SOAP encoding style for the value ( if different than the enclosing style )
* @ param boolean $unqualified a kludge for what should be XML namespace form handling
* @ return string value serialized as an XML string
* @ access private
*/
function serializeType ( $name , $type , $value , $use = 'encoded' , $encodingStyle = false , $unqualified = false )
{
$this -> debug ( " in serializeType: name= $name , type= $type , use= $use , encodingStyle= $encodingStyle , unqualified= " . ( $unqualified ? " unqualified " : " qualified " ));
$this -> appendDebug ( " value= " . $this -> varDump ( $value ));
if ( $use == 'encoded' && $encodingStyle ) {
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"' ;
}
// if a soapval has been supplied, let its type override the WSDL
if ( is_object ( $value ) && get_class ( $value ) == 'soapval' ) {
if ( $value -> type_ns ) {
$type = $value -> type_ns . ':' . $value -> type ;
$forceType = true ;
$this -> debug ( " in serializeType: soapval overrides type to $type " );
} elseif ( $value -> type ) {
$type = $value -> type ;
$forceType = true ;
$this -> debug ( " in serializeType: soapval overrides type to $type " );
} else {
$forceType = false ;
$this -> debug ( " in serializeType: soapval does not override type " );
}
$attrs = $value -> attributes ;
$value = $value -> value ;
$this -> debug ( " in serializeType: soapval overrides value to $value " );
if ( $attrs ) {
if ( ! is_array ( $value )) {
$value [ '!' ] = $value ;
}
foreach ( $attrs as $n => $v ) {
$value [ '!' . $n ] = $v ;
}
$this -> debug ( " in serializeType: soapval provides attributes " );
}
} else {
$forceType = false ;
}
$xml = '' ;
if ( strpos ( $type , ':' )) {
$uqType = substr ( $type , strrpos ( $type , ':' ) + 1 );
$ns = substr ( $type , 0 , strrpos ( $type , ':' ));
$this -> debug ( " in serializeType: got a prefixed type: $uqType , $ns " );
if ( $this -> getNamespaceFromPrefix ( $ns )) {
$ns = $this -> getNamespaceFromPrefix ( $ns );
$this -> debug ( " in serializeType: expanded prefixed type: $uqType , $ns " );
}
if ( $ns == $this -> XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/' ){
$this -> debug ( 'in serializeType: type namespace indicates XML Schema or SOAP Encoding type' );
if ( $unqualified && $use == 'literal' ) {
$elementNS = " xmlns= \" \" " ;
} else {
$elementNS = '' ;
}
if ( is_null ( $value )) {
if ( $use == 'literal' ) {
// TODO: depends on minOccurs
$xml = " < $name $elementNS /> " ;
} else {
// TODO: depends on nillable, which should be checked before calling this method
$xml = " < $name $elementNS xsi:nil= \" true \" xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " /> " ;
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
if ( $uqType == 'Array' ) {
// JBoss/Axis does this sometimes
return $this -> serialize_val ( $value , $name , false , false , false , false , $use );
}
if ( $uqType == 'boolean' ) {
if (( is_string ( $value ) && $value == 'false' ) || ( ! $value )) {
$value = 'false' ;
} else {
$value = 'true' ;
}
}
if ( $uqType == 'string' && gettype ( $value ) == 'string' ) {
$value = $this -> expandEntities ( $value );
}
if (( $uqType == 'long' || $uqType == 'unsignedLong' ) && gettype ( $value ) == 'double' ) {
$value = sprintf ( " %.0lf " , $value );
}
// it's a scalar
// TODO: what about null/nil values?
// check type isn't a custom type extending xmlschema namespace
if ( ! $this -> getTypeDef ( $uqType , $ns )) {
if ( $use == 'literal' ) {
if ( $forceType ) {
$xml = " < $name $elementNS xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " > $value </ $name > " ;
} else {
$xml = " < $name $elementNS > $value </ $name > " ;
}
} else {
$xml = " < $name $elementNS xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " $encodingStyle > $value </ $name > " ;
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
$this -> debug ( 'custom type extends XML Schema or SOAP Encoding namespace (yuck)' );
} else if ( $ns == 'http://xml.apache.org/xml-soap' ) {
$this -> debug ( 'in serializeType: appears to be Apache SOAP type' );
if ( $uqType == 'Map' ) {
$tt_prefix = $this -> getPrefixFromNamespace ( 'http://xml.apache.org/xml-soap' );
if ( ! $tt_prefix ) {
$this -> debug ( 'in serializeType: Add namespace for Apache SOAP type' );
$tt_prefix = 'ns' . rand ( 1000 , 9999 );
$this -> namespaces [ $tt_prefix ] = 'http://xml.apache.org/xml-soap' ;
// force this to be added to usedNamespaces
$tt_prefix = $this -> getPrefixFromNamespace ( 'http://xml.apache.org/xml-soap' );
}
$contents = '' ;
foreach ( $value as $k => $v ) {
$this -> debug ( " serializing map element: key $k , value $v " );
$contents .= '<item>' ;
$contents .= $this -> serialize_val ( $k , 'key' , false , false , false , false , $use );
$contents .= $this -> serialize_val ( $v , 'value' , false , false , false , false , $use );
$contents .= '</item>' ;
}
if ( $use == 'literal' ) {
if ( $forceType ) {
$xml = " < $name xsi:type= \" " . $tt_prefix . " : $uqType\ " > $contents </ $name > " ;
} else {
$xml = " < $name > $contents </ $name > " ;
}
} else {
$xml = " < $name xsi:type= \" " . $tt_prefix . " : $uqType\ " $encodingStyle > $contents </ $name > " ;
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
$this -> debug ( 'in serializeType: Apache SOAP type, but only support Map' );
}
} else {
// TODO: should the type be compared to types in XSD, and the namespace
// set to XSD if the type matches?
$this -> debug ( " in serializeType: No namespace for type $type " );
$ns = '' ;
$uqType = $type ;
}
if ( ! $typeDef = $this -> getTypeDef ( $uqType , $ns )){
$this -> setError ( " $type ( $uqType ) is not a supported type. " );
$this -> debug ( " in serializeType: $type ( $uqType ) is not a supported type. " );
return false ;
} else {
$this -> debug ( " in serializeType: found typeDef " );
$this -> appendDebug ( 'typeDef=' . $this -> varDump ( $typeDef ));
if ( substr ( $uqType , - 1 ) == '^' ) {
$uqType = substr ( $uqType , 0 , - 1 );
}
}
if ( ! isset ( $typeDef [ 'phpType' ])) {
$this -> setError ( " $type ( $uqType ) has no phpType. " );
$this -> debug ( " in serializeType: $type ( $uqType ) has no phpType. " );
return false ;
}
$phpType = $typeDef [ 'phpType' ];
$this -> debug ( " in serializeType: uqType: $uqType , ns: $ns , phptype: $phpType , arrayType: " . ( isset ( $typeDef [ 'arrayType' ]) ? $typeDef [ 'arrayType' ] : '' ) );
// if php type == struct, map value to the <all> element names
if ( $phpType == 'struct' ) {
if ( isset ( $typeDef [ 'typeClass' ]) && $typeDef [ 'typeClass' ] == 'element' ) {
$elementName = $uqType ;
if ( isset ( $typeDef [ 'form' ]) && ( $typeDef [ 'form' ] == 'qualified' )) {
$elementNS = " xmlns= \" $ns\ " " ;
} else {
$elementNS = " xmlns= \" \" " ;
}
} else {
$elementName = $name ;
if ( $unqualified ) {
$elementNS = " xmlns= \" \" " ;
} else {
$elementNS = '' ;
}
}
if ( is_null ( $value )) {
if ( $use == 'literal' ) {
// TODO: depends on minOccurs and nillable
$xml = " < $elementName $elementNS /> " ;
} else {
$xml = " < $elementName $elementNS xsi:nil= \" true \" xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " /> " ;
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
if ( is_object ( $value )) {
$value = get_object_vars ( $value );
}
if ( is_array ( $value )) {
$elementAttrs = $this -> serializeComplexTypeAttributes ( $typeDef , $value , $ns , $uqType );
if ( $use == 'literal' ) {
if ( $forceType ) {
$xml = " < $elementName $elementNS $elementAttrs xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " > " ;
} else {
$xml = " < $elementName $elementNS $elementAttrs > " ;
}
} else {
$xml = " < $elementName $elementNS $elementAttrs xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " $encodingStyle > " ;
}
if ( isset ( $typeDef [ 'simpleContent' ]) && $typeDef [ 'simpleContent' ] == 'true' ) {
if ( isset ( $value [ '!' ])) {
$xml .= $value [ '!' ];
$this -> debug ( " in serializeType: serialized simpleContent for type $type " );
} else {
$this -> debug ( " in serializeType: no simpleContent to serialize for type $type " );
}
} else {
// complexContent
$xml .= $this -> serializeComplexTypeElements ( $typeDef , $value , $ns , $uqType , $use , $encodingStyle );
}
$xml .= " </ $elementName > " ;
} else {
$this -> debug ( " in serializeType: phpType is struct, but value is not an array " );
$this -> setError ( " phpType is struct, but value is not an array: see debug output for details " );
$xml = '' ;
}
} elseif ( $phpType == 'array' ) {
if ( isset ( $typeDef [ 'form' ]) && ( $typeDef [ 'form' ] == 'qualified' )) {
$elementNS = " xmlns= \" $ns\ " " ;
} else {
if ( $unqualified ) {
$elementNS = " xmlns= \" \" " ;
} else {
$elementNS = '' ;
}
}
if ( is_null ( $value )) {
if ( $use == 'literal' ) {
// TODO: depends on minOccurs
$xml = " < $name $elementNS /> " ;
} else {
$xml = " < $name $elementNS xsi:nil= \" true \" xsi:type= \" " .
$this -> getPrefixFromNamespace ( 'http://schemas.xmlsoap.org/soap/encoding/' ) .
" :Array \" " .
$this -> getPrefixFromNamespace ( 'http://schemas.xmlsoap.org/soap/encoding/' ) .
':arrayType="' .
$this -> getPrefixFromNamespace ( $this -> getPrefix ( $typeDef [ 'arrayType' ])) .
':' .
$this -> getLocalPart ( $typeDef [ 'arrayType' ]) . " [0] \" /> " ;
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
if ( isset ( $typeDef [ 'multidimensional' ])) {
$nv = array ();
foreach ( $value as $v ) {
$cols = ',' . sizeof ( $v );
$nv = array_merge ( $nv , $v );
}
$value = $nv ;
} else {
$cols = '' ;
}
if ( is_array ( $value ) && sizeof ( $value ) >= 1 ) {
$rows = sizeof ( $value );
$contents = '' ;
foreach ( $value as $k => $v ) {
$this -> debug ( " serializing array element: $k , $v of type: $typeDef[arrayType] " );
//if (strpos($typeDef['arrayType'], ':') ) {
if ( ! in_array ( $typeDef [ 'arrayType' ], $this -> typemap [ 'http://www.w3.org/2001/XMLSchema' ])) {
$contents .= $this -> serializeType ( 'item' , $typeDef [ 'arrayType' ], $v , $use );
} else {
$contents .= $this -> serialize_val ( $v , 'item' , $typeDef [ 'arrayType' ], null , $this -> XMLSchemaVersion , false , $use );
}
}
} else {
$rows = 0 ;
$contents = null ;
}
// TODO: for now, an empty value will be serialized as a zero element
// array. Revisit this when coding the handling of null/nil values.
if ( $use == 'literal' ) {
$xml = " < $name $elementNS > "
. $contents
. " </ $name > " ;
} else {
$xml = " < $name $elementNS xsi:type= \" " . $this -> getPrefixFromNamespace ( 'http://schemas.xmlsoap.org/soap/encoding/' ) . ':Array" ' .
$this -> getPrefixFromNamespace ( 'http://schemas.xmlsoap.org/soap/encoding/' )
. ':arrayType="'
. $this -> getPrefixFromNamespace ( $this -> getPrefix ( $typeDef [ 'arrayType' ]))
. " : " . $this -> getLocalPart ( $typeDef [ 'arrayType' ]) . " [ $rows $cols ] \" > "
. $contents
. " </ $name > " ;
}
} elseif ( $phpType == 'scalar' ) {
if ( isset ( $typeDef [ 'form' ]) && ( $typeDef [ 'form' ] == 'qualified' )) {
$elementNS = " xmlns= \" $ns\ " " ;
} else {
if ( $unqualified ) {
$elementNS = " xmlns= \" \" " ;
} else {
$elementNS = '' ;
}
}
if ( $use == 'literal' ) {
if ( $forceType ) {
$xml = " < $name $elementNS xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " > $value </ $name > " ;
} else {
$xml = " < $name $elementNS > $value </ $name > " ;
}
} else {
$xml = " < $name $elementNS xsi:type= \" " . $this -> getPrefixFromNamespace ( $ns ) . " : $uqType\ " $encodingStyle > $value </ $name > " ;
}
}
$this -> debug ( " in serializeType: returning: $xml " );
return $xml ;
}
/**
* serializes the attributes for a complexType
*
* @ param array $typeDef our internal representation of an XML schema type ( or element )
* @ param mixed $value a native PHP value ( parameter value )
* @ param string $ns the namespace of the type
* @ param string $uqType the local part of the type
* @ return string value serialized as an XML string
* @ access private
*/
function serializeComplexTypeAttributes ( $typeDef , $value , $ns , $uqType ) {
$this -> debug ( " serializeComplexTypeAttributes for XML Schema type $ns : $uqType " );
$xml = '' ;
if ( isset ( $typeDef [ 'extensionBase' ])) {
$nsx = $this -> getPrefix ( $typeDef [ 'extensionBase' ]);
$uqTypex = $this -> getLocalPart ( $typeDef [ 'extensionBase' ]);
if ( $this -> getNamespaceFromPrefix ( $nsx )) {
$nsx = $this -> getNamespaceFromPrefix ( $nsx );
}
if ( $typeDefx = $this -> getTypeDef ( $uqTypex , $nsx )) {
$this -> debug ( " serialize attributes for extension base $nsx : $uqTypex " );
$xml .= $this -> serializeComplexTypeAttributes ( $typeDefx , $value , $nsx , $uqTypex );
} else {
$this -> debug ( " extension base $nsx : $uqTypex is not a supported type " );
}
}
if ( isset ( $typeDef [ 'attrs' ]) && is_array ( $typeDef [ 'attrs' ])) {
$this -> debug ( " serialize attributes for XML Schema type $ns : $uqType " );
if ( is_array ( $value )) {
$xvalue = $value ;
} elseif ( is_object ( $value )) {
$xvalue = get_object_vars ( $value );
} else {
$this -> debug ( " value is neither an array nor an object for XML Schema type $ns : $uqType " );
$xvalue = array ();
}
foreach ( $typeDef [ 'attrs' ] as $aName => $attrs ) {
if ( isset ( $xvalue [ '!' . $aName ])) {
$xname = '!' . $aName ;
$this -> debug ( " value provided for attribute $aName with key $xname " );
} elseif ( isset ( $xvalue [ $aName ])) {
$xname = $aName ;
$this -> debug ( " value provided for attribute $aName with key $xname " );
} elseif ( isset ( $attrs [ 'default' ])) {
$xname = '!' . $aName ;
$xvalue [ $xname ] = $attrs [ 'default' ];
$this -> debug ( 'use default value of ' . $xvalue [ $aName ] . ' for attribute ' . $aName );
} else {
$xname = '' ;
$this -> debug ( " no value provided for attribute $aName " );
}
if ( $xname ) {
$xml .= " $aName = \" " . $this -> expandEntities ( $xvalue [ $xname ]) . " \" " ;
}
}
} else {
$this -> debug ( " no attributes to serialize for XML Schema type $ns : $uqType " );
}
return $xml ;
}
/**
* serializes the elements for a complexType
*
* @ param array $typeDef our internal representation of an XML schema type ( or element )
* @ param mixed $value a native PHP value ( parameter value )
* @ param string $ns the namespace of the type
* @ param string $uqType the local part of the type
* @ param string $use use for part ( encoded | literal )
* @ param string $encodingStyle SOAP encoding style for the value ( if different than the enclosing style )
* @ return string value serialized as an XML string
* @ access private
*/
function serializeComplexTypeElements ( $typeDef , $value , $ns , $uqType , $use = 'encoded' , $encodingStyle = false ) {
$this -> debug ( " in serializeComplexTypeElements for XML Schema type $ns : $uqType " );
$xml = '' ;
if ( isset ( $typeDef [ 'extensionBase' ])) {
$nsx = $this -> getPrefix ( $typeDef [ 'extensionBase' ]);
$uqTypex = $this -> getLocalPart ( $typeDef [ 'extensionBase' ]);
if ( $this -> getNamespaceFromPrefix ( $nsx )) {
$nsx = $this -> getNamespaceFromPrefix ( $nsx );
}
if ( $typeDefx = $this -> getTypeDef ( $uqTypex , $nsx )) {
$this -> debug ( " serialize elements for extension base $nsx : $uqTypex " );
$xml .= $this -> serializeComplexTypeElements ( $typeDefx , $value , $nsx , $uqTypex , $use , $encodingStyle );
} else {
$this -> debug ( " extension base $nsx : $uqTypex is not a supported type " );
}
}
if ( isset ( $typeDef [ 'elements' ]) && is_array ( $typeDef [ 'elements' ])) {
$this -> debug ( " in serializeComplexTypeElements, serialize elements for XML Schema type $ns : $uqType " );
if ( is_array ( $value )) {
$xvalue = $value ;
} elseif ( is_object ( $value )) {
$xvalue = get_object_vars ( $value );
} else {
$this -> debug ( " value is neither an array nor an object for XML Schema type $ns : $uqType " );
$xvalue = array ();
}
// toggle whether all elements are present - ideally should validate against schema
if ( count ( $typeDef [ 'elements' ]) != count ( $xvalue )){
$optionals = true ;
}
foreach ( $typeDef [ 'elements' ] as $eName => $attrs ) {
if ( ! isset ( $xvalue [ $eName ])) {
if ( isset ( $attrs [ 'default' ])) {
$xvalue [ $eName ] = $attrs [ 'default' ];
$this -> debug ( 'use default value of ' . $xvalue [ $eName ] . ' for element ' . $eName );
}
}
// if user took advantage of a minOccurs=0, then only serialize named parameters
if ( isset ( $optionals )
&& ( ! isset ( $xvalue [ $eName ]))
&& ( ( ! isset ( $attrs [ 'nillable' ])) || $attrs [ 'nillable' ] != 'true' )
){
if ( isset ( $attrs [ 'minOccurs' ]) && $attrs [ 'minOccurs' ] <> '0' ) {
$this -> debug ( " apparent error: no value provided for element $eName with minOccurs= " . $attrs [ 'minOccurs' ]);
}
// do nothing
$this -> debug ( " no value provided for complexType element $eName and element is not nillable, so serialize nothing " );
} else {
// get value
if ( isset ( $xvalue [ $eName ])) {
$v = $xvalue [ $eName ];
} else {
$v = null ;
}
if ( isset ( $attrs [ 'form' ])) {
$unqualified = ( $attrs [ 'form' ] == 'unqualified' );
} else {
$unqualified = false ;
}
if ( isset ( $attrs [ 'maxOccurs' ]) && ( $attrs [ 'maxOccurs' ] == 'unbounded' || $attrs [ 'maxOccurs' ] > 1 ) && isset ( $v ) && is_array ( $v ) && $this -> isArraySimpleOrStruct ( $v ) == 'arraySimple' ) {
$vv = $v ;
foreach ( $vv as $k => $v ) {
if ( isset ( $attrs [ 'type' ]) || isset ( $attrs [ 'ref' ])) {
// serialize schema-defined type
$xml .= $this -> serializeType ( $eName , isset ( $attrs [ 'type' ]) ? $attrs [ 'type' ] : $attrs [ 'ref' ], $v , $use , $encodingStyle , $unqualified );
} else {
// serialize generic type (can this ever really happen?)
$this -> debug ( " calling serialize_val() for $v , $eName , false, false, false, false, $use " );
$xml .= $this -> serialize_val ( $v , $eName , false , false , false , false , $use );
}
}
} else {
if ( is_null ( $v ) && isset ( $attrs [ 'minOccurs' ]) && $attrs [ 'minOccurs' ] == '0' ) {
// do nothing
} elseif ( is_null ( $v ) && isset ( $attrs [ 'nillable' ]) && $attrs [ 'nillable' ] == 'true' ) {
// TODO: serialize a nil correctly, but for now serialize schema-defined type
$xml .= $this -> serializeType ( $eName , isset ( $attrs [ 'type' ]) ? $attrs [ 'type' ] : $attrs [ 'ref' ], $v , $use , $encodingStyle , $unqualified );
} elseif ( isset ( $attrs [ 'type' ]) || isset ( $attrs [ 'ref' ])) {
// serialize schema-defined type
$xml .= $this -> serializeType ( $eName , isset ( $attrs [ 'type' ]) ? $attrs [ 'type' ] : $attrs [ 'ref' ], $v , $use , $encodingStyle , $unqualified );
} else {
// serialize generic type (can this ever really happen?)
$this -> debug ( " calling serialize_val() for $v , $eName , false, false, false, false, $use " );
$xml .= $this -> serialize_val ( $v , $eName , false , false , false , false , $use );
}
}
}
}
} else {
$this -> debug ( " no elements to serialize for XML Schema type $ns : $uqType " );
}
return $xml ;
}
/**
* adds an XML Schema complex type to the WSDL types
*
* @ param string $name
* @ param string $typeClass ( complexType | simpleType | attribute )
* @ param string $phpType currently supported are array and struct ( php assoc array )
* @ param string $compositor ( all | sequence | choice )
* @ param string $restrictionBase namespace : name ( http :// schemas . xmlsoap . org / soap / encoding /: Array )
* @ param array $elements e . g . array ( name => array ( name => '' , type => '' ) )
* @ param array $attrs e . g . array ( array ( 'ref' => 'SOAP-ENC:arrayType' , 'wsdl:arrayType' => 'xsd:string[]' ))
* @ param string $arrayType as namespace : name ( xsd : string )
* @ see nusoap_xmlschema
* @ access public
*/
function addComplexType ( $name , $typeClass = 'complexType' , $phpType = 'array' , $compositor = '' , $restrictionBase = '' , $elements = array (), $attrs = array (), $arrayType = '' ) {
if ( count ( $elements ) > 0 ) {
$eElements = array ();
foreach ( $elements as $n => $e ){
// expand each element
$ee = array ();
foreach ( $e as $k => $v ) {
$k = strpos ( $k , ':' ) ? $this -> expandQname ( $k ) : $k ;
$v = strpos ( $v , ':' ) ? $this -> expandQname ( $v ) : $v ;
$ee [ $k ] = $v ;
}
$eElements [ $n ] = $ee ;
}
$elements = $eElements ;
}
if ( count ( $attrs ) > 0 ) {
foreach ( $attrs as $n => $a ){
// expand each attribute
foreach ( $a as $k => $v ) {
$k = strpos ( $k , ':' ) ? $this -> expandQname ( $k ) : $k ;
$v = strpos ( $v , ':' ) ? $this -> expandQname ( $v ) : $v ;
$aa [ $k ] = $v ;
}
$eAttrs [ $n ] = $aa ;
}
$attrs = $eAttrs ;
}
$restrictionBase = strpos ( $restrictionBase , ':' ) ? $this -> expandQname ( $restrictionBase ) : $restrictionBase ;
$arrayType = strpos ( $arrayType , ':' ) ? $this -> expandQname ( $arrayType ) : $arrayType ;
$typens = isset ( $this -> namespaces [ 'types' ]) ? $this -> namespaces [ 'types' ] : $this -> namespaces [ 'tns' ];
$this -> schemas [ $typens ][ 0 ] -> addComplexType ( $name , $typeClass , $phpType , $compositor , $restrictionBase , $elements , $attrs , $arrayType );
}
/**
* adds an XML Schema simple type to the WSDL types
*
* @ 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
* @ see nusoap_xmlschema
* @ access public
*/
function addSimpleType ( $name , $restrictionBase = '' , $typeClass = 'simpleType' , $phpType = 'scalar' , $enumeration = array ()) {
$restrictionBase = strpos ( $restrictionBase , ':' ) ? $this -> expandQname ( $restrictionBase ) : $restrictionBase ;
$typens = isset ( $this -> namespaces [ 'types' ]) ? $this -> namespaces [ 'types' ] : $this -> namespaces [ 'tns' ];
$this -> schemas [ $typens ][ 0 ] -> addSimpleType ( $name , $restrictionBase , $typeClass , $phpType , $enumeration );
}
/**
* adds an element to the WSDL types
*
* @ param array $attrs attributes that must include name and type
* @ see nusoap_xmlschema
* @ access public
*/
function addElement ( $attrs ) {
$typens = isset ( $this -> namespaces [ 'types' ]) ? $this -> namespaces [ 'types' ] : $this -> namespaces [ 'tns' ];
$this -> schemas [ $typens ][ 0 ] -> addElement ( $attrs );
}
/**
* register an operation with the server
*
* @ param string $name operation ( method ) name
* @ param array $in assoc array of input values : key = param name , value = param type
* @ param array $out assoc array of output values : key = param name , value = param type
* @ param string $namespace optional The namespace for the operation
* @ param string $soapaction optional The soapaction for the operation
* @ param string $style ( rpc | document ) optional The style for the operation Note : when 'document' is specified , parameter and return wrappers are created for you automatically
* @ param string $use ( encoded | literal ) optional The use for the parameters ( cannot mix right now )
* @ param string $documentation optional The description to include in the WSDL
* @ param string $encodingStyle optional ( usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded )
* @ access public
*/
function addOperation ( $name , $in = false , $out = false , $namespace = false , $soapaction = false , $style = 'rpc' , $use = 'encoded' , $documentation = '' , $encodingStyle = '' ){
if ( $use == 'encoded' && $encodingStyle == '' ) {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ;
}
if ( $style == 'document' ) {
$elements = array ();
foreach ( $in as $n => $t ) {
$elements [ $n ] = array ( 'name' => $n , 'type' => $t , 'form' => 'unqualified' );
}
$this -> addComplexType ( $name . 'RequestType' , 'complexType' , 'struct' , 'all' , '' , $elements );
$this -> addElement ( array ( 'name' => $name , 'type' => $name . 'RequestType' ));
$in = array ( 'parameters' => 'tns:' . $name . '^' );
$elements = array ();
foreach ( $out as $n => $t ) {
$elements [ $n ] = array ( 'name' => $n , 'type' => $t , 'form' => 'unqualified' );
}
$this -> addComplexType ( $name . 'ResponseType' , 'complexType' , 'struct' , 'all' , '' , $elements );
$this -> addElement ( array ( 'name' => $name . 'Response' , 'type' => $name . 'ResponseType' , 'form' => 'qualified' ));
$out = array ( 'parameters' => 'tns:' . $name . 'Response' . '^' );
}
// get binding
$this -> bindings [ $this -> serviceName . 'Binding' ][ 'operations' ][ $name ] =
array (
'name' => $name ,
'binding' => $this -> serviceName . 'Binding' ,
'endpoint' => $this -> endpoint ,
'soapAction' => $soapaction ,
'style' => $style ,
'input' => array (
'use' => $use ,
'namespace' => $namespace ,
'encodingStyle' => $encodingStyle ,
'message' => $name . 'Request' ,
'parts' => $in ),
'output' => array (
'use' => $use ,
'namespace' => $namespace ,
'encodingStyle' => $encodingStyle ,
'message' => $name . 'Response' ,
'parts' => $out ),
'namespace' => $namespace ,
'transport' => 'http://schemas.xmlsoap.org/soap/http' ,
'documentation' => $documentation );
// add portTypes
// add messages
if ( $in )
{
foreach ( $in as $pName => $pType )
{
if ( strpos ( $pType , ':' )) {
$pType = $this -> getNamespaceFromPrefix ( $this -> getPrefix ( $pType )) . " : " . $this -> getLocalPart ( $pType );
}
$this -> messages [ $name . 'Request' ][ $pName ] = $pType ;
}
} else {
$this -> messages [ $name . 'Request' ] = '0' ;
}
if ( $out )
{
foreach ( $out as $pName => $pType )
{
if ( strpos ( $pType , ':' )) {
$pType = $this -> getNamespaceFromPrefix ( $this -> getPrefix ( $pType )) . " : " . $this -> getLocalPart ( $pType );
}
$this -> messages [ $name . 'Response' ][ $pName ] = $pType ;
}
} else {
$this -> messages [ $name . 'Response' ] = '0' ;
}
return true ;
}
}
?> <?php
/**
*
* nusoap_parser class parses SOAP XML messages into native PHP values
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_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 ; // parsed SOAP Body
var $soapheader = NULL ; // parsed SOAP Header
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 __construct ( $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 nusoap_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 ( 'in nusoap_parser ctor, message:' );
$this -> appendDebug ( $this -> varDump ( $this -> message ));
$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
if ( $this -> root_header != '' && isset ( $this -> message [ $this -> root_header ][ 'result' ])){
$this -> soapheader = $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 == '' ) {
$this -> status = 'envelope' ;
} elseif ( $name == 'Header' && $this -> status == 'envelope' ) {
$this -> root_header = $pos ;
$this -> status = 'header' ;
} elseif ( $name == 'Body' && $this -> status == 'envelope' ){
$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 ( preg_match ( '/^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' ){
if ( isset ( $this -> message [ $pos ][ 'type' ]) && $this -> message [ $pos ][ 'type' ] == 'array' ) {
// do nothing: already processed arrayType
} else {
$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 ( preg_match ( $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 ( $pos == $this -> root_header ) {
$this -> status = 'envelope' ;
} elseif ( $name == 'Body' && $this -> status == 'body' ) {
$this -> status = 'envelope' ;
} elseif ( $name == 'Header' && $this -> status == 'header' ) { // will never happen
$this -> status = 'envelope' ;
} elseif ( $name == 'Envelope' && $this -> status == 'envelope' ) {
$this -> status = '' ;
}
// 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 ( SOAP Body )
*
* @ return mixed
* @ access public
* @ deprecated use get_soapbody instead
*/
function get_response (){
return $this -> soapresponse ;
}
/**
* get the parsed SOAP Body ( NULL if there was none )
*
* @ return mixed
* @ access public
*/
function get_soapbody (){
return $this -> soapresponse ;
}
/**
* get the parsed SOAP Header ( NULL if there was none )
*
* @ return mixed
* @ access public
*/
function get_soapheader (){
return $this -> soapheader ;
}
/**
* get the unparsed SOAP Header
*
* @ return string XML or empty if no Header
* @ 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 or generic compound type ' . $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' ];
}
}
}
$ret = is_array ( $params ) ? $params : array ();
$this -> debug ( 'in buildVal, return:' );
$this -> appendDebug ( $this -> varDump ( $ret ));
return $ret ;
} 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' ])) {
$ret = $this -> decodeSimple ( $cdata , $this -> message [ $pos ][ 'type' ], isset ( $this -> message [ $pos ][ 'type_namespace' ]) ? $this -> message [ $pos ][ 'type_namespace' ] : '' );
$this -> debug ( " in buildVal, return: $ret " );
return $ret ;
}
$parent = $this -> message [ $pos ][ 'parent' ];
if ( isset ( $this -> message [ $parent ][ 'type' ]) && ( $this -> message [ $parent ][ 'type' ] == 'array' ) && isset ( $this -> message [ $parent ][ 'arrayType' ])) {
$ret = $this -> decodeSimple ( $cdata , $this -> message [ $parent ][ 'arrayType' ], isset ( $this -> message [ $parent ][ 'arrayTypeNamespace' ]) ? $this -> message [ $parent ][ 'arrayTypeNamespace' ] : '' );
$this -> debug ( " in buildVal, return: $ret " );
return $ret ;
}
$ret = $this -> message [ $pos ][ 'cdata' ];
$this -> debug ( " in buildVal, return: $ret " );
return $ret ;
}
}
}
/**
* Backward compatibility
*/
class soap_parser extends nusoap_parser {
}
?> <?php
/**
*
* [ nu ] soapclient higher level class for easy usage .
*
* usage :
*
* // instantiate client with server info
* $soapclient = new nusoap_client ( string path [ , mixed wsdl ] );
*
* // call method, get results
* echo $soapclient -> call ( string methodname [ , array parameters ] );
*
* // bye bye client
* unset ( $soapclient );
*
* @ author Dietrich Ayala < dietrich @ ganx4 . com >
* @ author Scott Nichol < snichol @ users . sourceforge . net >
* @ version $Id : nusoap . php , v 1.123 2010 / 04 / 26 20 : 15 : 08 snichol Exp $
* @ access public
*/
class nusoap_client extends nusoap_base {
var $username = '' ; // Username for HTTP authentication
var $password = '' ; // Password for HTTP authentication
var $authtype = '' ; // Type of HTTP authentication
var $certRequest = array (); // Certificate for HTTP SSL authentication
var $requestHeaders = false ; // SOAP headers in request (text)
var $responseHeaders = '' ; // SOAP headers from response (incomplete namespace resolution) (text)
var $responseHeader = NULL ; // SOAP Header from response (parsed)
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 $portName = '' ; // port name to use in WSDL
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
var $curl_options = array (); // User-specified cURL options
var $bindingType = '' ; // WSDL operation binding type
var $use_curl = false ; // whether to always try to use cURL
/*
* 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 mixed $wsdl optional , set to 'wsdl' or true if using WSDL
* @ param string $proxyhost optional
* @ param string $proxyport optional
* @ param string $proxyusername optional
* @ param string $proxypassword optional
* @ param integer $timeout set the connection timeout
* @ param integer $response_timeout set the response timeout
* @ param string $portName optional portName in WSDL document
* @ access public
*/
function __construct ( $endpoint , $wsdl = false , $proxyhost = false , $proxyport = false , $proxyusername = false , $proxypassword = false , $timeout = 0 , $response_timeout = 30 , $portName = '' ){
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 ;
$this -> portName = $portName ;
$this -> debug ( " ctor wsdl= $wsdl timeout= $timeout response_timeout= $response_timeout " );
$this -> appendDebug ( 'endpoint=' . $this -> varDump ( $endpoint ));
// 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 );
$this -> checkWSDL ();
} else {
$this -> wsdlFile = $this -> endpoint ;
$this -> wsdl = null ;
$this -> debug ( 'will use lazy evaluation of wsdl from ' . $this -> endpoint );
}
$this -> endpointType = 'wsdl' ;
} else {
$this -> debug ( " instantiate SOAP with endpoint at $endpoint " );
$this -> endpointType = 'soap' ;
}
}
/**
* calls method , returns PHP native type
*
* @ param string $operation 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 , or associative array
* @ 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 , normally an associative array mirroring the structure of the XML response , false for certain fatal errors
* @ 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 ;
}
if ( $this -> endpointType == 'wsdl' && is_null ( $this -> wsdl )) {
$this -> loadWSDL ();
if ( $this -> getError ())
return false ;
}
// 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 , $this -> bindingType );
} 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 in WSDL.' );
$this -> debug ( " operation ' $operation ' not present in WSDL. " );
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 ) {
// http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
$payload = " < $nsPrefix : $operation xmlns: $nsPrefix = \" $namespace\ " > " .
$payload .
" </ $nsPrefix : $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 " " ;
}
}
}
}
/**
* check WSDL passed as an instance or pulled from an endpoint
*
* @ access private
*/
function checkWSDL () {
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
$this -> debug ( 'checkWSDL' );
// catch errors
if ( $errstr = $this -> wsdl -> getError ()) {
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
$this -> debug ( 'got wsdl error: ' . $errstr );
$this -> setError ( 'wsdl error: ' . $errstr );
} elseif ( $this -> operations = $this -> wsdl -> getOperations ( $this -> portName , 'soap' )) {
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
$this -> bindingType = 'soap' ;
$this -> debug ( 'got ' . count ( $this -> operations ) . ' operations from wsdl ' . $this -> wsdlFile . ' for binding type ' . $this -> bindingType );
} elseif ( $this -> operations = $this -> wsdl -> getOperations ( $this -> portName , 'soap12' )) {
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
$this -> bindingType = 'soap12' ;
$this -> debug ( 'got ' . count ( $this -> operations ) . ' operations from wsdl ' . $this -> wsdlFile . ' for binding type ' . $this -> bindingType );
$this -> debug ( '**************** WARNING: SOAP 1.2 BINDING *****************' );
} else {
$this -> appendDebug ( $this -> wsdl -> getDebug ());
$this -> wsdl -> clearDebug ();
$this -> debug ( 'getOperations returned false' );
$this -> setError ( 'no operations defined in the WSDL document!' );
}
}
/**
* instantiate wsdl object and parse wsdl file
*
* @ access public
*/
function loadWSDL () {
$this -> debug ( 'instantiating wsdl class with doc: ' . $this -> wsdlFile );
$this -> wsdl = new wsdl ( '' , $this -> proxyhost , $this -> proxyport , $this -> proxyusername , $this -> proxypassword , $this -> timeout , $this -> response_timeout , $this -> curl_options , $this -> use_curl );
$this -> wsdl -> setCredentials ( $this -> username , $this -> password , $this -> authtype , $this -> certRequest );
$this -> wsdl -> fetchWSDL ( $this -> wsdlFile );
$this -> checkWSDL ();
}
/**
* 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 ( $this -> endpointType == 'wsdl' && is_null ( $this -> wsdl )) {
$this -> loadWSDL ();
if ( $this -> getError ())
return false ;
}
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 preg_match ( '/^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 , $this -> curl_options , $this -> use_curl );
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 ( preg_match ( '/^http:/' , $this -> endpoint )){
//if(strpos($this->endpoint,'http:')){
$this -> responseData = $http -> send ( $msg , $timeout , $response_timeout , $this -> cookies );
} elseif ( preg_match ( '/^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 ) . ' headers:' );
$this -> appendDebug ( $this -> varDump ( $headers ));
if ( ! isset ( $headers [ 'content-type' ])) {
$this -> setError ( 'Response not of type text/xml (no content-type header)' );
return false ;
}
if ( ! strstr ( $headers [ 'content-type' ], 'text/xml' )) {
$this -> setError ( 'Response not of type text/xml: ' . $headers [ 'content-type' ]);
return false ;
}
if ( strpos ( $headers [ 'content-type' ], '=' )) {
$enc = str_replace ( '"' , '' , substr ( strstr ( $headers [ " content-type " ], '=' ), 1 ));
$this -> debug ( 'Got response encoding: ' . $enc );
if ( preg_match ( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i' , $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 nusoap_parser' );
$parser = new nusoap_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 SOAP headers
$this -> responseHeader = $parser -> get_soapheader ();
// get decoded message
$return = $parser -> get_soapbody ();
// add document for doclit support
$this -> document = $parser -> document ;
// destroy the parser object
unset ( $parser );
// return decode message
return $return ;
}
}
/**
* sets user - specified cURL options
*
* @ param mixed $option The cURL option ( always integer ? )
* @ param mixed $value The cURL option value
* @ access public
*/
function setCurlOption ( $option , $value ) {
$this -> debug ( " setCurlOption option= $option , value= " );
$this -> appendDebug ( $this -> varDump ( $value ));
$this -> curl_options [ $option ] = $value ;
}
/**
* sets the SOAP endpoint , which can override WSDL
*
* @ param string $endpoint The endpoint URL to use , or empty string or false to prevent override
* @ access public
*/
function setEndpoint ( $endpoint ) {
$this -> debug ( " setEndpoint( \" $endpoint\ " ) " );
$this -> forceEndpoint = $endpoint ;
}
/**
* set the SOAP headers
*
* @ param mixed $headers String of XML with SOAP header content , or array of soapval objects for SOAP headers
* @ access public
*/
function setHeaders ( $headers ){
$this -> debug ( " setHeaders headers= " );
$this -> appendDebug ( $this -> varDump ( $headers ));
$this -> requestHeaders = $headers ;
}
/**
* get the SOAP response headers ( namespace resolution incomplete )
*
* @ return string
* @ access public
*/
function getHeaders (){
return $this -> responseHeaders ;
}
/**
* get the SOAP response Header ( parsed )
*
* @ return mixed
* @ access public
*/
function getHeader (){
return $this -> responseHeader ;
}
/**
* 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 | ntlm )
* @ 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 -> debug ( " setCredentials username= $username authtype= $authtype certRequest= " );
$this -> appendDebug ( $this -> varDump ( $certRequest ));
$this -> username = $username ;
$this -> password = $password ;
$this -> authtype = $authtype ;
$this -> certRequest = $certRequest ;
}
/**
* use HTTP encoding
*
* @ param string $enc HTTP encoding
* @ access public
*/
function setHTTPEncoding ( $enc = 'gzip, deflate' ){
$this -> debug ( " setHTTPEncoding( \" $enc\ " ) " );
$this -> http_encoding = $enc ;
}
/**
* Set whether to try to use cURL connections if possible
*
* @ param boolean $use Whether to try to use cURL
* @ access public
*/
function setUseCURL ( $use ) {
$this -> debug ( " setUseCURL( $use ) " );
$this -> use_curl = $use ;
}
/**
* use HTTP persistent connections if possible
*
* @ access public
*/
function useHTTPPersistentConnection (){
$this -> debug ( " 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");
if ( $this -> getError ()) {
$this -> debug ( " Error from _getProxyClassCode, so return NULL " );
return null ;
}
// eval the class
eval ( $evalStr );
// instantiate proxy object
eval ( " \$ proxy = new nusoap_proxy_ $r (''); " );
// transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
$proxy -> endpointType = 'wsdl' ;
$proxy -> wsdlFile = $this -> wsdlFile ;
$proxy -> wsdl = $this -> wsdl ;
$proxy -> operations = $this -> operations ;
$proxy -> defaultRpcParams = $this -> defaultRpcParams ;
// transfer other state
$proxy -> soap_defencoding = $this -> soap_defencoding ;
$proxy -> username = $this -> username ;
$proxy -> password = $this -> password ;
$proxy -> authtype = $this -> authtype ;
$proxy -> certRequest = $this -> certRequest ;
$proxy -> requestHeaders = $this -> requestHeaders ;
$proxy -> endpoint = $this -> endpoint ;
$proxy -> forceEndpoint = $this -> forceEndpoint ;
$proxy -> proxyhost = $this -> proxyhost ;
$proxy -> proxyport = $this -> proxyport ;
$proxy -> proxyusername = $this -> proxyusername ;
$proxy -> proxypassword = $this -> proxypassword ;
$proxy -> http_encoding = $this -> http_encoding ;
$proxy -> timeout = $this -> timeout ;
$proxy -> response_timeout = $this -> response_timeout ;
$proxy -> persistentConnection = & $this -> persistentConnection ;
$proxy -> decode_utf8 = $this -> decode_utf8 ;
$proxy -> curl_options = $this -> curl_options ;
$proxy -> bindingType = $this -> bindingType ;
$proxy -> use_curl = $this -> use_curl ;
return $proxy ;
}
/**
* dynamically creates proxy class code
*
* @ return string PHP / NuSOAP code for the proxy class
* @ access private
*/
function _getProxyClassCode ( $r ) {
$this -> debug ( " in getProxy endpointType= $this->endpointType " );
$this -> appendDebug ( " wsdl= " . $this -> varDump ( $this -> wsdl ));
if ( $this -> endpointType != 'wsdl' ) {
$evalStr = 'A proxy can only be created for a WSDL client' ;
$this -> setError ( $evalStr );
$evalStr = " echo \" $evalStr\ " ; " ;
return $evalStr ;
}
if ( $this -> endpointType == 'wsdl' && is_null ( $this -> wsdl )) {
$this -> loadWSDL ();
if ( $this -> getError ()) {
return " echo \" " . $this -> getError () . " \" ; " ;
}
}
$evalStr = '' ;
foreach ( $this -> operations as $operation => $opData ) {
if ( $operation != '' ) {
// create param string and param comment string
if ( sizeof ( $opData [ 'input' ][ 'parts' ]) > 0 ) {
$paramStr = '' ;
$paramArrayStr = '' ;
$paramCommentStr = '' ;
foreach ( $opData [ 'input' ][ 'parts' ] as $name => $type ) {
$paramStr .= " \$ $name , " ;
$paramArrayStr .= " ' $name ' => \$ $name , " ;
$paramCommentStr .= " $type \$ $name , " ;
}
$paramStr = substr ( $paramStr , 0 , strlen ( $paramStr ) - 2 );
$paramArrayStr = substr ( $paramArrayStr , 0 , strlen ( $paramArrayStr ) - 2 );
$paramCommentStr = substr ( $paramCommentStr , 0 , strlen ( $paramCommentStr ) - 2 );
} else {
$paramStr = '' ;
$paramArrayStr = '' ;
$paramCommentStr = 'void' ;
}
$opData [ 'namespace' ] = ! isset ( $opData [ 'namespace' ]) ? 'http://testuri.com' : $opData [ 'namespace' ];
$evalStr .= " // $paramCommentStr
function " . str_replace('.', '__', $operation ) . " ( $paramStr ) {
\ $params = array ( $paramArrayStr );
return \ $this -> call ( '$operation' , \ $params , '".$opData[' namespace ']."' , '".(isset($opData[' soapAction ']) ? $opData[' soapAction '] : ' ')."' );
}
" ;
unset ( $paramStr );
unset ( $paramCommentStr );
}
}
$evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
'.$evalStr.'
} ' ;
return $evalStr ;
}
/**
* dynamically creates proxy class code
*
* @ return string PHP / NuSOAP code for the proxy class
* @ access public
*/
function getProxyClassCode () {
$r = rand ();
return $this -> _getProxyClassCode ( $r );
}
/**
* gets the HTTP body for the current request .
*
* @ param string $soapmsg The SOAP payload
* @ return string The HTTP body , which includes the SOAP payload
* @ access private
*/
function getHTTPBody ( $soapmsg ) {
return $soapmsg ;
}
/**
* gets the HTTP content type for the current request .
*
* Note : getHTTPBody must be called before this .
*
* @ return string the HTTP content type for the current request .
* @ access private
*/
function getHTTPContentType () {
return 'text/xml' ;
}
/**
* gets the HTTP content type charset for the current request .
* returns false for non - text content types .
*
* Note : getHTTPBody must be called before this .
*
* @ return string the HTTP content type charset for the current request .
* @ access private
*/
function getHTTPContentTypeCharset () {
return $this -> soap_defencoding ;
}
/*
* whether or not parser should decode utf8 element content
*
* @ return always returns true
* @ access public
*/
function decodeUTF8 ( $bool ){
$this -> decode_utf8 = $bool ;
return true ;
}
/**
* adds a new Cookie into $this -> cookies array
*
* @ param string $name Cookie Name
* @ param string $value Cookie Value
* @ return boolean if cookie - set was successful returns true , else false
* @ access public
*/
function setCookie ( $name , $value ) {
if ( strlen ( $name ) == 0 ) {
return false ;
}
$this -> cookies [] = array ( 'name' => $name , 'value' => $value );
return true ;
}
/**
* gets all Cookies
*
* @ return array with all internal cookies
* @ access public
*/
function getCookies () {
return $this -> cookies ;
}
/**
* checks all Cookies and delete those which are expired
*
* @ return boolean always return true
* @ access private
*/
function checkCookies () {
if ( sizeof ( $this -> cookies ) == 0 ) {
return true ;
}
$this -> debug ( 'checkCookie: check ' . sizeof ( $this -> cookies ) . ' cookies' );
$curr_cookies = $this -> cookies ;
$this -> cookies = array ();
foreach ( $curr_cookies as $cookie ) {
if ( ! is_array ( $cookie )) {
$this -> debug ( 'Remove cookie that is not an array' );
continue ;
}
if (( isset ( $cookie [ 'expires' ])) && ( ! empty ( $cookie [ 'expires' ]))) {
if ( strtotime ( $cookie [ 'expires' ]) > time ()) {
$this -> cookies [] = $cookie ;
} else {
$this -> debug ( 'Remove expired cookie ' . $cookie [ 'name' ]);
}
} else {
$this -> cookies [] = $cookie ;
}
}
$this -> debug ( 'checkCookie: ' . sizeof ( $this -> cookies ) . ' cookies left in array' );
return true ;
}
/**
* updates the current cookies with a new set
*
* @ param array $cookies new cookies with which to update current ones
* @ return boolean always return true
* @ access private
*/
function UpdateCookies ( $cookies ) {
if ( sizeof ( $this -> cookies ) == 0 ) {
// no existing cookies: take whatever is new
if ( sizeof ( $cookies ) > 0 ) {
$this -> debug ( 'Setting new cookie(s)' );
$this -> cookies = $cookies ;
}
return true ;
}
if ( sizeof ( $cookies ) == 0 ) {
// no new cookies: keep what we've got
return true ;
}
// merge
foreach ( $cookies as $newCookie ) {
if ( ! is_array ( $newCookie )) {
continue ;
}
if (( ! isset ( $newCookie [ 'name' ])) || ( ! isset ( $newCookie [ 'value' ]))) {
continue ;
}
$newName = $newCookie [ 'name' ];
$found = false ;
for ( $i = 0 ; $i < count ( $this -> cookies ); $i ++ ) {
$cookie = $this -> cookies [ $i ];
if ( ! is_array ( $cookie )) {
continue ;
}
if ( ! isset ( $cookie [ 'name' ])) {
continue ;
}
if ( $newName != $cookie [ 'name' ]) {
continue ;
}
$newDomain = isset ( $newCookie [ 'domain' ]) ? $newCookie [ 'domain' ] : 'NODOMAIN' ;
$domain = isset ( $cookie [ 'domain' ]) ? $cookie [ 'domain' ] : 'NODOMAIN' ;
if ( $newDomain != $domain ) {
continue ;
}
$newPath = isset ( $newCookie [ 'path' ]) ? $newCookie [ 'path' ] : 'NOPATH' ;
$path = isset ( $cookie [ 'path' ]) ? $cookie [ 'path' ] : 'NOPATH' ;
if ( $newPath != $path ) {
continue ;
}
$this -> cookies [ $i ] = $newCookie ;
$found = true ;
$this -> debug ( 'Update cookie ' . $newName . '=' . $newCookie [ 'value' ]);
break ;
}
if ( ! $found ) {
$this -> debug ( 'Add cookie ' . $newName . '=' . $newCookie [ 'value' ]);
$this -> cookies [] = $newCookie ;
}
}
return true ;
}
}
if ( ! extension_loaded ( 'soap' )) {
/**
* For backwards compatiblity , define soapclient unless the PHP SOAP extension is loaded .
*/
class soapclient extends nusoap_client {
}
}