Maj: NuSOAP 0.7.3

This commit is contained in:
Regis Houssin
2009-10-22 10:21:04 +00:00
parent c8db07011a
commit 9fc889c86a
14 changed files with 17298 additions and 15600 deletions

View File

@@ -17,8 +17,9 @@ FPDF 1.53 Public domain Yes PDF gene
FPDF_TPL 1.1.2 Apache Software License 2.0 No GPL3 only PDF templates management
FPDI 1.2.1 Apache Software License 2.0 No GPL3 only PDF templates management
FPDI_Protection 1.0.2 Apache Software License 2.0 No GPL3 only PDF encryption (8 files)
GeoIP x.x Yes GeoIP Maxmind conversion
MagPieRss 0.72 GPL 2.0 Yes Load RSS
NuSoap 0.6.5 LGPL 2.1 Yes Interfaces with third tools
NuSoap 0.7.3 LGPL 2.1 Yes Interfaces with third tools
PHP_WriteExcel 0.3.0 LGPL 2.1 Yes Excel files generation
PHP_ExcelReader 2.21 MIT License Yes Parse and retrieve information from XLS files
Prototype 1.6.0.3 MIT License Yes Ajax library
@@ -28,7 +29,6 @@ SimpleMail 1.2 GPL Yes SMTP lib
Smarty 2.6.26 LGPL 2.1 Yes Templates engine used by some pages
SMTPs 1.15 GPL Yes SMTPS library
VCard 2.0 GPL 2.0 Yes Fonctions vcard
GeoIP x.x Yes GeoIP Maxmind conversion
For licenses compatibility informations:
http://www.fsf.org/licensing/licenses/index_html

View File

