cvs: pear /SOAP Client.php Fault.php Message.php Parser.php Transport.php Value.php WSDL.php globals.php package.xml /SOAP/Transport HTTP.php
SMTP.php /SOAP/interop client_library.php client_params.php client_round2_base.php client_round2_pretty.php

From: Date: Thu, 28 Feb 2002 03:38:28 +0000
Subject: cvs: pear /SOAP Client.php Fault.php Message.php Parser.php Transport.php Value.php WSDL.php globals.php package.xml /SOAP/Transport HTTP.php
SMTP.php /SOAP/interop client_library.php client_params.php client_round2_base.php client_round2_pretty.php
Groups: php.pear.cvs 
Request: Send a blank email to pear-cvs+get-2624@lists.php.net to get a copy of this message
shane Wed Feb 27 22:38:28 2002 EDT Added files: /pear/SOAP Fault.php /pear/SOAP/interop client_library.php client_round2_pretty.php Modified files: /pear/SOAP Client.php Message.php Parser.php Transport.php Value.php WSDL.php globals.php package.xml /pear/SOAP/Transport HTTP.php SMTP.php /pear/SOAP/interop client_params.php client_round2_base.php Log: more pearification created 'prettty' html output for client interop reporting more wsdl work, wsdl import now realy does work working towards value type identification based on wsdl

