Fix: functions "ereg", "ereg_replace", "eregi", "eregi_replace" is deprecated since php 5.3.0

This commit is contained in:
Regis Houssin 2009-10-22 10:52:38 +00:00
parent 9fc889c86a
commit 6558d01348
22 changed files with 17359 additions and 15661 deletions

View File

@ -562,7 +562,7 @@ class nusoap_base {
case (is_array($val) || $type): case (is_array($val) || $type):
// detect if struct or array // detect if struct or array
$valueType = $this->isArraySimpleOrStruct($val); $valueType = $this->isArraySimpleOrStruct($val);
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){ if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
$this->debug("serialize_val: serialize array"); $this->debug("serialize_val: serialize array");
$i = 0; $i = 0;
if(is_array($val) && count($val)> 0){ if(is_array($val) && count($val)> 0){
@ -765,7 +765,7 @@ class nusoap_base {
*/ */
function expandQname($qname){ function expandQname($qname){
// get element prefix // get element prefix
if(strpos($qname,':') && !ereg('^http://',$qname)){ if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
// get unqualified name // get unqualified name
$name = substr(strstr($qname,':'),1); $name = substr(strstr($qname,':'),1);
// get ns prefix // get ns prefix
@ -905,16 +905,16 @@ function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp); $datestr = date('Y-m-d\TH:i:sO',$timestamp);
if($utc){ if($utc){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
} }
return false; return false;
@ -931,15 +931,15 @@ function timestamp_to_iso8601($timestamp,$utc=true){
*/ */
function iso8601_to_timestamp($datestr){ function iso8601_to_timestamp($datestr){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
// not utc // not utc
if($regs[8] != 'Z'){ if($regs[8] != 'Z'){
$op = substr($regs[8],0,1); $op = substr($regs[8],0,1);

View File

@ -207,7 +207,7 @@ class nusoap_parser extends nusoap_base {
$key_localpart = $this->getLocalPart($key); $key_localpart = $this->getLocalPart($key);
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if($key_prefix == 'xmlns'){ if($key_prefix == 'xmlns'){
if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){ if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
$this->XMLSchemaVersion = $value; $this->XMLSchemaVersion = $value;
$this->namespaces['xsd'] = $this->XMLSchemaVersion; $this->namespaces['xsd'] = $this->XMLSchemaVersion;
$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
@ -243,8 +243,8 @@ class nusoap_parser extends nusoap_base {
[5] length ::= nextDimension* Digit+ [5] length ::= nextDimension* Digit+
[6] nextDimension ::= Digit+ ',' [6] nextDimension ::= Digit+ ','
*/ */
$expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]'; $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
if(ereg($expr,$value,$regs)){ if(preg_match($expr,$value,$regs)){
$this->message[$pos]['typePrefix'] = $regs[1]; $this->message[$pos]['typePrefix'] = $regs[1];
$this->message[$pos]['arrayTypePrefix'] = $regs[1]; $this->message[$pos]['arrayTypePrefix'] = $regs[1];
if (isset($this->namespaces[$regs[1]])) { if (isset($this->namespaces[$regs[1]])) {

View File

@ -245,7 +245,7 @@ class nusoap_server extends nusoap_base {
} }
$this->debug("In service, query string=$qs"); $this->debug("In service, query string=$qs");
if (ereg('wsdl', $qs) ){ if (preg_match('/wsdl/', $qs) ){
$this->debug("In service, this is a request for WSDL"); $this->debug("In service, this is a request for WSDL");
if($this->externalWSDLURL){ if($this->externalWSDLURL){
if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
@ -717,7 +717,7 @@ class nusoap_server extends nusoap_base {
$payload .= $this->getDebugAsXMLComment(); $payload .= $this->getDebugAsXMLComment();
} }
$this->outgoing_headers[] = "Server: $this->title Server v$this->version"; $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
// Let the Web server decide about this // Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n"; //$this->outgoing_headers[] = "Connection: Close\r\n";

View File

@ -66,7 +66,7 @@ class soap_transport_http extends nusoap_base {
$this->ch_options = $curl_options; $this->ch_options = $curl_options;
} }
$this->use_curl = $use_curl; $this->use_curl = $use_curl;
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
} }
@ -829,7 +829,7 @@ class soap_transport_http extends nusoap_base {
} }
} }
// remove 100 headers // remove 100 headers
if (isset($lb) && ereg('^HTTP/1.1 100',$data)) { if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
unset($lb); unset($lb);
$data = ''; $data = '';
}// }//
@ -995,7 +995,7 @@ class soap_transport_http extends nusoap_base {
if ($data == '') { if ($data == '') {
// have nothing left; just remove 100 header(s) // have nothing left; just remove 100 header(s)
$data = $savedata; $data = $savedata;
while (ereg('^HTTP/1.1 100',$data)) { while (preg_match('/^HTTP\/1.1 100/',$data)) {
if ($pos = strpos($data,"\r\n\r\n")) { if ($pos = strpos($data,"\r\n\r\n")) {
$data = ltrim(substr($data,$pos)); $data = ltrim(substr($data,$pos));
} elseif($pos = strpos($data,"\n\n") ) { } elseif($pos = strpos($data,"\n\n") ) {

View File

@ -406,7 +406,7 @@ class nusoap_client extends nusoap_base {
// detect transport // detect transport
switch(true){ switch(true){
// http(s) // http(s)
case ereg('^http',$this->endpoint): case preg_match('/^http/',$this->endpoint):
$this->debug('transporting via HTTP'); $this->debug('transporting via HTTP');
if($this->persistentConnection == true && is_object($this->persistentConnection)){ if($this->persistentConnection == true && is_object($this->persistentConnection)){
$http =& $this->persistentConnection; $http =& $this->persistentConnection;
@ -428,10 +428,10 @@ class nusoap_client extends nusoap_base {
$http->setEncoding($this->http_encoding); $http->setEncoding($this->http_encoding);
} }
$this->debug('sending message, length='.strlen($msg)); $this->debug('sending message, length='.strlen($msg));
if(ereg('^http:',$this->endpoint)){ if(preg_match('/^http:/',$this->endpoint)){
//if(strpos($this->endpoint,'http:')){ //if(strpos($this->endpoint,'http:')){
$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
} elseif(ereg('^https',$this->endpoint)){ } elseif(preg('/^https/',$this->endpoint)){
//} elseif(strpos($this->endpoint,'https:')){ //} elseif(strpos($this->endpoint,'https:')){
//if(phpversion() == '4.3.0-dev'){ //if(phpversion() == '4.3.0-dev'){
//$response = $http->send($msg,$timeout,$response_timeout); //$response = $http->send($msg,$timeout,$response_timeout);

View File

@ -302,7 +302,7 @@ class wsdl extends nusoap_base {
$this->currentSchema->schemaStartElement($parser, $name, $attrs); $this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
} elseif (ereg('schema$', $name)) { } elseif (preg_match('/schema$/', $name)) {
$this->debug('Parsing WSDL schema'); $this->debug('Parsing WSDL schema');
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
$this->status = 'schema'; $this->status = 'schema';
@ -321,7 +321,7 @@ class wsdl extends nusoap_base {
if (count($attrs) > 0) { if (count($attrs) > 0) {
// register namespace declarations // register namespace declarations
foreach($attrs as $k => $v) { foreach($attrs as $k => $v) {
if (ereg("^xmlns", $k)) { if (preg_match("/^xmlns/", $k)) {
if ($ns_prefix = substr(strrchr($k, ':'), 1)) { if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
$this->namespaces[$ns_prefix] = $v; $this->namespaces[$ns_prefix] = $v;
} else { } else {
@ -346,7 +346,7 @@ class wsdl extends nusoap_base {
$attrs = array(); $attrs = array();
} }
// get element prefix, namespace and name // get element prefix, namespace and name
if (ereg(':', $name)) { if (preg_match('/:/', $name)) {
// get ns prefix // get ns prefix
$prefix = substr($name, 0, strpos($name, ':')); $prefix = substr($name, 0, strpos($name, ':'));
// get ns // get ns
@ -511,7 +511,7 @@ class wsdl extends nusoap_base {
*/ */
function end_element($parser, $name){ function end_element($parser, $name){
// unset schema status // unset schema status
if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) { if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
$this->status = ""; $this->status = "";
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();

View File

@ -199,7 +199,7 @@ class nusoap_xmlschema extends nusoap_base {
if(count($attrs) > 0){ if(count($attrs) > 0){
foreach($attrs as $k => $v){ foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if(ereg("^xmlns",$k)){ if(preg_match("/^xmlns/",$k)){
//$this->xdebug("$k: $v"); //$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k)); //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){ if($ns_prefix = substr(strrchr($k,':'),1)){
@ -311,7 +311,7 @@ class nusoap_xmlschema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
@ -331,7 +331,7 @@ class nusoap_xmlschema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
@ -741,7 +741,7 @@ class nusoap_xmlschema extends nusoap_base {
} elseif(isset($this->attributes[$type])){ } elseif(isset($this->attributes[$type])){
$this->xdebug("in getTypeDef, found attribute $type"); $this->xdebug("in getTypeDef, found attribute $type");
return $this->attributes[$type]; return $this->attributes[$type];
} elseif (ereg('_ContainedType$', $type)) { } elseif (preg_match('/_ContainedType$/', $type)) {
$this->xdebug("in getTypeDef, have an untyped element $type"); $this->xdebug("in getTypeDef, have an untyped element $type");
$typeDef['typeClass'] = 'simpleType'; $typeDef['typeClass'] = 'simpleType';
$typeDef['phpType'] = 'scalar'; $typeDef['phpType'] = 'scalar';

View File

@ -562,7 +562,7 @@ class nusoap_base {
case (is_array($val) || $type): case (is_array($val) || $type):
// detect if struct or array // detect if struct or array
$valueType = $this->isArraySimpleOrStruct($val); $valueType = $this->isArraySimpleOrStruct($val);
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){ if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
$this->debug("serialize_val: serialize array"); $this->debug("serialize_val: serialize array");
$i = 0; $i = 0;
if(is_array($val) && count($val)> 0){ if(is_array($val) && count($val)> 0){
@ -765,7 +765,7 @@ class nusoap_base {
*/ */
function expandQname($qname){ function expandQname($qname){
// get element prefix // get element prefix
if(strpos($qname,':') && !ereg('^http://',$qname)){ if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
// get unqualified name // get unqualified name
$name = substr(strstr($qname,':'),1); $name = substr(strstr($qname,':'),1);
// get ns prefix // get ns prefix
@ -905,16 +905,16 @@ function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp); $datestr = date('Y-m-d\TH:i:sO',$timestamp);
if($utc){ if($utc){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
} }
return false; return false;
@ -931,15 +931,15 @@ function timestamp_to_iso8601($timestamp,$utc=true){
*/ */
function iso8601_to_timestamp($datestr){ function iso8601_to_timestamp($datestr){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
// not utc // not utc
if($regs[8] != 'Z'){ if($regs[8] != 'Z'){
$op = substr($regs[8],0,1); $op = substr($regs[8],0,1);
@ -1267,7 +1267,7 @@ class nusoap_xmlschema extends nusoap_base {
if(count($attrs) > 0){ if(count($attrs) > 0){
foreach($attrs as $k => $v){ foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if(ereg("^xmlns",$k)){ if(preg_match("/^xmlns/",$k)){
//$this->xdebug("$k: $v"); //$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k)); //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){ if($ns_prefix = substr(strrchr($k,':'),1)){
@ -1379,7 +1379,7 @@ class nusoap_xmlschema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
@ -1399,7 +1399,7 @@ class nusoap_xmlschema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
@ -1809,7 +1809,7 @@ class nusoap_xmlschema extends nusoap_base {
} elseif(isset($this->attributes[$type])){ } elseif(isset($this->attributes[$type])){
$this->xdebug("in getTypeDef, found attribute $type"); $this->xdebug("in getTypeDef, found attribute $type");
return $this->attributes[$type]; return $this->attributes[$type];
} elseif (ereg('_ContainedType$', $type)) { } elseif (preg_match('/_ContainedType$/', $type)) {
$this->xdebug("in getTypeDef, have an untyped element $type"); $this->xdebug("in getTypeDef, have an untyped element $type");
$typeDef['typeClass'] = 'simpleType'; $typeDef['typeClass'] = 'simpleType';
$typeDef['phpType'] = 'scalar'; $typeDef['phpType'] = 'scalar';
@ -2173,7 +2173,7 @@ class soap_transport_http extends nusoap_base {
$this->ch_options = $curl_options; $this->ch_options = $curl_options;
} }
$this->use_curl = $use_curl; $this->use_curl = $use_curl;
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')'); $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
} }
@ -2936,7 +2936,7 @@ class soap_transport_http extends nusoap_base {
} }
} }
// remove 100 headers // remove 100 headers
if (isset($lb) && ereg('^HTTP/1.1 100',$data)) { if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
unset($lb); unset($lb);
$data = ''; $data = '';
}// }//
@ -3102,7 +3102,7 @@ class soap_transport_http extends nusoap_base {
if ($data == '') { if ($data == '') {
// have nothing left; just remove 100 header(s) // have nothing left; just remove 100 header(s)
$data = $savedata; $data = $savedata;
while (ereg('^HTTP/1.1 100',$data)) { while (preg_match('/^HTTP\/1.1 100/',$data)) {
if ($pos = strpos($data,"\r\n\r\n")) { if ($pos = strpos($data,"\r\n\r\n")) {
$data = ltrim(substr($data,$pos)); $data = ltrim(substr($data,$pos));
} elseif($pos = strpos($data,"\n\n") ) { } elseif($pos = strpos($data,"\n\n") ) {
@ -3654,7 +3654,7 @@ class nusoap_server extends nusoap_base {
} }
$this->debug("In service, query string=$qs"); $this->debug("In service, query string=$qs");
if (ereg('wsdl', $qs) ){ if (preg_match('/wsdl/', $qs) ){
$this->debug("In service, this is a request for WSDL"); $this->debug("In service, this is a request for WSDL");
if($this->externalWSDLURL){ if($this->externalWSDLURL){
if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
@ -4126,7 +4126,7 @@ class nusoap_server extends nusoap_base {
$payload .= $this->getDebugAsXMLComment(); $payload .= $this->getDebugAsXMLComment();
} }
$this->outgoing_headers[] = "Server: $this->title Server v$this->version"; $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
// Let the Web server decide about this // Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n"; //$this->outgoing_headers[] = "Connection: Close\r\n";
@ -4781,7 +4781,7 @@ class wsdl extends nusoap_base {
$this->currentSchema->schemaStartElement($parser, $name, $attrs); $this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
} elseif (ereg('schema$', $name)) { } elseif (preg_match('/schema$/', $name)) {
$this->debug('Parsing WSDL schema'); $this->debug('Parsing WSDL schema');
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
$this->status = 'schema'; $this->status = 'schema';
@ -4800,7 +4800,7 @@ class wsdl extends nusoap_base {
if (count($attrs) > 0) { if (count($attrs) > 0) {
// register namespace declarations // register namespace declarations
foreach($attrs as $k => $v) { foreach($attrs as $k => $v) {
if (ereg("^xmlns", $k)) { if (preg_match("/^xmlns/", $k)) {
if ($ns_prefix = substr(strrchr($k, ':'), 1)) { if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
$this->namespaces[$ns_prefix] = $v; $this->namespaces[$ns_prefix] = $v;
} else { } else {
@ -4825,7 +4825,7 @@ class wsdl extends nusoap_base {
$attrs = array(); $attrs = array();
} }
// get element prefix, namespace and name // get element prefix, namespace and name
if (ereg(':', $name)) { if (preg_match('/:/', $name)) {
// get ns prefix // get ns prefix
$prefix = substr($name, 0, strpos($name, ':')); $prefix = substr($name, 0, strpos($name, ':'));
// get ns // get ns
@ -4990,7 +4990,7 @@ class wsdl extends nusoap_base {
*/ */
function end_element($parser, $name){ function end_element($parser, $name){
// unset schema status // unset schema status
if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) { if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
$this->status = ""; $this->status = "";
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
@ -6587,7 +6587,7 @@ class nusoap_parser extends nusoap_base {
$key_localpart = $this->getLocalPart($key); $key_localpart = $this->getLocalPart($key);
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if($key_prefix == 'xmlns'){ if($key_prefix == 'xmlns'){
if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){ if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
$this->XMLSchemaVersion = $value; $this->XMLSchemaVersion = $value;
$this->namespaces['xsd'] = $this->XMLSchemaVersion; $this->namespaces['xsd'] = $this->XMLSchemaVersion;
$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
@ -6623,8 +6623,8 @@ class nusoap_parser extends nusoap_base {
[5] length ::= nextDimension* Digit+ [5] length ::= nextDimension* Digit+
[6] nextDimension ::= Digit+ ',' [6] nextDimension ::= Digit+ ','
*/ */
$expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]'; $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
if(ereg($expr,$value,$regs)){ if(preg_match($expr,$value,$regs)){
$this->message[$pos]['typePrefix'] = $regs[1]; $this->message[$pos]['typePrefix'] = $regs[1];
$this->message[$pos]['arrayTypePrefix'] = $regs[1]; $this->message[$pos]['arrayTypePrefix'] = $regs[1];
if (isset($this->namespaces[$regs[1]])) { if (isset($this->namespaces[$regs[1]])) {
@ -7422,7 +7422,7 @@ class nusoap_client extends nusoap_base {
// detect transport // detect transport
switch(true){ switch(true){
// http(s) // http(s)
case ereg('^http',$this->endpoint): case preg_match('/^http/',$this->endpoint):
$this->debug('transporting via HTTP'); $this->debug('transporting via HTTP');
if($this->persistentConnection == true && is_object($this->persistentConnection)){ if($this->persistentConnection == true && is_object($this->persistentConnection)){
$http =& $this->persistentConnection; $http =& $this->persistentConnection;
@ -7444,10 +7444,10 @@ class nusoap_client extends nusoap_base {
$http->setEncoding($this->http_encoding); $http->setEncoding($this->http_encoding);
} }
$this->debug('sending message, length='.strlen($msg)); $this->debug('sending message, length='.strlen($msg));
if(ereg('^http:',$this->endpoint)){ if(preg_match('/^http:/',$this->endpoint)){
//if(strpos($this->endpoint,'http:')){ //if(strpos($this->endpoint,'http:')){
$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
} elseif(ereg('^https',$this->endpoint)){ } elseif(preg_match('/^https/',$this->endpoint)){
//} elseif(strpos($this->endpoint,'https:')){ //} elseif(strpos($this->endpoint,'https:')){
//if(phpversion() == '4.3.0-dev'){ //if(phpversion() == '4.3.0-dev'){
//$response = $http->send($msg,$timeout,$response_timeout); //$response = $http->send($msg,$timeout,$response_timeout);

View File

@ -1128,7 +1128,7 @@ function _match($token)
default: default:
// if it's a reference // if it's a reference
if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and
!ereg("[0-9]",$this->_lookahead) and !preg_match("/[0-9]/",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.') and ($this->_lookahead != ':') and ($this->_lookahead != '.') and
($this->_lookahead != '!')) ($this->_lookahead != '!'))
{ {
@ -1136,32 +1136,32 @@ function _match($token)
} }
// If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1) // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1)
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z][0-9]+$/",$token) and elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\![A-Ia-i]?[A-Za-z][0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead) and !preg_match("/[0-9]/",$this->_lookahead) and
($this->_lookahead != ':') and ($this->_lookahead != '.')) ($this->_lookahead != ':') and ($this->_lookahead != '.'))
{ {
return $token; return $token;
} }
// if it's a range (A1:A2) // if it's a range (A1:A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead)) !preg_match("/[0-9]/",$this->_lookahead))
{ {
return $token; return $token;
} }
// if it's a range (A1..A2) // if it's a range (A1..A2)
elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and elseif (preg_match("/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead)) !preg_match("/[0-9]/",$this->_lookahead))
{ {
return $token; return $token;
} }
// If it's an external range like Sheet1:Sheet2!A1:B2 // If it's an external range like Sheet1:Sheet2!A1:B2
elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and elseif (preg_match("/^[A-Za-z0-9_]+(\:[A-Za-z0-9_]+)?\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead)) !preg_match("/[0-9]/",$this->_lookahead))
{ {
return $token; return $token;
} }
// If it's an external range like 'Sheet1:Sheet2'!A1:B2 // If it's an external range like 'Sheet1:Sheet2'!A1:B2
elseif (preg_match("/^'[A-Za-z0-9_ ]+(\:[A-Za-z0-9_ ]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and elseif (preg_match("/^'[A-Za-z0-9_ ]+(\:[A-Za-z0-9_ ]+)?'\!([A-Ia-i]?[A-Za-z])?[0-9]+:([A-Ia-i]?[A-Za-z])?[0-9]+$/",$token) and
!ereg("[0-9]",$this->_lookahead)) !preg_match("/[0-9]/",$this->_lookahead))
{ {
return $token; return $token;
} }
@ -1173,12 +1173,12 @@ function _match($token)
return $token; return $token;
} }
// If it's a string (of maximum 255 characters) // If it's a string (of maximum 255 characters)
elseif (ereg("^\"[^\"]{0,255}\"$",$token)) elseif (preg_match("/^\"[^\"]{0,255}\"$/",$token))
{ {
return $token; return $token;
} }
// if it's a function call // if it's a function call
elseif (eregi("^[A-Z0-9\xc0-\xdc\.]+$",$token) and ($this->_lookahead == "(")) { elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) {
return $token; return $token;
} }
return ''; return '';
@ -1283,7 +1283,7 @@ function _condition()
function _expression() function _expression()
{ {
// If it's a string return a string node // If it's a string return a string node
if (ereg("^\"[^\"]{0,255}\"$", $this->_current_token)) if (preg_match("/^\"[^\"]{0,255}\"$/", $this->_current_token))
{ {
$result = $this->_createTree($this->_current_token, '', ''); $result = $this->_createTree($this->_current_token, '', '');
$this->_advance(); $this->_advance();

View File

@ -436,3 +436,149 @@
- soap_server: when generating a fault while debug_flag is true, put debug into faultdetail - soap_server: when generating a fault while debug_flag is true, put debug into faultdetail
- wsdl: add enumeration parameter to addSimpleType - wsdl: add enumeration parameter to addSimpleType
- xmlschema: 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é 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 License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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: If you have any questions or comments, please email:
Dietrich Ayala 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 /* load classes
// necessary classes // necessary classes
@ -59,6 +79,7 @@ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
* nusoap_base * nusoap_base
* *
* @author Dietrich Ayala <dietrich@ganx4.com> * @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
@ -76,7 +97,7 @@ class nusoap_base {
* @var string * @var string
* @access private * @access private
*/ */
var $version = '0.7.2'; var $version = '0.7.3';
/** /**
* CVS revision for HTTP headers. * 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) * XML Schema types in an array of uri => (array of xml type => php type)
* is this legacy yet? * 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 * @var array
* @access public * @access public
*/ */
@ -308,7 +329,8 @@ class nusoap_base {
while (strpos($this->debug_str, '--')) { while (strpos($this->debug_str, '--')) {
$this->debug_str = str_replace('--', '- -', $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 string $type_ns The namespace for the type of the element
* @param array $attributes The attributes to serialize as name=>value pairs * @param array $attributes The attributes to serialize as name=>value pairs
* @param string $use The WSDL "use" (encoded|literal) * @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 * @return string The serialized element, possibly with child elements
* @access public * @access public
*/ */
function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded'){ 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"); $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('value=' . $this->varDump($val));
$this->appendDebug('attributes=' . $this->varDump($attributes)); $this->appendDebug('attributes=' . $this->varDump($attributes));
if(is_object($val) && get_class($val) == 'soapval'){ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
return $val->serialize($use); $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 // force valid name if necessary
if (is_numeric($name)) { if (is_numeric($name)) {
@ -421,20 +449,26 @@ class nusoap_base {
} }
// serialize null value // serialize null value
if (is_null($val)) { if (is_null($val)) {
$this->debug("serialize_val: serialize null");
if ($use == 'literal') { if ($use == 'literal') {
// TODO: depends on minOccurs // TODO: depends on minOccurs
return "<$name$xmlns $atts/>"; $xml = "<$name$xmlns$atts/>";
$this->debug("serialize_val returning $xml");
return $xml;
} else { } else {
if (isset($type) && isset($type_prefix)) { if (isset($type) && isset($type_prefix)) {
$type_str = " xsi:type=\"$type_prefix:$type\""; $type_str = " xsi:type=\"$type_prefix:$type\"";
} else { } else {
$type_str = ''; $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 // serialize if an xsd built-in primitive type
if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
$this->debug("serialize_val: serialize xsd built-in primitive type");
if (is_bool($val)) { if (is_bool($val)) {
if ($type == 'boolean') { if ($type == 'boolean') {
$val = $val ? 'true' : 'false'; $val = $val ? 'true' : 'false';
@ -445,65 +479,91 @@ class nusoap_base {
$val = $this->expandEntities($val); $val = $this->expandEntities($val);
} }
if ($use == 'literal') { if ($use == 'literal') {
return "<$name$xmlns $atts>$val</$name>"; $xml = "<$name$xmlns$atts>$val</$name>";
$this->debug("serialize_val returning $xml");
return $xml;
} else { } 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 // detect type and serialize
$xml = ''; $xml = '';
switch(true) { switch(true) {
case (is_bool($val) || $type == 'boolean'): case (is_bool($val) || $type == 'boolean'):
$this->debug("serialize_val: serialize boolean");
if ($type == 'boolean') { if ($type == 'boolean') {
$val = $val ? 'true' : 'false'; $val = $val ? 'true' : 'false';
} elseif (! $val) { } elseif (! $val) {
$val = 0; $val = 0;
} }
if ($use == 'literal') { if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>"; $xml .= "<$name$xmlns$atts>$val</$name>";
} else { } else {
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>"; $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
} }
break; break;
case (is_int($val) || is_long($val) || $type == 'int'): case (is_int($val) || is_long($val) || $type == 'int'):
$this->debug("serialize_val: serialize int");
if ($use == 'literal') { if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>"; $xml .= "<$name$xmlns$atts>$val</$name>";
} else { } else {
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>"; $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
} }
break; break;
case (is_float($val)|| is_double($val) || $type == 'float'): case (is_float($val)|| is_double($val) || $type == 'float'):
$this->debug("serialize_val: serialize float");
if ($use == 'literal') { if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>"; $xml .= "<$name$xmlns$atts>$val</$name>";
} else { } else {
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>"; $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
} }
break; break;
case (is_string($val) || $type == 'string'): case (is_string($val) || $type == 'string'):
$this->debug("serialize_val: serialize string");
$val = $this->expandEntities($val); $val = $this->expandEntities($val);
if ($use == 'literal') { if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>$val</$name>"; $xml .= "<$name$xmlns$atts>$val</$name>";
} else { } else {
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>"; $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
} }
break; break;
case is_object($val): case is_object($val):
if (! $name) { $this->debug("serialize_val: serialize object");
$name = get_class($val); if (get_class($val) == 'soapval') {
$this->debug("In serialize_val, used class name $name as element name"); $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 { } 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){ if ($use == 'literal') {
$pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use); $xml .= "<$name$xmlns$atts>$pXml</$name>";
} else {
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
} }
$xml .= '<'.$name.'>'.$pXml.'</'.$name.'>';
break; break;
break; break;
case (is_array($val) || $type): case (is_array($val) || $type):
// detect if struct or array // detect if struct or array
$valueType = $this->isArraySimpleOrStruct($val); $valueType = $this->isArraySimpleOrStruct($val);
if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){ if($valueType=='arraySimple' || preg_match('/^ArrayOf/',$type)){
$this->debug("serialize_val: serialize array");
$i = 0; $i = 0;
if(is_array($val) && count($val)> 0){ if(is_array($val) && count($val)> 0){
foreach($val as $v){ foreach($val as $v){
@ -565,13 +625,14 @@ class nusoap_base {
$xml = "<$name$xmlns$type_str$atts>".$xml."</$name>"; $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
} else { } else {
// got a struct // got a struct
$this->debug("serialize_val: serialize struct");
if(isset($type) && isset($type_prefix)){ if(isset($type) && isset($type_prefix)){
$type_str = " xsi:type=\"$type_prefix:$type\""; $type_str = " xsi:type=\"$type_prefix:$type\"";
} else { } else {
$type_str = ''; $type_str = '';
} }
if ($use == 'literal') { if ($use == 'literal') {
$xml .= "<$name$xmlns $atts>"; $xml .= "<$name$xmlns$atts>";
} else { } else {
$xml .= "<$name$xmlns$type_str$atts>"; $xml .= "<$name$xmlns$type_str$atts>";
} }
@ -590,9 +651,11 @@ class nusoap_base {
} }
break; break;
default: default:
$this->debug("serialize_val: serialize unknown");
$xml .= 'not detected, got '.gettype($val).' for '.$val; $xml .= 'not detected, got '.gettype($val).' for '.$val;
break; break;
} }
$this->debug("serialize_val returning $xml");
return $xml; return $xml;
} }
@ -600,7 +663,7 @@ class nusoap_base {
* serializes a message * serializes a message
* *
* @param string $body the XML of the SOAP body * @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 array $namespaces optional the namespaces used in generating the body and headers
* @param string $style optional (rpc|document) * @param string $style optional (rpc|document)
* @param string $use optional (encoded|literal) * @param string $use optional (encoded|literal)
@ -632,11 +695,15 @@ class nusoap_base {
if($headers){ if($headers){
if (is_array($headers)) { if (is_array($headers)) {
$xml = ''; $xml = '';
foreach ($headers as $header) { foreach ($headers as $k => $v) {
$xml .= $this->serialize_val($header, false, false, false, false, false, $use); 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; $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>"; $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
} }
@ -692,13 +759,13 @@ class nusoap_base {
/** /**
* expands (changes prefix to namespace) a qualified name * expands (changes prefix to namespace) a qualified name
* *
* @param string $string qname * @param string $qname qname
* @return string expanded qname * @return string expanded qname
* @access private * @access private
*/ */
function expandQname($qname){ function expandQname($qname){
// get element prefix // get element prefix
if(strpos($qname,':') && !ereg('^http://',$qname)){ if(strpos($qname,':') && !preg_match('/^http:\/\//',$qname)){
// get unqualified name // get unqualified name
$name = substr(strstr($qname,':'),1); $name = substr(strstr($qname,':'),1);
// get ns prefix // get ns prefix
@ -811,6 +878,16 @@ class nusoap_base {
ob_end_clean(); ob_end_clean();
return $ret_val; return $ret_val;
} }
/**
* represents the object as a string
*
* @return string
* @access public
*/
function __toString() {
return $this->varDump($this);
}
} }
// XML Schema Datatype Helper Functions // XML Schema Datatype Helper Functions
@ -821,22 +898,23 @@ class nusoap_base {
* convert unix timestamp to ISO 8601 compliant date string * convert unix timestamp to ISO 8601 compliant date string
* *
* @param string $timestamp Unix time stamp * @param string $timestamp Unix time stamp
* @param boolean $utc Whether the time stamp is UTC or local
* @access public * @access public
*/ */
function timestamp_to_iso8601($timestamp,$utc=true){ function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp); $datestr = date('Y-m-d\TH:i:sO',$timestamp);
if($utc){ if($utc){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]); return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
} }
return false; return false;
@ -853,15 +931,15 @@ function timestamp_to_iso8601($timestamp,$utc=true){
*/ */
function iso8601_to_timestamp($datestr){ function iso8601_to_timestamp($datestr){
$eregStr = $eregStr =
'([0-9]{4})-'. // centuries & years CCYY- '/([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM- '([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD '([0-9]{2})'. // days DD
'T'. // separator T 'T'. // separator T
'([0-9]{2}):'. // hours hh: '([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm: '([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss... '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
'(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's '(Z|[+\-][0-9]{2}:?[0-9]{2})?/'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
if(ereg($eregStr,$datestr,$regs)){ if(preg_match($eregStr,$datestr,$regs)){
// not utc // not utc
if($regs[8] != 'Z'){ if($regs[8] != 'Z'){
$op = substr($regs[8],0,1); $op = substr($regs[8],0,1);
@ -875,7 +953,8 @@ function iso8601_to_timestamp($datestr){
$regs[5] = $regs[5] - $m; $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 { } else {
return false; return false;
} }

View File

@ -11,7 +11,7 @@
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class soap_fault extends nusoap_base { class nusoap_fault extends nusoap_base {
/** /**
* The fault code (client|server) * The fault code (client|server)
* @var string * @var string
@ -40,12 +40,12 @@ class soap_fault extends nusoap_base {
/** /**
* constructor * 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 $faultactor only used when msg routed between multiple actors
* @param string $faultstring human readable error message * @param string $faultstring human readable error message
* @param mixed $faultdetail detail, typically a string or array of string * @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(); parent::nusoap_base();
$this->faultcode = $faultcode; $this->faultcode = $faultcode;
$this->faultactor = $faultactor; $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 Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class soap_parser extends nusoap_base { class nusoap_parser extends nusoap_base {
var $xml = ''; var $xml = '';
var $xml_encoding = ''; var $xml_encoding = '';
@ -35,7 +36,8 @@ class soap_parser extends nusoap_base {
var $fault_detail = ''; var $fault_detail = '';
var $depth_array = array(); var $depth_array = array();
var $debug_flag = true; 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 $responseHeaders = ''; // incoming SOAP headers (text)
var $body_position = 0; var $body_position = 0;
// for multiref parsing: // 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 * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
* @access public * @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(); parent::nusoap_base();
$this->xml = $xml; $this->xml = $xml;
$this->xml_encoding = $encoding; $this->xml_encoding = $encoding;
@ -87,7 +89,7 @@ class soap_parser extends nusoap_base {
} else { } else {
$this->debug('No XML declaration'); $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? // Create an XML parser - why not xml_parser_create_ns?
$this->parser = xml_parser_create($this->xml_encoding); $this->parser = xml_parser_create($this->xml_encoding);
// Set the options for parsing the XML data. // 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); $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
// get final value // get final value
$this->soapresponse = $this->message[$this->root_struct]['result']; $this->soapresponse = $this->message[$this->root_struct]['result'];
// get header value: no, because this is documented as XML string // get header value
// if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
// $this->responseHeaders = $this->message[$this->root_header]['result']; $this->soapheader = $this->message[$this->root_header]['result'];
// } }
// resolve hrefs/ids // resolve hrefs/ids
if(sizeof($this->multirefs) > 0){ if(sizeof($this->multirefs) > 0){
foreach($this->multirefs as $id => $hrefs){ foreach($this->multirefs as $id => $hrefs){
@ -177,10 +179,10 @@ class soap_parser extends nusoap_base {
// set status // set status
if($name == 'Envelope'){ if($name == 'Envelope'){
$this->status = 'envelope'; $this->status = 'envelope';
} elseif($name == 'Header'){ } elseif($name == 'Header' && $this->status = 'envelope'){
$this->root_header = $pos; $this->root_header = $pos;
$this->status = 'header'; $this->status = 'header';
} elseif($name == 'Body'){ } elseif($name == 'Body' && $this->status = 'envelope'){
$this->status = 'body'; $this->status = 'body';
$this->body_position = $pos; $this->body_position = $pos;
// set method // set method
@ -205,7 +207,7 @@ class soap_parser extends nusoap_base {
$key_localpart = $this->getLocalPart($key); $key_localpart = $this->getLocalPart($key);
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if($key_prefix == 'xmlns'){ if($key_prefix == 'xmlns'){
if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){ if(preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/',$value)){
$this->XMLSchemaVersion = $value; $this->XMLSchemaVersion = $value;
$this->namespaces['xsd'] = $this->XMLSchemaVersion; $this->namespaces['xsd'] = $this->XMLSchemaVersion;
$this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance'; $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
@ -216,17 +218,21 @@ class soap_parser extends nusoap_base {
$this->methodNamespace = $value; $this->methodNamespace = $value;
} }
// if it's a type declaration, set type // if it's a type declaration, set type
} elseif($key_localpart == 'type'){ } elseif($key_localpart == 'type'){
$value_prefix = $this->getPrefix($value); if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
$value_localpart = $this->getLocalPart($value); // do nothing: already processed arrayType
$this->message[$pos]['type'] = $value_localpart; } else {
$this->message[$pos]['typePrefix'] = $value_prefix; $value_prefix = $this->getPrefix($value);
if(isset($this->namespaces[$value_prefix])){ $value_localpart = $this->getLocalPart($value);
$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix]; $this->message[$pos]['type'] = $value_localpart;
} else if(isset($attrs['xmlns:'.$value_prefix])) { $this->message[$pos]['typePrefix'] = $value_prefix;
$this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix]; if(isset($this->namespaces[$value_prefix])){
} $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
// should do something here with the namespace of specified type? } 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'){ } elseif($key_localpart == 'arrayType'){
$this->message[$pos]['type'] = 'array'; $this->message[$pos]['type'] = 'array';
/* do arrayType ereg here /* do arrayType ereg here
@ -237,8 +243,8 @@ class soap_parser extends nusoap_base {
[5] length ::= nextDimension* Digit+ [5] length ::= nextDimension* Digit+
[6] nextDimension ::= Digit+ ',' [6] nextDimension ::= Digit+ ','
*/ */
$expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]'; $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
if(ereg($expr,$value,$regs)){ if(preg_match($expr,$value,$regs)){
$this->message[$pos]['typePrefix'] = $regs[1]; $this->message[$pos]['typePrefix'] = $regs[1];
$this->message[$pos]['arrayTypePrefix'] = $regs[1]; $this->message[$pos]['arrayTypePrefix'] = $regs[1];
if (isset($this->namespaces[$regs[1]])) { if (isset($this->namespaces[$regs[1]])) {
@ -422,19 +428,40 @@ class soap_parser extends nusoap_base {
} }
/** /**
* get the parsed message * get the parsed message (SOAP Body)
* *
* @return mixed * @return mixed
* @access public * @access public
* @deprecated use get_soapbody instead
*/ */
function get_response(){ function get_response(){
return $this->soapresponse; 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 * @access public
*/ */
function getHeaders(){ function getHeaders(){
@ -534,7 +561,7 @@ class soap_parser extends nusoap_base {
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') { //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
} else { } else {
// Apache Vector type: treat as an array // 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') { if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
$notstruct = 1; $notstruct = 1;
} else { } 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 { } else {
$this->debug('in buildVal, no children, building scalar'); $this->debug('in buildVal, no children, building scalar');
$cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : ''; $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
if (isset($this->message[$pos]['type'])) { 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']; $parent = $this->message[$pos]['parent'];
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) { 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 * that is capable of receiving messages and returning responses
* *
* NOTE: WSDL functionality is experimental
*
* @author Dietrich Ayala <dietrich@ganx4.com> * @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class soap_server extends nusoap_base { class nusoap_server extends nusoap_base {
/** /**
* HTTP headers of request * HTTP headers of request
* @var array * @var array
@ -33,6 +32,12 @@ class soap_server extends nusoap_base {
* @access public * @access public
*/ */
var $requestHeaders = ''; 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) * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
* @var string * @var string
@ -95,8 +100,8 @@ class soap_server extends nusoap_base {
*/ */
var $response = ''; var $response = '';
/** /**
* SOAP headers for response (text) * SOAP headers for response (text or array of soapval or associative array)
* @var string * @var mixed
* @access public * @access public
*/ */
var $responseHeaders = ''; var $responseHeaders = '';
@ -165,7 +170,7 @@ class soap_server extends nusoap_base {
* @param mixed $wsdl file path or URL (string), or wsdl instance (object) * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
* @access public * @access public
*/ */
function soap_server($wsdl=false){ function nusoap_server($wsdl=false){
parent::nusoap_base(); parent::nusoap_base();
// turn on debugging? // turn on debugging?
global $debug; global $debug;
@ -182,13 +187,13 @@ class soap_server extends nusoap_base {
} }
if (isset($debug)) { 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; $this->debug_flag = $debug;
} elseif (isset($_SERVER['QUERY_STRING'])) { } elseif (isset($_SERVER['QUERY_STRING'])) {
$qs = explode('&', $_SERVER['QUERY_STRING']); $qs = explode('&', $_SERVER['QUERY_STRING']);
foreach ($qs as $v) { foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') { 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); $this->debug_flag = substr($v, 6);
} }
} }
@ -196,7 +201,7 @@ class soap_server extends nusoap_base {
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
foreach ($qs as $v) { foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') { 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); $this->debug_flag = substr($v, 6);
} }
} }
@ -204,7 +209,7 @@ class soap_server extends nusoap_base {
// wsdl // wsdl
if($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')) { if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
$this->wsdl = $wsdl; $this->wsdl = $wsdl;
$this->externalWSDLURL = $this->wsdl->wsdl; $this->externalWSDLURL = $this->wsdl->wsdl;
@ -240,7 +245,7 @@ class soap_server extends nusoap_base {
} }
$this->debug("In service, query string=$qs"); $this->debug("In service, query string=$qs");
if (ereg('wsdl', $qs) ){ if (preg_match('/wsdl/', $qs) ){
$this->debug("In service, this is a request for WSDL"); $this->debug("In service, this is a request for WSDL");
if($this->externalWSDLURL){ if($this->externalWSDLURL){
if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
@ -324,9 +329,9 @@ class soap_server extends nusoap_base {
$this->debug("In parse_http_headers, use _SERVER"); $this->debug("In parse_http_headers, use _SERVER");
foreach ($_SERVER as $k => $v) { foreach ($_SERVER as $k => $v) {
if (substr($k, 0, 5) == 'HTTP_') { 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 { } else {
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
} }
if ($k == 'soapaction') { if ($k == 'soapaction') {
// get SOAPAction header // get SOAPAction header
@ -431,11 +436,11 @@ class soap_server extends nusoap_base {
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
$data = $degzdata; $data = $degzdata;
} else { } 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; return;
} }
} else { } else {
$this->fault('Client', 'This Server does not support compressed data'); $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
return; return;
} }
} }
@ -477,7 +482,7 @@ class soap_server extends nusoap_base {
$this->methodname = $this->opData['name']; $this->methodname = $this->opData['name'];
} else { } else {
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); $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; return;
} }
} else { } else {
@ -510,7 +515,7 @@ class soap_server extends nusoap_base {
if (!function_exists($this->methodname)) { if (!function_exists($this->methodname)) {
$this->debug("in invoke_method, function '$this->methodname' not found!"); $this->debug("in invoke_method, function '$this->methodname' not found!");
$this->result = 'fault: method 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; return;
} }
} else { } else {
@ -518,7 +523,7 @@ class soap_server extends nusoap_base {
if (!in_array($method_to_compare, get_class_methods($class))) { if (!in_array($method_to_compare, get_class_methods($class))) {
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
$this->result = 'fault: method 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; return;
} }
} }
@ -530,7 +535,7 @@ class soap_server extends nusoap_base {
$this->debug('ERROR: request not verified against method signature'); $this->debug('ERROR: request not verified against method signature');
$this->result = 'fault: request failed validation against method signature'; $this->result = 'fault: request failed validation against method signature';
// return fault // 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; return;
} }
@ -556,8 +561,8 @@ class soap_server extends nusoap_base {
} }
if ($this->methodparams) { if ($this->methodparams) {
foreach ($this->methodparams as $param) { foreach ($this->methodparams as $param) {
if (is_array($param)) { if (is_array($param) || is_object($param)) {
$this->fault('Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
return; return;
} }
$funcCall .= "\"$param\","; $funcCall .= "\"$param\",";
@ -579,11 +584,15 @@ class soap_server extends nusoap_base {
$instance = new $class (); $instance = new $class ();
$call_arg = array(&$instance, $method); $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->debug('in invoke_method, methodreturn:');
$this->appendDebug($this->varDump($this->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() { function serialize_return() {
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
// if fault // 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->debug('got a fault object from method');
$this->fault = $this->methodreturn; $this->fault = $this->methodreturn;
return; return;
@ -611,11 +620,15 @@ class soap_server extends nusoap_base {
$this->debug('got a(n) '.gettype($this->methodreturn).' from method'); $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
$this->debug('serializing return value'); $this->debug('serializing return value');
if($this->wsdl){ 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; $opParams = $this->methodreturn;
} else { } elseif (sizeof($this->opData['output']['parts']) == 1) {
// TODO: is this really necessary? $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); $opParams = array($this->methodreturn);
} }
$return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
@ -623,7 +636,7 @@ class soap_server extends nusoap_base {
$this->wsdl->clearDebug(); $this->wsdl->clearDebug();
if($errstr = $this->wsdl->getError()){ if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr); $this->debug('got wsdl error: '.$errstr);
$this->fault('Server', 'unable to serialize result'); $this->fault('SOAP-ENV:Server', 'unable to serialize result');
return; return;
} }
} else { } else {
@ -644,7 +657,8 @@ class soap_server extends nusoap_base {
if ($this->opData['style'] == 'rpc') { if ($this->opData['style'] == 'rpc') {
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
if ($this->opData['output']['use'] == 'literal') { 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 { } else {
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; $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 = ''; $encodingStyle = '';
} }
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. // 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 { } else {
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
} }
@ -703,7 +717,7 @@ class soap_server extends nusoap_base {
$payload .= $this->getDebugAsXMLComment(); $payload .= $this->getDebugAsXMLComment();
} }
$this->outgoing_headers[] = "Server: $this->title Server v$this->version"; $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
// Let the Web server decide about this // Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n"; //$this->outgoing_headers[] = "Connection: Close\r\n";
@ -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 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-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 // 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 // parser debug
$this->debug("parser debug: \n".$parser->getDebug()); $this->debug("parser debug: \n".$parser->getDebug());
// if fault occurred during message parsing // if fault occurred during message parsing
if($err = $parser->getError()){ if($err = $parser->getError()){
$this->result = 'fault: error in msg parsing: '.$err; $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 successfully parsed request into soapval object
} else { } else {
// get/set methodname // get/set methodname
$this->methodURI = $parser->root_struct_namespace; $this->methodURI = $parser->root_struct_namespace;
$this->methodname = $parser->root_struct_name; $this->methodname = $parser->root_struct_name;
$this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
$this->debug('calling parser->get_response()'); $this->debug('calling parser->get_soapbody()');
$this->methodparams = $parser->get_response(); $this->methodparams = $parser->get_soapbody();
// get SOAP headers // get SOAP headers
$this->requestHeaders = $parser->getHeaders(); $this->requestHeaders = $parser->getHeaders();
// get SOAP Header
$this->requestHeader = $parser->get_soapheader();
// add document for doclit support // add document for doclit support
$this->document = $parser->document; $this->document = $parser->document;
} }
@ -908,13 +924,20 @@ class soap_server extends nusoap_base {
if (isset($_SERVER)) { if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME']; $SERVER_NAME = $_SERVER['SERVER_NAME'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_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)) { } elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; $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']; $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 { } else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); $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) { if(false == $style) {
$style = "rpc"; $style = "rpc";
@ -953,7 +976,7 @@ class soap_server extends nusoap_base {
if ($faultdetail == '' && $this->debug_flag) { if ($faultdetail == '' && $this->debug_flag) {
$faultdetail = $this->getDebug(); $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; $this->fault->soap_defencoding = $this->soap_defencoding;
} }
@ -976,15 +999,20 @@ class soap_server extends nusoap_base {
$SERVER_NAME = $_SERVER['SERVER_NAME']; $SERVER_NAME = $_SERVER['SERVER_NAME'];
$SERVER_PORT = $_SERVER['SERVER_PORT']; $SERVER_PORT = $_SERVER['SERVER_PORT'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; $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)) { } elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; $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']; $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 { } else {
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); $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) { if ($SERVER_PORT == 80) {
$SERVER_PORT = ''; $SERVER_PORT = '';
} else { } else {
@ -1016,7 +1044,10 @@ class soap_server extends nusoap_base {
if ($schemaTargetNamespace != $namespace) { if ($schemaTargetNamespace != $namespace) {
$this->wsdl->namespaces['types'] = $schemaTargetNamespace; $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]->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/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); $this->wsdl->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 * NOTE: PHP must be compiled with the CURL extension for HTTPS support
* *
* @author Dietrich Ayala <dietrich@ganx4.com> * @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
@ -28,38 +29,97 @@ class soap_transport_http extends nusoap_base {
var $incoming_cookies = array(); var $incoming_cookies = array();
var $outgoing_payload = ''; var $outgoing_payload = '';
var $incoming_payload = ''; var $incoming_payload = '';
var $response_status_line; // HTTP response status line
var $useSOAPAction = true; var $useSOAPAction = true;
var $persistentConnection = false; var $persistentConnection = false;
var $ch = false; // cURL handle 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 $username = '';
var $password = ''; var $password = '';
var $authtype = ''; var $authtype = '';
var $digestRequest = array(); 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' // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem' // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem' // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
// passphrase: SSL key password/passphrase // passphrase: SSL key password/passphrase
// certpassword: SSL certificate password
// verifypeer: default is 1 // verifypeer: default is 1
// verifyhost: default is 1 // verifyhost: default is 1
/** /**
* constructor * 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(); parent::nusoap_base();
$this->debug("ctor url=$url use_curl=$use_curl curl_options:");
$this->appendDebug($this->varDump($curl_options));
$this->setURL($url); $this->setURL($url);
ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); if (is_array($curl_options)) {
$this->outgoing_headers['User-Agent'] = $this->title.'/'.$this->version.' ('.$rev[1].')'; $this->ch_options = $curl_options;
$this->debug('set User-Agent: ' . $this->outgoing_headers['User-Agent']); }
$this->use_curl = $use_curl;
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
} }
/**
* sets a cURL option
*
* @param mixed $option The cURL option (always integer?)
* @param mixed $value The cURL option value
* @access private
*/
function setCurlOption($option, $value) {
$this->debug("setCurlOption option=$option, value=");
$this->appendDebug($this->varDump($value));
curl_setopt($this->ch, $option, $value);
}
/**
* sets an HTTP header
*
* @param string $name The name of the header
* @param string $value The value of the header
* @access private
*/
function setHeader($name, $value) {
$this->outgoing_headers[$name] = $value;
$this->debug("set header $name: $value");
}
/**
* unsets an HTTP header
*
* @param string $name The name of the header
* @access private
*/
function unsetHeader($name) {
if (isset($this->outgoing_headers[$name])) {
$this->debug("unset header $name");
unset($this->outgoing_headers[$name]);
}
}
/**
* sets the URL to which to connect
*
* @param string $url The URL to which to connect
* @access private
*/
function setURL($url) { function setURL($url) {
$this->url = $url; $this->url = $url;
$u = parse_url($url); $u = parse_url($url);
foreach($u as $k => $v){ foreach($u as $k => $v){
$this->debug("$k = $v"); $this->debug("parsed URL $k = $v");
$this->$k = $v; $this->$k = $v;
} }
@ -82,17 +142,38 @@ class soap_transport_http extends nusoap_base {
// build headers // build headers
if (!isset($u['port'])) { if (!isset($u['port'])) {
$this->outgoing_headers['Host'] = $this->host; $this->setHeader('Host', $this->host);
} else { } 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'] != '') { if (isset($u['user']) && $u['user'] != '') {
$this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : ''); $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){ function connect($connection_timeout=0,$response_timeout=30){
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
// "regular" socket. // "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"); $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 // use persistent connection
if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
if (!feof($this->fp)) { if (!feof($this->fp)) {
@ -120,9 +209,7 @@ class soap_transport_http extends nusoap_base {
// munge host if using OpenSSL // munge host if using OpenSSL
if ($this->scheme == 'ssl') { if ($this->scheme == 'ssl') {
$host = 'ssl://' . $this->host; $host = 'ssl://' . $host;
} else {
$host = $this->host;
} }
$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout); $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'); $this->debug('socket connected');
return true; return true;
} else if ($this->scheme == 'https') { } else if ($this->io_method() == 'curl') {
if (!extension_loaded('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; 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 // init CURL
$this->ch = curl_init(); $this->ch = curl_init();
// set url // 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 // add path
$hostURL .= $this->path; $hostURL .= $this->path;
curl_setopt($this->ch, CURLOPT_URL, $hostURL); $this->setCurlOption(CURLOPT_URL, $hostURL);
// follow location headers (re-directs) // 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 // 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 // ask for the response output as the return value
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1); $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
// encode // encode
// We manage this ourselves through headers and encoding // We manage this ourselves through headers and encoding
// if(function_exists('gzuncompress')){ // if(function_exists('gzuncompress')){
// curl_setopt($this->ch, CURLOPT_ENCODING, 'deflate'); // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
// } // }
// persistent connection // persistent connection
if ($this->persistentConnection) { 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 // The way we send data, we cannot use persistent connections, since
// there will be some "junk" at the end of our request. // 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->persistentConnection = false;
$this->outgoing_headers['Connection'] = 'close'; $this->setHeader('Connection', 'close');
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
} }
// set timeout // set timeouts
if ($connection_timeout != 0) { 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, if ($this->scheme == 'https') {
// while PHP binaries are not compiled with a default location for the $this->debug('set cURL SSL verify options');
// CA cert bundle, so disable peer/host checking. // recent versions of cURL turn on peer/host checking by default,
//curl_setopt($this->ch, CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt'); // while PHP binaries are not compiled with a default location for the
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0); // CA cert bundle, so disable peer/host checking.
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0); //$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) // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
if ($this->authtype == 'certificate') { if ($this->authtype == 'certificate') {
if (isset($this->certRequest['cainfofile'])) { $this->debug('set cURL certificate options');
curl_setopt($this->ch, CURLOPT_CAINFO, $this->certRequest['cainfofile']); 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 { } else {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 1); $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
} }
if (isset($this->certRequest['verifyhost'])) { if ($this->proxy['username'] || $this->proxy['password']) {
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']); $this->debug('set cURL proxy authentication options');
} else { $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 1); if ($this->proxy['authtype'] == 'basic') {
} $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
if (isset($this->certRequest['sslcertfile'])) { }
curl_setopt($this->ch, CURLOPT_SSLCERT, $this->certRequest['sslcertfile']); if ($this->proxy['authtype'] == 'ntlm') {
} $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
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']);
} }
} }
$this->debug('cURL connection set up'); $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 string $data message data
* @param integer $timeout set connection timeout in seconds * @param integer $timeout set connection timeout in seconds
@ -270,7 +432,7 @@ class soap_transport_http extends nusoap_base {
// get response // get response
$respdata = $this->getResponse(); $respdata = $this->getResponse();
} else { } 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()'); $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 $timeout set connection timeout in seconds
* @param integer $response_timeout set response timeout in seconds * @param integer $response_timeout set response timeout in seconds
* @param array $cookies cookies to send * @param array $cookies cookies to send
* @return string data * @return string data
* @access public * @access public
* @deprecated
*/ */
function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) { function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
return $this->send($data, $timeout, $response_timeout, $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 $username
* @param string $password * @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 $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 * @access public
*/ */
function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) { 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 // cf. RFC 2617
if ($authtype == 'basic') { 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') { } elseif ($authtype == 'digest') {
if (isset($digestRequest['nonce'])) { if (isset($digestRequest['nonce'])) {
$digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1; $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
@ -320,7 +486,7 @@ class soap_transport_http extends nusoap_base {
$HA1 = md5($A1); $HA1 = md5($A1);
// A2 = Method ":" digest-uri-value // A2 = Method ":" digest-uri-value
$A2 = 'POST:' . $this->digest_uri; $A2 = $this->request_method . ':' . $this->digest_uri;
// H(A2) // H(A2)
$HA2 = md5($A2); $HA2 = md5($A2);
@ -347,21 +513,24 @@ class soap_transport_http extends nusoap_base {
$hashedDigest = md5($unhashedDigest); $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') { } elseif ($authtype == 'certificate') {
$this->certRequest = $certRequest; $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->username = $username;
$this->password = $password; $this->password = $password;
$this->authtype = $authtype; $this->authtype = $authtype;
$this->digestRequest = $digestRequest; $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 * @access public
*/ */
function setSOAPAction($soapaction) { function setSOAPAction($soapaction) {
$this->outgoing_headers['SOAPAction'] = '"' . $soapaction . '"'; $this->setHeader('SOAPAction', '"' . $soapaction . '"');
$this->debug('set SOAPAction: ' . $this->outgoing_headers['SOAPAction']);
} }
/** /**
@ -384,12 +552,10 @@ class soap_transport_http extends nusoap_base {
function setEncoding($enc='gzip, deflate') { function setEncoding($enc='gzip, deflate') {
if (function_exists('gzdeflate')) { if (function_exists('gzdeflate')) {
$this->protocol_version = '1.1'; $this->protocol_version = '1.1';
$this->outgoing_headers['Accept-Encoding'] = $enc; $this->setHeader('Accept-Encoding', $enc);
$this->debug('set Accept-Encoding: ' . $this->outgoing_headers['Accept-Encoding']);
if (!isset($this->outgoing_headers['Connection'])) { if (!isset($this->outgoing_headers['Connection'])) {
$this->outgoing_headers['Connection'] = 'close'; $this->setHeader('Connection', 'close');
$this->persistentConnection = false; $this->persistentConnection = false;
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
} }
set_magic_quotes_runtime(0); set_magic_quotes_runtime(0);
// deprecated // deprecated
@ -400,22 +566,58 @@ class soap_transport_http extends nusoap_base {
/** /**
* set proxy info here * set proxy info here
* *
* @param string $proxyhost * @param string $proxyhost use an empty string to remove proxy
* @param string $proxyport * @param string $proxyport
* @param string $proxyusername * @param string $proxyusername
* @param string $proxypassword * @param string $proxypassword
* @param string $proxyauthtype (basic|ntlm)
* @access public * @access public
*/ */
function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') { function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
$this->uri = $this->url; if ($proxyhost) {
$this->host = $proxyhost; $this->proxy = array(
$this->port = $proxyport; 'host' => $proxyhost,
if ($proxyusername != '' && $proxypassword != '') { 'port' => $proxyport,
$this->outgoing_headers['Proxy-Authorization'] = ' Basic '.base64_encode($proxyusername.':'.$proxypassword); 'username' => $proxyusername,
$this->debug('set Proxy-Authorization: ' . $this->outgoing_headers['Proxy-Authorization']); '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 * decode a string that is encoded w/ "chunked' transfer encoding
* as defined in RFC2068 19.4.6 * as defined in RFC2068 19.4.6
@ -475,16 +677,29 @@ class soap_transport_http extends nusoap_base {
return $new; 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 = '') { 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 // add content-length header
$this->outgoing_headers['Content-Length'] = strlen($data); $this->setHeader('Content-Length', strlen($data));
$this->debug('set Content-Length: ' . $this->outgoing_headers['Content-Length']);
// start building outgoing payload: // 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->debug("HTTP request: $req");
$this->outgoing_payload = "$req\r\n"; $this->outgoing_payload = "$req\r\n";
@ -509,6 +724,14 @@ class soap_transport_http extends nusoap_base {
$this->outgoing_payload .= $data; $this->outgoing_payload .= $data;
} }
/**
* sends the SOAP request via HTTP[S]
*
* @param string $data message data
* @param array $cookies cookies to send
* @return boolean true if OK, false if problem
* @access private
*/
function sendRequest($data, $cookies = NULL) { function sendRequest($data, $cookies = NULL) {
// build cookie string // build cookie string
$cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https'))); $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
@ -516,7 +739,7 @@ class soap_transport_http extends nusoap_base {
// build payload // build payload
$this->buildPayload($data, $cookie_str); $this->buildPayload($data, $cookie_str);
if ($this->scheme == 'http' || $this->scheme == 'ssl') { if ($this->io_method() == 'socket') {
// send payload // send payload
if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
$this->setError('couldn\'t write message data to socket'); $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)); $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
return true; return true;
} else if ($this->scheme == 'https') { } else if ($this->io_method() == 'curl') {
// set payload // 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 // turns out that the URI and HTTP version are appended to this, which
// some servers refuse to work with // some servers refuse to work with (so we no longer use this method!)
//curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $this->outgoing_payload); //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
$curl_headers = array();
foreach($this->outgoing_headers as $k => $v){ 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 != '') { if ($cookie_str != '') {
$curl_headers[] = 'Cookie: ' . $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") { if ($this->request_method == "POST") {
curl_setopt($this->ch, CURLOPT_POST, 1); $this->setCurlOption(CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data); $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
$this->debug('set cURL POST data');
} else { } else {
} }
// insert custom user-set cURL options
foreach ($this->ch_options as $key => $val) {
$this->setCurlOption($key, $val);
}
$this->debug('set cURL payload'); $this->debug('set cURL payload');
return true; return true;
} }
} }
/**
* gets the SOAP response via HTTP[S]
*
* @return string the response (also sets member variables like incoming_payload)
* @access private
*/
function getResponse(){ function getResponse(){
$this->incoming_payload = ''; $this->incoming_payload = '';
if ($this->scheme == 'http' || $this->scheme == 'ssl') { if ($this->io_method() == 'socket') {
// loop until headers have been retrieved // loop until headers have been retrieved
$data = ''; $data = '';
while (!isset($lb)){ while (!isset($lb)){
@ -587,8 +828,8 @@ class soap_transport_http extends nusoap_base {
$lb = "\n"; $lb = "\n";
} }
} }
// remove 100 header // remove 100 headers
if(isset($lb) && ereg('^HTTP/1.1 100',$data)){ if (isset($lb) && preg_match('/^HTTP\/1.1 100/',$data)) {
unset($lb); unset($lb);
$data = ''; $data = '';
}// }//
@ -714,7 +955,7 @@ class soap_transport_http extends nusoap_base {
// $this->incoming_payload = $header_data.$lb.$lb.$data; // $this->incoming_payload = $header_data.$lb.$lb.$data;
// } // }
} else if ($this->scheme == 'https') { } else if ($this->io_method() == 'curl') {
// send and receive // send and receive
$this->debug('send and receive with cURL'); $this->debug('send and receive with cURL');
$this->incoming_payload = curl_exec($this->ch); $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'); $this->debug('No cURL error, closing cURL');
curl_close($this->ch); curl_close($this->ch);
// remove 100 header(s) // try removing skippable headers
while (ereg('^HTTP/1.1 100',$data)) { $savedata = $data;
while ($this->isSkippableCurlHeader($data)) {
$this->debug("Found HTTP header to skip");
if ($pos = strpos($data,"\r\n\r\n")) { if ($pos = strpos($data,"\r\n\r\n")) {
$data = ltrim(substr($data,$pos)); $data = ltrim(substr($data,$pos));
} elseif($pos = strpos($data,"\n\n") ) { } 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 (preg_match('/^HTTP\/1.1 100/',$data)) {
if ($pos = strpos($data,"\r\n\r\n")) {
$data = ltrim(substr($data,$pos));
} elseif($pos = strpos($data,"\n\n") ) {
$data = ltrim(substr($data,$pos));
}
}
}
// separate content from HTTP headers // separate content from HTTP headers
if ($pos = strpos($data,"\r\n\r\n")) { if ($pos = strpos($data,"\r\n\r\n")) {
$lb = "\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_version = $arr[0];
$http_status = intval($arr[1]); $http_status = intval($arr[1]);
$http_reason = count($arr) > 2 ? $arr[2] : ''; $http_reason = count($arr) > 2 ? $arr[2] : '';
// see if we need to resend the request with http digest authentication // see if we need to resend the request with http digest authentication
if (isset($this->incoming_headers['location']) && $http_status == 301) { if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
$this->debug("Got 301 $http_reason with Location: " . $this->incoming_headers['location']); $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
$this->setURL($this->incoming_headers['location']); $this->setURL($this->incoming_headers['location']);
$this->tryagain = true; $this->tryagain = true;
return false; return false;
@ -904,19 +1160,30 @@ class soap_transport_http extends nusoap_base {
return $data; 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) { function setContentType($type, $charset = false) {
$this->outgoing_headers['Content-Type'] = $type . ($charset ? '; charset=' . $charset : ''); $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
$this->debug('set Content-Type: ' . $this->outgoing_headers['Content-Type']);
} }
/**
* specifies that an HTTP persistent connection should be used
*
* @return boolean whether the request was honored by this method.
* @access public
*/
function usePersistentConnection(){ function usePersistentConnection(){
if (isset($this->outgoing_headers['Accept-Encoding'])) { if (isset($this->outgoing_headers['Accept-Encoding'])) {
return false; return false;
} }
$this->protocol_version = '1.1'; $this->protocol_version = '1.1';
$this->persistentConnection = true; $this->persistentConnection = true;
$this->outgoing_headers['Connection'] = 'Keep-Alive'; $this->setHeader('Connection', 'Keep-Alive');
$this->debug('set Connection: ' . $this->outgoing_headers['Connection']);
return true; return true;
} }
@ -932,7 +1199,7 @@ class soap_transport_http extends nusoap_base {
*/ */
function parseCookie($cookie_str) { function parseCookie($cookie_str) {
$cookie_str = str_replace('; ', ';', $cookie_str) . ';'; $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
$data = explode(';', $cookie_str); $data = split(';', $cookie_str);
$value_str = $data[0]; $value_str = $data[0];
$cookie_param = 'domain='; $cookie_param = 'domain=';

View File

@ -87,7 +87,7 @@ class soapval extends nusoap_base {
* @access public * @access public
*/ */
function serialize($use='encoded') { 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 higher level class for easy usage. * [nu]soapclient higher level class for easy usage.
* *
* usage: * usage:
* *
* // instantiate client with server info * // 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 * // call method, get results
* echo $soapclient->call( string methodname [ ,array parameters] ); * echo $soapclient->call( string methodname [ ,array parameters] );
@ -19,17 +19,19 @@
* unset($soapclient); * unset($soapclient);
* *
* @author Dietrich Ayala <dietrich@ganx4.com> * @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class soapclient_nusoap extends nusoap_base { class nusoap_client extends nusoap_base {
var $username = ''; var $username = ''; // Username for HTTP authentication
var $password = ''; var $password = ''; // Password for HTTP authentication
var $authtype = ''; var $authtype = ''; // Type of HTTP authentication
var $certRequest = array(); var $certRequest = array(); // Certificate for HTTP SSL authentication
var $requestHeaders = false; // SOAP headers in request (text) var $requestHeaders = false; // SOAP headers in request (text)
var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (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 $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
var $endpoint; var $endpoint;
var $forceEndpoint = ''; // overrides WSDL 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 $cookies = array(); // Cookies from response or for request
var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode() 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 $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 * fault related variables
@ -89,7 +94,7 @@ class soapclient_nusoap extends nusoap_base {
* @param integer $response_timeout set the response timeout * @param integer $response_timeout set the response timeout
* @access public * @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(); parent::nusoap_base();
$this->endpoint = $endpoint; $this->endpoint = $endpoint;
$this->proxyhost = $proxyhost; $this->proxyhost = $proxyhost;
@ -99,6 +104,9 @@ class soapclient_nusoap extends nusoap_base {
$this->timeout = $timeout; $this->timeout = $timeout;
$this->response_timeout = $response_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 // make values
if($wsdl){ if($wsdl){
if (is_object($endpoint) && (get_class($endpoint) == '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->endpoint = $this->wsdl->wsdl;
$this->wsdlFile = $this->endpoint; $this->wsdlFile = $this->endpoint;
$this->debug('existing wsdl instance created from ' . $this->endpoint); $this->debug('existing wsdl instance created from ' . $this->endpoint);
$this->checkWSDL();
} else { } else {
$this->wsdlFile = $this->endpoint; $this->wsdlFile = $this->endpoint;
$this->wsdl = null;
// instantiate wsdl object and parse wsdl file $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
$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->endpointType = 'wsdl';
} else { } else {
$this->debug("instantiate SOAP with endpoint at $endpoint"); $this->debug("instantiate SOAP with endpoint at $endpoint");
$this->endpointType = 'soap'; $this->endpointType = 'soap';
@ -135,7 +130,7 @@ class soapclient_nusoap extends nusoap_base {
/** /**
* calls method, returns PHP native type * 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 * @param mixed $params An array, associative or simple, of the parameters
* for the method call, or a string that is the XML * for the method call, or a string that is the XML
* for the call. For rpc style, this call will * for the call. For rpc style, this call will
@ -150,7 +145,7 @@ class soapclient_nusoap extends nusoap_base {
* *must* include the wrapper. * *must* include the wrapper.
* @param string $namespace optional method namespace (WSDL can override) * @param string $namespace optional method namespace (WSDL can override)
* @param string $soapAction optional SOAPAction value (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 boolean $rpcParams optional (no longer used)
* @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override) * @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) * @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) { if ($headers) {
$this->requestHeaders = $headers; $this->requestHeaders = $headers;
} }
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
$this->loadWSDL();
if ($this->getError())
return false;
}
// serialize parameters // serialize parameters
if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
// use WSDL for operation // use WSDL for operation
@ -203,7 +203,7 @@ class soapclient_nusoap extends nusoap_base {
$payload = $params; $payload = $params;
} elseif (is_array($params)) { } elseif (is_array($params)) {
$this->debug("serializing param array for WSDL operation $operation"); $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 { } else {
$this->debug('params must be array or string'); $this->debug('params must be array or string');
$this->setError('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') { if ($use == 'literal') {
$this->debug("wrapping RPC request with literal method element"); $this->debug("wrapping RPC request with literal method element");
if ($namespace) { 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 { } else {
$payload = "<$operation>" . $payload . "</$operation>"; $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 * get available data pertaining to an operation
* *
@ -334,6 +376,11 @@ class soapclient_nusoap extends nusoap_base {
* @access public * @access public
*/ */
function getOperationData($operation){ function getOperationData($operation){
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
$this->loadWSDL();
if ($this->getError())
return false;
}
if(isset($this->operations[$operation])){ if(isset($this->operations[$operation])){
return $this->operations[$operation]; return $this->operations[$operation];
} }
@ -359,12 +406,12 @@ class soapclient_nusoap extends nusoap_base {
// detect transport // detect transport
switch(true){ switch(true){
// http(s) // http(s)
case ereg('^http',$this->endpoint): case preg_match('/^http/',$this->endpoint):
$this->debug('transporting via HTTP'); $this->debug('transporting via HTTP');
if($this->persistentConnection == true && is_object($this->persistentConnection)){ if($this->persistentConnection == true && is_object($this->persistentConnection)){
$http =& $this->persistentConnection; $http =& $this->persistentConnection;
} else { } else {
$http = new soap_transport_http($this->endpoint); $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
if ($this->persistentConnection) { if ($this->persistentConnection) {
$http->usePersistentConnection(); $http->usePersistentConnection();
} }
@ -381,10 +428,10 @@ class soapclient_nusoap extends nusoap_base {
$http->setEncoding($this->http_encoding); $http->setEncoding($this->http_encoding);
} }
$this->debug('sending message, length='.strlen($msg)); $this->debug('sending message, length='.strlen($msg));
if(ereg('^http:',$this->endpoint)){ if(preg_match('/^http:/',$this->endpoint)){
//if(strpos($this->endpoint,'http:')){ //if(strpos($this->endpoint,'http:')){
$this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies); $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
} elseif(ereg('^https',$this->endpoint)){ } elseif(preg('/^https/',$this->endpoint)){
//} elseif(strpos($this->endpoint,'https:')){ //} elseif(strpos($this->endpoint,'https:')){
//if(phpversion() == '4.3.0-dev'){ //if(phpversion() == '4.3.0-dev'){
//$response = $http->send($msg,$timeout,$response_timeout); //$response = $http->send($msg,$timeout,$response_timeout);
@ -434,9 +481,10 @@ class soapclient_nusoap extends nusoap_base {
* @access private * @access private
*/ */
function parseResponse($headers, $data) { 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')) { 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; return false;
} }
if (strpos($headers['content-type'], '=')) { 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 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-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');
$parser = new soap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8); $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
// add parser debug data to our debug // add parser debug data to our debug
$this->appendDebug($parser->getDebug()); $this->appendDebug($parser->getDebug());
// if parse errors // if parse errors
@ -464,8 +512,10 @@ class soapclient_nusoap extends nusoap_base {
} else { } else {
// get SOAP headers // get SOAP headers
$this->responseHeaders = $parser->getHeaders(); $this->responseHeaders = $parser->getHeaders();
// get SOAP headers
$this->responseHeader = $parser->get_soapheader();
// get decoded message // get decoded message
$return = $parser->get_response(); $return = $parser->get_soapbody();
// add document for doclit support // add document for doclit support
$this->document = $parser->document; $this->document = $parser->document;
// destroy the parser object // 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 * 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 * @access public
*/ */
function setEndpoint($endpoint) { function setEndpoint($endpoint) {
$this->debug("setEndpoint(\"$endpoint\")");
$this->forceEndpoint = $endpoint; $this->forceEndpoint = $endpoint;
} }
/** /**
* set the SOAP headers * 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 * @access public
*/ */
function setHeaders($headers){ function setHeaders($headers){
$this->debug("setHeaders headers=");
$this->appendDebug($this->varDump($headers));
$this->requestHeaders = $headers; $this->requestHeaders = $headers;
} }
@ -505,6 +571,16 @@ class soapclient_nusoap extends nusoap_base {
return $this->responseHeaders; return $this->responseHeaders;
} }
/**
* get the SOAP response Header (parsed)
*
* @return mixed
* @access public
*/
function getHeader(){
return $this->responseHeader;
}
/** /**
* set proxy info here * set proxy info here
* *
@ -526,11 +602,13 @@ class soapclient_nusoap extends nusoap_base {
* *
* @param string $username * @param string $username
* @param string $password * @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) * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
* @access public * @access public
*/ */
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) { 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->username = $username;
$this->password = $password; $this->password = $password;
$this->authtype = $authtype; $this->authtype = $authtype;
@ -540,19 +618,32 @@ class soapclient_nusoap extends nusoap_base {
/** /**
* use HTTP encoding * use HTTP encoding
* *
* @param string $enc * @param string $enc HTTP encoding
* @access public * @access public
*/ */
function setHTTPEncoding($enc='gzip, deflate'){ function setHTTPEncoding($enc='gzip, deflate'){
$this->debug("setHTTPEncoding(\"$enc\")");
$this->http_encoding = $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 * use HTTP persistent connections if possible
* *
* @access public * @access public
*/ */
function useHTTPPersistentConnection(){ function useHTTPPersistentConnection(){
$this->debug("useHTTPPersistentConnection");
$this->persistentConnection = true; $this->persistentConnection = true;
} }
@ -593,14 +684,18 @@ class soapclient_nusoap extends nusoap_base {
* @return object soap_proxy object * @return object soap_proxy object
* @access public * @access public
*/ */
function getProxy(){ function getProxy() {
$r = rand(); $r = rand();
$evalStr = $this->_getProxyClassCode($r); $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 the class
eval($evalStr); eval($evalStr);
// instantiate proxy object // 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 // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
$proxy->endpointType = 'wsdl'; $proxy->endpointType = 'wsdl';
$proxy->wsdlFile = $this->wsdlFile; $proxy->wsdlFile = $this->wsdlFile;
@ -608,21 +703,26 @@ class soapclient_nusoap extends nusoap_base {
$proxy->operations = $this->operations; $proxy->operations = $this->operations;
$proxy->defaultRpcParams = $this->defaultRpcParams; $proxy->defaultRpcParams = $this->defaultRpcParams;
// transfer other state // transfer other state
$proxy->soap_defencoding = $this->soap_defencoding;
$proxy->username = $this->username; $proxy->username = $this->username;
$proxy->password = $this->password; $proxy->password = $this->password;
$proxy->authtype = $this->authtype; $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->proxyhost = $this->proxyhost;
$proxy->proxyport = $this->proxyport; $proxy->proxyport = $this->proxyport;
$proxy->proxyusername = $this->proxyusername; $proxy->proxyusername = $this->proxyusername;
$proxy->proxypassword = $this->proxypassword; $proxy->proxypassword = $this->proxypassword;
$proxy->http_encoding = $this->http_encoding;
$proxy->timeout = $this->timeout; $proxy->timeout = $this->timeout;
$proxy->response_timeout = $this->response_timeout; $proxy->response_timeout = $this->response_timeout;
$proxy->http_encoding = $this->http_encoding; $proxy->persistentConnection = &$this->persistentConnection;
$proxy->persistentConnection = $this->persistentConnection; $proxy->decode_utf8 = $this->decode_utf8;
$proxy->requestHeaders = $this->requestHeaders; $proxy->curl_options = $this->curl_options;
$proxy->soap_defencoding = $this->soap_defencoding; $proxy->bindingType = $this->bindingType;
$proxy->endpoint = $this->endpoint; $proxy->use_curl = $this->use_curl;
$proxy->forceEndpoint = $this->forceEndpoint;
return $proxy; return $proxy;
} }
@ -633,11 +733,20 @@ class soapclient_nusoap extends nusoap_base {
* @access private * @access private
*/ */
function _getProxyClassCode($r) { function _getProxyClassCode($r) {
$this->debug("in getProxy endpointType=$this->endpointType");
$this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
if ($this->endpointType != 'wsdl') { if ($this->endpointType != 'wsdl') {
$evalStr = 'A proxy can only be created for a WSDL client'; $evalStr = 'A proxy can only be created for a WSDL client';
$this->setError($evalStr); $this->setError($evalStr);
$evalStr = "echo \"$evalStr\";";
return $evalStr; return $evalStr;
} }
if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
$this->loadWSDL();
if ($this->getError()) {
return "echo \"" . $this->getError() . "\";";
}
}
$evalStr = ''; $evalStr = '';
foreach ($this->operations as $operation => $opData) { foreach ($this->operations as $operation => $opData) {
if ($operation != '') { if ($operation != '') {
@ -656,6 +765,7 @@ class soapclient_nusoap extends nusoap_base {
$paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2); $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
} else { } else {
$paramStr = ''; $paramStr = '';
$paramArrayStr = '';
$paramCommentStr = 'void'; $paramCommentStr = 'void';
} }
$opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace']; $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
@ -669,7 +779,7 @@ class soapclient_nusoap extends nusoap_base {
unset($paramCommentStr); unset($paramCommentStr);
} }
} }
$evalStr = 'class soap_proxy_'.$r.' extends soapclient_nusoap { $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
'.$evalStr.' '.$evalStr.'
}'; }';
return $evalStr; return $evalStr;
@ -738,7 +848,7 @@ class soapclient_nusoap extends nusoap_base {
* *
* @param string $name Cookie Name * @param string $name Cookie Name
* @param string $value Cookie Value * @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 * @access public
*/ */
function setCookie($name, $value) { function setCookie($name, $value) {
@ -762,7 +872,7 @@ class soapclient_nusoap extends nusoap_base {
/** /**
* checks all Cookies and delete those which are expired * checks all Cookies and delete those which are expired
* *
* @return always return true * @return boolean always return true
* @access private * @access private
*/ */
function checkCookies() { function checkCookies() {
@ -795,7 +905,7 @@ class soapclient_nusoap extends nusoap_base {
* updates the current cookies with a new set * updates the current cookies with a new set
* *
* @param array $cookies new cookies with which to update current ones * @param array $cookies new cookies with which to update current ones
* @return always return true * @return boolean always return true
* @access private * @access private
*/ */
function UpdateCookies($cookies) { function UpdateCookies($cookies) {
@ -856,4 +966,12 @@ class soapclient_nusoap extends nusoap_base {
return true; 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 Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
@ -45,6 +47,13 @@ class wsdl extends nusoap_base {
var $proxypassword = ''; var $proxypassword = '';
var $timeout = 0; var $timeout = 0;
var $response_timeout = 30; 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 * constructor
@ -56,82 +65,96 @@ class wsdl extends nusoap_base {
* @param string $proxypassword * @param string $proxypassword
* @param integer $timeout set the connection timeout * @param integer $timeout set the connection timeout
* @param integer $response_timeout set the response 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 * @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(); parent::nusoap_base();
$this->wsdl = $wsdl; $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
$this->proxyhost = $proxyhost; $this->proxyhost = $proxyhost;
$this->proxyport = $proxyport; $this->proxyport = $proxyport;
$this->proxyusername = $proxyusername; $this->proxyusername = $proxyusername;
$this->proxypassword = $proxypassword; $this->proxypassword = $proxypassword;
$this->timeout = $timeout; $this->timeout = $timeout;
$this->response_timeout = $response_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 // parse wsdl file
if ($wsdl != "") { if ($this->wsdl != "") {
$this->debug('initial wsdl URL: ' . $wsdl); $this->parseWSDL($this->wsdl);
$this->parseWSDL($wsdl);
} }
// imports // imports
// TODO: handle imports more properly, grabbing them in-line and nesting them // TODO: handle imports more properly, grabbing them in-line and nesting them
$imported_urls = array(); $imported_urls = array();
$imported = 1; $imported = 1;
while ($imported > 0) { while ($imported > 0) {
$imported = 0; $imported = 0;
// Schema imports // Schema imports
foreach ($this->schemas as $ns => $list) { foreach ($this->schemas as $ns => $list) {
foreach ($list as $xs) { foreach ($list as $xs) {
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple! $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
foreach ($xs->imports as $ns2 => $list2) { foreach ($xs->imports as $ns2 => $list2) {
for ($ii = 0; $ii < count($list2); $ii++) { for ($ii = 0; $ii < count($list2); $ii++) {
if (! $list2[$ii]['loaded']) { if (! $list2[$ii]['loaded']) {
$this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true; $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
$url = $list2[$ii]['location']; $url = $list2[$ii]['location'];
if ($url != '') { if ($url != '') {
$urlparts = parse_url($url); $urlparts = parse_url($url);
if (!isset($urlparts['host'])) { if (!isset($urlparts['host'])) {
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') . $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; 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");
} }
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! // WSDL imports
foreach ($this->import as $ns => $list) { $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
for ($ii = 0; $ii < count($list); $ii++) { foreach ($this->import as $ns => $list) {
if (! $list[$ii]['loaded']) { for ($ii = 0; $ii < count($list); $ii++) {
$this->import[$ns][$ii]['loaded'] = true; if (! $list[$ii]['loaded']) {
$url = $list[$ii]['location']; $this->import[$ns][$ii]['loaded'] = true;
if ($url != '') { $url = $list[$ii]['location'];
$urlparts = parse_url($url); if ($url != '') {
if (!isset($urlparts['host'])) { $urlparts = parse_url($url);
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') . if (!isset($urlparts['host'])) {
substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path']; $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); if (! in_array($url, $imported_urls)) {
$imported++; $this->parseWSDL($url);
$imported_urls[] = $url; $imported++;
} $imported_urls[] = $url;
} else { }
$this->debug("Unexpected scenario: empty URL for unloaded import"); } else {
} $this->debug("Unexpected scenario: empty URL for unloaded import");
} }
} }
} }
} }
}
// add new data to operation data // add new data to operation data
foreach($this->bindings as $binding => $bindingData) { foreach($this->bindings as $binding => $bindingData) {
if (isset($bindingData['operations']) && is_array($bindingData['operations'])) { 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'] ])){ 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'] ]; $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]['style'] = $bindingData['style'];
} }
$this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : ''; $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
@ -160,7 +184,7 @@ class wsdl extends nusoap_base {
} }
} }
} }
} }
/** /**
* parses the wsdl document * parses the wsdl document
@ -168,8 +192,9 @@ class wsdl extends nusoap_base {
* @param string $wsdl path or URL * @param string $wsdl path or URL
* @access private * @access private
*/ */
function parseWSDL($wsdl = '') function parseWSDL($wsdl = '') {
{ $this->debug("parse WSDL at path=$wsdl");
if ($wsdl == '') { if ($wsdl == '') {
$this->debug('no wsdl passed to parseWSDL()!!'); $this->debug('no wsdl passed to parseWSDL()!!');
$this->setError('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')) { if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
$this->debug('getting WSDL http(s) URL ' . $wsdl); $this->debug('getting WSDL http(s) URL ' . $wsdl);
// get 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->request_method = 'GET';
$tr->useSOAPAction = false; $tr->useSOAPAction = false;
if($this->proxyhost && $this->proxyport){ if($this->proxyhost && $this->proxyport){
$tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword); $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'); $tr->setEncoding('gzip, deflate');
$wsdl_string = $tr->send('', $this->timeout, $this->response_timeout); $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
//$this->debug("WSDL request\n" . $tr->outgoing_payload); //$this->debug("WSDL request\n" . $tr->outgoing_payload);
@ -274,11 +302,11 @@ class wsdl extends nusoap_base {
$this->currentSchema->schemaStartElement($parser, $name, $attrs); $this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
} elseif (ereg('schema$', $name)) { } elseif (preg_match('/schema$/', $name)) {
$this->debug('Parsing WSDL schema'); $this->debug('Parsing WSDL schema');
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")"); // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
$this->status = 'schema'; $this->status = 'schema';
$this->currentSchema = new xmlschema('', '', $this->namespaces); $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
$this->currentSchema->schemaStartElement($parser, $name, $attrs); $this->currentSchema->schemaStartElement($parser, $name, $attrs);
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
@ -293,7 +321,7 @@ class wsdl extends nusoap_base {
if (count($attrs) > 0) { if (count($attrs) > 0) {
// register namespace declarations // register namespace declarations
foreach($attrs as $k => $v) { foreach($attrs as $k => $v) {
if (ereg("^xmlns", $k)) { if (preg_match("/^xmlns/", $k)) {
if ($ns_prefix = substr(strrchr($k, ':'), 1)) { if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
$this->namespaces[$ns_prefix] = $v; $this->namespaces[$ns_prefix] = $v;
} else { } else {
@ -318,7 +346,7 @@ class wsdl extends nusoap_base {
$attrs = array(); $attrs = array();
} }
// get element prefix, namespace and name // get element prefix, namespace and name
if (ereg(':', $name)) { if (preg_match('/:/', $name)) {
// get ns prefix // get ns prefix
$prefix = substr($name, 0, strpos($name, ':')); $prefix = substr($name, 0, strpos($name, ':'));
// get ns // get ns
@ -332,12 +360,12 @@ class wsdl extends nusoap_base {
case 'message': case 'message':
if ($name == 'part') { if ($name == 'part') {
if (isset($attrs['type'])) { 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']; $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
} }
if (isset($attrs['element'])) { if (isset($attrs['element'])) {
$this->debug("msg " . $this->currentMessage . ": found part $attrs[name]: " . implode(',', $attrs)); $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element']; $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
} }
} }
break; break;
@ -483,7 +511,7 @@ class wsdl extends nusoap_base {
*/ */
function end_element($parser, $name){ function end_element($parser, $name){
// unset schema status // unset schema status
if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) { if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
$this->status = ""; $this->status = "";
$this->appendDebug($this->currentSchema->getDebug()); $this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug(); $this->currentSchema->clearDebug();
@ -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) function getBindingData($binding)
{ {
if (is_array($this->bindings[$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 * 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 * @return array
* @access public * @access public
*/ */
function getOperations($bindingType = 'soap') function getOperations($bindingType = 'soap') {
{
$ops = array(); $ops = array();
if ($bindingType == 'soap') { if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
} elseif ($bindingType == 'soap12') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
} }
// loop thru ports // loop thru ports
foreach($this->ports as $port => $portData) { 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 * returns an associative array of data necessary for calling an operation
* *
* @param string $operation , name of operation * @param string $operation name of operation
* @param string $bindingType , type of binding eg: soap * @param string $bindingType type of binding eg: soap, soap12
* @return array * @return array
* @access public * @access public
*/ */
@ -570,6 +617,8 @@ class wsdl extends nusoap_base {
{ {
if ($bindingType == 'soap') { if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
} elseif ($bindingType == 'soap12') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
} }
// loop thru ports // loop thru ports
foreach($this->ports as $port => $portData) { 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 * returns an associative array of data necessary for calling an operation
* *
* @param string $soapAction soapAction for 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 * @return array
* @access public * @access public
*/ */
function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') { function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
if ($bindingType == 'soap') { if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/'; $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
} elseif ($bindingType == 'soap12') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
} }
// loop thru ports // loop thru ports
foreach($this->ports as $port => $portData) { foreach($this->ports as $port => $portData) {
@ -626,11 +677,11 @@ class wsdl extends nusoap_base {
* 'attrs' => array() // refs to attributes array * 'attrs' => array() // refs to attributes array
* ) * )
* *
* @param $type string the type * @param string $type the type
* @param $ns string namespace (not prefix) of the type * @param string $ns namespace (not prefix) of the type
* @return mixed * @return mixed
* @access public * @access public
* @see xmlschema * @see nusoap_xmlschema
*/ */
function getTypeDef($type, $ns) { function getTypeDef($type, $ns) {
$this->debug("in getTypeDef: type=$type, ns=$ns"); $this->debug("in getTypeDef: type=$type, ns=$ns");
@ -638,13 +689,22 @@ class wsdl extends nusoap_base {
$ns = $this->namespaces['tns']; $ns = $this->namespaces['tns'];
$this->debug("in getTypeDef: type namespace forced to $ns"); $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])) { if (isset($this->schemas[$ns])) {
$this->debug("in getTypeDef: have schema for namespace $ns"); $this->debug("in getTypeDef: have schema for namespace $ns");
for ($i = 0; $i < count($this->schemas[$ns]); $i++) { for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
$xs = &$this->schemas[$ns][$i]; $xs = &$this->schemas[$ns][$i];
$t = $xs->getTypeDef($type); $t = $xs->getTypeDef($type);
$this->appendDebug($xs->getDebug()); //$this->appendDebug($xs->getDebug());
$xs->clearDebug(); //$xs->clearDebug();
if ($t) { if ($t) {
if (!isset($t['phpType'])) { if (!isset($t['phpType'])) {
// get info for type to tack onto the element // get info for type to tack onto the element
@ -841,7 +901,7 @@ class wsdl extends nusoap_base {
} }
// types // types
if (count($this->schemas)>=1) { if (count($this->schemas)>=1) {
$xml .= "\n<types>"; $xml .= "\n<types>\n";
foreach ($this->schemas as $ns => $list) { foreach ($this->schemas as $ns => $list) {
foreach ($list as $xs) { foreach ($list as $xs) {
$xml .= $xs->serializeSchema(); $xml .= $xs->serializeSchema();
@ -872,13 +932,17 @@ class wsdl extends nusoap_base {
} }
} }
$ns = $this->getNamespaceFromPrefix($typePrefix); $ns = $this->getNamespaceFromPrefix($typePrefix);
$typeDef = $this->getTypeDef($this->getLocalPart($partType), $ns); $localPart = $this->getLocalPart($partType);
$typeDef = $this->getTypeDef($localPart, $ns);
if ($typeDef['typeClass'] == 'element') { if ($typeDef['typeClass'] == 'element') {
$elementortype = 'element'; $elementortype = 'element';
if (substr($localPart, -1) == '^') {
$localPart = substr($localPart, 0, -1);
}
} else { } else {
$elementortype = 'type'; $elementortype = 'type';
} }
$xml .= '<part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $this->getLocalPart($partType) . '" />'; $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
} }
} }
$xml .= '</message>'; $xml .= '</message>';
@ -890,38 +954,38 @@ class wsdl extends nusoap_base {
$portType_xml = ''; $portType_xml = '';
foreach($this->bindings as $bindingName => $attrs) { foreach($this->bindings as $bindingName => $attrs) {
$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">'; $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'] . '">'; $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
foreach($attrs['operations'] as $opName => $opParts) { foreach($attrs['operations'] as $opName => $opParts) {
$binding_xml .= '<operation name="' . $opName . '">'; $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
$binding_xml .= '<soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>'; $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') { if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
$enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"'; $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
} else { } else {
$enc_style = ''; $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'] != '') { if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
$enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"'; $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
} else { } else {
$enc_style = ''; $enc_style = '';
} }
$binding_xml .= '<output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>'; $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
$binding_xml .= '</operation>'; $binding_xml .= "\n" . ' </operation>';
$portType_xml .= '<operation name="' . $opParts['name'] . '"'; $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
if (isset($opParts['parameterOrder'])) { if (isset($opParts['parameterOrder'])) {
$portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"'; $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
} }
$portType_xml .= '>'; $portType_xml .= '>';
if(isset($opParts['documentation']) && $opParts['documentation'] != '') { 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 .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
$portType_xml .= '<output message="tns:' . $opParts['output']['message'] . '"/>'; $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
$portType_xml .= '</operation>'; $portType_xml .= "\n" . ' </operation>';
} }
$portType_xml .= '</portType>'; $portType_xml .= "\n" . '</portType>';
$binding_xml .= '</binding>'; $binding_xml .= "\n" . '</binding>';
} }
$xml .= $portType_xml . $binding_xml; $xml .= $portType_xml . $binding_xml;
} }
@ -929,17 +993,105 @@ class wsdl extends nusoap_base {
$xml .= "\n<service name=\"" . $this->serviceName . '">'; $xml .= "\n<service name=\"" . $this->serviceName . '">';
if (count($this->ports) >= 1) { if (count($this->ports) >= 1) {
foreach($this->ports as $pName => $attrs) { foreach($this->ports as $pName => $attrs) {
$xml .= '<port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">'; $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
$xml .= '<soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>'; $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
$xml .= '</port>'; $xml .= "\n" . ' </port>';
} }
} }
$xml .= '</service>'; $xml .= "\n" . '</service>';
return $xml . "\n</definitions>"; 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 * serialize PHP values according to a WSDL message definition
* contrary to the method name, this is not limited to RPC
* *
* TODO * TODO
* - multi-ref serialization * - multi-ref serialization
@ -948,12 +1100,12 @@ class wsdl extends nusoap_base {
* @param string $operation operation name * @param string $operation operation name
* @param string $direction (input|output) * @param string $direction (input|output)
* @param mixed $parameters parameter value(s) * @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) * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
* @access public * @access public
*/ */
function serializeRPCParameters($operation, $direction, $parameters) function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
{ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
$this->appendDebug('parameters=' . $this->varDump($parameters)); $this->appendDebug('parameters=' . $this->varDump($parameters));
if ($direction != 'input' && $direction != 'output') { 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"'); $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
return false; return false;
} }
if (!$opData = $this->getOperationData($operation)) { if (!$opData = $this->getOperationData($operation, $bindingType)) {
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation); $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation); $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
return false; return false;
} }
$this->debug('opData:'); $this->debug('in serializeRPCParameters: opData:');
$this->appendDebug($this->varDump($opData)); $this->appendDebug($this->varDump($opData));
// Get encoding style for output and set to current // Get encoding style for output and set to current
@ -979,14 +1131,29 @@ class wsdl extends nusoap_base {
// set input params // set input params
$xml = ''; $xml = '';
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) { 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']; $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)) { if (is_array($parameters)) {
$parametersArrayType = $this->isArraySimpleOrStruct($parameters); $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
$this->debug('have ' . count($parameters) . ' parameter(s) provided as ' . $parametersArrayType . ' to serialize'); $parameter_count = count($parameters);
foreach($opData[$direction]['parts'] as $name => $type) { $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
$this->debug('serializing part "'.$name.'" of type "'.$type.'"'); // 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 // Track encoding style
if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) { if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
$encodingStyle = $opData[$direction]['encodingStyle']; $encodingStyle = $opData[$direction]['encodingStyle'];
@ -1024,9 +1191,10 @@ class wsdl extends nusoap_base {
* - multi-ref serialization * - multi-ref serialization
* - validate PHP values against type definitions, return errors if invalid * - validate PHP values against type definitions, return errors if invalid
* *
* @param string $ type name * @param string $operation operation name
* @param mixed $ param value * @param string $direction (input|output)
* @return mixed new param or false if initial value didn't validate * @param mixed $parameters parameter value(s)
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
* @access public * @access public
* @deprecated * @deprecated
*/ */
@ -1159,7 +1327,7 @@ class wsdl extends nusoap_base {
if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
$this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type'); $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
if ($unqualified && $use == 'literal') { if ($unqualified && $use == 'literal') {
$elementNS = " xmlns=\"\""; $elementNS = " xmlns=\"\"";
} else { } else {
$elementNS = ''; $elementNS = '';
@ -1175,6 +1343,10 @@ class wsdl extends nusoap_base {
$this->debug("in serializeType: returning: $xml"); $this->debug("in serializeType: returning: $xml");
return $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 ($uqType == 'boolean') {
if ((is_string($value) && $value == 'false') || (! $value)) { if ((is_string($value) && $value == 'false') || (! $value)) {
$value = 'false'; $value = 'false';
@ -1252,6 +1424,9 @@ class wsdl extends nusoap_base {
} else { } else {
$this->debug("in serializeType: found typeDef"); $this->debug("in serializeType: found typeDef");
$this->appendDebug('typeDef=' . $this->varDump($typeDef)); $this->appendDebug('typeDef=' . $this->varDump($typeDef));
if (substr($uqType, -1) == '^') {
$uqType = substr($uqType, 0, -1);
}
} }
$phpType = $typeDef['phpType']; $phpType = $typeDef['phpType'];
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') ); $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 * adds an XML Schema complex type to the WSDL types
* *
* @param string name * @param string $name
* @param string typeClass (complexType|simpleType|attribute) * @param string $typeClass (complexType|simpleType|attribute)
* @param string phpType: currently supported are array and struct (php assoc array) * @param string $phpType currently supported are array and struct (php assoc array)
* @param string compositor (all|sequence|choice) * @param string $compositor (all|sequence|choice)
* @param string restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array) * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
* @param array elements = array ( name => array(name=>'',type=>'') ) * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
* @param array attrs = array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')) * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
* @param string arrayType: namespace:name (xsd:string) * @param string $arrayType as namespace:name (xsd:string)
* @see xmlschema * @see nusoap_xmlschema
* @access public * @access public
*/ */
function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') { function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
if (count($elements) > 0) { if (count($elements) > 0) {
$eElements = array();
foreach($elements as $n => $e){ foreach($elements as $n => $e){
// expand each element // expand each element
$ee = array();
foreach ($e as $k => $v) { foreach ($e as $k => $v) {
$k = strpos($k,':') ? $this->expandQname($k) : $k; $k = strpos($k,':') ? $this->expandQname($k) : $k;
$v = strpos($v,':') ? $this->expandQname($v) : $v; $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 $typeClass (should always be simpleType)
* @param string $phpType (should always be scalar) * @param string $phpType (should always be scalar)
* @param array $enumeration array of values * @param array $enumeration array of values
* @see xmlschema * @see nusoap_xmlschema
* @access public * @access public
*/ */
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 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 * adds an element to the WSDL types
* *
* @param array $attrs attributes that must include name and type * @param array $attrs attributes that must include name and type
* @see xmlschema * @see nusoap_xmlschema
* @access public * @access public
*/ */
function addElement($attrs) { function addElement($attrs) {
@ -1660,15 +1837,15 @@ class wsdl extends nusoap_base {
} }
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements); $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType')); $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
$in = array('parameters' => 'tns:' . $name); $in = array('parameters' => 'tns:' . $name . '^');
$elements = array(); $elements = array();
foreach ($out as $n => $t) { foreach ($out as $n => $t) {
$elements[$n] = array('name' => $n, 'type' => $t); $elements[$n] = array('name' => $n, 'type' => $t);
} }
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements); $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType')); $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
$out = array('parameters' => 'tns:' . $name . 'Response'); $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
} }
// get binding // get binding

View File

@ -1,16 +1,21 @@
<?php <?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 * 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> * @author Ingo Fischer <ingo@apollon.de>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class wsdlcache { class nusoap_wsdlcache {
/** /**
* @var resource * @var resource
* @access private * @access private
@ -39,7 +44,7 @@ class wsdlcache {
* @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
* @access public * @access public
*/ */
function wsdlcache($cache_dir='.', $cache_lifetime=0) { function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
$this->fplock = array(); $this->fplock = array();
$this->cache_dir = $cache_dir != '' ? $cache_dir : '.'; $this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
$this->cache_lifetime = $cache_lifetime; $this->cache_lifetime = $cache_lifetime;
@ -86,6 +91,11 @@ class wsdlcache {
} }
} }
// see what there is to return // 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"); $fp = @fopen($filename, "r");
if ($fp) { if ($fp) {
$s = implode("", @file($filename)); $s = implode("", @file($filename));
@ -93,7 +103,7 @@ class wsdlcache {
$this->debug("Got $wsdl ($filename) from cache"); $this->debug("Got $wsdl ($filename) from cache");
} else { } else {
$s = null; $s = null;
$this->debug("$wsdl ($filename) not in cache"); $this->debug("$wsdl ($filename) not in cache (2)");
} }
$this->releaseMutex($filename); $this->releaseMutex($filename);
return (!is_null($s)) ? unserialize($s) : null; return (!is_null($s)) ? unserialize($s) : null;
@ -136,6 +146,11 @@ class wsdlcache {
$s = serialize($wsdl_instance); $s = serialize($wsdl_instance);
if ($this->obtainMutex($filename, "w")) { if ($this->obtainMutex($filename, "w")) {
$fp = fopen($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); fputs($fp, $s);
fclose($fp); fclose($fp);
$this->debug("Put $wsdl_instance->wsdl ($filename) in cache"); $this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
@ -173,6 +188,10 @@ class wsdlcache {
*/ */
function remove($wsdl) { function remove($wsdl) {
$filename = $this->createFilename($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 // ignore errors obtaining mutex
$this->obtainMutex($filename, "w"); $this->obtainMutex($filename, "w");
$ret = unlink($filename); $ret = unlink($filename);
@ -181,4 +200,10 @@ class wsdlcache {
return $ret; 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 * parses an XML Schema, allows access to it's data, other utility methods.
* no validation... yet. * imperfect, no validation... yet, but quite functional.
* very experimental and limited. As is discussed on XML-DEV, I'm one of the people
* that just doesn't have time to read the spec(s) thoroughly, and just have a couple of trusty
* tutorials I refer to :)
* *
* @author Dietrich Ayala <dietrich@ganx4.com> * @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class XMLSchema extends nusoap_base { class nusoap_xmlschema extends nusoap_base {
// files // files
var $schema = ''; var $schema = '';
@ -53,9 +51,9 @@ class XMLSchema extends nusoap_base {
* @param string $namespaces namespaces defined in enclosing XML * @param string $namespaces namespaces defined in enclosing XML
* @access public * @access public
*/ */
function XMLSchema($schema='',$xml='',$namespaces=array()){ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
parent::nusoap_base(); parent::nusoap_base();
$this->debug('xmlschema class instantiated, inside constructor'); $this->debug('nusoap_xmlschema class instantiated, inside constructor');
// files // files
$this->schema = $schema; $this->schema = $schema;
$this->xml = $xml; $this->xml = $xml;
@ -81,8 +79,8 @@ class XMLSchema extends nusoap_base {
/** /**
* parse an XML file * parse an XML file
* *
* @param string $xml, path/URL to XML file * @param string $xml path/URL to XML file
* @param string $type, (schema | xml) * @param string $type (schema | xml)
* @return boolean * @return boolean
* @access public * @access public
*/ */
@ -109,7 +107,7 @@ class XMLSchema extends nusoap_base {
* parse an XML string * parse an XML string
* *
* @param string $xml path or URL * @param string $xml path or URL
* @param string $type, (schema|xml) * @param string $type (schema|xml)
* @access private * @access private
*/ */
function parseString($xml,$type){ 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 * start-element handler
* *
@ -186,7 +199,7 @@ class XMLSchema extends nusoap_base {
if(count($attrs) > 0){ if(count($attrs) > 0){
foreach($attrs as $k => $v){ foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespaces // if ns declarations, add to class level array of valid namespaces
if(ereg("^xmlns",$k)){ if(preg_match("/^xmlns/",$k)){
//$this->xdebug("$k: $v"); //$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k)); //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){ if($ns_prefix = substr(strrchr($k,':'),1)){
@ -284,6 +297,8 @@ class XMLSchema extends nusoap_base {
case 'complexType': case 'complexType':
array_push($this->complexTypeStack, $this->currentComplexType); array_push($this->complexTypeStack, $this->currentComplexType);
if(isset($attrs['name'])){ 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->xdebug('processing named complexType '.$attrs['name']);
//$this->currentElement = false; //$this->currentElement = false;
$this->currentComplexType = $attrs['name']; $this->currentComplexType = $attrs['name'];
@ -296,15 +311,16 @@ class XMLSchema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
} }
}else{ } else {
$this->xdebug('processing unnamed complexType for element '.$this->currentElement); $name = $this->CreateTypeName($this->currentElement);
$this->currentComplexType = $this->currentElement . '_ContainedType'; $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
$this->currentComplexType = $name;
//$this->currentElement = false; //$this->currentElement = false;
$this->complexTypes[$this->currentComplexType] = $attrs; $this->complexTypes[$this->currentComplexType] = $attrs;
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType'; $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
@ -315,7 +331,7 @@ class XMLSchema extends nusoap_base {
// minOccurs="0" maxOccurs="unbounded" /> // minOccurs="0" maxOccurs="unbounded" />
// </sequence> // </sequence>
// </complexType> // </complexType>
if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){ if(isset($attrs['base']) && preg_match('/:Array$/',$attrs['base'])){
$this->xdebug('complexType is unusual array'); $this->xdebug('complexType is unusual array');
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array'; $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
} else { } else {
@ -325,9 +341,6 @@ class XMLSchema extends nusoap_base {
break; break;
case 'element': case 'element':
array_push($this->elementStack, $this->currentElement); 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'])) { if (!isset($attrs['form'])) {
$attrs['form'] = $this->schemaInfo['elementFormDefault']; $attrs['form'] = $this->schemaInfo['elementFormDefault'];
} }
@ -351,24 +364,25 @@ class XMLSchema extends nusoap_base {
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type']; $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
} }
$this->currentElement = $attrs['name']; $this->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$ename = $attrs['name']; $ename = $attrs['name'];
} elseif(isset($attrs['ref'])){ } elseif(isset($attrs['ref'])){
$this->xdebug("processing element as ref to ".$attrs['ref']); $this->xdebug("processing element as ref to ".$attrs['ref']);
$this->currentElement = "ref to ".$attrs['ref']; $this->currentElement = "ref to ".$attrs['ref'];
$ename = $this->getLocalPart($attrs['ref']); $ename = $this->getLocalPart($attrs['ref']);
} else { } 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->currentElement = $attrs['name'];
$this->elements[ $attrs['name'] ] = $attrs; $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['name'] . '_ContainedType';
$this->elements[ $attrs['name'] ]['type'] = $attrs['type'];
$ename = $attrs['name']; $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; $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; break;
case 'enumeration': // restriction value list member 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'] ]['typeClass'] = 'simpleType';
$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar'; $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
} else { } else {
$this->xdebug('processing unnamed simpleType for element '.$this->currentElement); $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
$this->currentSimpleType = $this->currentElement . '_ContainedType'; $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
$this->currentSimpleType = $name;
//$this->currentElement = false; //$this->currentElement = false;
$this->simpleTypes[$this->currentSimpleType] = $attrs; $this->simpleTypes[$this->currentSimpleType] = $attrs;
$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar'; $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
@ -578,13 +593,13 @@ class XMLSchema extends nusoap_base {
// simple types // simple types
if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
foreach($this->simpleTypes as $typeName => $eParts){ 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'])) { if (isset($eParts['enumeration'])) {
foreach ($eParts['enumeration'] as $e) { foreach ($eParts['enumeration'] as $e) {
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n"; $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
} }
} }
$xml .= " </$schemaPrefix:simpleType>"; $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
} }
} }
// elements // elements
@ -600,9 +615,15 @@ class XMLSchema extends nusoap_base {
} }
} }
// finish 'er up // 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) { 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"; $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
return $xml; return $xml;
@ -624,8 +645,8 @@ class XMLSchema extends nusoap_base {
* returns false if no type exists, or not w/ the given namespace * 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' * else returns a string that is either a native php type, or 'struct'
* *
* @param string $type, name of defined type * @param string $type name of defined type
* @param string $ns, namespace of type * @param string $ns namespace of type
* @return mixed * @return mixed
* @access public * @access public
* @deprecated * @deprecated
@ -656,7 +677,7 @@ class XMLSchema extends nusoap_base {
* *
* For simpleType or element, the array has different keys. * For simpleType or element, the array has different keys.
* *
* @param string * @param string $type
* @return mixed * @return mixed
* @access public * @access public
* @see addComplexType * @see addComplexType
@ -665,10 +686,17 @@ class XMLSchema extends nusoap_base {
*/ */
function getTypeDef($type){ function getTypeDef($type){
//$this->debug("in getTypeDef for type $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"); $this->xdebug("in getTypeDef, found complexType $type");
return $this->complexTypes[$type]; return $this->complexTypes[$type];
} elseif(isset($this->simpleTypes[$type])){ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
$this->xdebug("in getTypeDef, found simpleType $type"); $this->xdebug("in getTypeDef, found simpleType $type");
if (!isset($this->simpleTypes[$type]['phpType'])) { if (!isset($this->simpleTypes[$type]['phpType'])) {
// get info for type to tack onto the simple type // get info for type to tack onto the simple type
@ -713,7 +741,7 @@ class XMLSchema extends nusoap_base {
} elseif(isset($this->attributes[$type])){ } elseif(isset($this->attributes[$type])){
$this->xdebug("in getTypeDef, found attribute $type"); $this->xdebug("in getTypeDef, found attribute $type");
return $this->attributes[$type]; return $this->attributes[$type];
} elseif (ereg('_ContainedType$', $type)) { } elseif (preg_match('/_ContainedType$/', $type)) {
$this->xdebug("in getTypeDef, have an untyped element $type"); $this->xdebug("in getTypeDef, have an untyped element $type");
$typeDef['typeClass'] = 'simpleType'; $typeDef['typeClass'] = 'simpleType';
$typeDef['phpType'] = 'scalar'; $typeDef['phpType'] = 'scalar';
@ -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 * 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 * @return mixed
* @access public * @access public
* @deprecated * @deprecated
@ -737,7 +765,7 @@ class XMLSchema extends nusoap_base {
if($typeDef = $this->getTypeDef($type)){ if($typeDef = $this->getTypeDef($type)){
$str .= '<'.$type; $str .= '<'.$type;
if(is_array($typeDef['attrs'])){ if(is_array($typeDef['attrs'])){
foreach($attrs as $attName => $data){ foreach($typeDef['attrs'] as $attName => $data){
$str .= " $attName=\"{type = ".$data['type']."}\""; $str .= " $attName=\"{type = ".$data['type']."}\"";
} }
} }
@ -762,8 +790,8 @@ class XMLSchema extends nusoap_base {
* returns HTML form elements that allow a user * returns HTML form elements that allow a user
* to enter values for creating an instance of the given type. * to enter values for creating an instance of the given type.
* *
* @param string $name, name for type instance * @param string $name name for type instance
* @param string $type, name of type * @param string $type name of type
* @return string * @return string
* @access public * @access public
* @deprecated * @deprecated
@ -865,7 +893,7 @@ class XMLSchema extends nusoap_base {
* @param string $phpType (should always be scalar) * @param string $phpType (should always be scalar)
* @param array $enumeration array of values * @param array $enumeration array of values
* @access public * @access public
* @see xmlschema * @see nusoap_xmlschema
* @see getTypeDef * @see getTypeDef
*/ */
function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) { 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 * adds an element to the schema
* *
* @param array $attrs attributes that must include name and type * @param array $attrs attributes that must include name and type
* @see xmlschema * @see nusoap_xmlschema
* @access public * @access public
*/ */
function addElement($attrs) { 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 License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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: If you have any questions or comments, please email:
Dietrich Ayala Dietrich Ayala
@ -37,15 +43,15 @@ require_once('Mail/mimeDecode.php');
require_once('Mail/mimePart.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. * 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 * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
* @version $Id$ * @version $Id$
* @access public * @access public
*/ */
class soapclientmime extends soapclient_nusoap { class nusoap_client_mime extends nusoap_client {
/** /**
* @var array Each array element in the return is an associative array with keys * @var array Each array element in the return is an associative array with keys
* data, filename, contenttype, cid * data, filename, contenttype, cid
@ -126,7 +132,7 @@ class soapclientmime extends soapclient_nusoap {
*/ */
function getHTTPBody($soapmsg) { function getHTTPBody($soapmsg) {
if (count($this->requestAttachments) > 0) { 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); $mimeMessage =& new Mail_mimePart('', $params);
unset($params); unset($params);
@ -231,8 +237,9 @@ class soapclientmime extends soapclient_nusoap {
$structure = Mail_mimeDecode::decode($params); $structure = Mail_mimeDecode::decode($params);
foreach ($structure->parts as $part) { 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']); $this->debug('Have root part of type ' . $part->headers['content-type']);
$root = $part->body;
$return = parent::parseResponse($part->headers, $part->body); $return = parent::parseResponse($part->headers, $part->body);
} else { } else {
$this->debug('Have an attachment of type ' . $part->headers['content-type']); $this->debug('Have an attachment of type ' . $part->headers['content-type']);
@ -245,27 +252,36 @@ class soapclientmime extends soapclient_nusoap {
} }
if (isset($return)) { if (isset($return)) {
$this->responseData = $root;
return $return; return $return;
} }
$this->setError('No root part found in multipart/related content'); $this->setError('No root part found in multipart/related content');
return; return '';
} }
$this->debug('Not multipart/related'); $this->debug('Not multipart/related');
return parent::parseResponse($headers, $data); 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. * 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 * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
* @version $Id$ * @version $Id$
* @access public * @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 * @var array Each array element in the return is an associative array with keys
* data, filename, contenttype, cid * data, filename, contenttype, cid
@ -346,7 +362,7 @@ class nusoapservermime extends soap_server {
*/ */
function getHTTPBody($soapmsg) { function getHTTPBody($soapmsg) {
if (count($this->responseAttachments) > 0) { 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); $mimeMessage =& new Mail_mimePart('', $params);
unset($params); unset($params);
@ -451,7 +467,7 @@ class nusoapservermime extends soap_server {
$structure = Mail_mimeDecode::decode($params); $structure = Mail_mimeDecode::decode($params);
foreach ($structure->parts as $part) { 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']); $this->debug('Have root part of type ' . $part->headers['content-type']);
$return = parent::parseRequest($part->headers, $part->body); $return = parent::parseRequest($part->headers, $part->body);
} else { } else {
@ -475,4 +491,11 @@ class nusoapservermime extends soap_server {
return parent::parseRequest($headers, $data); return parent::parseRequest($headers, $data);
} }
} }
/*
* For backwards compatiblity
*/
class nusoapservermime extends nusoap_server_mime {
}
?> ?>