The NuSOAP project home is:
http://sourceforge.net/projects/nusoap/
-The primary support for NuSOAP is the mailing list:
-nusoap-general@lists.sourceforge.net
+The primary support for NuSOAP is the Help forum on the project home page.
If you have any questions or comments, please email:
// class variable emulation
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
-$GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
+$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
/**
*
* @var string
* @access private
*/
- var $version = '0.7.3';
+ var $version = '0.9.5';
/**
* CVS revision for HTTP headers.
*
* @var string
* @access private
*/
- var $revision = '$Revision$';
+ var $revision = '$Revision: 1.123 $';
/**
* Current error string (manipulated by getError/setError)
*
* @access public
*/
function nusoap_base() {
- $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
}
/**
* @access public
*/
function getGlobalDebugLevel() {
- return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
+ return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
}
/**
* @access public
*/
function setGlobalDebugLevel($level) {
- $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
+ $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
}
/**
/**
* convert unix timestamp to ISO 8601 compliant date string
*
-* @param string $timestamp Unix time stamp
+* @param int $timestamp Unix time stamp
* @param boolean $utc Whether the time stamp is UTC or local
+* @return mixed ISO 8601 date string or false
* @access public
*/
function timestamp_to_iso8601($timestamp,$utc=true){
$datestr = date('Y-m-d\TH:i:sO',$timestamp);
+ $pos = strrpos($datestr, "+");
+ if ($pos === FALSE) {
+ $pos = strrpos($datestr, "-");
+ }
+ if ($pos !== FALSE) {
+ if (strlen($datestr) == $pos + 5) {
+ $datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
+ }
+ }
if($utc){
- $pregStr =
+ $pattern = '/'.
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
- '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+ '/';
- if(preg_match("/$pregStr/",$datestr,$regs)){
+ if(preg_match($pattern,$datestr,$regs)){
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
}
return false;
* convert ISO 8601 compliant date string to unix timestamp
*
* @param string $datestr ISO 8601 compliant date string
+* @return mixed Unix timestamp (int) or false
* @access public
*/
function iso8601_to_timestamp($datestr){
- $pregStr =
+ $pattern = '/'.
'([0-9]{4})-'. // centuries & years CCYY-
'([0-9]{2})-'. // months MM-
'([0-9]{2})'. // days DD
'([0-9]{2}):'. // hours hh:
'([0-9]{2}):'. // minutes mm:
'([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
- '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
- if(preg_match("/$pregStr/",$datestr,$regs)){
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'. // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
+ '/';
+ if(preg_match($pattern,$datestr,$regs)){
// not utc
if($regs[8] != 'Z'){
$op = substr($regs[8],0,1);
* Mainly used for returning faults from deployed functions
* in a server instance.
* @author Dietrich Ayala <dietrich@ganx4.com>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class nusoap_fault extends nusoap_base {
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class nusoap_xmlschema extends nusoap_base {
if(count($attrs) > 0){
foreach($attrs as $k => $v){
// if ns declarations, add to class level array of valid namespaces
- if(preg_match("/^xmlns/",$k)){
+ if(preg_match('/^xmlns/',$k)){
//$this->xdebug("$k: $v");
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
if($ns_prefix = substr(strrchr($k,':'),1)){
$this->xdebug("parsing attribute:");
$this->appendDebug($this->varDump($attrs));
if (!isset($attrs['form'])) {
+ // TODO: handle globals
$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
}
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
}
break;
case 'complexContent': // (optional) content for a complexType
+ $this->xdebug("do nothing for element $name");
break;
case 'complexType':
array_push($this->complexTypeStack, $this->currentComplexType);
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
}
}
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
break;
case 'element':
array_push($this->elementStack, $this->currentElement);
if (!isset($attrs['form'])) {
+ if ($this->currentComplexType) {
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
+ } else {
+ // global
+ $attrs['form'] = 'qualified';
+ }
}
if(isset($attrs['type'])){
$this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
case 'extension': // simpleContent or complexContent type extension
$this->xdebug('extension ' . $attrs['base']);
if ($this->currentComplexType) {
+ $ns = $this->getPrefix($attrs['base']);
+ if ($ns == '') {
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
+ } else {
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
}
+ } else {
+ $this->xdebug('no current complexType to set extensionBase');
+ }
break;
case 'import':
if (isset($attrs['schemaLocation'])) {
- //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
+ $this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
$this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
} else {
- //$this->xdebug('import namespace ' . $attrs['namespace']);
+ $this->xdebug('import namespace ' . $attrs['namespace']);
$this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
$this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
}
}
break;
+ case 'include':
+ if (isset($attrs['schemaLocation'])) {
+ $this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
+ $this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
+ } else {
+ $this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
+ }
+ break;
case 'list': // simpleType value list
+ $this->xdebug("do nothing for element $name");
break;
case 'restriction': // simpleType, simpleContent or complexContent value restriction
$this->xdebug('restriction ' . $attrs['base']);
}
break;
case 'simpleContent': // (optional) content for a complexType
+ if ($this->currentComplexType) { // This should *always* be
+ $this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
+ } else {
+ $this->xdebug("do nothing for element $name because there is no current complexType");
+ }
break;
case 'simpleType':
array_push($this->simpleTypeStack, $this->currentSimpleType);
}
break;
case 'union': // simpleType type list
+ $this->xdebug("do nothing for element $name");
break;
default:
- //$this->xdebug("do not have anything to do for element $name");
+ $this->xdebug("do not have any logic to process element $name");
}
}
// move on...
if($name == 'complexType'){
$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
+ $this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
$this->currentComplexType = array_pop($this->complexTypeStack);
//$this->currentElement = false;
}
}
if($name == 'simpleType'){
$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
+ $this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
$this->currentSimpleType = array_pop($this->simpleTypeStack);
}
}
if (isset($etype['elements'])) {
$this->elements[$type]['elements'] = $etype['elements'];
}
+ if (isset($etype['extensionBase'])) {
+ $this->elements[$type]['extensionBase'] = $etype['extensionBase'];
+ }
} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
$this->xdebug("in getTypeDef, element $type is an XSD type");
$this->elements[$type]['phpType'] = 'scalar';
* xsd:anyType and user-defined types.
*
* @author Dietrich Ayala <dietrich@ganx4.com>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class soapval extends nusoap_base {
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class soap_transport_http extends nusoap_base {
$this->ch_options = $curl_options;
}
$this->use_curl = $use_curl;
- preg_match('/\$Revisio/' . 'n: ([^ ]+)', $this->revision, $rev);
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
}
} else if ($this->io_method() == 'curl') {
if (!extension_loaded('curl')) {
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
- $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to included cURL.');
+ $this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
return false;
}
// Avoid warnings when PHP does not have these options
$this->setHeader('Connection', 'close');
$this->persistentConnection = false;
}
- set_magic_quotes_runtime(0);
- // deprecated
+ // deprecated as of PHP 5.3.0
+ //set_magic_quotes_runtime(0);
$this->encoding = $enc;
}
}
// debugging guides.
// add content-length header
+ if ($this->request_method != 'GET') {
$this->setHeader('Content-Length', strlen($data));
+ }
// start building outgoing payload:
if ($this->proxy) {
*/
function parseCookie($cookie_str) {
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
- $data = split(';', $cookie_str);
+ $data = preg_split('/;/', $cookie_str);
$value_str = $data[0];
$cookie_param = 'domain=';
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class nusoap_server extends nusoap_base {
function service($data){
global $HTTP_SERVER_VARS;
+ if (isset($_SERVER['REQUEST_METHOD'])) {
+ $rm = $_SERVER['REQUEST_METHOD'];
+ } elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
+ $rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
+ } else {
+ $rm = '';
+ }
+
if (isset($_SERVER['QUERY_STRING'])) {
$qs = $_SERVER['QUERY_STRING'];
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
} else {
$qs = '';
}
- $this->debug("In service, query string=$qs");
+ $this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
- if (preg_match('/wsdl/', $qs) ){
+ if ($rm == 'POST') {
+ $this->debug("In service, invoke the request");
+ $this->parse_request($data);
+ if (! $this->fault) {
+ $this->invoke_method();
+ }
+ if (! $this->fault) {
+ $this->serialize_return();
+ }
+ $this->send_response();
+ } elseif (preg_match('/wsdl/', $qs) ){
$this->debug("In service, this is a request for WSDL");
if($this->externalWSDLURL){
- if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
+ if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
+ $this->debug("In service, re-direct for WSDL");
header('Location: '.$this->externalWSDLURL);
} else { // assume file
+ $this->debug("In service, use file passthru for WSDL");
header("Content-Type: text/xml\r\n");
+ $pos = strpos($this->externalWSDLURL, "file://");
+ if ($pos === false) {
+ $filename = $this->externalWSDLURL;
+ } else {
+ $filename = substr($this->externalWSDLURL, $pos + 7);
+ }
$fp = fopen($this->externalWSDLURL, 'r');
fpassthru($fp);
}
} elseif ($this->wsdl) {
+ $this->debug("In service, serialize WSDL");
header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
print $this->wsdl->serialize($this->debug_flag);
if ($this->debug_flag) {
print $this->getDebugAsXMLComment();
}
} else {
+ $this->debug("In service, there is no WSDL");
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
print "This service does not provide WSDL";
}
- } elseif ($data == '' && $this->wsdl) {
- $this->debug("In service, there is no data, so return Web description");
+ } elseif ($this->wsdl) {
+ $this->debug("In service, return Web description");
print $this->wsdl->webDescription();
} else {
- $this->debug("In service, invoke the request");
- $this->parse_request($data);
- if (! $this->fault) {
- $this->invoke_method();
- }
- if (! $this->fault) {
- $this->serialize_return();
- }
- $this->send_response();
+ $this->debug("In service, no Web description");
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
+ print "This service does not provide a Web description";
}
}
function invoke_method() {
$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
+ //
+ // if you are debugging in this area of the code, your service uses a class to implement methods,
+ // you use SOAP RPC, and the client is .NET, please be aware of the following...
+ // when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
+ // method name. that is fine for naming the .NET methods. it is not fine for properly constructing
+ // the XML request and reading the XML response. you need to add the RequestElementName and
+ // ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
+ // generates for the method. these parameters are used to specify the correct XML element names
+ // for .NET to use, i.e. the names with the '.' in them.
+ //
+ $orig_methodname = $this->methodname;
if ($this->wsdl) {
if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
// if a . is present in $this->methodname, we see if there is a class in scope,
// which could be referred to. We will also distinguish between two deliminators,
// to allow methods to be called a the class or an instance
- $class = '';
- $method = '';
if (strpos($this->methodname, '..') > 0) {
$delim = '..';
} else if (strpos($this->methodname, '.') > 0) {
} else {
$delim = '';
}
+ $this->debug("in invoke_method, delim=$delim");
- if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
- class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
+ $class = '';
+ $method = '';
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
+ $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
+ if (class_exists($try_class)) {
// get the class and method name
- $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
+ $class = $try_class;
$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
$this->debug("in invoke_method, class=$class method=$method delim=$delim");
+ } else {
+ $this->debug("in invoke_method, class=$try_class not found");
+ }
+ } else {
+ $try_class = '';
+ $this->debug("in invoke_method, no class to try");
}
// does method exist?
if (!function_exists($this->methodname)) {
$this->debug("in invoke_method, function '$this->methodname' not found!");
$this->result = 'fault: method not found';
- $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
return;
}
} else {
if (!in_array($method_to_compare, get_class_methods($class))) {
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
$this->result = 'fault: method not found';
- $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
return;
}
}
function serialize_return() {
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
// if fault
- if (isset($this->methodreturn) && ((@get_class($this->methodreturn) == 'soap_fault') || (@get_class($this->methodreturn) == 'nusoap_fault'))) {
+ if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
$this->debug('got a fault object from method');
$this->fault = $this->methodreturn;
return;
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
if ($this->opData['output']['use'] == 'literal') {
// http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace
+ if ($this->methodURI) {
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
} else {
+ $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
+ }
+ } else {
+ if ($this->methodURI) {
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
+ } else {
+ $payload = '<'.$this->methodname.'Response>'.$return_val.'</'.$this->methodname.'Response>';
+ }
}
} else {
$this->debug('style is not rpc for serialization: assume document');
//if($this->debug_flag){
$this->appendDebug($this->wsdl->getDebug());
// }
- if (isset($opData['output']['encodingStyle'])) {
- $encodingStyle = $opData['output']['encodingStyle'];
+ if (isset($this->opData['output']['encodingStyle'])) {
+ $encodingStyle = $this->opData['output']['encodingStyle'];
} else {
$encodingStyle = '';
}
$payload .= $this->getDebugAsXMLComment();
}
$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
- preg_match('/\$Revisio: ([^ ]+)/', $this->revision, $rev);
+ preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
// Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n";
* @access private
*/
function parseRequest($headers, $data) {
- $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
+ $this->appendDebug($this->varDump($headers));
+ if (!isset($headers['content-type'])) {
+ $this->setError('Request not of type text/xml (no content-type header)');
+ return false;
+ }
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Request not of type text/xml');
return false;
if(false == $use) {
$use = "encoded";
}
- if ($use == 'encoded' && $encodingStyle = '') {
+ if ($use == 'encoded' && $encodingStyle == '') {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
}
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class wsdl extends nusoap_base {
$this->appendDebug($tr->getDebug());
// catch errors
if($err = $tr->getError() ){
- $errstr = 'HTTP ERROR: '.$err;
+ $errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: '.$err;
$this->debug($errstr);
$this->setError($errstr);
unset($tr);
if (count($attrs) > 0) {
// register namespace declarations
foreach($attrs as $k => $v) {
- if (preg_match("/^xmlns/", $k)) {
+ if (preg_match('/^xmlns/',$k)) {
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
$this->namespaces[$ns_prefix] = $v;
} else {
*/
function end_element($parser, $name){
// unset schema status
- if (/*ereg('types$', $name) ||*/ preg_match('/schema$/', $name)) {
+ if (/*preg_match('/types$/', $name) ||*/ preg_match('/schema$/', $name)) {
$this->status = "";
$this->appendDebug($this->currentSchema->getDebug());
$this->currentSchema->clearDebug();
/**
* returns an assoc array of operation names => operation data
*
+ * @param string $portName WSDL port name
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
* @return array
* @access public
*/
- function getOperations($bindingType = 'soap') {
+ function getOperations($portName = '', $bindingType = 'soap') {
$ops = array();
if ($bindingType == 'soap') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
} elseif ($bindingType == 'soap12') {
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
+ } else {
+ $this->debug("getOperations bindingType $bindingType may not be supported");
}
+ $this->debug("getOperations for port '$portName' bindingType $bindingType");
// loop thru ports
foreach($this->ports as $port => $portData) {
+ $this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
+ if ($portName == '' || $port == $portName) {
// binding type of port matches parameter
if ($portData['bindingType'] == $bindingType) {
- //$this->debug("getOperations for port $port");
+ $this->debug("getOperations found port $port bindingType $bindingType");
//$this->debug("port data: " . $this->varDump($portData));
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
// merge bindings
}
}
}
+ }
+ if (count($ops) == 0) {
+ $this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
+ }
return $ops;
}
for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
$xs = &$this->schemas[$ns][$i];
$t = $xs->getTypeDef($type);
- //$this->appendDebug($xs->getDebug());
- //$xs->clearDebug();
+ $this->appendDebug($xs->getDebug());
+ $xs->clearDebug();
if ($t) {
+ $this->debug("in getTypeDef: found type $type");
if (!isset($t['phpType'])) {
// get info for type to tack onto the element
$uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
if (isset($etype['attrs'])) {
$t['attrs'] = $etype['attrs'];
}
+ } else {
+ $this->debug("did not find type for [element] $type");
}
}
return $t;
}
}
+ $this->debug("in getTypeDef: did not find type $type");
} else {
$this->debug("in getTypeDef: do not have schema for namespace $ns");
}
background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
.title {
font-family: arial; font-size: 26px; color: #ffffff;
- background-color: #999999; width: 105%; margin-left: 0px;
- padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
+ background-color: #999999; width: 100%;
+ margin-left: 0px; margin-right: 0px;
+ padding-top: 10px; padding-bottom: 10px;}
.hidden {
position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
font-family: arial; overflow: hidden; width: 600;
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])) {
+ if (isset($parameters[$name])) {
$this->debug("in parametersMatchWrapped: have parameter named $name");
$matches++;
} else {
// 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)) {
+ if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
+ // TODO: consider checking here for double-wrapping, when
+ // service function wraps, then NuSOAP wraps again
+ $this->debug("change simple array to associative with 'parameters' element");
+ $parameters['parameters'] = $parameters[0];
+ unset($parameters[0]);
+ }
+ if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
$this->debug('check whether caller\'s parameters match the wrapped ones');
if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
$this->debug('wrap the parameters for the caller');
$uqType = substr($uqType, 0, -1);
}
}
+ if (!isset($typeDef['phpType'])) {
+ $this->setError("$type ($uqType) has no phpType.");
+ $this->debug("in serializeType: $type ($uqType) has no phpType.");
+ return false;
+ }
$phpType = $typeDef['phpType'];
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
// if php type == struct, map value to the <all> element names
}
if (is_null($value)) {
if ($use == 'literal') {
- // TODO: depends on minOccurs
+ // TODO: depends on minOccurs and nillable
$xml = "<$elementName$elementNS/>";
} else {
$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
}
+ if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
+ if (isset($value['!'])) {
+ $xml .= $value['!'];
+ $this->debug("in serializeType: serialized simpleContent for type $type");
+ } else {
+ $this->debug("in serializeType: no simpleContent to serialize for type $type");
+ }
+ } else {
+ // complexContent
$xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
+ }
$xml .= "</$elementName>";
} else {
$this->debug("in serializeType: phpType is struct, but value is not an array");
* @access private
*/
function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
+ $this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
$xml = '';
+ if (isset($typeDef['extensionBase'])) {
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
+ if ($this->getNamespaceFromPrefix($nsx)) {
+ $nsx = $this->getNamespaceFromPrefix($nsx);
+ }
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
+ $this->debug("serialize attributes for extension base $nsx:$uqTypex");
+ $xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
+ } else {
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
+ }
+ }
if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
$this->debug("serialize attributes for XML Schema type $ns:$uqType");
if (is_array($value)) {
} else {
$this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
}
- if (isset($typeDef['extensionBase'])) {
- $ns = $this->getPrefix($typeDef['extensionBase']);
- $uqType = $this->getLocalPart($typeDef['extensionBase']);
- if ($this->getNamespaceFromPrefix($ns)) {
- $ns = $this->getNamespaceFromPrefix($ns);
- }
- if ($typeDef = $this->getTypeDef($uqType, $ns)) {
- $this->debug("serialize attributes for extension base $ns:$uqType");
- $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
- } else {
- $this->debug("extension base $ns:$uqType is not a supported type");
- }
- }
return $xml;
}
* @access private
*/
function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
+ $this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
$xml = '';
+ if (isset($typeDef['extensionBase'])) {
+ $nsx = $this->getPrefix($typeDef['extensionBase']);
+ $uqTypex = $this->getLocalPart($typeDef['extensionBase']);
+ if ($this->getNamespaceFromPrefix($nsx)) {
+ $nsx = $this->getNamespaceFromPrefix($nsx);
+ }
+ if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
+ $this->debug("serialize elements for extension base $nsx:$uqTypex");
+ $xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
+ } else {
+ $this->debug("extension base $nsx:$uqTypex is not a supported type");
+ }
+ }
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
$this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
if (is_array($value)) {
}
}
} else {
- if (isset($attrs['type']) || isset($attrs['ref'])) {
+ if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
+ // do nothing
+ } elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
+ // TODO: serialize a nil correctly, but for now serialize schema-defined type
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
+ } elseif (isset($attrs['type']) || isset($attrs['ref'])) {
// serialize schema-defined type
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
} else {
} else {
$this->debug("no elements to serialize for XML Schema type $ns:$uqType");
}
- if (isset($typeDef['extensionBase'])) {
- $ns = $this->getPrefix($typeDef['extensionBase']);
- $uqType = $this->getLocalPart($typeDef['extensionBase']);
- if ($this->getNamespaceFromPrefix($ns)) {
- $ns = $this->getNamespaceFromPrefix($ns);
- }
- if ($typeDef = $this->getTypeDef($uqType, $ns)) {
- $this->debug("serialize elements for extension base $ns:$uqType");
- $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
- } else {
- $this->debug("extension base $ns:$uqType is not a supported type");
- }
- }
return $xml;
}
if ($style == 'document') {
$elements = array();
foreach ($in as $n => $t) {
- $elements[$n] = array('name' => $n, 'type' => $t);
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
}
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
$elements = array();
foreach ($out as $n => $t) {
- $elements[$n] = array('name' => $n, 'type' => $t);
+ $elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
}
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class nusoap_parser extends nusoap_base {
$this->debug("XML payload:\n" . $xml);
$this->setError($err);
} else {
+ $this->debug('in nusoap_parser ctor, message:');
+ $this->appendDebug($this->varDump($this->message));
$this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
// get final value
$this->soapresponse = $this->message[$this->root_struct]['result'];
$name = substr(strstr($name,':'),1);
}
// set status
- if($name == 'Envelope'){
+ if ($name == 'Envelope' && $this->status == '') {
$this->status = 'envelope';
- } elseif($name == 'Header' && $this->status = 'envelope'){
+ } elseif ($name == 'Header' && $this->status == 'envelope') {
$this->root_header = $pos;
$this->status = 'header';
- } elseif($name == 'Body' && $this->status = 'envelope'){
+ } elseif ($name == 'Body' && $this->status == 'envelope'){
$this->status = 'body';
$this->body_position = $pos;
// set method
}
} elseif($key_localpart == 'arrayType'){
$this->message[$pos]['type'] = 'array';
- /* do arrayType preg here
+ /* do arrayType ereg here
[1] arrayTypeValue ::= atype asize
[2] atype ::= QName rank*
[3] rank ::= '[' (',')* ']'
[5] length ::= nextDimension* Digit+
[6] nextDimension ::= Digit+ ','
*/
- $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
- if(preg_match("/$expr/",$value,$regs)){
+ $expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
+ if(preg_match($expr,$value,$regs)){
$this->message[$pos]['typePrefix'] = $regs[1];
$this->message[$pos]['arrayTypePrefix'] = $regs[1];
if (isset($this->namespaces[$regs[1]])) {
if($pos == $this->root_struct){
$this->status = 'body';
$this->root_struct_namespace = $this->message[$pos]['namespace'];
- } elseif($name == 'Body'){
+ } elseif ($pos == $this->root_header) {
+ $this->status = 'envelope';
+ } elseif ($name == 'Body' && $this->status == 'body') {
$this->status = 'envelope';
- } elseif($name == 'Header'){
+ } elseif ($name == 'Header' && $this->status == 'header') { // will never happen
$this->status = 'envelope';
- } elseif($name == 'Envelope'){
- //
+ } elseif ($name == 'Envelope' && $this->status == 'envelope') {
+ $this->status = '';
}
// set parent back to my parent
$this->parent = $this->message[$pos]['parent'];
*
* @author Dietrich Ayala <dietrich@ganx4.com>
* @author Scott Nichol <snichol@users.sourceforge.net>
-* @version $Id$
+* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
* @access public
*/
class nusoap_client extends nusoap_base {
var $proxyport = '';
var $proxyusername = '';
var $proxypassword = '';
+ var $portName = ''; // port name to use in WSDL
var $xml_encoding = ''; // character set encoding of incoming (response) messages
var $http_encoding = false;
var $timeout = 0; // HTTP connection timeout
* constructor
*
* @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
- * @param bool $wsdl optional, set to true if using WSDL
- * @param int $portName optional portName in WSDL document
- * @param string $proxyhost
- * @param string $proxyport
- * @param string $proxyusername
- * @param string $proxypassword
+ * @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
+ * @param string $proxyhost optional
+ * @param string $proxyport optional
+ * @param string $proxyusername optional
+ * @param string $proxypassword optional
* @param integer $timeout set the connection timeout
* @param integer $response_timeout set the response timeout
+ * @param string $portName optional portName in WSDL document
* @access public
*/
- function nusoap_client($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, $portName = ''){
parent::nusoap_base();
$this->endpoint = $endpoint;
$this->proxyhost = $proxyhost;
$this->proxypassword = $proxypassword;
$this->timeout = $timeout;
$this->response_timeout = $response_timeout;
+ $this->portName = $portName;
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
$this->appendDebug('endpoint=' . $this->varDump($endpoint));
* @param boolean $rpcParams optional (no longer used)
* @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
* @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
- * @return mixed response from SOAP call
+ * @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
* @access public
*/
function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
// operation not in WSDL
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
- $this->setError( 'operation '.$operation.' not present.');
- $this->debug("operation '$operation' not present.");
+ $this->setError('operation '.$operation.' not present in WSDL.');
+ $this->debug("operation '$operation' not present in WSDL.");
return false;
} else {
// no WSDL
$this->debug('checkWSDL');
// catch errors
if ($errstr = $this->wsdl->getError()) {
+ $this->appendDebug($this->wsdl->getDebug());
+ $this->wsdl->clearDebug();
$this->debug('got wsdl error: '.$errstr);
$this->setError('wsdl error: '.$errstr);
- } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap')) {
+ $this->appendDebug($this->wsdl->getDebug());
+ $this->wsdl->clearDebug();
$this->bindingType = 'soap';
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
- } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
+ } elseif ($this->operations = $this->wsdl->getOperations($this->portName, 'soap12')) {
+ $this->appendDebug($this->wsdl->getDebug());
+ $this->wsdl->clearDebug();
$this->bindingType = 'soap12';
$this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
$this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
} else {
+ $this->appendDebug($this->wsdl->getDebug());
+ $this->wsdl->clearDebug();
$this->debug('getOperations returned false');
$this->setError('no operations defined in the WSDL document!');
}
*/
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 = 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();
function parseResponse($headers, $data) {
$this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
$this->appendDebug($this->varDump($headers));
+ if (!isset($headers['content-type'])) {
+ $this->setError('Response not of type text/xml (no content-type header)');
+ return false;
+ }
if (!strstr($headers['content-type'], 'text/xml')) {
$this->setError('Response not of type text/xml: ' . $headers['content-type']);
return false;