Index: pear/SOAP/Client.php diff -u pear/SOAP/Client.php:1.6 pear/SOAP/Client.php:1.7 --- pear/SOAP/Client.php:1.6 Mon Feb 25 13:59:46 2002 +++ pear/SOAP/Client.php Wed Feb 27 22:38:27 2002 @@ -17,14 +17,15 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Client.php,v 1.6 2002/02/25 18:59:46 shane Exp $ +// $Id: Client.php,v 1.7 2002/02/28 03:38:27 shane Exp $ // -require_once 'PEAR.php'; +require_once 'SOAP/Value.php'; +require_once 'SOAP/Base.php'; require_once 'SOAP/Transport.php'; require_once 'SOAP/Message.php'; -require_once 'SOAP/Value.php'; require_once 'SOAP/WSDL.php'; +require_once 'SOAP/Fault.php'; /** * SOAP Client Class @@ -37,13 +38,13 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Client.php,v 1.6 2002/02/25 18:59:46 shane Exp $ +* @version $Id: Client.php,v 1.7 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Stig Bakken <ssb@fast.no> Conversion to PEAR * @author Dietrich Ayala <dietrich@ganx4.com> Original Author */ -class SOAP_Client extends PEAR +class SOAP_Client extends SOAP_Base { var $fault, $faultcode, $faultstring, $faultdetail; var $endpoint, $portName; @@ -61,7 +62,7 @@ */ function SOAP_Client($endpoint,$wsdl=false,$portName=false) { - parent::PEAR(); + parent::SOAP_Base('Client'); $this->endpoint = $endpoint; $this->portName = $portName; @@ -70,30 +71,13 @@ $this->endpointType = 'wsdl'; // instantiate wsdl class $this->wsdl = new SOAP_WSDL($this->endpoint); + if ($this->wsdl->fault) { + $this->raiseSoapFault($this->wsdl->fault); + } } } /** - * SOAP_Client::_setFault - * - * @params string method - * @params array params - * @params string namespace (not required if using wsdl) - * @params string soapAction (not required if using wsdl) - * - * @return array of results - * @access public - function _setFault($code, $summary, $detail = '') - { - $this->debug("FAULT: $summary<br>\n"); - $this->fault = true; - $this->faultcode = $code; - $this->faultstring = $summary; - $this->faultdetail = $detail; - } - */ - - /** * SOAP_Client::call * * @params string method @@ -106,39 +90,58 @@ */ function call($method,$params=array(),$namespace=false,$soapAction=false) { - $this->fault = FALSE; + $this->fault = null; if ($this->endpointType == 'wsdl') { // get portName if (!$this->portName) { $this->portName = $this->wsdl->getPortName($method); + if (PEAR::isError($this->portName)) { + return $this->raiseSoapFault($this->portName); + } } // get endpoint - if (!$this->endpoint = $this->wsdl->getEndpoint($this->portName)) { - return $this->raiseError("no port of name '$this->portName' in the wsdl at that location!", -1); + $this->endpoint = $this->wsdl->getEndpoint($this->portName); + if (PEAR::isError($this->endpoint)) { + return $this->raiseSoapFault($this->endpoint); } $this->debug("endpoint: $this->endpoint"); $this->debug("portName: $this->portName"); // get operation data - if ($opData = $this->wsdl->getOperationData($this->portName,$method)) { - $soapAction = $opData['soapAction']; - - // set input params - $i = count($opData['input']['parts'])-1; + $opData = $this->wsdl->getOperationData($this->portName,$method); + if (PEAR::isError($opData)) { + return $this->raiseSoapFault($opData); + } + $soapAction = $opData['soapAction']; + // set input params + $nparams = array(); + if (count($opData['input']['parts']) > 0) { + $i=0; + // XXX this seems very wrong, we should be creating SOAP_Value + // classes at this point, setting the correct type defined by the wsdl foreach ($opData['input']['parts'] as $name => $type) { if (isset($params[$name])) { $nparams[$name] = $params[$name]; } else { - $nparams[$name] = $params[$i]; + // XXX assuming it's an array, not a hash + $nparams[$name] = $params[$i++]; + } + if (gettype($nparams[$name]) != 'soap_value') { + // type is a qname likely, split it apart, and get the type namespace from wsdl + $type_namespace = NULL; + if ($qname = split(':', $type)) { + $type_namespace = $this->wsdl->namespaces[$qname[0]]; + $type = $qname[1]; + } + $nparams[$name] = new SOAP_Value($name, $type, $nparams[$name], NULL, $type_namespace, $this->wsdl); } } - $params = $nparams; - } else { - return $this->raiseError("could not get operation info from wsdl for operation: $method", -1); - return false; } + $params = $nparams; } + + $this->debug("soapAction: $soapAction"); // get namespace if (!$namespace && $this->endpointType == 'wsdl') { @@ -152,71 +155,74 @@ $this->debug("namespace: $namespace"); // make message - $soapmsg = new SOAP_Message($method,$params,$namespace); + $soapmsg = new SOAP_Message($method,$params,$namespace, NULL, $this->wsdl); + if ($soapmsg->fault) { + return $this->raiseSoapFault($soapmsg->fault); + } + //$this->debug( "<xmp>".$soapmsg->serialize()."</xmp>"); // instantiate client $dbg = "calling server at '$this->endpoint'..."; $soap_transport = new SOAP_Transport($this->endpoint, $this->debug_flag); - + if ($soap_transport->fault) { + return $this->raiseSoapFault($soap_transport->fault); + } + $this->debug($dbg.'instantiated client successfully'); $this->debug("endpoint: $this->endpoint<br>\n"); // send $dbg = "sending msg w/ soapaction '$soapAction'..."; + // serialize the message $soap_data = $soapmsg->serialize(); - $result = $soap_transport->send($this->response,$soap_data,$soapAction); - if ($result && !PEAR::isError($result)) { - // parse the response - $return = $soapmsg->parseResponse($this->response); - $this->debug($soap_transport->debug_str); - $this->debug($dbg.'sent message successfully and got a(n) '.gettype($return).' back'); - - // check for valid response - if (strcasecmp(get_class($return),'SOAP_Value')==0) { - // decode to native php datatype - $returnArray = $return->decode(); - // fault? - if (is_array($returnArray)) { - if (isset($returnArray['faultcode']) || isset($returnArray['SOAP-ENV:faultcode'])) { - $this->debug('got fault'); - $this->fault = true; - foreach ($returnArray as $k => $v) { - //print "$k = $v<br>"; - if (stristr($k,'faultcode')) $this->faultcode = $v; - if (stristr($k,'faultstring')) $this->faultstring = $v; - if (stristr($k,'faultdetail')) $this->faultdetail = $v; - $this->debug("$k = $v<br>"); - } - return false; - } - // return array of return values - if (count($returnArray) == 1) { - return array_shift($returnArray); - } - return $returnArray; - } - return $returnArray; - } else { - return $this->raiseError('didn\'t get SOAP_Value object back from client', -1); - } + if (PEAR::isError($soap_data)) { + return $this->raiseSoapFault($soap_data); + } + + // send the message + $this->response = $soap_transport->send($soap_data,$soapAction); + if ($soap_transport->fault) { + return $this->raiseSoapFault($this->response); } - return $this->raiseError('client send/recieve error', -1); - } - - /** - * maintains a string of debug data - * - * @params string data - * @access private - */ - function debug($string) - { - if ($this->debug_flag) { - $this->debug_data .= 'SOAP_Client: '.preg_replace("/>/","/>\r\n/",$string)."\n"; + // parse the response + $return = $soapmsg->parseResponse($this->response); + $this->debug($soap_transport->debug_str); + $this->debug($dbg.'sent message successfully and got a(n) '.gettype($return).' back'); + + // check for valid response + if (PEAR::isError($return)) { + return $this->raiseSoapFault($return); + } else + if (strcasecmp(get_class($return),'SOAP_Value')!=0) { + return $this->raiseSoapFault('didn\'t get SOAP_Value object back from client'); + } + + // decode to native php datatype + $returnArray = $return->decode(); + // fault? + if (PEAR::isError($returnArray)) { + return $this->raiseSoapFault($returnArray); + } + if (is_array($returnArray)) { + if (isset($returnArray['faultcode']) || isset($returnArray['SOAP-ENV:faultcode'])) { + foreach ($returnArray as $k => $v) { + if (stristr($k,'faultcode')) $this->faultcode = $v; + if (stristr($k,'faultstring')) $this->faultstring = $v; + if (stristr($k,'faultdetail')) $this->faultdetail = $v; + if (stristr($k,'faultactor')) $this->faultactor = $v; + } + return $this->raiseSoapFault($this->faultstring, $this->faultdetail, $this->faultactor, $this->faultcode); + } + // return array of return values + if (count($returnArray) == 1) { + return array_shift($returnArray); + } + return $returnArray; } + return $returnArray; } } Index: pear/SOAP/Message.php diff -u pear/SOAP/Message.php:1.6 pear/SOAP/Message.php:1.7 --- pear/SOAP/Message.php:1.6 Mon Feb 25 13:59:47 2002 +++ pear/SOAP/Message.php Wed Feb 27 22:38:27 2002 @@ -17,12 +17,13 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Message.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +// $Id: Message.php,v 1.7 2002/02/28 03:38:27 shane Exp $ // -require_once('SOAP/globals.php'); -require_once('SOAP/Parser.php'); -require_once('SOAP/Value.php'); +require_once 'SOAP/globals.php'; +require_once 'SOAP/Base.php'; +require_once 'SOAP/Parser.php'; +require_once 'SOAP/Value.php'; /** * SOAP Message Class @@ -31,12 +32,12 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Message.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +* @version $Id: Message.php,v 1.7 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Message * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author */ -class SOAP_Message +class SOAP_Message extends SOAP_Base { /** * SOAP::Message constructor @@ -50,14 +51,15 @@ * * @access public */ - function SOAP_Message($method,$params,$method_namespace='http://testuri.org',$new_namespaces=NULL) + function SOAP_Message($method,$params,$method_namespace='http://testuri.org',$new_namespaces=NULL, $wsdl=NULL) { // globalize method namespace global $methodNamespace; $methodNamespace = $method_namespace; + parent::SOAP_Base('Message'); // make method struct - $this->value = new SOAP_Value($method,'struct',$params,$method_namespace); + $this->value = new SOAP_Value($method,'Struct',$params,$method_namespace, NULL, $wsdl); if (is_array($new_namespaces)) { global $SOAP_namespaces; @@ -163,19 +165,6 @@ $ret = $response->getResponse(); $this->debug($response->debug_str); return $ret; - } - - /** - * maintains a string of debug data - * - * @params string data - * @access private - */ - function debug($string) - { - if ($this->debug_flag) { - $this->debug_str .= 'SOAP_Message: '.preg_replace("/>/","/>\r\n/",$string)."\n"; - } } /** Index: pear/SOAP/Parser.php diff -u pear/SOAP/Parser.php:1.6 pear/SOAP/Parser.php:1.7 --- pear/SOAP/Parser.php:1.6 Mon Feb 25 13:59:47 2002 +++ pear/SOAP/Parser.php Wed Feb 27 22:38:27 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Parser.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +// $Id: Parser.php,v 1.7 2002/02/28 03:38:27 shane Exp $ // require_once('SOAP/globals.php'); @@ -30,7 +30,7 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Parser.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +* @version $Id: Parser.php,v 1.7 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Parser * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author @@ -241,7 +241,7 @@ } $this->root_struct[] = $this->curent_root_struct = $pos; - $this->message[$pos]['type'] = 'struct'; + $this->message[$pos]['type'] = 'Struct'; } } @@ -331,7 +331,7 @@ // XXX check on integrating wsdl validation here if ($this->message[$pos]['type'] == '') { if ($this->message[$pos]['children'] != '') { - $this->message[$pos]['type'] = 'struct'; + $this->message[$pos]['type'] = 'Struct'; } else { $parent = $this->message[$pos]['parent']; if ($this->message[$parent]['type'] == 'array' && @@ -415,7 +415,7 @@ $this->debug('ERROR: did not successfully eval the msg'); $this->fault = true; - return new SOAP_Value('Fault','struct',array(new SOAP_Value('faultcode','string','SOAP-ENV:Parser'),new SOAP_Value('faultstring','string',"couldn't build response"))); + return new SOAP_Value('Fault','Struct',array(new SOAP_Value('faultcode','string','SOAP-ENV:Parser'),new SOAP_Value('faultstring','string',"couldn't build response"))); } } Index: pear/SOAP/Transport.php diff -u pear/SOAP/Transport.php:1.6 pear/SOAP/Transport.php:1.7 --- pear/SOAP/Transport.php:1.6 Mon Feb 25 13:59:47 2002 +++ pear/SOAP/Transport.php Wed Feb 27 22:38:27 2002 @@ -17,10 +17,10 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Transport.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +// $Id: Transport.php,v 1.7 2002/02/28 03:38:27 shane Exp $ // -require_once('PEAR.php'); +require_once 'SOAP/Base.php'; /** * SOAP Transport Layer @@ -29,15 +29,13 @@ * no knowlege of the transport protocols is available at this level * * @access public -* @version $Id: Transport.php,v 1.6 2002/02/25 18:59:47 shane Exp $ +* @version $Id: Transport.php,v 1.7 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Transport * @author Shane Caraveo <shane@php.net> */ -class SOAP_Transport extends PEAR +class SOAP_Transport extends SOAP_Base { var $transport = NULL; - var $outgoing_payload = ''; - var $incoming_payload = ''; var $errmsg = ''; /** @@ -49,6 +47,7 @@ */ function SOAP_Transport($url, $debug = 0) { + parent::SOAP_Base('TRANSPORT'); /* only HTTP transport for now, later look at url for scheme */ $this->debug_flag = $debug; @@ -64,32 +63,33 @@ return; } $this->errmsg = "No Transport for {$urlparts['scheme']}"; + $this->raiseSoapFault($this->errmsg); } /** * send a soap package, get a soap response * - * @param string &$response soap response (in xml) * @param string &$soap_data soap data to be sent (in xml) * @param string $action SOAP Action * @param int $timeout protocol timeout in seconds * - * @return boolean + * @return string &$response soap response (in xml) * @access public */ - function send(&$response, &$soap_data, $action = '', $timeout=0) + function &send(&$soap_data, $action = '', $timeout=0) { - if (!$this->transport) return $this->raiseError($this->errmsg, -1); + if (!$this->transport) { + return $this->raiseSoapFault($this->errmsg); + } - if (!$this->transport->send($soap_data, $response, $action, $timeout)) { - $this->errmsg = $this->transport->errmsg; - return $this->raiseError($this->transport->errmsg, -1); + $response = $this->transport->send($soap_data, $action, $timeout); + if (PEAR::isError($response)) { + return $this->raiseSoapFault($response); } - $this->outgoing_payload = $this->transport->outgoing_payload; + #echo "\n OUTGOING: ".$this->transport->outgoing_payload."\n\n"; - #echo "\n INCOMING: ".$this->transport->incoming_payload."\n\n"; #echo "\n INCOMING: ".preg_replace("/>/",">\n",$this->transport->incoming_payload)."\n\n"; - return TRUE; + return $response; } } // end SOAP_Transport Index: pear/SOAP/Value.php diff -u pear/SOAP/Value.php:1.9 pear/SOAP/Value.php:1.10 --- pear/SOAP/Value.php:1.9 Mon Feb 25 13:59:47 2002 +++ pear/SOAP/Value.php Wed Feb 27 22:38:27 2002 @@ -17,11 +17,12 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Value.php,v 1.9 2002/02/25 18:59:47 shane Exp $ +// $Id: Value.php,v 1.10 2002/02/28 03:38:27 shane Exp $ // -require_once('SOAP/globals.php'); -require_once('SOAP/Type/dateTime.php'); -require_once('SOAP/Type/hexBinary.php'); +require_once 'SOAP/Base.php'; +require_once 'SOAP/globals.php'; +require_once 'SOAP/Type/dateTime.php'; +require_once 'SOAP/Type/hexBinary.php'; /** * SOAP::Value * this class converts values between PHP and SOAP @@ -29,35 +30,36 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Value.php,v 1.9 2002/02/25 18:59:47 shane Exp $ +* @version $Id: Value.php,v 1.10 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author */ -class SOAP_Value +class SOAP_Value extends SOAP_Base { var $convert_strings = FALSE; var $value = ''; var $type_code = 0; var $type_prefix = false; var $array_type = ''; - var $debug_flag = true; - var $debug_str = ''; var $name = ''; var $type; var $soapTypes; var $namespace = ''; var $prefix = ''; + var $wsdl; - function SOAP_Value($name='',$type=false,$value=-1,$namespace=false,$type_namespace=false) + function SOAP_Value($name='',$type=false,$value=-1,$namespace=NULL,$type_namespace=NULL, $wsdl=NULL) { global $soapTypes, $SOAP_typemap, $SOAP_namespaces, $methodNamespace; + parent::SOAP_Base('Value'); // detect type if not passed #print("Entering SOAP_Value - name: '$name' type: '$type' value: $value\n"); $this->soapTypes = $soapTypes; $this->name = $name; + $this->wsdl = $wsdl; $this->type = $this->_getSoapType($value, $type); #$this->debug("Entering SOAP_Value - name: '$name' type: '$type' value: $value"); #print("Entering SOAP_Value - name: '$name' type: '$type' value: $value\n"); @@ -83,7 +85,7 @@ $this->type_prefix = $SOAP_namespaces[$type_namespace]; // if type namespace was not explicitly passed, and we're not in a method struct: - } elseif (!$this->type_prefix && $type != 'struct' /*!isset($type_namespace)*/) { + } elseif (!$this->type_prefix && $type != 'Struct' /*!isset($type_namespace)*/) { // try to get type prefix from typeMap if ($ns = $this->verifyType($this->type)) { $this->type_prefix = $SOAP_namespaces[$ns]; @@ -98,12 +100,12 @@ $this->type_code = VALUE_SCALAR; $this->addScalar($value,$this->type,$name); // if array - } elseif (strcasecmp('array',$this->type) == 0 || + } elseif (strcasecmp('Array',$this->type) == 0 || strcasecmp('ur-type',$this->type) == 0) { $this->type_code = VALUE_ARRAY; $this->addArray($value); // if struct - } elseif (stristr($this->type,'struct')) { + } elseif (stristr($this->type,'Struct')) { $this->type_code = VALUE_STRUCT; $this->addStruct($value); } elseif (is_array($value)) { @@ -134,13 +136,13 @@ // if SOAP_Value, add.. if (strcasecmp(get_class($v),'SOAP_Value')==0) { $this->value[] = $v; - $this->debug($v->debug_str); + $this->debug($v->debug_data); // else make obj and serialize } else { $type = ''; $type = $this->_getSoapType($v, $type); $new_val = new SOAP_Value('item',$type,$v); - $this->debug($new_val->debug_str); + $this->debug($new_val->debug_data); $this->value[] = $new_val; } } @@ -156,13 +158,13 @@ // if serialize, if SOAP_Value if (strcasecmp(get_class($v),'SOAP_Value')==0) { $this->value[] = $v; - $this->debug($v->debug_str); + $this->debug($v->debug_data); // else make obj and serialize } else { $type = NULL; $type = $this->_getSoapType($v, $type); $new_val = new SOAP_Value($k,$type,$v); - $this->debug($new_val->debug_str); + $this->debug($new_val->debug_data); $this->value[] = $new_val; } } @@ -261,7 +263,7 @@ // to serialize multi-dimensional array's $numtypes = $this->_getArrayType($soapval->value, $array_type, $ar_size, $xml); #$numtypes = 0; - + $array_type_prefix = ''; if ($numtypes != 1) { $xml =''; foreach ($soapval->value as $array_val) { @@ -270,18 +272,20 @@ } $ar_size = count($soapval->value); - - if (count($array_types) > 1) { - $array_type = 'xsd:ur-type'; - } elseif (count($array_types) == 1) { - if ($array_val->type_prefix != '') { - $array_type = $array_val->type_prefix.':'.$array_val->type; - } else { - $array_type = $array_val->type; - } - } + $numtypes = count($array_types); + $array_type = $array_val->type; + $array_type_prefix = $array_val->type_prefix; $offset = " SOAP-ENC:offset=\"[0]\""; } + if ($numtypes > 1) { + $array_type = 'xsd:ur-type'; + } elseif ($numtypes == 1) { + if ($array_type_prefix != '') { + $array_type = $array_type_prefix.':'.$array_type; + } elseif ($array_type_prefix = $this->getPrefix($array_type)) { + $array_type = $array_type_prefix.':'.$array_type; + } + } $xml = "<$soapval->name xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_type."[$ar_size]\"$offset>\n".$xml."</$soapval->name>\n"; break; @@ -369,10 +373,7 @@ return $soapval->value; } # couldn't decode, return a fault! - return array('faultcode' => 'SOAP-ENV:Value', - 'faultstring' => 'couldn\'t decode response, invalid type_code', - 'faultdetail' => '' - ); + return $this->raiseSoapFault('couldn\'t decode response, invalid type_code'); } // pass it a type, and it attempts to return a namespace uri @@ -398,10 +399,11 @@ // alias for verifyType() - pass it a type, and it returns it's prefix function getPrefix($type) { - if ($prefix = $this->verifyType($type)) { - return $prefix; + global $SOAP_namespaces; + if ($uri = $this->verifyType($type)) { + return $SOAP_namespaces[$uri]; } - return false; + return NULL; } @@ -417,7 +419,11 @@ */ function _getSoapType(&$value, &$type) { $doconvert = FALSE; - if (!$type) { + #if (!$type && $this->wsdl && $this->name) { + # # look up the name in the wsdl + # print "WSDL"; + #} + if (!$type || !$this->verifyType($type)) { if (is_object($value)) { # allows for creating special classes to handle soap types $type = get_class($value); @@ -426,9 +432,9 @@ } elseif (isArray($value)) { foreach ($value as $k => $v) { if (preg_match("/^[0-9]+$/",$k)) { - $type = 'array'; + $type = 'Array'; } else { - $type = 'struct'; + $type = 'Struct'; } break; } @@ -474,12 +480,6 @@ return $type; } - function debug($string) - { - if ($this->debug_flag) { - $this->debug_str .= 'SOAP_Value: '.preg_replace("/>/","/>\r\n/",$string)."\n"; - } - } } // support functions Index: pear/SOAP/WSDL.php diff -u pear/SOAP/WSDL.php:1.6 pear/SOAP/WSDL.php:1.7 --- pear/SOAP/WSDL.php:1.6 Mon Feb 25 20:29:37 2002 +++ pear/SOAP/WSDL.php Wed Feb 27 22:38:27 2002 @@ -17,9 +17,10 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: WSDL.php,v 1.6 2002/02/26 01:29:37 shane Exp $ +// $Id: WSDL.php,v 1.7 2002/02/28 03:38:27 shane Exp $ // -require_once('SOAP/globals.php'); +require_once 'SOAP/Base.php'; +require_once 'SOAP/globals.php'; /** * SOAP_WSDL @@ -33,73 +34,153 @@ * implement IDL type syntax declaration so we can generate WSDL * * @access public -* @version $Id: WSDL.php,v 1.6 2002/02/26 01:29:37 shane Exp $ +* @version $Id: WSDL.php,v 1.7 2002/02/28 03:38:27 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author */ -class SOAP_WSDL { - // define internal arrays of bindings, ports, operations, messages, etc. +class SOAP_WSDL extends SOAP_Base +{ + var $tns = NULL; + var $definition = array(); + var $namespaces = array(); var $complexTypes = array(); var $messages = array(); - var $currentMessage; - var $currentOperation; var $portTypes = array(); - var $currentPortType; var $bindings = array(); - var $currentBinding; var $ports = array(); var $imports = array(); + + function SOAP_WSDL($uri=false) { + parent::SOAP_Base('WSDL'); + $this->uri = $uri; + $this->parse($uri); + } + + function parse($uri) { + $parser = new SOAP_WSDL_Parser($uri, $this); + if ($parser->fault) { + $this->raiseSoapFault($parser->fault); + } + } + + function getEndpoint($portName) + { + if ($endpoint = $this->ports[$portName]['location']) { + return $endpoint; + } + return $this->raiseSoapFault("no endpoint for port for $portName",$this->uri); + } + + // find the name of the first port that contains an operation of name $operation + function getPortName($operation) + { + foreach($this->ports as $port => $portAttrs) { + if ($this->bindings[$portAttrs['binding']]['operations'][$operation] != '') { + return $port; + } + } + return $this->raiseSoapFault("no operation $operation in wsdl", $this->uri); + } + + function getOperationData($portName,$operation) + { + if ($binding = $this->ports[$portName]['binding']) { + // get operation data from binding + if (is_array($this->bindings[$binding]['operations'][$operation])) { + $opData = $this->bindings[$binding]['operations'][$operation]; + } + // get operation data from porttype + $portType = $this->bindings[$binding]['type']; + if (!$portType) { + return $this->raiseSoapFault("no port type for binding $binding in wsdl ".$this->uri); + } + if (is_array($this->portTypes[$portType][$operation])) { + $opData['parameterOrder'] = $this->portTypes[$portType][$operation]['parameterOrder']; + $opData['input'] = array_merge($opData['input'],$this->portTypes[$portType][$operation]['input']); + $opData['output'] = array_merge($opData['output'],$this->portTypes[$portType][$operation]['output']); + } + // message data from messages + $inputMsg = $opData['input']['message']; + $opData['input']['parts'] = $this->messages[$inputMsg]; + $outputMsg = $opData['output']['message']; + $opData['output']['parts'] = $this->messages[$outputMsg]; + return $opData; + } + return $this->raiseSoapFault("no binding for port $portName in wsdl", $this->uri); + } + + function getSoapAction($portName,$operation) + { + if ($soapAction = $this->bindings[$this->ports[$portName]['binding']]['operations'][$operation]['soapAction']) { + return $soapAction; + } + return false; + } + + function getNamespace($portName,$operation) + { + if ($namespace = $this->bindings[$this->ports[$portName]['binding']]['operations'][$operation]['input']['namespace']) { + return $namespace; + } + return false; + } +} + +class SOAP_WSDL_Parser extends SOAP_Base +{ + // define internal arrays of bindings, ports, operations, messages, etc. + var $currentMessage; + var $currentOperation; + var $currentPortType; + var $currentBinding; var $currentPort; - // debug switch - var $debug_flag = false; // parser vars var $position; var $depth; var $depth_array = array(); var $tns = NULL; var $soapns = 'soap'; - var $fault = FALSE; + var $uri = ''; + // constructor - function SOAP_WSDL($wsdl=false) { - $this->parse($wsdl); + function SOAP_WSDL_Parser($uri, &$wsdl) { + parent::SOAP_Base('WSDLPARSER'); + $this->uri = $uri; + $this->wsdl = &$wsdl; + $this->parse($uri); } - function parse($wsdl) { + function parse($uri) { // Check whether content has been read. - if ($wsdl) { - // XXX implement caching - $fd = @file($wsdl); - if (!$fd) { - $this->fault = true; - $this->debug('Unable to retreive WSDL file'); - return false; - } - $wsdl_string = join('',$fd); - // Create an XML parser. - $parser = xml_parser_create(); - // Set the options for parsing the XML data. - //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); - // Set the object for the parser. - xml_set_object($parser, $this); - // Set the element handlers for the parser. - xml_set_element_handler($parser, 'startElement','endElement'); - xml_set_character_data_handler($parser,'characterData'); - //xml_set_default_handler($this->parser, 'defaultHandler'); - - // Parse the XML file. - if (!xml_parse($parser,$wsdl_string,true)) { - // Display an error message. - $this->debug(sprintf('XML error on line %d: %s', - xml_get_current_line_number($parser), - xml_error_string(xml_get_error_code($parser)))); - $this->fault = true; - } - xml_parser_free($parser); + // XXX implement caching + $fd = @file($uri); + if (!$fd) { + return $this->raiseSoapFault('Unable to retreive WSDL file', $uri); } - return $this->fault; + $wsdl_string = join('',$fd); + // Create an XML parser. + $parser = xml_parser_create(); + // Set the options for parsing the XML data. + //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + // Set the object for the parser. + xml_set_object($parser, $this); + // Set the element handlers for the parser. + xml_set_element_handler($parser, 'startElement','endElement'); + xml_set_character_data_handler($parser,'characterData'); + //xml_set_default_handler($this->parser, 'defaultHandler'); + + // Parse the XML file. + if (!xml_parse($parser,$wsdl_string,true)) { + $detail = sprintf('XML error on line %d: %s', + xml_get_current_line_number($parser), + xml_error_string(xml_get_error_code($parser))); + return $this->raiseSoapFault("Unable to parse WSDL file $uri",$detail); + } + xml_parser_free($parser); + return TRUE; } // start-element handler @@ -132,65 +213,65 @@ $this->schemaStatus = 'complexType'; break; case 'element': - $this->complexTypes[$this->currentElement]['elements'][$attrs['name']] = $attrs; + $this->wsdl->complexTypes[$this->currentElement]['elements'][$attrs['name']] = $attrs; break; case 'complexContent': break; case 'restriction': - $this->complexTypes[$this->currentElement]['restrictionBase'] = $attrs['base']; + $this->wsdl->complexTypes[$this->currentElement]['restrictionBase'] = $attrs['base']; break; case 'sequence': - $this->complexTypes[$this->currentElement]['order'] = 'sequence'; + $this->wsdl->complexTypes[$this->currentElement]['order'] = 'sequence'; break; case 'all': - $this->complexTypes[$this->currentElement]['order'] = 'all'; + $this->wsdl->complexTypes[$this->currentElement]['order'] = 'all'; break; case 'attribute': if ($attrs['ref']) { - $this->complexTypes[$this->currentElement]['attrs'][$attrs['ref']] = $attrs; + $this->wsdl->complexTypes[$this->currentElement]['attrs'][$attrs['ref']] = $attrs; } elseif ($attrs['name']) { - $this->complexTypes[$this->currentElement]['attrs'][$attrs['name']] = $attrs; + $this->wsdl->complexTypes[$this->currentElement]['attrs'][$attrs['name']] = $attrs; } break; } break; case 'message': if ($name == 'part') { - $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; + $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs['type']; } break; case 'portType': switch($name) { case 'operation': $this->currentOperation = $attrs['name']; - $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; + $this->wsdl->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder']; break; default: - $this->portTypes[$this->currentPortType][$this->currentOperation][$name]= $attrs; + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]= $attrs; $qname = split(':',$attrs['message']); $qname = array_reverse($qname); // this way, the type will always be zero - $this->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qname[0]; - $this->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qname[1]; + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qname[0]; + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qname[1]; break; } break; case 'binding': switch($name) { case $this->soapns.':binding': - $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding],$attrs); + $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding],$attrs); break; case 'operation': $this->currentOperation = $attrs['name']; - $this->bindings[$this->currentBinding]['operations'][$attrs['name']] = array(); + $this->wsdl->bindings[$this->currentBinding]['operations'][$attrs['name']] = array(); break; case $this->soapns.':operation': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction']; break; case 'input': $this->opStatus = 'input'; case $this->soapns.':body': - $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs; break; case 'output': $this->opStatus = 'output'; @@ -201,21 +282,21 @@ switch($name) { case 'port': $this->currentPort = $attrs['name']; - $this->ports[$attrs['name']] = $attrs; + $this->wsdl->ports[$attrs['name']] = $attrs; // XXX hack to deal with binding namespaces $qname = split(':',$attrs['binding']); $qname = array_reverse($qname); // this way, the type will always be zero - $this->ports[$attrs['name']]['binding'] = $qname[0]; - $this->ports[$attrs['name']]['namespace'] = $qname[1]; + $this->wsdl->ports[$attrs['name']]['binding'] = $qname[0]; + $this->wsdl->ports[$attrs['name']]['namespace'] = $qname[1]; break; case $this->soapns.':address': - $this->ports[$this->currentPort]['location'] = $attrs['location']; + $this->wsdl->ports[$this->currentPort]['location'] = $attrs['location']; break; } case 'import': switch($name) { case 'documentation': - $this->imports[$attrs['namespace']]['documentation'] = $attrs; + $this->wsdl->imports[$attrs['namespace']]['documentation'] = $attrs; default: $this->debug('ERROR, only documentation allowed inside IMPORT\n'); } @@ -227,10 +308,13 @@ //XXX $import = ''; if ($attrs['location']) { - $this->parse($attrs['location']); + $result = $this->parse($attrs['location'], $this->wsdl); + if (PEAR::isError($result)) { + return $result; + } } - $this->imports[$attrs['namespace']] = array( + $this->wsdl->imports[$attrs['namespace']] = array( 'location' => $attrs['location'], 'namespace' => $attrs['namespace']); $this->currentImport = $attrs['namespace']; @@ -240,12 +324,12 @@ break; case 'message': $this->status = 'message'; - $this->messages[$attrs['name']] = array(); + $this->wsdl->messages[$attrs['name']] = array(); $this->currentMessage = $attrs['name']; break; case 'portType': $this->status = 'portType'; - $this->portTypes[$attrs['name']] = array(); + $this->wsdl->portTypes[$attrs['name']] = array(); $this->currentPortType = $attrs['name']; break; case 'binding': @@ -253,15 +337,15 @@ $this->currentBinding = $attrs['name']; $qname = split(':',$attrs['type']); $qname = array_reverse($qname); // this way, the type will always be zero - $this->bindings[$attrs['name']]['type'] = $qname[0]; - $this->bindings[$attrs['name']]['namespace'] = $qname[1]; + $this->wsdl->bindings[$this->currentBinding]['type'] = $qname[0]; + $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qname[1]; break; case 'service': - $this->serviceName = $attrs['name']; + $this->wsdl->serviceName = $attrs['name']; $this->status = 'service'; break; case 'definitions': - $this->wsdl_info = $attrs; + $this->wsdl->definition = $attrs; foreach ($attrs as $name=>$value) { if (strcasecmp($value,SOAP_SCHEMA)==0) { $s = split(':',$name); @@ -271,9 +355,8 @@ } if ($ns) { $namespace = 'xmlns:'.$ns; - if (!$this->wsdl_info[$namespace]) { - $this->debug("WSDL Parse Error, no namespace for $namespace\n"); - return; + if (!$this->wsdl->definition[$namespace]) { + return $this->raiseSoapFault("parse error, no namespace for $namespace",$this->uri); } $this->tns = $ns; } @@ -281,62 +364,6 @@ } } - function getEndpoint($portName) - { - if ($endpoint = $this->ports[$portName]['location']) { - return $endpoint; - } - return false; - } - - // find the name of the first port that contains an operation of name $operation - function getPortName($operation) - { - foreach($this->ports as $port => $portAttrs) { - if ($this->bindings[$portAttrs['binding']]['operations'][$operation] != '') { - return $port; - } - } - } - - function getOperationData($portName,$operation) - { - if ($binding = $this->ports[$portName]['binding']) { - // get operation data from binding - if (is_array($this->bindings[$binding]['operations'][$operation])) { - $opData = $this->bindings[$binding]['operations'][$operation]; - } - // get operation data from porttype - $portType = $this->bindings[$binding]['type']; - if (is_array($this->portTypes[$portType][$operation])) { - $opData['parameterOrder'] = $this->portTypes[$portType][$operation]['parameterOrder']; - $opData['input'] = array_merge($opData['input'],$this->portTypes[$portType][$operation]['input']); - $opData['output'] = array_merge($opData['output'],$this->portTypes[$portType][$operation]['output']); - } - // message data from messages - $inputMsg = $opData['input']['message']; - $opData['input']['parts'] = $this->messages[$inputMsg]; - $outputMsg = $opData['output']['message']; - $opData['output']['parts'] = $this->messages[$outputMsg]; - } - return $opData; - } - - function getSoapAction($portName,$operation) - { - if ($soapAction = $this->bindings[$this->ports[$portName]['binding']]['operations'][$operation]['soapAction']) { - return $soapAction; - } - return false; - } - - function getNamespace($portName,$operation) - { - if ($namespace = $this->bindings[$this->ports[$portName]['binding']]['operations'][$operation]['input']['namespace']) { - return $namespace; - } - return false; - } // end-element handler function endElement($parser, $name) @@ -350,18 +377,11 @@ // element content handler function characterData($parser, $data) { - $pos = $this->depth_array[$this->depth]; - $this->message[$pos]['cdata'] .= $data; - } - - function debug($string) - { - if ($this->debug_flag) { - $this->debug_str .= "wsdl: $string\n"; - } + #$pos = $this->depth_array[$this->depth]; + #$this->wsdl->messages[$pos]['cdata'] .= $data; } } -#$wsdl = new wsdl("http://www.whitemesa.net/wsdl/std/interop.wsdl"); +#$wsdl = new SOAP_WSDL("http://www.apache.org/~rubys/ApacheSoap.wsdl"); #print "end"; ?> Index: pear/SOAP/globals.php diff -u pear/SOAP/globals.php:1.3 pear/SOAP/globals.php:1.4 --- pear/SOAP/globals.php:1.3 Mon Feb 25 00:06:36 2002 +++ pear/SOAP/globals.php Wed Feb 27 22:38:27 2002 @@ -17,127 +17,127 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: globals.php,v 1.3 2002/02/25 05:06:36 shane Exp $ +// $Id: globals.php,v 1.4 2002/02/28 03:38:27 shane Exp $ // // make errors handle properly in windows (thx, thong@xmethods.com) error_reporting(2039); -if (!function_exists("version_compare") || - version_compare(phpversion(), "4.1", "<")) { - die("requires PHP 4.1 or higher\n"); +if (!function_exists('version_compare') || + version_compare(phpversion(), '4.1', '<')) { + die('requires PHP 4.1 or higher\n'); } -if (version_compare(phpversion(), "4.1", ">=") && - version_compare(phpversion(), "4.2", "<")) { - define("FLOAT","double"); +if (version_compare(phpversion(), '4.1', '>=') && + version_compare(phpversion(), '4.2', '<')) { + define('FLOAT','double'); } else { - define("FLOAT","float"); + define('FLOAT','float'); } # for float support # is there a way to calculate INF for the platform? -define("INF", 1.8e307); -define("NAN", 0.0); +define('INF', 1.8e307); +define('NAN', 0.0); # define types for value -define("VALUE_SCALAR",1); -define("VALUE_ARRAY",2); -define("VALUE_STRUCT",3); +define('VALUE_SCALAR',1); +define('VALUE_ARRAY',2); +define('VALUE_STRUCT',3); -define("SOAP_LIBRARY_NAME","PEAR-SOAPx4 0.6"); +define('SOAP_LIBRARY_NAME','PEAR-SOAPx4 0.6'); // set schema version -define("SOAP_XML_SCHEMA_VERSION","http://www.w3.org/2001/XMLSchema"); -define("SOAP_XML_SCHEMA_1999","http://www.w3.org/1999/XMLSchema"); -define("SOAP_SCHEMA","http://schemas.xmlsoap.org/wsdl/soap/"); -define("SOAP_SCHEMA_ENCODING","http://schemas.xmlsoap.org/soap/encoding/"); -define("SOAP_ENVELOP","http://schemas.xmlsoap.org/soap/envelope/"); -define("SOAP_INTEROPORG","http://soapinterop.org/xsd"); +define('SOAP_XML_SCHEMA_VERSION','http://www.w3.org/2001/XMLSchema'); +define('SOAP_XML_SCHEMA_1999','http://www.w3.org/1999/XMLSchema'); +define('SOAP_SCHEMA','http://schemas.xmlsoap.org/wsdl/soap/'); +define('SOAP_SCHEMA_ENCODING','http://schemas.xmlsoap.org/soap/encoding/'); +define('SOAP_ENVELOP','http://schemas.xmlsoap.org/soap/envelope/'); +define('SOAP_INTEROPORG','http://soapinterop.org/xsd'); // load types into typemap array /* -$SOAP_typemap["http://www.w3.org/2001/XMLSchema"] = array( - "string","boolean","float","double","decimal","duration","dateTime","time", - "date","gYearMonth","gYear","gMonthDay","gDay","gMonth","hexBinary","base64Binary", +$SOAP_typemap['http://www.w3.org/2001/XMLSchema'] = array( + 'string','boolean','float','double','decimal','duration','dateTime','time', + 'date','gYearMonth','gYear','gMonthDay','gDay','gMonth','hexBinary','base64Binary', // derived datatypes - "normalizedString","token","language","NMTOKEN","NMTOKENS","Name","NCName","ID", - "IDREF","IDREFS","ENTITY","ENTITIES","integer","nonPositiveInteger", - "negativeInteger","long","int","short","byte","nonNegativeInteger", - "unsignedLong","unsignedInt","unsignedShort","unsignedByte","positiveInteger"); -$SOAP_typemap["http://www.w3.org/1999/XMLSchema"] = array( - "i4","int","boolean","string","double","float","dateTime", - "timeInstant","base64Binary","base64","ur-type"); -$SOAP_typemap[SOAP_INTEROPORG] = array("SOAPStruct"); -$SOAP_typemap[SOAP_SCHEMA_ENCODING] = array("base64","array","Array"); + 'normalizedString','token','language','NMTOKEN','NMTOKENS','Name','NCName','ID', + 'IDREF','IDREFS','ENTITY','ENTITIES','integer','nonPositiveInteger', + 'negativeInteger','long','int','short','byte','nonNegativeInteger', + 'unsignedLong','unsignedInt','unsignedShort','unsignedByte','positiveInteger'); +$SOAP_typemap['http://www.w3.org/1999/XMLSchema'] = array( + 'i4','int','boolean','string','double','float','dateTime', + 'timeInstant','base64Binary','base64','ur-type'); +$SOAP_typemap[SOAP_INTEROPORG] = array('SOAPStruct'); +$SOAP_typemap[SOAP_SCHEMA_ENCODING] = array('base64','array','Array'); */ $SOAP_typemap[SOAP_XML_SCHEMA_VERSION] = array( - "string" => "string", - "boolean" => "boolean", - "float" => FLOAT, - "double" => "double", - "decimal" => "integer", - "duration" => "integer", - "dateTime" => "string", - "time" => "string", - "date" => "string", - "gYearMonth" => "integer", - "gYear" => "integer", - "gMonthDay" => "integer", - "gDay" => "integer", - "gMonth" => "integer", - "hexBinary" => "string", - "base64Binary" => "string", + 'string' => 'string', + 'boolean' => 'boolean', + 'float' => FLOAT, + 'double' => 'double', + 'decimal' => 'integer', + 'duration' => 'integer', + 'dateTime' => 'string', + 'time' => 'string', + 'date' => 'string', + 'gYearMonth' => 'integer', + 'gYear' => 'integer', + 'gMonthDay' => 'integer', + 'gDay' => 'integer', + 'gMonth' => 'integer', + 'hexBinary' => 'string', + 'base64Binary' => 'string', // derived datatypes - "normalizedString" => "string", - "token" => "string", - "language" => "string", - "NMTOKEN" => "string", - "NMTOKENS" => "string", - "Name" => "string", - "NCName" => "string", - "ID" => "string", - "IDREF" => "string", - "IDREFS" => "string", - "ENTITY" => "string", - "ENTITIES" => "string", - "integer" => "integer", - "nonPositiveInteger" => "integer", - "negativeInteger" => "integer", - "long" => "integer", - "int" => "integer", - "short" => "integer", - "byte" => "string", - "nonNegativeInteger" => "integer", - "unsignedLong" => "integer", - "unsignedInt" => "integer", - "unsignedShort" => "integer", - "unsignedByte" => "integer", - "positiveInteger" => "integer" + 'normalizedString' => 'string', + 'token' => 'string', + 'language' => 'string', + 'NMTOKEN' => 'string', + 'NMTOKENS' => 'string', + 'Name' => 'string', + 'NCName' => 'string', + 'ID' => 'string', + 'IDREF' => 'string', + 'IDREFS' => 'string', + 'ENTITY' => 'string', + 'ENTITIES' => 'string', + 'integer' => 'integer', + 'nonPositiveInteger' => 'integer', + 'negativeInteger' => 'integer', + 'long' => 'integer', + 'int' => 'integer', + 'short' => 'integer', + 'byte' => 'string', + 'nonNegativeInteger' => 'integer', + 'unsignedLong' => 'integer', + 'unsignedInt' => 'integer', + 'unsignedShort' => 'integer', + 'unsignedByte' => 'integer', + 'positiveInteger' => 'integer' ); $SOAP_typemap[SOAP_XML_SCHEMA_1999] = array( - "i4" => "integer", - "int" => "integer", - "boolean" => "boolean", - "string" => "string", - "double" => "double", - "float" => FLOAT, - "dateTime" => "string", - "timeInstant" => "string", - "base64Binary" => "string", - "base64" => "string", - "ur-type" => "string" + 'i4' => 'integer', + 'int' => 'integer', + 'boolean' => 'boolean', + 'string' => 'string', + 'double' => 'double', + 'float' => FLOAT, + 'dateTime' => 'string', + 'timeInstant' => 'string', + 'base64Binary' => 'string', + 'base64' => 'string', + 'ur-type' => 'string' ); -$SOAP_typemap[SOAP_INTEROPORG] = array("SOAPStruct" => "array"); -$SOAP_typemap[SOAP_SCHEMA_ENCODING] = array("base64" => "string","array" => "array","Array" => "array"); +$SOAP_typemap[SOAP_INTEROPORG] = array('SOAPStruct' => 'array'); +$SOAP_typemap[SOAP_SCHEMA_ENCODING] = array('base64' => 'string','array' => 'array','Array' => 'array', 'Struct'=>'array'); // load namespace uris into an array of uri => prefix $SOAP_namespaces = array( - SOAP_ENVELOP => "SOAP-ENV", - SOAP_XML_SCHEMA_VERSION => "xsd", - SOAP_XML_SCHEMA_VERSION."-instance" => "xsi", - SOAP_SCHEMA_ENCODING => "SOAP-ENC", - SOAP_INTEROPORG=>"si"); + SOAP_ENVELOP => 'SOAP-ENV', + SOAP_XML_SCHEMA_VERSION => 'xsd', + SOAP_XML_SCHEMA_VERSION.'-instance' => 'xsi', + SOAP_SCHEMA_ENCODING => 'SOAP-ENC', + SOAP_INTEROPORG=>'si'); -$SOAP_xmlEntities = array("quot" => '"',"amp" => "&", - "lt" => "<","gt" => ">","apos" => "'"); +$SOAP_xmlEntities = array('quot' => '"','amp' => '&', + 'lt' => '<','gt' => '>','apos' => "'"); ?> Index: pear/SOAP/package.xml diff -u pear/SOAP/package.xml:1.4 pear/SOAP/package.xml:1.5 --- pear/SOAP/package.xml:1.4 Mon Feb 25 00:06:36 2002 +++ pear/SOAP/package.xml Wed Feb 27 22:38:28 2002 @@ -26,6 +26,7 @@ <dir name="/" baseinstalldir="SOAP"> <file role="php">Client.php</file> <file role="php">Server.php</file> + <file role="php">Fault.php</file> <file role="php">Message.php</file> <file role="php">Value.php</file> <file role="php">Parser.php</file> @@ -46,6 +47,8 @@ <dir name="interop" role="test"> <file role="test">client_params.php</file> <file role="test">client_round2_base.php</file> + <file role="test">client_library.php</file> + <file role="test">client_round2_pretty.php</file> <file role="test">interop.php</file> <file role="test">server_soapinterop_base.php</file> <file role="test">server_soapinterop_groupB.php</file> Index: pear/SOAP/Transport/HTTP.php diff -u pear/SOAP/Transport/HTTP.php:1.6 pear/SOAP/Transport/HTTP.php:1.7 --- pear/SOAP/Transport/HTTP.php:1.6 Mon Feb 25 13:59:49 2002 +++ pear/SOAP/Transport/HTTP.php Wed Feb 27 22:38:28 2002 @@ -16,20 +16,21 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: HTTP.php,v 1.6 2002/02/25 18:59:49 shane Exp $ +// $Id: HTTP.php,v 1.7 2002/02/28 03:38:28 shane Exp $ // -require_once('SOAP/globals.php'); +require_once 'SOAP/globals.php'; +require_once 'SOAP/Base.php'; /** * HTTP Transport for SOAP * * @access public -* @version $Id: HTTP.php,v 1.6 2002/02/25 18:59:49 shane Exp $ +* @version $Id: HTTP.php,v 1.7 2002/02/28 03:38:28 shane Exp $ * @package SOAP::Transport::HTTP * @author Shane Caraveo <shane@php.net> */ -class SOAP_Transport_HTTP +class SOAP_Transport_HTTP extends SOAP_Base { var $credentials = ''; var $_userAgent; @@ -49,6 +50,7 @@ */ function SOAP_Transport_HTTP($URL) { + parent::SOAP_Base('HTTP'); $this->urlparts = @parse_url($URL); $this->url = $URL; $this->_userAgent = SOAP_LIBRARY_NAME; @@ -58,25 +60,24 @@ * send and receive soap data * * @param string &$msg outgoing post data - * @param string &$response response data, minus http headers * @param string $action SOAP Action header data * @param int $timeout socket timeout, default 0 or off * - * @return boolean (success or failure) + * @return string|fault response * @access public */ - function send(&$msg, &$response, $action = '', $timeout=0) + function &send(&$msg, $action = '', $timeout=0) { if (!$this->_validateUrl()) { - return FALSE; + return $this->raiseSoapFault($this->errmsg); } if ($timeout) $this->timeout = $timeout; if (strcasecmp($this->urlparts['scheme'],'HTTP') == 0) { - return $this->_sendHTTP($msg, $response, $action); + return $this->_sendHTTP($msg, $action); } else if (strcasecmp($this->urlparts['scheme'],'HTTPS') == 0) { - return $this->_sendHTTPS($msg, $response, $action); + return $this->_sendHTTPS($msg, $action); } - return FALSE; + return $this->raiseSoapFault('Invalid url scheme '.$this->url); } /** @@ -110,6 +111,7 @@ return FALSE; } if (!isset($this->urlparts['host'])) { + $this->errmsg = "No host in URL $url"; return FALSE; } if (!isset($this->urlparts['port'])) { @@ -143,7 +145,7 @@ * @return string outgoing_payload * @access private */ - function _getRequest(&$msg, $action) + function &_getRequest(&$msg, $action) { $this->outgoing_payload = "POST {$this->urlparts['path']} HTTP/1.0\r\n". @@ -161,13 +163,12 @@ * send outgoing request, and read/parse response * * @param string &$msg outgoing SOAP package - * @param string &$response response data, minus http headers * @param string $action SOAP Action * - * @return boolean + * @return string &$response response data, minus http headers * @access private */ - function _sendHTTP(&$msg, &$response, $action = '') + function &_sendHTTP(&$msg, $action = '') { $this->_getRequest($msg, $action); @@ -179,11 +180,11 @@ } if (!$fp) { $this->errmsg = "Unable to connect to {$this->urlparts['host']}:{$this->urlparts['port']}"; - return FALSE; + return $this->raiseSoapFault($this->errmsg); } if (!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { $this->errmsg = "Error POSTing Data to {$this->urlparts['host']}"; - return FALSE; + return $this->raiseSoapFault($this->errmsg); } // get reponse @@ -195,23 +196,21 @@ if (!$this->_parseResponse()) { $this->errmsg = 'Invalid HTTP Response'; - return FALSE; + return $this->raiseSoapFault($this->errmsg, $this->outgoing_payload."\n\n".$this->incoming_payload); } - $response = $this->response; - return TRUE; + return $this->response; } /** * send outgoing request, and read/parse response, via HTTPS * * @param string &$msg outgoing SOAP package - * @param string &$response response data, minus http headers * @param string $action SOAP Action * - * @return boolean + * @return string &$response response data, minus http headers * @access private */ - function _sendHTTPS(&$msg, &$response, $action) + function &_sendHTTPS(&$msg, $action) { /* NOTE This function uses the CURL functions * Your php must be compiled with CURL @@ -219,7 +218,7 @@ if (!extension_loaded('php_curl')) { $this->errno = -1; $this->errmsg = 'CURL Extension is required for HTTPS'; - return FALSE; + return $this->raiseSoapFault($this->errmsg); } $this->_getRequest($msg, $action); @@ -234,10 +233,10 @@ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_VERBOSE,1); - $response=curl_exec($ch); + $this->response=curl_exec($ch); curl_close($ch); - return TRUE; + return $this->response; } }; // end SOAP_Transport_HTTP ?> Index: pear/SOAP/Transport/SMTP.php diff -u pear/SOAP/Transport/SMTP.php:1.3 pear/SOAP/Transport/SMTP.php:1.4 --- pear/SOAP/Transport/SMTP.php:1.3 Mon Feb 25 13:59:49 2002 +++ pear/SOAP/Transport/SMTP.php Wed Feb 27 22:38:28 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: SMTP.php,v 1.3 2002/02/25 18:59:49 shane Exp $ +// $Id: SMTP.php,v 1.4 2002/02/28 03:38:28 shane Exp $ // // Status: rough draft, untested // @@ -27,18 +27,19 @@ // ability to define smtp options (encoding, from, etc.) // -require_once('SOAP/globals.php'); -require_once('SOAP/Message.php'); +require_once 'SOAP/globals.php'; +require_once 'SOAP/Message.php'; +require_once 'SOAP/Base.php'; /** * SMTP Transport for SOAP * * @access public -* @version $Id: SMTP.php,v 1.3 2002/02/25 18:59:49 shane Exp $ +* @version $Id: SMTP.php,v 1.4 2002/02/28 03:38:28 shane Exp $ * @package SOAP::Transport::SMTP * @author Shane Caraveo <shane@php.net> */ -class SOAP_Transport_SMTP +class SOAP_Transport_SMTP extends SOAP_Base { var $credentials = ''; var $_userAgent; @@ -58,6 +59,7 @@ */ function SOAP_Transport_SMTP($URL) { + parent::SOAP_Base('SMTP'); $this->urlparts = @parse_url($URL); $this->url = $URL; $this->_userAgent = SOAP_LIBRARY_NAME; @@ -67,17 +69,16 @@ * send and receive soap data * * @param string &$msg outgoing post data - * @param string &$response response data, minus http headers * @param string $action SOAP Action header data * @param int $timeout socket timeout, default 0 or off * - * @return boolean (success or failure) + * @return string &$response response data, minus http headers * @access public */ - function send(&$msg, &$response, $action = '', $timeout=0) + function send(&$msg, $action = '', $timeout=0) { if (!$this->_validateUrl()) { - return FALSE; + return $this->raiseSoapFault($this->errmsg); } $headers = "From: $action\n". @@ -94,7 +95,7 @@ $val = new SOAP_Value('return','boolean',TRUE); } else { $val = new SOAP_Value('Fault','struct',array( - new SOAP_Value('faultcode','string','SOAP-ENV:Transport'), + new SOAP_Value('faultcode','string','SOAP-ENV:Transport:SMTP'), new SOAP_Value('faultstring','string',"couldn't send message to $action") )); } Index: pear/SOAP/interop/client_params.php diff -u pear/SOAP/interop/client_params.php:1.4 pear/SOAP/interop/client_params.php:1.5 --- pear/SOAP/interop/client_params.php:1.4 Mon Feb 25 13:59:50 2002 +++ pear/SOAP/interop/client_params.php Wed Feb 27 22:38:28 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: client_params.php,v 1.4 2002/02/25 18:59:50 shane Exp $ +// $Id: client_params.php,v 1.5 2002/02/28 03:38:28 shane Exp $ // require_once("SOAP/Value.php"); @@ -74,9 +74,9 @@ ); $method_params["base"]['php']["echoStructArray"]["inputStructArray"] = array( - "item" => array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325), - "item" => array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325), - "item" => array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325) + array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325), + array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325), + array("varString"=>"arg", "varInt"=>34, "varFloat"=>325.325) ); $method_params["base"]['soapval']["echoStructArray"]["inputStructArray"] = new SOAP_Value("inputStructArray","Array", Index: pear/SOAP/interop/client_round2_base.php diff -u pear/SOAP/interop/client_round2_base.php:1.9 pear/SOAP/interop/client_round2_base.php:1.10 --- pear/SOAP/interop/client_round2_base.php:1.9 Mon Feb 25 20:29:37 2002 +++ pear/SOAP/interop/client_round2_base.php Wed Feb 27 22:38:28 2002 @@ -1,4 +1,5 @@ <?php +// this script is usefull for quickly testing stuff, use the 'pretty' file for html output // // +----------------------------------------------------------------------+ // | PHP Version 4 | @@ -17,24 +18,28 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: client_round2_base.php,v 1.9 2002/02/26 01:29:37 shane Exp $ +// $Id: client_round2_base.php,v 1.10 2002/02/28 03:38:28 shane Exp $ // +set_time_limit(0); require_once("SOAP/Client.php"); require_once("client_params.php"); require_once("SOAP/test/test.utility.php"); +require_once("SOAP/interop/client_library.php"); error_reporting(E_ALL ^ E_NOTICE); $localonly = 0; // set to 1 to test only your local server -$usebuiltin = 0; // use builtin list of endpoints +$usebuiltin = 1; // use builtin list of endpoints $usewsdl = 1; $test = 'base'; // which test to do: base, GroupB, GroupC -$parm = 'soapval'; // use base types: php, soapval +$parm = 'php'; // use base types: php, soapval $show = 1; $debug = 0; -$numservers = 0; // zero for all of them -$testfunc = ''; // test a single function -$specificendpoint = ''; //"http://63.142.188.184:1122/"; // endpoint url +$numservers = 1; // zero for all of them +$testfunc = 'echoStructArray'; // test a single function +$specificendpoint = 'http://nagoya.apache.org:5049/soap/servlet/rpcrouter'; //"http://63.142.188.184:1122/"; // endpoint url +// slow or unavailable sites in interop list +$skip = array(); if ($localonly) { # define your test servers endpointURL here @@ -73,208 +78,7 @@ getInteropEndpoints($test) ) { print "Got ".count($endpoints)." endpoints\n"; - do_interopTest($method_params[$test][$parm], $testfunc, $numservers); -} - -function getInteropEndpoints($base = "base") { - global $endpoints; - $endpoints = array(); - // get other interop endpoints - $soapclient = new SOAP_Client("http://www.whitemesa.net/interopInfo"); - if($endpointArray = $soapclient->call("GetEndpointInfo",array("groupName"=>$base),"http://soapinterop.org/info/","http://soapinterop.org/info/")){ - if (PEAR::isError($endpointArray)) { - print_r($endpointArray); - return FALSE; - } - #print_r($endpointArray); - foreach($endpointArray as $k => $v){ - $endpoints[$v["endpointName"]] = $v; - } - return count($endpoints) > 0; - } - print "<xmp>$soapclient->debug_data</xmp>"; - return FALSE; -} - -function decode_soapval($soapval) -{ - if (gettype($soapval) == "object" && strcasecmp(get_class($soapval),"SOAP_Value") == 0) { - $val = $soapval->decode(); - } else { - $val = $soapval; - } - if (is_array($val)) { - foreach($val as $k => $v) { - if (gettype($v) == "object" && strcasecmp(get_class($v),"SOAP_Value") == 0) { - $val[$k] = decode_soapval($v); - } - } - } - return $val; -} - -function test_result($expect, $result) -{ - $ok = 0; - $expect_type = gettype($expect); - $result_type = gettype($result); - if ($expect_type == "array" && $result_type == "array") { - # compare arrays - $ok = array_compare($expect, $result); - } else { - $ok = string_compare($expect, $result); - } - return $ok; -} - -function do_endpoint_method($endpoint, $method, $method_params, $show = 0, $debug = 0) { - global $endpoints, $method_expect,$usewsdl; - - $success = FALSE; - if ($debug) $show = 1; - if ($debug) { - echo str_repeat("-",50)."<br>\n"; - } - echo "testing $endpoint : $method : "; - if ($debug) { - print "method params: "; - print_r($method_params); - print "\n"; - } - - $endpoint_info = $endpoints[$endpoint]; - - $endpoints[$endpoint]["methods"][$method] = array(); - if ($usewsdl) { - if (array_key_exists('wsdlURL',$endpoint_info)) { - if (!array_key_exists('client',$endpoints[$endpoint])) { - $endpoints[$endpoint]['client'] = new SOAP_Client($endpoint_info['wsdlURL'],1); - } - $soap = $endpoints[$endpoint]['client']; - if ($soap->wsdl->fault) { - echo "WSDL error in $endpoint\n"; - return FALSE; - } - } else { - echo "No WSDL for $endpoint\n"; - return FALSE; - } - } else { - $soap = new SOAP_Client($endpoint_info['endpointURL']); - } - $soap->debug_flag = true; - if ($usewsdl) { - $return = $soap->call($method,$method_params); - } else { - $return = $soap->call($method,$method_params,'http://soapinterop.org/','http://soapinterop.org/'); - } - - if(!PEAR::isError($return) && !$soap->fault){ - if (is_array($method_params) && count($method_params) == 1) { - $sent = array_shift($method_params); - } else { - $sent = $method_params; - } - $endpoints[$endpoint]["methods"][$method]['sent'] = $sent; - $endpoints[$endpoint]["methods"][$method]['return'] = $return; - - # we need to decode what we sent so we can compare! - $sent = decode_soapval($sent); - - $ok = test_result($sent,$return); - if (!$ok && array_key_exists($method,$method_expect)) { - $ok = test_result($method_expect[$method],$return); - } - - if($ok){ - $endpoints[$endpoint]["methods"][$method]['success'] = 1; - $success = TRUE; - print "PASSED<br>\n"; - } else { - $endpoints[$endpoint]["methods"][$method]['success'] = 0; - print "FAILED - return: ".gettype($return)."<br>\n"; - if ($debug)print "Debug: ".$soap->debug_data."\n"; - if ($show) { - print "<pre>\nSENT: ["; - print_r($sent); - print "]<br>\nRECEIVED: ["; - print_r($return); - if (array_key_exists($method,$method_expect)) { - print "]<br>\nEXPECTED: ["; - print_r($method_expect[$method]); - } - print "]<br></pre>\n"; - } - } - return $success; - } - print "FAILED <br>\nERROR: Was unable to send or receive. Debug: $soap->faultcode $soap->faultstring $soap->faultdetail<br>\n"; - if ($debug) print " Debug: $soap->debug_data<br>\n"; - $endpoints[$endpoint]["connectFailed"]++; - return false; -} - -function do_interopTest(&$method_params, $onlyfunc, $num_endpoints = 1) { - global $endpoints; - global $show; - global $debug; - global $specificendpoint; - $totals = array(); - // slow or unavailable sites in interop list - $skip = array('http://explorer.ne.mediaone.net/app/interop/interop'); - $xskip = array( - 'www.themindelectric.net', - 'http://soap.bluestone.com/hpws/soap/EchoService', #slow - 'http://easysoap.sourceforge.net/cgi-bin/interopserver', - 'http://www.quakersoft.net/cgi-bin/interop2_server.cgi', - 'http://www.soapware.org/xmethodsInterop', - 'http://demo.openlinksw.com:8890/Interop', - 'http://www.whitemesa.net/interop/std', - 'http://www.phalanxsys.com/ilabA/untyped/target.asp', - 'http://explorer.ne.mediaone.net/app/interop/interop', - - ); - - $i = 0; - foreach($endpoints as $endpoint => $endpoint_info){ - if ($specificendpoint && $endpoint_info['endpointURL'] != $specificendpoint) continue; - if (in_array($endpoint_info['endpointURL'], $skip)) continue; - $totals['servers']++; - $endpoints[$endpoint]["methods"] = array(); - print "Processing $endpoint at {$endpoint_info['endpointURL']}<br>\n"; - foreach(array_keys($method_params) as $func){ - if (!is_array($method_results[$func])) $method_results[$func] = array(); - if ($onlyfunc && $func != $onlyfunc) continue; - if (do_endpoint_method($endpoint, $func, $method_params[$func],$show,$debug)) { - $endpoint_info["methods"][$func]['success'] = TRUE; - $totals['success']++; - } else { - $endpoint_info["methods"][$func]['success'] = FALSE; - $totals['fail']++; - } - $totals['calls']++; - } - if ($num_endpoints && ++$i >= $num_endpoints) break; - } - echo "\n\nServers: {$totals['servers']} Calls: {$totals['calls']} Success: {$totals['success']} Fail: {$totals['fail']}<br>\n"; - -/* - echo "\n\n\n"; - echo "<h2>Method Results:</h2>\n"; - foreach ($method_results as $method => $results) { - echo $method.': S='.$results['success'].' F='.$results['failure'].' CF: '.$method_results[$method]['connectFailure']."<br>\n"; - } - - echo "\n\n\n"; - echo "<h2>Endpoint Results:</h2>\n"; - foreach ($endpoints as $endpoint => $endpoint_info) { - if (!is_array($endpoint_info["methods"])) continue; - echo "<h3>$endpoint</h3>\n"; - foreach($endpoint_info["methods"] as $method => $results) { - echo $method. " " .($results['success']?"succeeded":"Failed")."<br>\n";; - } - } -*/ + do_interopTest($method_params[$test][$parm]); } ?> Index: pear/SOAP/Fault.php +++ pear/SOAP/Fault.php <?php // // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2002 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // // $Id: Fault.php,v 1.1 2002/02/28 03:38:27 shane Exp $ // require_once('PEAR.php'); require_once('SOAP/Message.php'); // reference http://www.w3.org/TR/SOAP/ Section 4.4 class SOAP_Fault extends PEAR_Error { function SOAP_Fault($message = 'unknown error', $code = null, $mode = null, $options = null, $userinfo = null) { if (is_array($userinfo)) { $actor = $userinfo['actor']; $detail = $userinfo['detail']; } else { $actor = 'Unknown'; $detail = $userinfo; } parent::PEAR_Error($message, $code, $mode, $options, $detail); $this->error_message_prefix = $actor; } // set up a fault function message() { return new SOAP_Message('Fault', array( 'faultcode' => $this->code, 'faultstring' => $this->message, 'faultactor' => $this->error_message_prefix, 'faultdetail' => $this->userinfo ), SOAP_ENVELOP ); } function getFault() { return array( 'faultcode' => $this->code, 'faultstring' => $this->message, 'faultactor' => $this->error_message_prefix, 'faultdetail' => $this->userinfo ); } function getActor() { return $this->error_message_prefix; } function getDetail() { return $this->userinfo; } } ?> Index: pear/SOAP/interop/client_library.php +++ pear/SOAP/interop/client_library.php <?php $totals = array(); function getInteropEndpoints($base = "base") { global $endpoints; $endpoints = array(); // get other interop endpoints $soapclient = new SOAP_Client("http://www.whitemesa.net/interopInfo"); if($endpointArray = $soapclient->call("GetEndpointInfo",array("groupName"=>$base),"http://soapinterop.org/info/","http://soapinterop.org/info/")){ if (PEAR::isError($endpointArray)) { print_r($endpointArray); return FALSE; } #print_r($endpointArray); foreach($endpointArray as $k => $v){ $endpoints[$v["endpointName"]] = $v; } return count($endpoints) > 0; } print "<xmp>$soapclient->debug_data</xmp>"; return FALSE; } function decode_soapval($soapval) { if (gettype($soapval) == "object" && strcasecmp(get_class($soapval),"SOAP_Value") == 0) { $val = $soapval->decode(); } else { $val = $soapval; } if (is_array($val)) { foreach($val as $k => $v) { if (gettype($v) == "object" && strcasecmp(get_class($v),"SOAP_Value") == 0) { $val[$k] = decode_soapval($v); } } } return $val; } function test_result($expect, $result) { $ok = 0; $expect_type = gettype($expect); $result_type = gettype($result); if ($expect_type == "array" && $result_type == "array") { # compare arrays $ok = array_compare($expect, $result); } else { $ok = string_compare($expect, $result); } return $ok; } function do_endpoint_method($endpoint, $method, $method_params) { global $endpoints, $method_expect,$usewsdl, $show, $debug; if ($debug) $show = 1; if ($debug) { echo str_repeat("-",50)."<br>\n"; } if ($show) echo "testing $endpoint : $method : "; if ($debug) { print "method params: "; print_r($method_params); print "\n"; } $endpoint_info = $endpoints[$endpoint]; $endpoints[$endpoint]["methods"][$method] = array(); if ($usewsdl) { if (array_key_exists('wsdlURL',$endpoint_info)) { if (!array_key_exists('client',$endpoints[$endpoint])) { $endpoints[$endpoint]['client'] = new SOAP_Client($endpoint_info['wsdlURL'],1); } $soap = $endpoints[$endpoint]['client']; if ($soap->wsdl->fault) { #echo "WSDL error in $endpoint\n"; $endpoints[$endpoint]["methods"][$method]['success'] = 0; $endpoints[$endpoint]["methods"][$method]['reason'] = 'WSDL'; return FALSE; } } else { #echo "No WSDL for $endpoint\n"; $endpoints[$endpoint]["methods"][$method]['success'] = 0; $endpoints[$endpoint]["methods"][$method]['reason'] = 'WSDL'; return FALSE; } } else { $soap = new SOAP_Client($endpoint_info['endpointURL']); } $soap->debug_flag = true; if ($usewsdl) { $return = $soap->call($method,$method_params); } else { $return = $soap->call($method,$method_params,'http://soapinterop.org/','http://soapinterop.org/'); } if(!PEAR::isError($return)){ if (is_array($method_params) && count($method_params) == 1) { $sent = array_shift($method_params); } else { $sent = $method_params; } $endpoints[$endpoint]["methods"][$method]['sent'] = $sent; $endpoints[$endpoint]["methods"][$method]['return'] = $return; # we need to decode what we sent so we can compare! $sent = decode_soapval($sent); $ok = test_result($sent,$return); if (!$ok && array_key_exists($method,$method_expect)) { $ok = test_result($method_expect[$method],$return); } if($ok){ $endpoints[$endpoint]["methods"][$method]['success'] = 1; $success = TRUE; if ($show) print "PASSED<br>\n"; } else { $endpoints[$endpoint]["methods"][$method]['success'] = 0; $endpoints[$endpoint]["methods"][$method]['fault'] = array('faultcode'=>'RESULT', 'faultstring'=>'The returned result did not match what we expected to receive'); if ($show) print "FAILED - return: ".gettype($return)."<br>\n"; if ($debug) print "Debug: ".HTMLSpecialChars($soap->debug_data)."\n"; if ($show) { print "<pre>\nSENT: ["; print_r($sent); print "]<br>\nRECEIVED: ["; print_r($return); if (array_key_exists($method,$method_expect)) { print "]<br>\nEXPECTED: ["; print_r($method_expect[$method]); } print "]<br></pre>\n"; } } return $ok; } $fault = $return->getFault(); $endpoints[$endpoint]["methods"][$method]['fault'] = $fault; $endpoints[$endpoint]["methods"][$method]['success'] = 0; $endpoints[$endpoint]["connectFailed"]++; if ($show) { print "FAILED <br>\nERROR: ". HTMLSpecialChars($fault['faultcode']).' '. HTMLSpecialChars($fault['faultstring']).' '. HTMLSpecialChars($fault['faultdetail'])."<br>\n"; } if ($debug) print " Debug: $soap->debug_data<br>\n"; return false; } function do_interopTest(&$method_params) { global $endpoints, $show, $debug, $specificendpoint, $numservers, $testfunc, $totals, $skip; #clear totals $totals = array(); $i = 0; foreach($endpoints as $endpoint => $endpoint_info){ if ($specificendpoint && $endpoint_info['endpointURL'] != $specificendpoint) continue; if (in_array($endpoint_info['endpointURL'], $skip)) continue; $totals['servers']++; $endpoints[$endpoint]["methods"] = array(); if ($show) print "Processing $endpoint at {$endpoint_info['endpointURL']}<br>\n"; $skipendpoint = FALSE; foreach(array_keys($method_params) as $func){ if ($testfunc && $func != $testfunc) continue; if ($skipendpoint) { $endpoints[$endpoint]["methods"][$func]['fault'] = $skipfault; $totals['fail']++; } else { if (do_endpoint_method($endpoint, $func, $method_params[$func])) { $totals['success']++; } else { $skipendpoint = $endpoints[$endpoint]["methods"][$func]['fault']['faultcode']=='HTTP'; $skipfault = $endpoints[$endpoint]["methods"][$func]['fault']; $totals['fail']++; } } $totals['calls']++; } if ($numservers && ++$i >= $numservers) break; } } function outputTables($test, $parm,$usewsdl, &$endpoints, $methods) { global $totals; echo "<b>Testing $test "; if ($usewsdl) echo "using WSDL "; else echo "using Direct calls "; echo "with $parm values</b><br>\n"; echo "\n\n<b>Servers: {$totals['servers']} Calls: {$totals['calls']} Success: {$totals['success']} Fail: {$totals['fail']}</b><br>\n"; echo "<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n"; echo "<tr><td class=\"BLANK\">Endpoint</td>"; foreach ($methods as $func) { echo "<td class=\"BLANK\">$func</td>"; } echo "</tr>\n"; $faults = array(); foreach ($endpoints as $endpoint => $endpoint_info) { echo "<tr><td class=\"BLANK\">$endpoint</td>"; foreach ($methods as $func) { if ($endpoints[$endpoint]["methods"][$func]['success']) { echo '<td class="OK">OK</td>'; } else { $fault = $endpoints[$endpoint]["methods"][$func]['fault']; if (!$fault['faultcode']) $fault['faultcode'] = 'Unknown'; $faults[] = "$endpoint:$func: {$fault['faultcode']} {$fault['faultstring']}"; echo "<td class=\"{$fault['faultcode']}\">{$fault['faultcode']}</td>"; } } echo "</tr>\n"; } echo "</table><br>\n"; if (count($faults) > 0) { echo "<b>ERROR Details:</b><br>\n<ul>\n"; # output more error detail foreach ($faults as $fault) { echo '<li>'.$fault."</li>\n"; } } echo "</ul><br><br>\n"; } ?> Index: pear/SOAP/interop/client_round2_pretty.php +++ pear/SOAP/interop/client_round2_pretty.php <?php // NOTE: do not run this directly under a web server, as it will take a very long // time to execute. Run from a command line or something, and redirect output // to an html file. // // +----------------------------------------------------------------------+ // | PHP Version 4 | // +----------------------------------------------------------------------+ // | Copyright (c) 1997-2002 The PHP Group | // +----------------------------------------------------------------------+ // | This source file is subject to version 2.02 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | // | http://www.php.net/license/2_02.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // // $Id: client_round2_pretty.php,v 1.1 2002/02/28 03:38:28 shane Exp $ // set_time_limit(0); require_once("SOAP/Client.php"); require_once("client_params.php"); require_once("SOAP/test/test.utility.php"); require_once("SOAP/interop/client_library.php"); error_reporting(E_ALL ^ E_NOTICE); $localonly = 0; // set to 1 to test only your local server $usebuiltin = $localonly || 0; // use builtin list of endpoints $usewsdl = 0; $testtype = array(0,1); // with or without wsdl $tests = array_keys($method_params); $parms = array_keys($method_params[$tests[0]]); $show = 0; $debug = 0; $numservers = 0; // zero for all of them $testfunc = ''; // test a single function $specificendpoint = ''; //"http://63.142.188.184:1122/"; // endpoint url // slow or unavailable sites in interop list $skip = array(); //endpoints to skip if ($localonly) { # define your test servers endpointURL here $endpoints[$SOAP_LibraryName] = array( 'endpointURL' => 'http://127.0.0.1/soap/interop.php', 'name' => $SOAP_LibraryName); } elseif ($usebuiltin) { # for doing short tests $endpoints['SilverStream'] = array( 'endpointURL' => 'http://explorer.ne.mediaone.net/app/interop/interop', 'wsdlURL' => 'http://www.xmethods.net/soapbuilders/silverstream/InteropTest.wsdl', 'name' => 'SilverStream'); #$endpoints['SIM'] = array( # 'endpointURL' => 'http://soapinterop.simdb.com/round2', # 'wsdlURL' => 'http://soapinterop.simdb.com/round2?WSDL', # 'name' => 'SIM'); #$endpoints['4s4c'] = array( # 'endpointURL' => 'http://soap.4s4c.com/ilab/soap.asp', # 'wsdlURL' => 'http://www.pocketsoap.com/services/ilab.wsdl', # 'name' => '4s4c'); #$endpoints['Apache Axis'] = array( # 'endpointURL' => 'http://nagoya.apache.org:5049/axis/services/echo', # 'wsdlURL' => 'http://nagoya.apache.org:5049/axis/services/echo?wsdl', # 'name' => 'Apache Axis'); #$endpoints['Apache SOAP 2.2'] = array( # 'endpointURL' => 'http://nagoya.apache.org:5049/soap/servlet/rpcrouter', # 'wsdlURL' => 'http://www.apache.org/~rubys/ApacheSoap.wsdl', # 'name' => 'Apache SOAP 2.2'); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <style> TD { background-color: Red; } TD.BLANK { background-color: White; } TD.OK { background-color: Lime; } TD.CONNECT { background-color: Yellow; } TD.TRANSPORT { background-color: Yellow; } TD.WSDL { background-color: Yellow; } TD.WSDLPARSER { background-color: Yellow; } TD.HTTP { background-color: Yellow; } TD.SMTP { background-color: Yellow; } </style> <title>PEAR-PHP SOAP Interop Tests</title> </head> <body bgcolor="White" text="Black"> <h2 align="center">SOAP Client Interop Test Results: Round2</h2> <p> Notes: Tests are done both "Direct" and with "WSDL". WSDL tests use the supplied interop WSDL to run the tests against. The Direct method uses an internal prebuilt list of methods and parameters for the test.</p> <p> Tests are also run against two methods of generating method parameters. The first, 'php', attempts to directly serialize PHP variables into soap values. The second method, 'soapval', uses a SOAP_Value class to define what the type of the value is. The second method is more interopable than the first by nature. </p> <p> More detail about errors (marked yellow or red) will follow each table. If we have an HTTP error attempting to connect to the endpoint, we will mark all consecutive attempts as errors, and skip testing that endpoint. This reduces the time it takes to run the tests if a server is unavailable. </p> <p> More information on Round 2 Interopability is available at <a href="http://www.whitemesa.com/interop.htm">http://www.whitemesa.com/interop.htm</a>. </p> <?php foreach ($tests as $test) { foreach ($parms as $parm) { if (!$usebuiltin) getInteropEndpoints($test); foreach ($testtype as $usewsdl) { echo "<!-- DEBUG OUTPUT\n"; do_interopTest($method_params[$test][$parm]); echo "#-->\n"; outputTables($test, $parm, $usewsdl, $endpoints, array_keys($method_params[$test][$parm])); } } } ?> </body> </html>
« previous php.pear.cvs (#2624) next »