@@ -436,3 +436,149 @@
- soap_server: when generating a fault while debug_flag is true, put debug into faultdetail
- wsdl: add enumeration parameter to addSimpleType
- xmlschema: add enumeration parameter to addSimpleType
2006-02-02, version 0.7.2
- soapclient: initialize paramArrayStr to improve proxy generation
- soap_parser: handle PHP5 soapclient's incorrect transmission of WSDL-described SOAP encoded arrays.
- soap_server: don't assume _SERVER['HTTPS'] is set; try HTTP_SERVER_VARS['HTTPS'] if it is not
- soap_server: "flatten out" the parameter array to call_user_func_array (thanks Andr<64> Mamitzsch)
- soap_server: make thrown exceptions conform to specs
- wsdl: use serialize_val to serialize an array when the XSD type is soapenc:Array (JBoss/Axis does this)
- wsdl: change formatting of serialized XML for the WSDL
- xmlschema: change formatting of namespaces when serializing XML for the schema
2006-04-07, version 0.7.2
- soap_server: if methodparams is not an array, call call_user_func_array with an empty array (thanks Eric Grossi)
- wsdl: distinguish parts with element specified from those with type specified by suffixing element names with ^
- wsdl: do a case-insensitive match on schema URI when looking for type
- xmlschema: only get element (not type) when name has ^ suffix
2006-05-16, version 0.7.2
- soapclient: add getHeader to get parsed SOAP Header
- soap_parser: check status when receiving Header or Body element
- soap_parser: add soapheader
- soap_server: add requestHeader with parsed SOAP Header
2006-06-15, version 0.7.2
- wsdl: fix bug in addComplexType (thanks Maarten Meijer)
- soap_transport_http: change cURL message
2007-03-19, version 0.7.2
- soapclient: declare as nusoapclient, then also subclass soapclient if SOAP extension not loaded
- soapclientmime: declare as nusoapclientmime, then also subclass soapclientmime if SOAP extension not loaded
2007-03-28, version 0.7.2
- nusoap_base: fix serialization of a soapval when its value is a soapval
- soapval: fix serialization of a soapval when its value is a soapval
- soapval: add __toString (cf. http://article.gmane.org/gmane.comp.php.nusoap.general/2776)
- nusoapclient: use lazy retrieval of WSDL instead of always getting it in the constructor
- nusoapclient: fix getProxy that was broken in last revision
- wsdl: add ability to set authorization credentials and retrieve WSDL outside of constructor
2007-04-05, version 0.7.2
- nusoapclientmime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
- nusoapclientmime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
- nusoapservermime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
- nusoapservermime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
- nusoap_base: remove extra whitespace from some XML elements
- nusoap_base: allow SOAP headers to be specified as an associative array (thanks Unique)
- nusoap_base: implement __toString
- nusoap_base: improve doc accuracy and consistency (thanks Martin K?gler)
- iso8601_to_timestamp: avoid problem with negative hours after calculation, etc. (thanks Guntram Trebs)
- nusoapclient: support user-settable cURL options (thanks Ciprian Popovici)
- nusoapclient: call SOAP 1.2 binding operations if no SOAP 1.1 present (there is no reason to believe this will always work!)
- nusoapclient: improve doc accuracy and consistency (thanks Martin K?gler)
- soap_server: don't try to use eval to call function when any parameter is an object
- soap_server: don't print return value within debug string; returned objects would need __toString in PHP 5.2
- soap_server: use URL scheme for WSDL access as the scheme in SOAPAction
- soap_server: strip port number from server name (some FastCGI implementations include port in server name)
- soap_transport_http: support user-settable cURL options (thanks Ciprian Popovici)
- soap_transport_http: use cURL for NTLM authentication
- soap_transport_http: make digest authentication work for GET as well as POST
- soap_transport_http: improve doc accuracy and consistency (thanks Martin K?gler)
- soapval: remove __toString
- wsdl: set operation style if necessary, but do not override one already provided (thanks Raffaele Capobianco)
- wsdl: check SOAP 1.2 binding operations if no SOAP 1.1 present
- wsdl: improve doc accuracy and consistency (thanks Martin K?gler)
- xmlschema: fix simpleType serialization
- xmlschema: improve doc accuracy and consistency (thanks Martin K?gler)
2007-04-09, version 0.7.2
- nusoapclient: set decode_utf8 when creating a proxy (thanks Dmitri Dmitrienko)
- nusoapclient: rename class to nusoap_client
- soap_fault: also provide a class named nusoap_fault
- soap_parser: also provide a class named nusoap_parser
- soap_server: also provide a class named nusoap_server
- soap_transport_http: skip HTTP responses 301 and 401 when using cURL
- soap_transport_http: don't force HTTP Connection header when using cURL
- soap_transport_http: don't set HTTP Host and Content-Length headers when using cURL
- soap_transport_http: support CURLOPT_SSLCERTPASSWD (thanks David Blanco)
- wsdl: support user-settable cURL options (thanks Ciprian Popovici)
- wsdl: serialize parameters for non-SOAP 1.1 binding operations (there is no reason to believe this will always work!)
- xmlschema: also provide a class named nusoap_xmlschema
- nusoapclientmime: rename class to nusoap_client_mime
- nusoapservermime: rename class to nusoap_server_mime
2007-04-11, version 0.7.2
- nusoap_client: enable cURL usage to be forced (thanks Giunta Gaetano)
- soap_transport_http: enable cURL proxy usage (thanks Giunta Gaetano)
- soap_transport_http: enable cURL usage to be forced (thanks Giunta Gaetano)
- soap_transport_http: use cURL's HTTP authentication options for basic, digest
- wsdl: enable cURL usage to be forced (thanks Giunta Gaetano)
2007-04-12, version 0.7.2
- nusoap_client: add debug
- nusoap_xmlschema: don't add elements of complexTypes to elements array (thanks Heiko Hund)
- soap_transport_http: set cURL connection timeout if supported
- soap_transport_http: add debug when setting cURL option
- soap_transport_http: fix digest authentication broken in previous revision
- wsdl: add debug
- wsdlcache: address some issues with non-existing cache-files and PHP Warnings which came in such cases (thanks Ingo Fischer)
- wsdlcache: change class name to nusoap_wsdlcache
2007-04-13, version 0.7.2
- wsdl: wrap parameters if unwrapped values are supplied and WSDL specifies Microsoft-style wrapping
2007-04-16, version 0.7.2
- nusoap_base: avoid warning in getDebugAsXMLComment
- nusoap_client: small debug change
- nusoap_client_mime: set responseData when the root part is found
2007-04-17, version 0.7.2
- soap_transport_http: improve detection of undefined cURL options (thanks Ingo Fischer)
2007-05-28, version 0.7.2
- soap_transport_http: support digest authentication opaque feature (cf. RFC 2617) (thanks Daniel Lacroix)
- soap_transport_http: check safe_mode and open_basedir before setting CURLOPT_FOLLOWLOCATION
- soap_transport_http: skip "HTTP/1.0 200 Connection established" header when cURL returns it (thanks Raimund Jacob)
- nusoap_client: improve handling when getProxy is called and WSDL is not being used
- nusoap_base: add comments about which specifications are used/implemented by NuSOAP
- nusoap_xmlschema: create names for unnamed types that are unique by scope within XML Schema
2007-06-11, version 0.7.2
- wsdl: wrap return value if unwrapped value is supplied and WSDL specifies Microsoft-style wrapping
2007-06-22, version 0.7.2
- nusoap_xmlschema: fix serialization of simpleType restriction (thanks Rizwan Tejpar)
2007-07-30, version 0.7.2
- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
2007-10-21, version 0.7.2
- nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
- nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
2007-10-26, version 0.7.2
- nusoap_server: Fix munging of _SERVER variables that start with HTTP_ (thanks Thomas Wieczorek)
2007-10-30, version 0.7.2
- nusoap_xmlschema: Serialize values for elementFormDefault, attributeFormDefault
- wsdl: Improve consistency between doc/lit schema auto-wrapping and client's parsed schema
- nusoap_server: Correct bug that placed encodingType in Envelope for doc/lit
- nusoap_server: Specify elementFormDefault for schema within doc/lit wsdl
2007-10-31, version 0.7.2
- wsdl: Fix typo in parametersMatchWrapped (thanks Sam Stepanyan)
- soap_transport_http: Fix three typos in setProxy (thanks Sam Stepanyan)
- nusoap_xmlschema: Fix typo in serializeTypeDef (thanks Sam Stepanyan)

View File

@@ -21,6 +21,12 @@ 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 mailing list:
nusoap-general@lists.sourceforge.net
If you have any questions or comments, please email:
Dietrich Ayala
@@ -32,6 +38,20 @@ 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
@@ -59,6 +79,7 @@ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
* nusoap_base
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$
* @access public
*/
@@ -76,7 +97,7 @@ class nusoap_base {
* @var string
* @access private
*/
var $version = '0.7.2';
var $version = '0.7.3';
/**
* CVS revision for HTTP headers.
*
@@ -157,7 +178,7 @@ class nusoap_base {
/**
* XML Schema types in an array of uri => (array of xml type => php type)
* is this legacy yet?
* no, this is used by the xmlschema class to verify type => namespace mappings.
* no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
* @var array
* @access public
*/
@@ -308,7 +329,8 @@ class nusoap_base {
while (strpos($this->debug_str, '--')) {
$this->debug_str = str_replace('--', '- -', $this->debug_str);
}
return "<!--\n" . $this->debug_str . "\n-->";
$ret = "<!--\n" . $this->debug_str . "\n-->";
return $ret;
}
/**
@@ -379,16 +401,22 @@ class nusoap_base {
* @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'){
$this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use");
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'){
return $val->serialize($use);
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)) {
@@ -421,20 +449,26 @@ class nusoap_base {
}
// serialize null value
if (is_null($val)) {
$this->debug("serialize_val: serialize null");
if ($use == 'literal') {
// TODO: depends on minOccurs
return "<$name$xmlns $atts/>";
$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 = '';
}
return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
$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';
@@ -445,65 +479,91 @@ class nusoap_base {
$val = $this->expandEntities($val);
}
if ($use == 'literal') {
return "<$name$xmlns $atts>$val</$name>";
$xml = "<$name$xmlns$atts>$val</$name>";
$this->debug("serialize_val returning $xml");
return $xml;
} else {
return "<$name$xmlns $atts xsi:type=\"xsd:$type\">$val</$name>";
$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>";
$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>";
$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>";
$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>";
$xml .= "<$name$xmlns$atts>$val</$name>";
} else {
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
}
break;
case is_object($val):
if (! $name) {
$name = get_class($val);
$this->debug("In serialize_val, used class name $name as element name");
$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 {
$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
$type_str = '';
}
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 ($use == 'literal') {
$xml .= "<$name$xmlns$atts>$pXml</$name>";
} else {
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
}
$xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
break;
break;
case (is_array($val) || $type):
// detect if struct or array
$valueType = $this->isArraySimpleOrStruct($val);
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
$this->debug("serialize_val: serialize array");
$i = 0;
if(is_array($val) && count($val)> 0){
foreach($val as $v){
@@ -565,13 +625,14 @@ class nusoap_base {
$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>";
$xml .= "<$name$xmlns$atts>";
} else {
$xml .= "<$name$xmlns$type_str$atts>";
}
@@ -590,9 +651,11 @@ class nusoap_base {
}
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;
}
@@ -600,7 +663,7 @@ class nusoap_base {
* 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
* @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)
@@ -632,11 +695,15 @@ class nusoap_base {
if($headers){
if (is_array($headers)) {
$xml = '';
foreach ($headers as $header) {
$xml .= $this->serialize_val($header, false, false, false, false, false, $use);
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, serialzied array of headers to $headers");
$this->debug("In serializeEnvelope, serialized array of headers to $headers");
}
$headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
}
@@ -692,7 +759,7 @@ class nusoap_base {
/**
* expands (changes prefix to namespace) a qualified name
*
* @param string $string qname
* @param string $qname qname
* @return string expanded qname
* @access private
*/
@@ -811,6 +878,16 @@ class nusoap_base {
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
@@ -821,6 +898,7 @@ class nusoap_base {
* convert unix timestamp to ISO 8601 compliant date string
*
* @param string $timestamp Unix time stamp
* @param boolean $utc Whether the time stamp is UTC or local
* @access public
*/
function timestamp_to_iso8601($timestamp,$utc=true){
@@ -875,7 +953,8 @@ function iso8601_to_timestamp($datestr){
$regs[5] = $regs[5] - $m;
}
}
return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
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;
}

View File

@@ -11,7 +11,7 @@
* @version $Id$
* @access public
*/
class soap_fault extends nusoap_base {
class nusoap_fault extends nusoap_base {
/**
* The fault code (client|server)
* @var string
@@ -40,12 +40,12 @@ class soap_fault extends nusoap_base {
/**
* constructor
*
* @param string $faultcode (client | server)
* @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 soap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
parent::nusoap_base();
$this->faultcode = $faultcode;
$this->faultactor = $faultactor;
@@ -80,7 +80,11 @@ class soap_fault extends nusoap_base {
}
}
/**
* Backward compatibility
*/
class soap_fault extends nusoap_fault {
}
?>

View File

@@ -5,13 +5,14 @@
/**
*
* soap_parser class parses SOAP XML messages into native PHP values
* 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$
* @access public
*/
class soap_parser extends nusoap_base {
class nusoap_parser extends nusoap_base {
var $xml = '';
var $xml_encoding = '';
@@ -35,7 +36,8 @@ class soap_parser extends nusoap_base {
var $fault_detail = '';
var $depth_array = array();
var $debug_flag = true;
var $soapresponse = NULL;
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:
@@ -55,7 +57,7 @@ class soap_parser extends nusoap_base {
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
* @access public
*/
function soap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
parent::nusoap_base();
$this->xml = $xml;
$this->xml_encoding = $encoding;
@@ -87,7 +89,7 @@ class soap_parser extends nusoap_base {
} else {
$this->debug('No XML declaration');
}
$this->debug('Entering soap_parser(), length='.strlen($xml).', encoding='.$encoding);
$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.
@@ -113,10 +115,10 @@ class soap_parser extends nusoap_base {
$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
// get final value
$this->soapresponse = $this->message[$this->root_struct]['result'];
// get header value: no, because this is documented as XML string
// if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
// $this->responseHeaders = $this->message[$this->root_header]['result'];
// }
// 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){
@@ -177,10 +179,10 @@ class soap_parser extends nusoap_base {
// set status
if($name == 'Envelope'){
$this->status = 'envelope';
} elseif($name == 'Header'){
} elseif($name == 'Header' && $this->status = 'envelope'){
$this->root_header = $pos;
$this->status = 'header';
} elseif($name == 'Body'){
} elseif($name == 'Body' && $this->status = 'envelope'){
$this->status = 'body';
$this->body_position = $pos;
// set method
@@ -216,17 +218,21 @@ class soap_parser extends nusoap_base {
$this->methodNamespace = $value;
}
// if it's a type declaration, set type
} elseif($key_localpart == 'type'){
$value_prefix = $this->getPrefix($value);
$value_localpart = $this->getLocalPart($value);
$this->message[$pos]['type'] = $value_localpart;
$this->message[$pos]['typePrefix'] = $value_prefix;
if(isset($this->namespaces[$value_prefix])){
$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
} else if(isset($attrs['xmlns:'.$value_prefix])) {
$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
}
// should do something here with the namespace of specified type?
} elseif($key_localpart == '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
@@ -422,19 +428,40 @@ class soap_parser extends nusoap_base {
}
/**
* get the parsed message
* get the parsed message (SOAP Body)
*
* @return mixed
* @access public
* @deprecated use get_soapbody instead
*/
function get_response(){
return $this->soapresponse;
}
/**
* get the parsed headers
* get the parsed SOAP Body (NULL if there was none)
*
* @return string XML or empty if no headers
* @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(){
@@ -534,7 +561,7 @@ class soap_parser extends nusoap_base {
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
} else {
// Apache Vector type: treat as an array
$this->debug('in buildVal, adding Java Vector '.$this->message[$pos]['name']);
$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 {
@@ -577,23 +604,36 @@ class soap_parser extends nusoap_base {
}
}
}
return is_array($params) ? $params : array();
$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'])) {
return $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
$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'])) {
return $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
$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;
}
return $this->message[$pos]['cdata'];
$ret = $this->message[$pos]['cdata'];
$this->debug("in buildVal, return: $ret");
return $ret;
}
}
}
/**
* Backward compatibility
*/
class soap_parser extends nusoap_parser {
}
?>

View File

@@ -5,16 +5,15 @@
/**
*
* soap_server allows the user to create a SOAP server
* nusoap_server allows the user to create a SOAP server
* that is capable of receiving messages and returning responses
*
* NOTE: WSDL functionality is experimental
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$
* @access public
*/
class soap_server extends nusoap_base {
class nusoap_server extends nusoap_base {
/**
* HTTP headers of request
* @var array
@@ -33,6 +32,12 @@ class soap_server extends nusoap_base {
* @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
@@ -95,8 +100,8 @@ class soap_server extends nusoap_base {
*/
var $response = '';
/**
* SOAP headers for response (text)
* @var string
* SOAP headers for response (text or array of soapval or associative array)
* @var mixed
* @access public
*/
var $responseHeaders = '';
@@ -165,7 +170,7 @@ class soap_server extends nusoap_base {
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
* @access public
*/
function soap_server($wsdl=false){
function nusoap_server($wsdl=false){
parent::nusoap_base();
// turn on debugging?
global $debug;
@@ -182,13 +187,13 @@ class soap_server extends nusoap_base {
}
if (isset($debug)) {
$this->debug("In soap_server, set debug_flag=$debug based on global flag");
$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
$this->debug_flag = $debug;
} elseif (isset($_SERVER['QUERY_STRING'])) {
$qs = explode('&', $_SERVER['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
$this->debug_flag = substr($v, 6);
}
}
@@ -196,7 +201,7 @@ class soap_server extends nusoap_base {
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
$this->debug_flag = substr($v, 6);
}
}
@@ -204,7 +209,7 @@ class soap_server extends nusoap_base {
// wsdl
if($wsdl){
$this->debug("In soap_server, WSDL is specified");
$this->debug("In nusoap_server, WSDL is specified");
if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
$this->wsdl = $wsdl;
$this->externalWSDLURL = $this->wsdl->wsdl;
@@ -324,9 +329,9 @@ class soap_server extends nusoap_base {
$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)))); $k = strtolower(substr($k, 5));
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
} else {
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
}
if ($k == 'soapaction') {
// get SOAPAction header
@@ -431,11 +436,11 @@ class soap_server extends nusoap_base {
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
$data = $degzdata;
} else {
$this->fault('Client', 'Errors occurred when trying to decode the data');
$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
return;
}
} else {
$this->fault('Client', 'This Server does not support compressed data');
$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
return;
}
}
@@ -477,7 +482,7 @@ class soap_server extends nusoap_base {
$this->methodname = $this->opData['name'];
} else {
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
$this->fault('Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
return;
}
} else {
@@ -510,7 +515,7 @@ class soap_server extends nusoap_base {
if (!function_exists($this->methodname)) {
$this->debug("in invoke_method, function '$this->methodname' not found!");
$this->result = 'fault: method not found';
$this->fault('Client',"method '$this->methodname' not defined in service");
$this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
return;
}
} else {
@@ -518,7 +523,7 @@ class soap_server extends nusoap_base {
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('Client',"method '$this->methodname' not defined in service");
$this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
return;
}
}
@@ -530,7 +535,7 @@ class soap_server extends nusoap_base {
$this->debug('ERROR: request not verified against method signature');
$this->result = 'fault: request failed validation against method signature';
// return fault
$this->fault('Client',"Operation '$this->methodname' not defined in service.");
$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
return;
}
@@ -556,8 +561,8 @@ class soap_server extends nusoap_base {
}
if ($this->methodparams) {
foreach ($this->methodparams as $param) {
if (is_array($param)) {
$this->fault('Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
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\",";
@@ -579,11 +584,15 @@ class soap_server extends nusoap_base {
$instance = new $class ();
$call_arg = array(&$instance, $method);
}
$this->methodreturn = call_user_func_array($call_arg, $this->methodparams);
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 $this->methodreturn of type ".gettype($this->methodreturn));
$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
}
/**
@@ -600,7 +609,7 @@ class soap_server extends nusoap_base {
function serialize_return() {
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
// if fault
if (isset($this->methodreturn) && (get_class($this->methodreturn) == 'soap_fault')) {
if (isset($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;
@@ -611,11 +620,15 @@ class soap_server extends nusoap_base {
$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
$this->debug('serializing return value');
if($this->wsdl){
// weak attempt at supporting multiple output params
if(sizeof($this->opData['output']['parts']) > 1){
if (sizeof($this->opData['output']['parts']) > 1) {
$this->debug('more than one output part, so use the method return unchanged');
$opParams = $this->methodreturn;
} else {
// TODO: is this really necessary?
} 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);
@@ -623,7 +636,7 @@ class soap_server extends nusoap_base {
$this->wsdl->clearDebug();
if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr);
$this->fault('Server', 'unable to serialize result');
$this->fault('SOAP-ENV:Server', 'unable to serialize result');
return;
}
} else {
@@ -644,7 +657,8 @@ class soap_server extends nusoap_base {
if ($this->opData['style'] == 'rpc') {
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
if ($this->opData['output']['use'] == 'literal') {
$payload = '<'.$this->methodname.'Response xmlns="'.$this->methodURI.'">'.$return_val.'</'.$this->methodname."Response>";
// 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 = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
} else {
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
}
@@ -667,7 +681,7 @@ class soap_server extends nusoap_base {
$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'],$encodingStyle);
$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);
}
@@ -800,25 +814,27 @@ class soap_server extends nusoap_base {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-1';
}
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
// parse response, get soap parser obj
$parser = new soap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
$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('Client',"error in msg parsing:\n".$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_response()');
$this->methodparams = $parser->get_response();
$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;
}
@@ -908,13 +924,20 @@ class soap_server extends nusoap_base {
if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
} elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
} else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
}
$soapaction = "http://$SERVER_NAME$SCRIPT_NAME/$name";
if ($HTTPS == '1' || $HTTPS == 'on') {
$SCHEME = 'https';
} else {
$SCHEME = 'http';
}
$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
}
if(false == $style) {
$style = "rpc";
@@ -953,7 +976,7 @@ class soap_server extends nusoap_base {
if ($faultdetail == '' && $this->debug_flag) {
$faultdetail = $this->getDebug();
}
$this->fault = new soap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
$this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
$this->fault->soap_defencoding = $this->soap_defencoding;
}
@@ -976,15 +999,20 @@ class soap_server extends nusoap_base {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SERVER_PORT = $_SERVER['SERVER_PORT'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$HTTPS = $_SERVER['HTTPS'];
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
} elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
$HTTPS = $HTTP_SERVER_VARS['HTTPS'];
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
} else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is 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 {
@@ -1016,7 +1044,10 @@ class soap_server extends nusoap_base {
if ($schemaTargetNamespace != $namespace) {
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
}
$this->wsdl->schemas[$schemaTargetNamespace][0] = new xmlschema('', '', $this->wsdl->namespaces);
$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);
@@ -1032,7 +1063,11 @@ class soap_server extends nusoap_base {
}
}
/**
* Backward compatibility
*/
class soap_server extends nusoap_server {
}
?>

View File

@@ -8,6 +8,7 @@
* 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$
* @access public
*/
@@ -28,38 +29,97 @@ class soap_transport_http extends nusoap_base {
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, verifypeer (optional), verifyhost (optional)
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 soap_transport_http($url){
function soap_transport_http($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;
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
$this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')';
$this->debug('set User-Agent: ' . $this->outgoing_headers['User-Agent']);
$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("$k = $v");
$this->debug("parsed URL $k = $v");
$this->$k = $v;
}
@@ -82,17 +142,38 @@ class soap_transport_http extends nusoap_base {
// build headers
if (!isset($u['port'])) {
$this->outgoing_headers['Host'] = $this->host;
$this->setHeader('Host', $this->host);
} else {
$this->outgoing_headers['Host'] = $this->host.':'.$this->port;
$this->setHeader('Host', $this->host.':'.$this->port);
}
$this->debug('set Host: ' . $this->outgoing_headers['Host']);
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.
@@ -107,7 +188,15 @@ class soap_transport_http extends nusoap_base {
// }
// }
$this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
if ($this->scheme == 'http' || $this->scheme == 'ssl') {
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)) {
@@ -120,9 +209,7 @@ class soap_transport_http extends nusoap_base {
// munge host if using OpenSSL
if ($this->scheme == 'ssl') {
$host = 'ssl://' . $this->host;
} else {
$host = $this->host;
$host = 'ssl://' . $host;
}
$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
@@ -152,81 +239,156 @@ class soap_transport_http extends nusoap_base {
$this->debug('socket connected');
return true;
} else if ($this->scheme == 'https') {
} 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('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 included cURL.');
return false;
}
$this->debug('connect using https');
// 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 != '') ? "https://$this->host:$this->port" : "https://$this->host";
$hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
// add path
$hostURL .= $this->path;
curl_setopt($this->ch, CURLOPT_URL, $hostURL);
$this->setCurlOption(CURLOPT_URL, $hostURL);
// follow location headers (re-directs)
curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, 1);
if (ini_get('safe_mode') || ini_get('open_basedir')) {
$this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
$this->debug('safe_mode = ');
$this->appendDebug($this->varDump(ini_get('safe_mode')));
$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
curl_setopt($this->ch, CURLOPT_HEADER, 1);
$this->setCurlOption(CURLOPT_HEADER, 1);
// ask for the response output as the return value
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
$this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
// encode
// We manage this ourselves through headers and encoding
// if(function_exists('gzuncompress')){
// curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate');
// $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.
//curl_setopt($this->ch, CURL_HTTP_VERSION_1_1, true);
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
$this->persistentConnection = false;
$this->outgoing_headers['Connection'] = 'close';
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
$this->setHeader('Connection', 'close');
}
// set timeout
// set timeouts
if ($connection_timeout != 0) {
curl_setopt($this->ch, CURLOPT_TIMEOUT, $connection_timeout);
$this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
}
if ($response_timeout != 0) {
$this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
}
// TODO: cURL has added a connection timeout separate from the response timeout
//if ($connection_timeout != 0) {
// curl_setopt($this->ch, CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
//}
//if ($response_timeout != 0) {
// curl_setopt($this->ch, CURLOPT_TIMEOUT, $response_timeout);
//}
// 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.
//curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
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') {
if (isset($this->certRequest['cainfofile'])) {
curl_setopt($this->ch, CURLOPT_CAINFO, $this->certRequest['cainfofile']);
// 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 (isset($this->certRequest['verifypeer'])) {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
}
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 {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1);
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
}
if (isset($this->certRequest['verifyhost'])) {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
} else {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1);
}
if (isset($this->certRequest['sslcertfile'])) {
curl_setopt($this->ch, CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
}
if (isset($this->certRequest['sslkeyfile'])) {
curl_setopt($this->ch, CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
}
if (isset($this->certRequest['passphrase'])) {
curl_setopt($this->ch, CURLOPT_SSLKEYPASSWD , $this->certRequest['passphrase']);
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');
@@ -239,7 +401,7 @@ class soap_transport_http extends nusoap_base {
}
/**
* send the SOAP message via HTTP
* 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
@@ -270,7 +432,7 @@ class soap_transport_http extends nusoap_base {
// get response
$respdata = $this->getResponse();
} else {
$this->setError('Too many tries to get an OK response');
$this->setError("Too many tries to get an OK response ($this->response_status_line)");
}
}
$this->debug('end of send()');
@@ -279,14 +441,15 @@ class soap_transport_http extends nusoap_base {
/**
* send the SOAP message via HTTPS 1.0 using CURL
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
*
* @param string $msg message data
* @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
* @deprecated
*/
function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
return $this->send($data, $timeout, $response_timeout, $cookies);
@@ -297,16 +460,19 @@ class soap_transport_http extends nusoap_base {
*
* @param string $username
* @param string $password
* @param string $authtype (basic, digest, certificate)
* @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, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
* @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("Set credentials for authtype $authtype");
$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->outgoing_headers['Authorization'] = 'Basic '.base64_encode(str_replace(':','',$username).':'.$password);
$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;
@@ -320,7 +486,7 @@ class soap_transport_http extends nusoap_base {
$HA1 = md5($A1);
// A2 = Method ":" digest-uri-value
$A2 = 'POST:' . $this->digest_uri;
$A2 = $this->request_method . ':' . $this->digest_uri;
// H(A2)
$HA2 = md5($A2);
@@ -347,21 +513,24 @@ class soap_transport_http extends nusoap_base {
$hashedDigest = md5($unhashedDigest);
$this->outgoing_headers['Authorization'] = 'Digest username="' . $username . '", realm="' . $digestRequest['realm'] . '", nonce="' . $nonce . '", uri="' . $this->digest_uri . '", cnonce="' . $cnonce . '", nc=' . sprintf("%08x", $digestRequest['nc']) . ', qop="' . $digestRequest['qop'] . '", response="' . $hashedDigest . '"';
$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;
if (isset($this->outgoing_headers['Authorization'])) {
$this->debug('set Authorization: ' . substr($this->outgoing_headers['Authorization'], 0, 12) . '...');
} else {
$this->debug('Authorization header not set');
}
}
/**
@@ -371,8 +540,7 @@ class soap_transport_http extends nusoap_base {
* @access public
*/
function setSOAPAction($soapaction) {
$this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"';
$this->debug('set SOAPAction: ' . $this->outgoing_headers['SOAPAction']);
$this->setHeader('SOAPAction', '"' . $soapaction . '"');
}
/**
@@ -384,12 +552,10 @@ class soap_transport_http extends nusoap_base {
function setEncoding($enc='gzip, deflate') {
if (function_exists('gzdeflate')) {
$this->protocol_version = '1.1';
$this->outgoing_headers['Accept-Encoding'] = $enc;
$this->debug('set Accept-Encoding: ' . $this->outgoing_headers['Accept-Encoding']);
$this->setHeader('Accept-Encoding', $enc);
if (!isset($this->outgoing_headers['Connection'])) {
$this->outgoing_headers['Connection'] = 'close';
$this->setHeader('Connection', 'close');
$this->persistentConnection = false;
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
}
set_magic_quotes_runtime(0);
// deprecated
@@ -400,22 +566,58 @@ class soap_transport_http extends nusoap_base {
/**
* set proxy info here
*
* @param string $proxyhost
* @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 = '') {
$this->uri = $this->url;
$this->host = $proxyhost;
$this->port = $proxyport;
if ($proxyusername != '' && $proxypassword != '') {
$this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword);
$this->debug('set Proxy-Authorization: ' . $this->outgoing_headers['Proxy-Authorization']);
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
@@ -475,16 +677,29 @@ class soap_transport_http extends nusoap_base {
return $new;
}
/*
* Writes payload, including HTTP headers, to $this->outgoing_payload.
/**
* 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
$this->outgoing_headers['Content-Length'] = strlen($data);
$this->debug('set Content-Length: ' . $this->outgoing_headers['Content-Length']);
$this->setHeader('Content-Length', strlen($data));
// start building outgoing payload:
$req = "$this->request_method $this->uri HTTP/$this->protocol_version";
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";
@@ -509,6 +724,14 @@ class soap_transport_http extends nusoap_base {
$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')));
@@ -516,7 +739,7 @@ class soap_transport_http extends nusoap_base {
// build payload
$this->buildPayload($data, $cookie_str);
if ($this->scheme == 'http' || $this->scheme == 'ssl') {
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');
@@ -525,33 +748,51 @@ class soap_transport_http extends nusoap_base {
}
$this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
return true;
} else if ($this->scheme == 'https') {
} else if ($this->io_method() == 'curl') {
// set payload
// TODO: cURL does say this should only be the verb, and in fact it
// 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
//curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
// 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){
$curl_headers[] = "$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;
}
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $curl_headers);
$this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
$this->debug('set cURL HTTP headers');
if ($this->request_method == "POST") {
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
$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->scheme == 'http' || $this->scheme == 'ssl') {
if ($this->io_method() == 'socket') {
// loop until headers have been retrieved
$data = '';
while (!isset($lb)){
@@ -587,8 +828,8 @@ class soap_transport_http extends nusoap_base {
$lb = "\n";
}
}
// remove 100 header
if(isset($lb) && ereg('^HTTP/1.1 100',$data)){
// remove 100 headers
if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
unset($lb);
$data = '';
}//
@@ -714,7 +955,7 @@ class soap_transport_http extends nusoap_base {
// $this->incoming_payload = $header_data.$lb.$lb.$data;
// }
} else if ($this->scheme == 'https') {
} else if ($this->io_method() == 'curl') {
// send and receive
$this->debug('send and receive with cURL');
$this->incoming_payload = curl_exec($this->ch);
@@ -740,8 +981,10 @@ class soap_transport_http extends nusoap_base {
$this->debug('No cURL error, closing cURL');
curl_close($this->ch);
// remove 100 header(s)
while (ereg('^HTTP/1.1 100',$data)) {
// 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") ) {
@@ -749,6 +992,18 @@ class soap_transport_http extends nusoap_base {
}
}
if ($data == '') {
// have nothing left; just remove 100 header(s)
$data = $savedata;
while (ereg('^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";
@@ -787,14 +1042,15 @@ class soap_transport_http extends nusoap_base {
}
}
$arr = explode(' ', $header_array[0], 3);
$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) {
$this->debug("Got 301 $http_reason with Location: " . $this->incoming_headers['location']);
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;
@@ -832,7 +1088,7 @@ class soap_transport_http extends nusoap_base {
($http_status >= 400 && $http_status <= 417) ||
($http_status >= 501 && $http_status <= 505)
) {
$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient_nusoap->response has contents of the response)");
$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
return false;
}
@@ -904,19 +1160,30 @@ class soap_transport_http extends nusoap_base {
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->outgoing_headers['Content-Type'] = $type . ($charset ? '; charset=' . $charset : '');
$this->debug('set Content-Type: ' . $this->outgoing_headers['Content-Type']);
$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->outgoing_headers['Connection'] = 'Keep-Alive';
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
$this->setHeader('Connection', 'Keep-Alive');
return true;
}
@@ -932,7 +1199,7 @@ class soap_transport_http extends nusoap_base {
*/
function parseCookie($cookie_str) {
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
$data = explode(';', $cookie_str);
$data = split(';', $cookie_str);
$value_str = $data[0];
$cookie_param = 'domain=';

View File

@@ -87,7 +87,7 @@ class soapval extends nusoap_base {
* @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);
return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
}
/**

View File

@@ -5,12 +5,12 @@
/**
*
* soapclient_nusoap higher level class for easy usage.
* [nu]soapclient higher level class for easy usage.
*
* usage:
*
* // instantiate client with server info
* $soapclient = new soapclient_nusoap( string path [ ,boolean wsdl] );
* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
*
* // call method, get results
* echo $soapclient->call( string methodname [ ,array parameters] );
@@ -19,17 +19,19 @@
* unset($soapclient);
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$
* @access public
*/
class soapclient_nusoap extends nusoap_base {
class nusoap_client extends nusoap_base {
var $username = '';
var $password = '';
var $authtype = '';
var $certRequest = array();
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
@@ -50,6 +52,9 @@ class soapclient_nusoap extends nusoap_base {
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
@@ -89,7 +94,7 @@ class soapclient_nusoap extends nusoap_base {
* @param integer $response_timeout set the response timeout
* @access public
*/
function soapclient_nusoap($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
parent::nusoap_base();
$this->endpoint = $endpoint;
$this->proxyhost = $proxyhost;
@@ -99,6 +104,9 @@ class soapclient_nusoap extends nusoap_base {
$this->timeout = $timeout;
$this->response_timeout = $response_timeout;
$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')) {
@@ -106,26 +114,13 @@ class soapclient_nusoap extends nusoap_base {
$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;
// instantiate wsdl object and parse wsdl file
$this->debug('instantiating wsdl class with doc: '.$endpoint);
$this->wsdl =& new wsdl($this->wsdlFile,$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout);
}
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
// catch errors
if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr);
$this->setError('wsdl error: '.$errstr);
} elseif($this->operations = $this->wsdl->getOperations()){
$this->debug( 'got '.count($this->operations).' operations from wsdl '.$this->wsdlFile);
$this->endpointType = 'wsdl';
} else {
$this->debug( 'getOperations returned false');
$this->setError('no operations defined in the WSDL document!');
$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';
@@ -135,7 +130,7 @@ class soapclient_nusoap extends nusoap_base {
/**
* calls method, returns PHP native type
*
* @param string $method SOAP server URL or path
* @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
@@ -150,7 +145,7 @@ class soapclient_nusoap extends nusoap_base {
* *must* include the wrapper.
* @param string $namespace optional method namespace (WSDL can override)
* @param string $soapAction optional SOAPAction value (WSDL can override)
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers
* @param 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)
@@ -174,6 +169,11 @@ class soapclient_nusoap extends nusoap_base {
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
@@ -203,7 +203,7 @@ class soapclient_nusoap extends nusoap_base {
$payload = $params;
} elseif (is_array($params)) {
$this->debug("serializing param array for WSDL operation $operation");
$payload = $this->wsdl->serializeRPCParameters($operation,'input',$params);
$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');
@@ -260,7 +260,10 @@ class soapclient_nusoap extends nusoap_base {
if ($use == 'literal') {
$this->debug("wrapping RPC request with literal method element");
if ($namespace) {
$payload = "<$operation xmlns=\"$namespace\">" . $payload . "</$operation>";
// 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>";
}
@@ -326,6 +329,45 @@ class soapclient_nusoap extends nusoap_base {
}
}
/**
* 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->debug('got wsdl error: '.$errstr);
$this->setError('wsdl error: '.$errstr);
} elseif ($this->operations = $this->wsdl->getOperations('soap')) {
$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('soap12')) {
$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->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
*
@@ -334,6 +376,11 @@ class soapclient_nusoap extends nusoap_base {
* @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];
}
@@ -364,7 +411,7 @@ class soapclient_nusoap extends nusoap_base {
if($this->persistentConnection == true && is_object($this->persistentConnection)){
$http =& $this->persistentConnection;
} else {
$http = new soap_transport_http($this->endpoint);
$http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
if ($this->persistentConnection) {
$http->usePersistentConnection();
}
@@ -434,9 +481,10 @@ class soapclient_nusoap extends nusoap_base {
* @access private
*/
function parseResponse($headers, $data) {
$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
$this->appendDebug($this->varDump($headers));
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Response not of type text/xml');
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
return false;
}
if (strpos($headers['content-type'], '=')) {
@@ -451,8 +499,8 @@ class soapclient_nusoap extends nusoap_base {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-1';
}
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
$parser = new soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
$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
@@ -464,8 +512,10 @@ class soapclient_nusoap extends nusoap_base {
} else {
// get SOAP headers
$this->responseHeaders = $parser->getHeaders();
// get SOAP headers
$this->responseHeader = $parser->get_soapheader();
// get decoded message
$return = $parser->get_response();
$return = $parser->get_soapbody();
// add document for doclit support
$this->document = $parser->document;
// destroy the parser object
@@ -475,23 +525,39 @@ class soapclient_nusoap extends nusoap_base {
}
}
/**
* 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 $endpoint string The endpoint URL to use, or empty string or false to prevent override
* @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 $headers mixed String of XML with SOAP header content, or array of soapval objects for 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;
}
@@ -505,6 +571,16 @@ class soapclient_nusoap extends nusoap_base {
return $this->responseHeaders;
}
/**
* get the SOAP response Header (parsed)
*
* @return mixed
* @access public
*/
function getHeader(){
return $this->responseHeader;
}
/**
* set proxy info here
*
@@ -526,11 +602,13 @@ class soapclient_nusoap extends nusoap_base {
*
* @param string $username
* @param string $password
* @param string $authtype (basic|digest|certificate)
* @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;
@@ -540,19 +618,32 @@ class soapclient_nusoap extends nusoap_base {
/**
* use HTTP encoding
*
* @param string $enc
* @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;
}
@@ -593,14 +684,18 @@ class soapclient_nusoap extends nusoap_base {
* @return object soap_proxy object
* @access public
*/
function getProxy(){
function getProxy() {
$r = rand();
$evalStr = $this->_getProxyClassCode($r);
//$this->debug("proxy class: $evalStr";
//$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 soap_proxy_$r('');");
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;
@@ -608,21 +703,26 @@ class soapclient_nusoap extends nusoap_base {
$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->http_encoding = $this->http_encoding;
$proxy->persistentConnection = $this->persistentConnection;
$proxy->requestHeaders = $this->requestHeaders;
$proxy->soap_defencoding = $this->soap_defencoding;
$proxy->endpoint = $this->endpoint;
$proxy->forceEndpoint = $this->forceEndpoint;
$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;
}
@@ -633,11 +733,20 @@ class soapclient_nusoap extends nusoap_base {
* @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 != '') {
@@ -656,6 +765,7 @@ class soapclient_nusoap extends nusoap_base {
$paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
} else {
$paramStr = '';
$paramArrayStr = '';
$paramCommentStr = 'void';
}
$opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
@@ -669,7 +779,7 @@ class soapclient_nusoap extends nusoap_base {
unset($paramCommentStr);
}
}
$evalStr = 'class soap_proxy_'.$r.' extends soapclient_nusoap {
$evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
'.$evalStr.'
}';
return $evalStr;
@@ -738,7 +848,7 @@ class soapclient_nusoap extends nusoap_base {
*
* @param string $name Cookie Name
* @param string $value Cookie Value
* @return if cookie-set was successful returns true, else false
* @return boolean if cookie-set was successful returns true, else false
* @access public
*/
function setCookie($name, $value) {
@@ -762,7 +872,7 @@ class soapclient_nusoap extends nusoap_base {
/**
* checks all Cookies and delete those which are expired
*
* @return always return true
* @return boolean always return true
* @access private
*/
function checkCookies() {
@@ -795,7 +905,7 @@ class soapclient_nusoap extends nusoap_base {
* updates the current cookies with a new set
*
* @param array $cookies new cookies with which to update current ones
* @return always return true
* @return boolean always return true
* @access private
*/
function UpdateCookies($cookies) {
@@ -856,4 +966,12 @@ class soapclient_nusoap extends nusoap_base {
return true;
}
}
if (!extension_loaded('soap')) {
/**
* For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
*/
class soapclient extends nusoap_client {
}
}
?>

View File

@@ -4,9 +4,11 @@
/**
* parses a WSDL file, allows access to it's data, other utility methods
* 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$
* @access public
*/
@@ -45,6 +47,13 @@ class wsdl extends nusoap_base {
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
@@ -56,82 +65,96 @@ class wsdl extends nusoap_base {
* @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 wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30){
function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
parent::nusoap_base();
$this->wsdl = $wsdl;
$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 ($wsdl != "") {
$this->debug('initial wsdl URL: ' . $wsdl);
$this->parseWSDL($wsdl);
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");
$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");
}
}
}
}
}
// 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'])) {
@@ -151,7 +174,8 @@ class wsdl extends nusoap_base {
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'] ];
}
if (isset($bindingData['style'])) {
// 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'] : '';
@@ -160,7 +184,7 @@ class wsdl extends nusoap_base {
}
}
}
}
}
/**
* parses the wsdl document
@@ -168,8 +192,9 @@ class wsdl extends nusoap_base {
* @param string $wsdl path or URL
* @access private
*/
function parseWSDL($wsdl = '')
{
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()!!');
@@ -182,12 +207,15 @@ class wsdl extends nusoap_base {
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);
$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);
@@ -278,7 +306,7 @@ class wsdl extends nusoap_base {
$this->debug('Parsing WSDL schema');
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
$this->status = 'schema';
$this->currentSchema = new xmlschema('', '', $this->namespaces);
$this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug();
@@ -332,12 +360,12 @@ class wsdl extends nusoap_base {
case 'message':
if ($name == 'part') {
if (isset($attrs['type'])) {
$this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs));
$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 $attrs[name]: " . implode(',', $attrs));
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'];
$this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
}
}
break;
@@ -522,6 +550,24 @@ class wsdl extends nusoap_base {
}
}
/**
* 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])) {
@@ -532,15 +578,16 @@ class wsdl extends nusoap_base {
/**
* returns an assoc array of operation names => operation data
*
* @param string $bindingType eg: soap, smtp, dime (only soap is currently supported)
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
* @return array
* @access public
*/
function getOperations($bindingType = 'soap')
{
function getOperations($bindingType = 'soap') {
$ops = array();
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) {
@@ -561,8 +608,8 @@ class wsdl extends nusoap_base {
/**
* 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
* @param string $operation name of operation
* @param string $bindingType type of binding eg: soap, soap12
* @return array
* @access public
*/
@@ -570,6 +617,8 @@ class wsdl extends nusoap_base {
{
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) {
@@ -592,13 +641,15 @@ class wsdl extends nusoap_base {
* 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
* @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) {
@@ -626,11 +677,11 @@ class wsdl extends nusoap_base {
* 'attrs' => array() // refs to attributes array
* )
*
* @param $type string the type
* @param $ns string namespace (not prefix) of the type
* @param string $type the type
* @param string $ns namespace (not prefix) of the type
* @return mixed
* @access public
* @see xmlschema
* @see nusoap_xmlschema
*/
function getTypeDef($type, $ns) {
$this->debug("in getTypeDef: type=$type, ns=$ns");
@@ -638,13 +689,22 @@ class wsdl extends nusoap_base {
$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();
//$this->appendDebug($xs->getDebug());
//$xs->clearDebug();
if ($t) {
if (!isset($t['phpType'])) {
// get info for type to tack onto the element
@@ -841,7 +901,7 @@ class wsdl extends nusoap_base {
}
// types
if (count($this->schemas)>=1) {
$xml .= "\n<types>";
$xml .= "\n<types>\n";
foreach ($this->schemas as $ns => $list) {
foreach ($list as $xs) {
$xml .= $xs->serializeSchema();
@@ -872,13 +932,17 @@ class wsdl extends nusoap_base {
}
}
$ns = $this->getNamespaceFromPrefix($typePrefix);
$typeDef = $this->getTypeDef($this->getLocalPart($partType), $ns);
$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 .= '<part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />';
$xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
}
}
$xml .= '</message>';
@@ -890,38 +954,38 @@ class wsdl extends nusoap_base {
$portType_xml = '';
foreach($this->bindings as $bindingName => $attrs) {
$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
$binding_xml .= '<soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
$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 .= '<operation name="' . $opName . '">';
$binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
$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 .= '<input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
$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 .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
$binding_xml .= '</operation>';
$portType_xml .= '<operation name="' . $opParts['name'] . '"';
$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 .= '<documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
$portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
}
$portType_xml .= '<input message="tns:' . $opParts['input']['message'] . '"/>';
$portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>';
$portType_xml .= '</operation>';
$portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
$portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
$portType_xml .= "\n" . ' </operation>';
}
$portType_xml .= '</portType>';
$binding_xml .= '</binding>';
$portType_xml .= "\n" . '</portType>';
$binding_xml .= "\n" . '</binding>';
}
$xml .= $portType_xml . $binding_xml;
}
@@ -929,17 +993,105 @@ class wsdl extends nusoap_base {
$xml .= "\n<service name=\"" . $this->serviceName . '">';
if (count($this->ports) >= 1) {
foreach($this->ports as $pName => $attrs) {
$xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
$xml .= '<soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
$xml .= '</port>';
$xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
$xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
$xml .= "\n" . ' </port>';
}
}
$xml .= '</service>';
$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;
$change = false;
if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
$this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
$change = true;
}
foreach ($typeDef['elements'] as $name => $attrs) {
if ($change) {
$this->debug("in parametersMatchWrapped: change parameter $element to name $name");
$parameters[$name] = $parameters[$elements];
unset($parameters[$elements]);
$matches++;
} elseif (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
@@ -948,12 +1100,12 @@ class wsdl extends nusoap_base {
* @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)
{
$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
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') {
@@ -961,12 +1113,12 @@ class wsdl extends nusoap_base {
$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);
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('opData:');
$this->debug('in serializeRPCParameters: opData:');
$this->appendDebug($this->varDump($opData));
// Get encoding style for output and set to current
@@ -979,14 +1131,29 @@ class wsdl extends nusoap_base {
// 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 ' . count($opData[$direction]['parts']) . ' part(s) to serialize');
$this->debug("have $part_count part(s) to serialize using $style/$use");
if (is_array($parameters)) {
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
$this->debug('have ' . count($parameters) . ' parameter(s) provided as ' . $parametersArrayType . ' to serialize');
foreach($opData[$direction]['parts'] as $name => $type) {
$this->debug('serializing part "'.$name.'" of type "'.$type.'"');
$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 ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
$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'];
@@ -1024,9 +1191,10 @@ class wsdl extends nusoap_base {
* - multi-ref serialization
* - validate PHP values against type definitions, return errors if invalid
*
* @param string $ type name
* @param mixed $ param value
* @return mixed new param or false if initial value didn't validate
* @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
*/
@@ -1159,7 +1327,7 @@ class wsdl extends nusoap_base {
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') {
if ($unqualified && $use == 'literal') {
$elementNS = " xmlns=\"\"";
} else {
$elementNS = '';
@@ -1175,6 +1343,10 @@ class wsdl extends nusoap_base {
$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';
@@ -1252,6 +1424,9 @@ class wsdl extends nusoap_base {
} else {
$this->debug("in serializeType: found typeDef");
$this->appendDebug('typeDef=' . $this->varDump($typeDef));
if (substr($uqType, -1) == '^') {
$uqType = substr($uqType, 0, -1);
}
}
$phpType = $typeDef['phpType'];
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
@@ -1559,21 +1734,23 @@ class wsdl extends nusoap_base {
/**
* 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 = array ( name => array(name=>'',type=>'') )
* @param array attrs = array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
* @param string arrayType: namespace:name (xsd:string)
* @see xmlschema
* @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;
@@ -1612,7 +1789,7 @@ class wsdl extends nusoap_base {
* @param string $typeClass (should always be simpleType)
* @param string $phpType (should always be scalar)
* @param array $enumeration array of values
* @see xmlschema
* @see nusoap_xmlschema
* @access public
*/
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
@@ -1626,7 +1803,7 @@ class wsdl extends nusoap_base {
* adds an element to the WSDL types
*
* @param array $attrs attributes that must include name and type
* @see xmlschema
* @see nusoap_xmlschema
* @access public
*/
function addElement($attrs) {
@@ -1660,15 +1837,15 @@ class wsdl extends nusoap_base {
}
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
$in = array('parameters' => 'tns:' . $name);
$in = array('parameters' => 'tns:' . $name . '^');
$elements = array();
foreach ($out as $n => $t) {
$elements[$n] = array('name' => $n, 'type' => $t);
}
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType'));
$out = array('parameters' => 'tns:' . $name . 'Response');
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
$out = array('parameters' => 'tns:' . $name . 'Response' . '^');
}
// get binding

View File

@@ -1,16 +1,21 @@
<?php
/*
The NuSOAP project home is:
http://sourceforge.net/projects/nusoap/
The primary support for NuSOAP is the mailing list:
nusoap-general@lists.sourceforge.net
*/
/**
* caches instances of the wsdl class
*
* @author Scott Nichol <snichol@computer.org>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @author Ingo Fischer <ingo@apollon.de>
* @version $Id$
* @access public
*/
class wsdlcache {
class nusoap_wsdlcache {
/**
* @var resource
* @access private
@@ -39,7 +44,7 @@ class wsdlcache {
* @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
* @access public
*/
function wsdlcache($cache_dir='.', $cache_lifetime=0) {
function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
$this->fplock = array();
$this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
$this->cache_lifetime = $cache_lifetime;
@@ -86,6 +91,11 @@ class wsdlcache {
}
}
// see what there is to return
if (!file_exists($filename)) {
$this->debug("$wsdl ($filename) not in cache (1)");
$this->releaseMutex($filename);
return null;
}
$fp = @fopen($filename, "r");
if ($fp) {
$s = implode("", @file($filename));
@@ -93,7 +103,7 @@ class wsdlcache {
$this->debug("Got $wsdl ($filename) from cache");
} else {
$s = null;
$this->debug("$wsdl ($filename) not in cache");
$this->debug("$wsdl ($filename) not in cache (2)");
}
$this->releaseMutex($filename);
return (!is_null($s)) ? unserialize($s) : null;
@@ -136,6 +146,11 @@ class wsdlcache {
$s = serialize($wsdl_instance);
if ($this->obtainMutex($filename, "w")) {
$fp = fopen($filename, "w");
if (! $fp) {
$this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache");
$this->releaseMutex($filename);
return false;
}
fputs($fp, $s);
fclose($fp);
$this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
@@ -173,6 +188,10 @@ class wsdlcache {
*/
function remove($wsdl) {
$filename = $this->createFilename($wsdl);
if (!file_exists($filename)) {
$this->debug("$wsdl ($filename) not in cache to be removed");
return false;
}
// ignore errors obtaining mutex
$this->obtainMutex($filename, "w");
$ret = unlink($filename);
@@ -181,4 +200,10 @@ class wsdlcache {
return $ret;
}
}
/**
* For backward compatibility
*/
class wsdlcache extends nusoap_wsdlcache {
}
?>

View File

@@ -4,17 +4,15 @@
/**
* parses an XML Schema, allows access to it's data, other utility methods
* no validation... yet.
* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
* tutorials I refer to :)
* 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$
* @access public
*/
class XMLSchema extends nusoap_base {
class nusoap_xmlschema extends nusoap_base {
// files
var $schema = '';
@@ -53,9 +51,9 @@ class XMLSchema extends nusoap_base {
* @param string $namespaces namespaces defined in enclosing XML
* @access public
*/
function XMLSchema($schema='',$xml='',$namespaces=array()){
function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
parent::nusoap_base();
$this->debug('xmlschema class instantiated, inside constructor');
$this->debug('nusoap_xmlschema class instantiated, inside constructor');
// files
$this->schema = $schema;
$this->xml = $xml;
@@ -81,8 +79,8 @@ class XMLSchema extends nusoap_base {
/**
* parse an XML file
*
* @param string $xml, path/URL to XML file
* @param string $type, (schema | xml)
* @param string $xml path/URL to XML file
* @param string $type (schema | xml)
* @return boolean
* @access public
*/
@@ -109,7 +107,7 @@ class XMLSchema extends nusoap_base {
* parse an XML string
*
* @param string $xml path or URL
* @param string $type, (schema|xml)
* @param string $type (schema|xml)
* @access private
*/
function parseString($xml,$type){
@@ -152,6 +150,21 @@ class XMLSchema extends nusoap_base {
}
}
/**
* 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
*
@@ -284,6 +297,8 @@ class XMLSchema extends nusoap_base {
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'];
@@ -302,9 +317,10 @@ class XMLSchema extends nusoap_base {
} else {
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
}
}else{
$this->xdebug('processing unnamed complexType for element '.$this->currentElement);
$this->currentComplexType = $this->currentElement . '_ContainedType';
} 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';
@@ -325,9 +341,6 @@ class XMLSchema extends nusoap_base {
break;
case 'element':
array_push($this->elementStack, $this->currentElement);
// elements defined as part of a complex type should
// not really be added to $this->elements, but for some
// reason, they are
if (!isset($attrs['form'])) {
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
}
@@ -351,24 +364,25 @@ class XMLSchema extends nusoap_base {
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
}
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$ename = $attrs['name'];
} elseif(isset($attrs['ref'])){
$this->xdebug("processing element as ref to ".$attrs['ref']);
$this->currentElement = "ref to ".$attrs['ref'];
$ename = $this->getLocalPart($attrs['ref']);
} else {
$this->xdebug("processing untyped element ".$attrs['name']);
$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
$this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
$this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
$ename = $attrs['name'];
}
if(isset($ename) && $this->currentComplexType){
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
@@ -434,8 +448,9 @@ class XMLSchema extends nusoap_base {
$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
} else {
$this->xdebug('processing unnamed simpleType for element '.$this->currentElement);
$this->currentSimpleType = $this->currentElement . '_ContainedType';
$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';
@@ -578,13 +593,13 @@ class XMLSchema extends nusoap_base {
// 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";
$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
if (isset($eParts['enumeration'])) {
foreach ($eParts['enumeration'] as $e) {
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
}
}
$xml .= " </$schemaPrefix:simpleType>";
$xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
}
}
// elements
@@ -600,9 +615,15 @@ class XMLSchema extends nusoap_base {
}
}
// finish 'er up
$el = "<$schemaPrefix:schema targetNamespace=\"$this->schemaTargetNamespace\"\n";
$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\"\n";
$el .= " xmlns:$nsp=\"$ns\"";
}
$xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
return $xml;
@@ -624,8 +645,8 @@ class XMLSchema extends nusoap_base {
* 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
* @param string $type name of defined type
* @param string $ns namespace of type
* @return mixed
* @access public
* @deprecated
@@ -656,7 +677,7 @@ class XMLSchema extends nusoap_base {
*
* For simpleType or element, the array has different keys.
*
* @param string
* @param string $type
* @return mixed
* @access public
* @see addComplexType
@@ -665,10 +686,17 @@ class XMLSchema extends nusoap_base {
*/
function getTypeDef($type){
//$this->debug("in getTypeDef for type $type");
if(isset($this->complexTypes[$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(isset($this->simpleTypes[$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
@@ -727,7 +755,7 @@ class XMLSchema extends nusoap_base {
/**
* returns a sample serialization of a given type, or false if no type by the given name
*
* @param string $type, name of type
* @param string $type name of type
* @return mixed
* @access public
* @deprecated
@@ -737,7 +765,7 @@ class XMLSchema extends nusoap_base {
if($typeDef = $this->getTypeDef($type)){
$str .= '<'.$type;
if(is_array($typeDef['attrs'])){
foreach($attrs as $attName => $data){
foreach($typeDef['attrs'] as $attName => $data){
$str .= " $attName=\"{type = ".$data['type']."}\"";
}
}
@@ -762,8 +790,8 @@ class XMLSchema extends nusoap_base {
* 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
* @param string $name name for type instance
* @param string $type name of type
* @return string
* @access public
* @deprecated
@@ -865,7 +893,7 @@ class XMLSchema extends nusoap_base {
* @param string $phpType (should always be scalar)
* @param array $enumeration array of values
* @access public
* @see xmlschema
* @see nusoap_xmlschema
* @see getTypeDef
*/
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
@@ -885,7 +913,7 @@ class XMLSchema extends nusoap_base {
* adds an element to the schema
*
* @param array $attrs attributes that must include name and type
* @see xmlschema
* @see nusoap_xmlschema
* @access public
*/
function addElement($attrs) {
@@ -900,7 +928,11 @@ class XMLSchema extends nusoap_base {
}
}
/**
* Backward compatibility
*/
class XMLSchema extends nusoap_xmlschema {
}
?>

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,12 @@ 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 mailing list:
nusoap-general@lists.sourceforge.net
If you have any questions or comments, please email:
Dietrich Ayala
@@ -37,15 +43,15 @@ require_once('Mail/mimeDecode.php');
require_once('Mail/mimePart.php');
/**
* soapclientmime client supporting MIME attachments defined at
* nusoap_client_mime client supporting MIME attachments defined at
* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
*
* @author Scott Nichol <snichol@sourceforge.net>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
* @version $Id$
* @access public
*/
class soapclientmime extends soapclient {
class nusoap_client_mime extends nusoap_client {
/**
* @var array Each array element in the return is an associative array with keys
* data, filename, contenttype, cid
@@ -126,7 +132,7 @@ class soapclientmime extends soapclient {
*/
function getHTTPBody($soapmsg) {
if (count($this->requestAttachments) > 0) {
$params['content_type'] = 'multipart/related; type=text/xml';
$params['content_type'] = 'multipart/related; type="text/xml"';
$mimeMessage =& new Mail_mimePart('', $params);
unset($params);
@@ -231,8 +237,9 @@ class soapclientmime extends soapclient {
$structure = Mail_mimeDecode::decode($params);
foreach ($structure->parts as $part) {
if (!isset($part->disposition)) {
if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
$this->debug('Have root part of type ' . $part->headers['content-type']);
$root = $part->body;
$return = parent::parseResponse($part->headers, $part->body);
} else {
$this->debug('Have an attachment of type ' . $part->headers['content-type']);
@@ -245,27 +252,36 @@ class soapclientmime extends soapclient {
}
if (isset($return)) {
$this->responseData = $root;
return $return;
}
$this->setError('No root part found in multipart/related content');
return;
return '';
}
$this->debug('Not multipart/related');
return parent::parseResponse($headers, $data);
}
}
/*
* For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
*/
if (!extension_loaded('soap')) {
class soapclientmime extends nusoap_client_mime {
}
}
/**
* nusoapservermime server supporting MIME attachments defined at
* nusoap_server_mime server supporting MIME attachments defined at
* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
*
* @author Scott Nichol <snichol@sourceforge.net>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
* @version $Id$
* @access public
*/
class nusoapservermime extends soap_server {
class nusoap_server_mime extends nusoap_server {
/**
* @var array Each array element in the return is an associative array with keys
* data, filename, contenttype, cid
@@ -346,7 +362,7 @@ class nusoapservermime extends soap_server {
*/
function getHTTPBody($soapmsg) {
if (count($this->responseAttachments) > 0) {
$params['content_type'] = 'multipart/related; type=text/xml';
$params['content_type'] = 'multipart/related; type="text/xml"';
$mimeMessage =& new Mail_mimePart('', $params);
unset($params);
@@ -451,7 +467,7 @@ class nusoapservermime extends soap_server {
$structure = Mail_mimeDecode::decode($params);
foreach ($structure->parts as $part) {
if (!isset($part->disposition)) {
if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
$this->debug('Have root part of type ' . $part->headers['content-type']);
$return = parent::parseRequest($part->headers, $part->body);
} else {
@@ -475,4 +491,11 @@ class nusoapservermime extends soap_server {
return parent::parseRequest($headers, $data);
}
}
/*
* For backwards compatiblity
*/
class nusoapservermime extends nusoap_server_mime {
}
?>