cvs: pear /SOAP Base.php Client.php Fault.php Header.php Message.php Parser.php Server.php Value.php WSDL.php globals.php package.xml /SOAP/Server
Email.php Email_Gateway.php /SOAP/Transport HTTP.php SMTP.php /SOAP/example attachment.php /SOAP/interop client_round2_interop.php
client_round2_params.php client_round2_run.php server_round2.php server_round2_base.php server_round2_groupB.php server_round2_groupC.php
server_round2_test.php /SOAP/test 5.2.1.simpletypes.string.php 5.2.simpletypes.php test.utility.php
| From: | Shane Caraveo | Date: | Mon, 13 May 2002 06:47:11 +0000 |
| Subject: | cvs: pear /SOAP Base.php Client.php Fault.php Header.php Message.php Parser.php Server.php Value.php WSDL.php globals.php package.xml /SOAP/Server Email.php Email_Gateway.php /SOAP/Transport HTTP.php SMTP.php /SOAP/example attachment.php /SOAP/interop client_round2_interop.php client_round2_params.php client_round2_run.php server_round2.php server_round2_base.php server_round2_groupB.php server_round2_groupC.php server_round2_test.php /SOAP/test 5.2.1.simpletypes.string.php 5.2.simpletypes.php test.utility.php |
||
| Groups: | php.pear.cvs | ||
| Request: | Send a blank email to pear-cvs+get-3795@lists.php.net to get a copy of this message | ||
shane Mon May 13 02:47:11 2002 EDT
Added files:
/pear/SOAP/example attachment.php
Removed files:
/pear/SOAP Header.php Message.php globals.php
Modified files:
/pear/SOAP Base.php Client.php Fault.php Parser.php Server.php
Value.php WSDL.php package.xml
/pear/SOAP/Server Email.php Email_Gateway.php
/pear/SOAP/Transport HTTP.php SMTP.php
/pear/SOAP/interop client_round2_interop.php
client_round2_params.php client_round2_run.php
server_round2.php server_round2_base.php
server_round2_groupB.php
server_round2_groupC.php server_round2_test.php
/pear/SOAP/test 5.2.1.simpletypes.string.php 5.2.simpletypes.php
test.utility.php
Log:
Major changes
1. soap_value changed to light-weight class, serializing is 'more' optimized now
2. DIME support
3. SwA support (SOAP with Attachments)
DIME and SwA are experimental still, no testing with other soap toolkits has
been done on them. They do work fine within PEAR::SOAP.
Last big todo before release...optimize parser.
Index: pear/SOAP/Base.php diff -u pear/SOAP/Base.php:1.7 pear/SOAP/Base.php:1.8 --- pear/SOAP/Base.php:1.7 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Base.php Mon May 13 02:47:09 2002 @@ -17,23 +17,163 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +// $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ // require_once 'PEAR.php'; #require_once 'SOAP/Fault.php'; +require_once 'SOAP/Type/dateTime.php'; +require_once 'SOAP/Type/hexBinary.php'; + +// optional features +$SOAP_options = array(); + +include_once 'Mail/mimePart.php'; +include_once 'Mail/mimeDecode.php'; +if (class_exists('Mail_mimePart')) { + $SOAP_options['Mime'] = 1; +} + +include_once 'Net/DIME.php'; +if (class_exists('DIME_Message')) { + $SOAP_options['DIME'] = 1; +} + +#error_reporting(E_ALL & ~E_NOTICE); + +/** +* Enable debugging informations? +* +* @const SOAP_DEBUG +*/ +define('SOAP_DEBUG', false); + +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'); +} else { + 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('SOAP_LIBRARY_NAME', 'PEAR-SOAP 0.6.1'); +// set schema version +define('SOAP_XML_SCHEMA_VERSION', 'http://www.w3.org/2001/XMLSchema'); +define('SOAP_XML_SCHEMA_INSTANCE', 'http://www.w3.org/2001/XMLSchema-instance'); +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_DEFAULT_ENCODING', 'UTF-8'); + +if (!function_exists('is_a')) +{ + function is_a($object, $class_name) + { + if (get_class($object) == $class_name) return TRUE; + else return is_subclass_of($object, $class_name); + } +} /** * SOAP_Base * Common base class of all Soap lclasses * * @access public -* @version $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates */ class SOAP_Base extends PEAR { + var $_XMLSchema = array('http://www.w3.org/2001/XMLSchema', 'http://www.w3.org/1999/XMLSchema'); + var $_XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; + + // load types into typemap array + var $_typemap = array( + 'http://www.w3.org/2001/XMLSchema' => array( + 'string' => 'string', + 'boolean' => 'boolean', + 'float' => FLOAT, + 'double' => FLOAT, + 'decimal' => FLOAT, + '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', + 'anyType' => 'string', + 'anyURI' => 'string', + 'QName' => 'string' + ), + 'http://www.w3.org/1999/XMLSchema' => array( + 'i4' => 'integer', + 'int' => 'integer', + 'boolean' => 'boolean', + 'string' => 'string', + 'double' => FLOAT, + 'float' => FLOAT, + 'dateTime' => 'string', + 'timeInstant' => 'string', + 'base64Binary' => 'string', + 'base64' => 'string', + 'ur-type' => 'string' + ), + 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64' => 'string','array' => 'array','Array' => 'array', 'Struct'=>'array') + ); + + // load namespace uris into an array of uri => prefix + var $_namespaces; + var $_ns_count = 0; + # supported encodings, limited by XML extension + var $_encodings = array('ISO-8859-1','US-ASCII','UTF-8'); + + var $_xmlEntities = array ( '&' => '&', '<' => '<', '>' => '>', "'" => ''', '"' => '"' ); + + var $doconversion = TRUE; + + var $attachments = array(); /** * Store debugging information in $debug_data? @@ -66,19 +206,49 @@ */ var $fault = NULL; - + var $wsdl = NULL; /** * Constructor * * @param string error code * @see $debug_data, debug() */ - function SOAP_Base($faultcode) + function SOAP_Base($faultcode = 'Client') { $this->myfaultcode = $faultcode; + $this->resetNamespaces(); parent::PEAR('SOAP_Fault'); } + function resetNamespaces() + { + $this->_namespaces = array( + 'http://schemas.xmlsoap.org/soap/envelope/' => 'SOAP-ENV', + 'http://www.w3.org/2001/XMLSchema' => 'xsd', + 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', + 'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC'); + } + + /** + * setSchemaVersion + * + * sets the schema version used in the soap message + * + * @param string (see globals.php) + * + * @access private + */ + function setSchemaVersion($schemaVersion) + { + if (!in_array($schemaVersion, $this->_XMLSchema)) { + return $this->raiseSoapFault("unsuported XMLSchema $schemaVersion"); + } + $this->_XMLSchemaVersion = $schemaVersion; + $tmpNS = array_flip($this->_namespaces); + $tmpNS['xsd'] = $this->_XMLSchemaVersion; + $tmpNS['xsi'] = $this->_XMLSchemaVersion.'-instance'; + $this->_namespaces = array_flip($tmpNS); + } /** * Raise a soap error @@ -127,6 +297,513 @@ } } + function getNamespacePrefix($ns) + { + if (array_key_exists($ns,$this->_namespaces)) { + return $this->_namespaces[$ns]; + } + $prefix = 'ns'.count($this->_namespaces); + $this->_namespaces[$ns] = $prefix; + return $prefix; + return NULL; + } + + function serializeValue($value, $name = '', $type = false, $elNamespace = NULL, $typeNamespace=NULL, $options=array(), $attributes = array()) + { + $namespaces = array(); + $xmlout_value = NULL; + $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = $xmlout_type = $xmlns = ''; + + if (!$name || is_numeric($name)) $name = 'item'; + + if (!is_null($value)) { + list($ptype,$arrayType,$array_type_ns) = $this->_getSchemaType($type, $name, $typeNamespace); + if (!$ptype) $ptype = $this->_getType($value); + if (!$type) $type = $ptype; + + #if ($ptype == 'object') { + # return $value->serialize($this); + #} else + if (strcasecmp($ptype,'Struct')==0 || strcasecmp($type,'Struct')==0) { + // struct + foreach ($value as $k => $v) { + if (is_object($v)) + $xmlout_value .= $v->serialize($this); + else + $xmlout_value .= $this->serializeValue($v,$k); + } + } else if (strcasecmp($ptype,'Array')==0 || strcasecmp($type,'Array')==0) { + // array + $typeNamespace = SOAP_SCHEMA_ENCODING; + $type = 'Array'; + $numtypes = 0; + // XXX this will be slow on larger array's. Basicly, it flattens array's to allow us + // to serialize multi-dimensional array's. We only do this if arrayType is set, + // which will typicaly only happen if we are using WSDL + if (isset($options['flatten']) || ($arrayType && strchr($arrayType,','))) { + $numtypes = $this->_multiArrayType($value, $arrayType, $ar_size, $xmlout_value); + } + + $array_type = $array_type_prefix = ''; + if ($numtypes != 1) { + $array_types = array(); + $array_val = NULL; + + // serialize each array element + foreach ($value as $array_val) { + if (is_object($array_val)) { + $array_type = $array_val->type; + $array_types[$array_type] = 1; + $array_type_ns = $array_val->type_namespace; + $xmlout_value .= $array_val->serialize($this); + } else { + $array_type = $this->_getType($array_val); + $array_types[$array_type] = 1; + $xmlout_value .= $this->serializeValue($array_val,'item', $array_type); + } + } + + $ar_size = count($value); + $numtypes = count($array_types); + $xmlout_offset = " SOAP-ENC:offset=\"[0]\""; + if ($numtypes == 1) $arrayType = $array_type; + // using anyType is more interoperable + if ($array_type == 'Struct') { + $array_type = ''; + } else if ($array_type == 'Array') { + $arrayType = 'anyType'; + $array_type_prefix = 'xsd'; + } else + if (!$arrayType) $arrayType = $array_type; + } + if (!isset($arrayType) || $numtypes > 1) { + $arrayType = 'xsd:anyType'; // should reference what schema we're using + } else { + if ($array_type_ns) { + $array_type_prefix = $this->getNamespacePrefix($array_type_ns); + } else if (array_key_exists($arrayType, $this->_typemap[$this->_XMLSchemaVersion])) { + $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; + } + if ($array_type_prefix) + $arrayType = $array_type_prefix.':'.$arrayType; + } + $xmlout_arrayType = " SOAP-ENC:arrayType=\"".$arrayType."[$ar_size]\""; + + } else if ($type == 'string') { + $xmlout_value = htmlspecialchars($value); + } else { + $xmlout_value = $value; + } + } + // add namespaces + if ($elNamespace) { + $elPrefix = $this->getNamespacePrefix($elNamespace); + $xmlout_name = "$elPrefix:$name"; + } else { + $xmlout_name = $name; + } + + if ($typeNamespace) { + $typePrefix = $this->getNamespacePrefix($typeNamespace); + $xmlout_type = "$typePrefix:$type"; + } else if ($type && array_key_exists($type, $this->_typemap[$this->_XMLSchemaVersion])) { + $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; + $xmlout_type = "$typePrefix:$type"; + } + + // handle additional attributes + $xml_attr = ''; + if (count($attributes)) { + foreach ($attributes as $k => $v) { + $kqn = new QName($k); + $vqn = new QName($v); + $xml_attr .= ' '.$kqn->fqn().'="'.$vqn->fqn().'"'; + } + } + + // store the attachement for mime encoding + if (isset($options['attachment'])) + $this->attachments[] = $options['attachment']; + + if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\""; + if (is_null($xmlout_value)) { + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xml_attr/>"; + } else { + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType$xmlout_offset$xml_attr>". + $xmlout_value."</$xmlout_name>"; + } + return $xml; + } + + function _getSchemaType($type, $name, $type_namespace) + { + if ($this->wsdl) { + # see if it's a complex type so we can deal properly with SOAPENC:arrayType + if ($name && $type) { + # XXX TODO: + # look up the name in the wsdl and validate the type + foreach ($this->wsdl->complexTypes as $ns=> $types) { + if (array_key_exists($type, $types)) { + if (array_key_exists('base', $types[$type])) { + return array($types[$type]['base'],$types[$type]['type'],$this->wsdl->namespaces[$types[$type]['namespace']]); + } + if (array_key_exists('arrayType', $types[$type])) { + return array('Array',$types[$type]['arrayType'],$this->wsdl->namespaces[$types[$type]['namespace']]); + } + if (array_key_exists('elements', $types[$type]) && + array_key_exists($name, $types[$type]['elements'])) { + $type = $types[$this->type]['elements']['type']; + return array($type,NULL,$this->wsdl->namespaces[$types[$type]['namespace']]); + } + } + } + } + if ($type && $type_namespace) { + $arrayType = NULL; + # XXX TODO: + # this code currently handles only one way of encoding array types in wsdl + # need to do a generalized function to figure out complex types + $p = $this->wsdl->ns[$type_namespace]; + if ($p && + array_key_exists($p, $this->wsdl->complexTypes) && + array_key_exists($type, $this->wsdl->complexTypes[$p])) { + if ($arrayType = $this->wsdl->complexTypes[$p][$type]['arrayType']) { + $type = 'Array'; + } else if ($this->wsdl->complexTypes[$p][$type]['order']=='sequence' && + array_key_exists('elements', $this->wsdl->complexTypes[$p][$type])) { + reset($this->wsdl->complexTypes[$p][$type]['elements']); + # assume an array + if (count($this->wsdl->complexTypes[$p][$type]['elements']) == 1) { + $arg = current($this->wsdl->complexTypes[$p][$type]['elements']); + $arrayType = $arg['type']; + $type = 'Array'; + } else { + foreach($this->wsdl->complexTypes[$p][$type]['elements'] as $element) { + if ($element['name'] == $type) { + $arrayType = $element['type']; + $type = $element['type']; + } + } + } + } else { + $type = 'Struct'; + } + return array($type,$arrayType,$type_namespace); + } + } + } + return array(NULL,NULL,NULL); + } + + /** + * SOAP::Value::_getType + * + * convert php type to soap type + * @param string value + * + * @return string type - soap type + * @access private + */ + function _getType(&$value) { + $type = gettype($value); + switch ($type) { + case 'object': + if (is_a($value,'soap_value')) { + $type = $value->type; + } + break; + case 'array': + $type = $this->isHash($value)?'Struct':'Array'; + break; + case 'integer': + case 'long': + $type = 'int'; + break; + case 'boolean': + $value = $value?'true':'false'; + break; + case 'double': + $type = 'float'; // double is deprecated in 4.2 and later + break; + case 'NULL': + $type = ''; + break; + case 'string': + if ($this->doconversion) { + if (is_numeric($value)) { + if (strstr($value,'.')) $type = 'float'; + else $type = 'int'; + } else + if (SOAP_Type_hexBinary::is_hexbin($value)) { + $type = 'hexBinary'; + } else + if ($this->isBase64($value)) { + $type = 'base64Binary'; + } else { + $dt = new SOAP_Type_dateTime($value); + if ($dt->toUnixtime() != -1) { + $type = 'dateTime'; + #$value = $dt->toSOAP(); + } + } + } + default: + break; + } + return $type; + } + + function _multiArrayType(&$value, &$type, &$size, &$xml) + { + $sz = count($value); + if ($sz > 1) { + // seems we have a multi dimensional array, figure it out if we do + foreach ($value as $array_val) { + $this->_multiArrayType($array_val, $type, $size, $xml); + } + + if ($size) { + $size = $sz.','.$size; + } else { + $size = $sz; + } + return 1; + } else { + if (is_object($value)) { + $type = $value->type; + $xml .= $value->serialize($this); + } else { + $type = $this->_getType($value); + $xml .= $this->serializeValue($value,'item',$type); + } + } + $size = NULL; + return 1; + } + // support functions + /** + * + * @param string + * @return string + */ + function isBase64(&$value) + { + $l = strlen($value); + if ($l > 0) + return $value[$l-1] == '=' && preg_match("/[A-Za-z=\/\+]+/",$value); + return FALSE; + } + + /** + * + * @param mixed + * @return boolean + */ + function isHash(&$a) { + # XXX I realy dislike having to loop through this in php code, + # realy large arrays will be slow. We need a C function to do this. + $names = array(); + $it = 0; + foreach ($a as $k => $v) { + # checking the type is faster than regexp. + $t = gettype($k); + if ($t != 'integer') { + return TRUE; + } else if (gettype($v) == 'object' && is_a($v,'soap_value')) { + $names[$v->name] = 1; + } + // if someone has a large hash they should realy be defining the type + if ($it++ > 10) return FALSE; + } + return count($names)>1; + } + + function un_htmlentities($string) + { + $trans_tbl = get_html_translation_table (HTML_ENTITIES); + $trans_tbl = array_flip($trans_tbl); + return strtr($string, $trans_tbl); + } + + /** + * + * @param mixed + */ + function decode($soapval) + { + if (!is_object($soapval)) { + return $soapval; + } else if (is_array($soapval->value)) { + $return = array(); + $counter = 1; + $isstruct = TRUE; // assume it's a struct + foreach ($soapval->value as $item) { + if (!$isstruct) { + $return[] = $this->decode($item); + } else if (isset($return[$item->name])) { + // this is realy an array, we need to redirect + $isstruct = FALSE; + $return = array($return[$item->name], $this->decode($item)); + } else { + $return[$item->name] = $this->decode($item); + } + } + return $return; + } + + if ($soapval->type == 'boolean') { + if ($soapval->value != '0' && strcasecmp($soapval->value,'false') !=0) { + $soapval->value = TRUE; + } else { + $soapval->value = FALSE; + } + } else if ($soapval->type && array_key_exists($soapval->type, $this->_typemap[SOAP_XML_SCHEMA_VERSION])) { + # if we can, lets set php's variable type + settype($soapval->value, $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); + } + return $soapval->value; + } + + /** + * creates the soap envelope with the soap envelop data + * + * @param string $payload soap data (in xml) + * @return associative array (headers,body) + * @access private + */ + function _makeEnvelope($method, $headers=NULL, $encoding = SOAP_DEFAULT_ENCODING) + { + $header_xml = $ns_string = ''; + + if ($headers) { + foreach ($headers as $header) { + $header_xml .= $header->serialize($this); + } + $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n"; + } + $body = "<SOAP-ENV:Body>\r\n".$method->serialize($this)."\r\n</SOAP-ENV:Body>\r\n"; + + foreach ($this->_namespaces as $k => $v) { + $ns_string .= " xmlns:$v=\"$k\"\r\n "; + } + + $xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n". + "<SOAP-ENV:Envelope $ns_string SOAP-ENV:encodingStyle=\"" . SOAP_SCHEMA_ENCODING . "\">\r\n". + "$header_xml$body</SOAP-ENV:Envelope>\r\n"; + + return $xml; + } + + function _makeMimeMessage($xml, $encoding = SOAP_DEFAULT_ENCODING) + { + global $SOAP_options; + + if (!isset($SOAP_options['Mime'])) { + return $this->raiseSoapFault('Mime is not installed'); + } + + // encode any attachments + // see http://www.w3.org/TR/SOAP-attachments + // now we have to mime encode the message + $params = array('content_type' => 'multipart/related; type=text/xml'); + $msg = new Mail_mimePart('', $params); + // add the xml part + $params['content_type'] = 'text/xml'; + $params['charset'] = $encoding; + $params['encoding'] = 'base64'; + $msg->addSubPart($xml, $params); + + // add the attachements + foreach ($this->attachments as $attachment) { + $msg->addSubPart($attachment['body'],$attachment); + } + return $msg->encode(); + } + + // XXX this needs to be used from the Transport system + function _makeDIMEMessage($xml) + { + global $SOAP_options; + + if (!isset($SOAP_options['DIME'])) { + return $this->raiseSoapFault('DIME is not installed'); + } + + // encode any attachments + // see http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt + // now we have to DIME encode the message + $dime = new DIME_Message(); + $msg = $dime->encodeData($xml,SOAP_ENVELOP,NULL,DIME_TYPE_URI); + + // add the attachements + foreach ($this->attachments as $attachment) { + $msg .= $dime->encodeData($attachment['body'],$attachment['content_type'],$attachment['cid'],DIME_TYPE_MEDIA); + } + $msg .= $dime->endMessage(); + return $msg; + } + + function decodeMimeMessage(&$data, &$headers, &$attachments) + { + global $SOAP_options; + if (!isset($SOAP_options['Mime'])) { + $this->makeFault('Server','Mime Unsupported, install PEAR::Mail::Mime'); + return; + } + + $params['include_bodies'] = TRUE; + $params['decode_bodies'] = TRUE; + $params['decode_headers'] = TRUE; + + $decoder = new Mail_mimeDecode($data); + $structure = $decoder->decode($params); + + if (isset($structure->body)) { + $data = $structure->body; + $headers = $structure->headers; + return; + } else if (isset($structure->parts)) { + $data = $structure->parts[0]->body; + $headers = $structure->parts[0]->headers; + if (count($structure->parts) > 1) { + $mime_parts = array_splice($structure->parts,1); + // prepare the parts for the soap parser + + foreach ($mime_parts as $p) { + if (isset($p->headers['content-location'])) { + // XXX TODO: modify location per SwA note section 3 + // http://www.w3.org/TR/SOAP-attachments + $attachments[$p->headers['content-location']] = $p->body; + } else { + $cid = 'cid:'.substr($p->headers['content-id'],1,strlen($p->headers['content-id'])-2); + $attachments[$cid] = $p->body; + } + } + } + return; + } + $this->makeFault('Server','Mime parsing error'); + } + + function decodeDIMEMessage(&$data, &$headers, &$attachments) + { + // XXX this SHOULD be moved to the transport layer, e.g. PHP itself + // should handle parsing DIME ;) + $dime = new DIME_Message(); + $dime->decodeData($data); + if (strcasecmp($dime->parts[0]['type'],SOAP_ENVELOP) !=0 || + strcasecmp($dime->parts[0]['type'],SOAP_ENVELOP) !=0) { + $this->makeFault('Server','Dime record 1 is not a SOAP envelop!'); + } else { + $data = $dime->parts[0]['data']; + $headers['content-type'] = 'text/xml'; // fake it for now + foreach ($dime->parts as $part) { + // XXX we need to handle URI's better + $attachments['cid:'.$part['id']] = $part['data']; + } + } + } + } /** @@ -134,7 +811,7 @@ * class used to handle QNAME values in XML * * @access public -* @version $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates */ @@ -142,26 +819,44 @@ { var $name = ''; var $ns = ''; + var $namespace=''; #var $arrayInfo = ''; - function QName($name) { - if (strpos($name, ':') != FALSE) { + function QName($name, $namespace = '') { + if ($name && $name[0] == '{') { + preg_match('/\{(.*?)\}(.*)/',$name, $m); + $this->name = $m[2]; + $this->namespace = $m[1]; + } else if (strpos($name, ':') != FALSE) { $s = split(':',$name); $s = array_reverse($s); $this->name = $s[0]; $this->ns = $s[1]; + $this->namespace = $namespace; } else { $this->name = $name; + $this->namespace = $namespace; } # a little more magic than should be in a qname - #$p = strpos($this->name, '['); - #if ($p) { - # # XXX need to re-examine this logic later - # # chop off [] - # $this->arrayInfo = substr($this->name, $p); - # $this->name = substr($this->name, 0, $p); - #} + $p = strpos($this->name, '['); + if ($p) { + # XXX need to re-examine this logic later + # chop off [] + $this->arraySize = split(',',substr($this->name,$p+1, strlen($this->name)-$p-2)); + $this->arrayInfo = substr($this->name, $p); + $this->name = substr($this->name, 0, $p); + } + } + + function fqn() + { + if ($this->namespace) { + return '{'.$this->namespace.'}'.$this->name; + } else if ($this->ns) { + return $this->ns.':'.$this->name; + } + return $this->name; } } -?> +?> \ No newline at end of file Index: pear/SOAP/Client.php diff -u pear/SOAP/Client.php:1.28 pear/SOAP/Client.php:1.29 --- pear/SOAP/Client.php:1.28 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Client.php Mon May 13 02:47:09 2002 @@ -17,13 +17,12 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Client.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +// $Id: Client.php,v 1.29 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Value.php'; require_once 'SOAP/Base.php'; require_once 'SOAP/Transport.php'; -require_once 'SOAP/Message.php'; require_once 'SOAP/WSDL.php'; require_once 'SOAP/Fault.php'; @@ -38,7 +37,7 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Client.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Client.php,v 1.29 2002/05/13 06:47:09 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 @@ -105,6 +104,8 @@ * @var string Contains the character encoding used for XML parser, etc. */ var $encoding = SOAP_DEFAULT_ENCODING; + + var $headers = NULL; /** * SOAP_Client constructor * @@ -142,8 +143,7 @@ */ function setEncoding($encoding) { - global $SOAP_Encodings; - if (in_array($encoding, $SOAP_Encodings)) { + if (in_array($encoding, $this->_encodings)) { $this->encoding = $encoding; return NULL; } @@ -162,17 +162,14 @@ */ function addHeader($soap_value) { - if (!$this->soapmsg) { - soap_reset_namespaces(); - $this->soapmsg = new SOAP_Message(NULL, $this->wsdl); - } # add a new header to the message - if (get_class($soap_value) == 'soap_header') { - $this->soapmsg->addHeader($soap_value); + if (is_a($soap_value,'soap_header')) { + #$this->soapmsg->addHeader($soap_value); + $this->headers[] = $soap_value; } else if (gettype($soap_value) == 'array') { // name, value, namespace, mustunderstand, actor - $h = new SOAP_Header($soap_value[0], NULL, $soap_value[1], $soap_value[2], $soap_value[3], $soap_value[4]); - $this->soapmsg->addHeader($h); + $h = new SOAP_Header($soap_value[0], NULL, $soap_value[1], $soap_value[2], $soap_value[3]); + $this->headers[] = $h; } else { $this->raiseSoapFault("Don't understand the header info you provided. Must be array or SOAP_Header."); } @@ -211,15 +208,10 @@ $this->fault = null; $options = array(); - // make message - if (!$this->soapmsg) { - soap_reset_namespaces(); - $this->soapmsg = new SOAP_Message(NULL, $this->wsdl); - } - if (gettype($namespace) == 'array') { $options = $namespace; - $namespace = $options['namespace']; + if (isset($options['namespace'])) $namespace = $options['namespace']; + else $namespace = false; } else { // we'll place soapaction into our array for usage in the transport $options['soapaction'] = $soapAction; @@ -264,16 +256,17 @@ $nparams[$name] = current($params); next($params); } - if (gettype($nparams[$name]) != 'object' && - get_class($nparams[$name]) != 'soap_value') { + if (gettype($nparams[$name]) != 'object' || + !is_a($nparams[$name],'soap_value')) { // type is a qname likely, split it apart, and get the type namespace from wsdl $qname = new QName($type); if ($qname->ns) $type_namespace = $this->wsdl->namespaces[$qname->ns]; else $type_namespace = NULL; + $qname->namespace = $type_namespace; $type = $qname->name; - $nparams[$name] = new SOAP_Value($name, $qname->name, $nparams[$name], NULL, $type_namespace, $this->wsdl); + $nparams[$name] = new SOAP_Value($name, $qname->fqn(), $nparams[$name]); } } } @@ -282,21 +275,50 @@ $this->setSchemaVersion(SOAP_XML_SCHEMA_VERSION); } - $this->soapmsg->method($method, $params, $namespace); - if ($this->soapmsg->fault) { - return $this->raiseSoapFault($this->soapmsg->fault); - } - // serialize the message - $soap_data = $this->soapmsg->serialize($this->encoding); - - if (PEAR::isError($soap_data)) { - return $this->raiseSoapFault($soap_data); + $mqname = new QName($method, $namespace); + $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params); + $soap_msg = $this->_makeEnvelope($methodValue, $this->headers, $this->encoding); + + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if (isset($options['Mime'])) { + $soap_msg = $this->_makeMimeMessage($soap_msg, $this->encoding); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg, $this->encoding); + $options['headers']['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } } // instantiate client - $dbg = "calling server at '$this->endpoint'..."; - + if (is_array($soap_msg)) { + $soap_data = $soap_msg['body']; + if (count($soap_msg['headers'])) { + if (isset($options['headers'])) { + $options['headers'] = array_merge($options['headers'],$soap_msg['headers']); + } else { + $options['headers'] = $soap_msg['headers']; + } + } + } else { + $soap_data = $soap_msg; + } + #$f = fopen('/tmp/dime.data','wb+'); + #if ($f) { + # fwrite($f,$soap_data); + # fclose($f); + # return; + #} $soap_transport = new SOAP_Transport($this->endpoint, $this->encoding); if ($soap_transport->fault) { @@ -319,7 +341,7 @@ } // parse the response - $this->response = new SOAP_Parser($this->response, $soap_transport->result_encoding); + $this->response = new SOAP_Parser($this->response, $soap_transport->result_encoding,$soap_transport->transport->attachments); if ($this->response->fault) { return $this->raiseSoapFault($this->response->fault); } @@ -327,20 +349,20 @@ $return = $this->response->getResponse(); $headers = $this->response->getHeaders(); if ($headers) { - $this->headers = $headers->decode(); + $this->headers = $this->decode($headers); } - $this->soapmsg = NULL; + #$this->soapmsg = NULL; // check for valid response if (PEAR::isError($return)) { return $this->raiseSoapFault($return); - } else if (strcasecmp(get_class($return), 'SOAP_Value') != 0) { + } else if (!is_a($return,'soap_value')) { return $this->raiseSoapFault("didn't get SOAP_Value object back from client"); } // decode to native php datatype - $returnArray = $return->decode(); + $returnArray = $this->decode($return); // fault? if (PEAR::isError($returnArray)) { return $this->raiseSoapFault($returnArray); @@ -364,25 +386,6 @@ return $returnArray; } - /** - * setSchemaVersion - * - * sets the schema version used in the soap message - * - * @param string (see globals.php) - * - * @access private - */ - function setSchemaVersion($schemaVersion) - { - global $SOAP_namespaces; - $this->XMLSchemaVersion = $schemaVersion; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - } - /** * SOAP_Client::__call * Index: pear/SOAP/Fault.php diff -u pear/SOAP/Fault.php:1.6 pear/SOAP/Fault.php:1.7 --- pear/SOAP/Fault.php:1.6 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Fault.php Mon May 13 02:47:09 2002 @@ -17,10 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Fault.php,v 1.6 2002/04/27 18:33:25 shane Exp $ +// $Id: Fault.php,v 1.7 2002/05/13 06:47:09 shane Exp $ // require_once('PEAR.php'); -require_once('SOAP/Message.php'); /** * SOAP_Fault @@ -30,7 +29,7 @@ * @access public * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more * @author Dietrich Ayala <dietrich@ganx4.com> Original Author - * @version $Id: Fault.php,v 1.6 2002/04/27 18:33:25 shane Exp $ + * @version $Id: Fault.php,v 1.7 2002/05/13 06:47:09 shane Exp $ */ class SOAP_Fault extends PEAR_Error { @@ -70,17 +69,15 @@ */ function message() { - $msg = new SOAP_Message(); - $msg->method('Fault', - array( + $msg = new SOAP_Base(); + $params = array( new SOAP_Value('faultcode', 'QName', 'SOAP-ENV:'.$this->code), new SOAP_Value('faultstring', 'string', $this->message), new SOAP_Value('faultactor', 'anyURI', $this->error_message_prefix), new SOAP_Value('detail', 'string', $this->userinfo) - ), - SOAP_ENVELOP - ); - return $msg; + ); + $methodValue = new SOAP_Value('{'.SOAP_ENVELOP.'}Fault', 'Struct', $params); + return $msg->_makeEnvelope($methodValue); } /** Index: pear/SOAP/Parser.php diff -u pear/SOAP/Parser.php:1.21 pear/SOAP/Parser.php:1.22 --- pear/SOAP/Parser.php:1.21 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Parser.php Mon May 13 02:47:09 2002 @@ -17,10 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Parser.php,v 1.21 2002/04/27 18:33:25 shane Exp $ +// $Id: Parser.php,v 1.22 2002/05/13 06:47:09 shane Exp $ // -require_once 'SOAP/globals.php'; require_once 'SOAP/Base.php'; require_once 'SOAP/Value.php'; @@ -31,7 +30,7 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Parser.php,v 1.21 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Parser.php,v 1.22 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Parser * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author @@ -43,11 +42,11 @@ var $pos_stat = 0; var $depth = 0; var $default_namespace = ''; - var $namespaces = array(); var $message = array(); var $depth_array = array(); var $previous_element = ''; var $soapresponse = NULL; + var $soapheaders = NULL; var $parent = 0; var $root_struct_name = array(); var $header_struct_name = array(); @@ -69,14 +68,15 @@ * @param string xml content * @param string xml character encoding, defaults to 'UTF-8' */ - function SOAP_Parser($xml, $encoding = SOAP_DEFAULT_ENCODING) + function SOAP_Parser($xml, $encoding = SOAP_DEFAULT_ENCODING, $attachments=NULL) { parent::SOAP_Base('Parser'); $this->setSchemaVersion(SOAP_XML_SCHEMA_VERSION); $this->xml = $xml; $this->xml_encoding = $encoding; - + $this->attachments = $attachments; + // check the xml tag for encoding if (preg_match('/<\?xml.*?encoding=(?:[\'|"])([\w\d-]*)?.*?(?:[\'|"])\?>/',$xml,$m)) { $this->xml_encoding = strtoupper($m[1]); @@ -113,23 +113,7 @@ } } - /** - * setSchemaVersion - * sets the schema for the resulting message - * - * @param string schema version - * @access private - */ - function setSchemaVersion($schemaVersion) - { - global $SOAP_namespaces; - $this->XMLSchemaVersion = $schemaVersion; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - } - + /** * domulti * recurse to build a multi-dim array, used by buildResponse @@ -157,7 +141,7 @@ { $response = NULL; - if ($this->message[$pos]['children'] != '') { + if (isset($this->message[$pos]['children'])) { $children = explode('|',$this->message[$pos]['children']); foreach ($children as $c => $child_pos) { @@ -189,7 +173,8 @@ } } $response = $newresp; - } else if ($this->message[$pos]['arrayOffset'][0] > 0) { + } else if (isset($this->message[$pos]['arrayOffset']) && + $this->message[$pos]['arrayOffset'][0] > 0) { # check for padding $pad = $this->message[$pos]['arrayOffset'][0]+count($response)*-1; $response = array_pad($response,$pad,NULL); @@ -198,9 +183,13 @@ } // add current node's value if ($response) { - $response = new SOAP_Value($this->message[$pos]["name"], $this->message[$pos]["type"] , $response, $this->message[$pos]["namespace"], $this->message[$pos]['type_namespace']); + $nqn = new Qname($this->message[$pos]["name"],$this->message[$pos]["namespace"]); + $tqn = new Qname($this->message[$pos]["type"],$this->message[$pos]["type_namespace"]); + $response = new SOAP_Value($nqn->fqn(), $nqn->fqn(), $response); } else { - $response = new SOAP_Value($this->message[$pos]['name'], $this->message[$pos]['type'] , $this->message[$pos]['cdata'], $this->message[$pos]["namespace"], $this->message[$pos]['type_namespace']); + $nqn = new Qname($this->message[$pos]["name"],$this->message[$pos]["namespace"]); + $tqn = new Qname($this->message[$pos]["type"],$this->message[$pos]["type_namespace"]); + $response = new SOAP_Value($nqn->fqn(), $nqn->fqn(), $this->message[$pos]['cdata']); } // handle header attribute that we need if (array_key_exists('actor',$this->message[$pos])) { @@ -220,13 +209,15 @@ */ function startElement($parser, $name, $attrs) { - global $SOAP_XMLSchema; // position in a total number of elements, starting from 0 // update class level pos $pos = $this->position++; // and set mine $this->message[$pos] = array(); + $this->message[$pos]['type'] = ''; + $this->message[$pos]['type_namespace'] = ''; + $this->message[$pos]['cdata'] = ''; $this->message[$pos]['pos'] = $pos; $this->message[$pos]['id'] = ''; @@ -238,7 +229,10 @@ // else add self as child to whoever the current parent is if ($pos != 0) { - $this->message[$this->parent]['children'] .= "|$pos"; + if (isset($this->message[$this->parent]['children'])) + $this->message[$this->parent]['children'] .= "|$pos"; + else + $this->message[$this->parent]['children'] = $pos; } // set my parent @@ -290,16 +284,6 @@ // set attrs $this->message[$pos]['attrs'] = $attrs; - // see if namespace is defined in tag - if (array_key_exists('xmlns:'.$qname->ns,$attrs)) { - $namespace = $attrs['xmlns:'.$qname->ns]; - } else { - // get namespace - $namespace = $qname->ns?$this->namespaces[$qname->ns]:$this->default_namespace; - } - $this->message[$pos]['namespace'] = $namespace; - $this->default_namespace = $namespace; - // loop through atts, logging ns and type declarations foreach ($attrs as $key => $value) { // if ns declarations, add to class level array of valid namespaces @@ -307,11 +291,11 @@ if ($kqn->ns == 'xmlns') { $prefix = $kqn->name; - if (in_array($value, $SOAP_XMLSchema)) { + if (in_array($value, $this->_XMLSchema)) { $this->setSchemaVersion($value); } - $this->namespaces[$prefix] = $value; + $this->_namespaces[$prefix] = $value; // set method namespace # XXX unused??? @@ -328,20 +312,21 @@ } elseif ($kqn->name == 'type') { $vqn = new QName($value); $this->message[$pos]['type'] = $vqn->name; - $this->message[$pos]['type_namespace'] = $this->namespaces[$vqn->ns]; + $this->message[$pos]['type_namespace'] = $this->_namespaces[$vqn->ns]; #print "set type for {$this->message[$pos]['name']} to {$this->message[$pos]['type']}\n"; // should do something here with the namespace of specified type? } elseif ($kqn->name == 'arrayType') { $vqn = new QName($value); $this->message[$pos]['type'] = 'Array'; - $type = $vqn->name; - $sa = strpos($type,'['); - if ($sa > 0) { - $this->message[$pos]['arraySize'] = split(',',substr($type,$sa+1, strlen($type)-$sa-2)); - $type = substr($type, 0, $sa); - } - $this->message[$pos]['arrayType'] = $type; + #$type = $vqn->name; + $this->message[$pos]['arraySize'] = $vqn->arraySize; + #$sa = strpos($type,'['); + #if ($sa > 0) { + # $this->message[$pos]['arraySize'] = split(',',substr($type,$sa+1, strlen($type)-$sa-2)); + # $type = substr($type, 0, $sa); + #} + $this->message[$pos]['arrayType'] = $vqn->name; } elseif ($kqn->name == 'offset') { $this->message[$pos]['arrayOffset'] = split(',',substr($value, 1, strlen($value)-2)); @@ -351,23 +336,36 @@ $this->references[$value] = $pos; $this->message[$pos]['id'] = $value; - } elseif ($kqn->name == 'href' && $value[0] == '#') { - $ref = substr($value, 1); - if (array_key_exists($ref,$this->references)) { - # cdata, type, inval - $ref_pos = $this->references[$ref]; - $this->message[$pos]['children'] = &$this->message[$ref_pos]['children']; - $this->message[$pos]['cdata'] = &$this->message[$ref_pos]['cdata']; - $this->message[$pos]['type'] = &$this->message[$ref_pos]['type']; - $this->message[$pos]['arraySize'] = &$this->message[$ref_pos]['arraySize']; - $this->message[$pos]['arrayType'] = &$this->message[$ref_pos]['arrayType']; - } else { - # reverse reference, store in 'need reference' - if (!is_array($this->need_references[$ref])) $this->need_references[$ref] = array(); - $this->need_references[$ref][] = $pos; + } elseif ($kqn->name == 'href') { + if ($value[0] == '#') { + $ref = substr($value, 1); + if (array_key_exists($ref,$this->references)) { + # cdata, type, inval + $ref_pos = $this->references[$ref]; + $this->message[$pos]['children'] = &$this->message[$ref_pos]['children']; + $this->message[$pos]['cdata'] = &$this->message[$ref_pos]['cdata']; + $this->message[$pos]['type'] = &$this->message[$ref_pos]['type']; + $this->message[$pos]['arraySize'] = &$this->message[$ref_pos]['arraySize']; + $this->message[$pos]['arrayType'] = &$this->message[$ref_pos]['arrayType']; + } else { + # reverse reference, store in 'need reference' + if (!isset($this->need_references[$ref])) $this->need_references[$ref] = array(); + $this->need_references[$ref][] = $pos; + } + } else if (isset($this->attachments[$value])) { + $this->message[$pos]['cdata'] = $this->attachments[$value]; } } } + // see if namespace is defined in tag + if (array_key_exists('xmlns:'.$qname->ns,$attrs)) { + $namespace = $attrs['xmlns:'.$qname->ns]; + } else { + // get namespace + $namespace = $qname->ns?$this->_namespaces[$qname->ns]:$this->default_namespace; + } + $this->message[$pos]['namespace'] = $namespace; + $this->default_namespace = $namespace; } /** @@ -387,7 +385,7 @@ // get type if not explicitly declared in an xsi:type attribute // XXX check on integrating wsdl validation here if ($this->message[$pos]['type'] == '') { - if ($this->message[$pos]['children'] != '') { + if (isset($this->message[$pos]['children'])) { /* this is slow, need to look at some faster method $children = explode('|',$this->message[$pos]['children']); if (count($children) > 2 && @@ -444,7 +442,10 @@ function characterData($parser, $data) { $pos = $this->depth_array[$this->depth]; - $this->message[$pos]['cdata'] .= $data; + if (isset($this->message[$pos]['cdata'])) + $this->message[$pos]['cdata'] .= $data; + else + $this->message[$pos]['cdata'] = $data; } /** @@ -499,4 +500,4 @@ } } -?> +?> \ No newline at end of file Index: pear/SOAP/Server.php diff -u pear/SOAP/Server.php:1.20 pear/SOAP/Server.php:1.21 --- pear/SOAP/Server.php:1.20 Wed Apr 24 03:41:18 2002 +++ pear/SOAP/Server.php Mon May 13 02:47:09 2002 @@ -17,18 +17,14 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Server.php,v 1.20 2002/04/24 07:41:18 shane Exp $ +// $Id: Server.php,v 1.21 2002/05/13 06:47:09 shane Exp $ // -require_once 'SOAP/globals.php'; +require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; require_once 'SOAP/Parser.php'; -require_once 'SOAP/Message.php'; require_once 'SOAP/Value.php'; -// make errors handle properly in windows -#error_reporting(2039); - $soap_server_fault = NULL; function SOAP_ServerErrorHandler($errno, $errmsg, $filename, $linenum, $vars) { global $soap_server_fault; @@ -44,12 +40,13 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Server.php,v 1.20 2002/04/24 07:41:18 shane Exp $ +* @version $Id: Server.php,v 1.21 2002/05/13 06:47:09 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_Server { +class SOAP_Server extends SOAP_Base +{ /** * @@ -92,17 +89,17 @@ function SOAP_Server() { ini_set('track_errors',1); + parent::SOAP_Base('Server'); } function _getContentEncoding($content_type) { - global $SOAP_Encodings; // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set $this->xml_encoding = 'UTF-8'; - if (!$test && strpos($content_type,'=')) { + if (strpos($content_type,'=')) { $enc = strtoupper(str_replace('"',"",substr(strstr($content_type,'='),1))); - if (!in_array($enc, $SOAP_Encodings)) { + if (!in_array($enc, $this->_encodings)) { return FALSE; } $this->xml_encoding = $enc; @@ -110,60 +107,104 @@ return TRUE; } + // parses request and posts response function service($data, $endpoint = '', $test = FALSE) { - global $_ENV, $_SERVER; + $response = NULL; + $attachments = array(); + $headers = array(); + $useEncoding = 'DIME'; // figure out our endpoint $this->endpoint = $endpoint; - if (!$this->endpoint) { + if (!$test && !$this->endpoint) { // we'll try to build our endpoint $this->endpoint = 'http://'.$_SERVER['SERVER_NAME']; if ($_SERVER['SERVER_PORT']) $this->endpoint .= ':'.$_SERVER['SERVER_PORT']; - $this->endpoint .= $PHP_SELF; + $this->endpoint .= $_SERVER['SCRIPT_NAME']; } // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set - if (!$this->_getContentEncoding($_SERVER['CONTENT_TYPE'])) { - $this->xml_encoding = SOAP_DEFAULT_ENCODING; - // an encoding we don't understand, return a fault - $this->makeFault('Server','Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8'); - $response = $this->getFaultMessage(); + if (isset($_SERVER['CONTENT_TYPE'])) { + if (strcasecmp($_SERVER['CONTENT_TYPE'],'application/dime')==0) { + $this->decodeDIMEMessage($data,$headers,$attachments); + $useEncoding = 'DIME'; + } else if (stristr($_SERVER['CONTENT_TYPE'],'multipart/related')) { + // this is a mime message, lets decode it. + $data = 'Content-Type: '.stripslashes($_SERVER['CONTENT_TYPE'])."\r\n\r\n".$data; + $this->decodeMimeMessage($data,$headers,$attachments); + $useEncoding = 'Mime'; + } + if (!isset($headers['content-type'])) { + $headers['content-type'] = $_SERVER['CONTENT_TYPE']; + } + if (!$this->soapfault && + !$this->_getContentEncoding($headers['content-type'])) { + $this->xml_encoding = SOAP_DEFAULT_ENCODING; + // an encoding we don't understand, return a fault + $this->makeFault('Server','Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8'); + } } // if this is not a POST with Content-Type text/xml, try to return a WSDL file - if (!$response && !$test && ($_SERVER['REQUEST_METHOD'] != 'POST' || - strncmp($_SERVER['CONTENT_TYPE'],'text/xml',8) != 0)) { + if (!$this->soapfault && !$test && ($_SERVER['REQUEST_METHOD'] != 'POST' || + strncmp($headers['content-type'],'text/xml',8) != 0)) { // this is not possibly a valid soap request, try to return a WSDL file - $this->makeFault('Server',"Invalid SOAP request, must be POST with content-type: text/xml"); - $response = $this->getFaultMessage(); + $this->makeFault('Server',"Invalid SOAP request, must be POST with content-type: text/xml, got: {$headers['content-type']}"); } - if (!$response) { + if (!$this->soapfault) { // $response is a soap_msg object - $response = $this->parseRequest($data); + $soap_msg = $this->parseRequest($data, $attachments); + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if ($useEncoding == 'Mime') { + $soap_msg = $this->_makeMimeMessage($soap_msg); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg); + $header['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + } + + if (is_array($soap_msg)) { + $response = $soap_msg['body']; + if (count($soap_msg['headers'])) { + $header = $soap_msg['headers']; + } + } else { + $response = $soap_msg; + } } - $payload = $response->serialize($this->response_encoding); - // print headers if ($this->soapfault) { - #$header[] = "Status: 500 Internal Server Error\r\n"; - $header[] = "HTTP/1.1 500 Soap Fault\r\n"; + $hdrs = "HTTP/1.1 500 Soap Fault\r\n"; + $response = $this->getFaultMessage(); } else { - #$header[] = "Status: 200 OK\r\n"; - $header[] = "HTTP/1.1 200 OK\r\n"; + $hdrs = "HTTP/1.1 200 OK\r\n"; } + header($hdrs); - $header[] = 'Server: ' . SOAP_LIBRARY_NAME . "\r\n"; - $header[] = "Content-Type: text/xml; charset=$this->response_encoding\r\n"; - $header[] = 'Content-Length: ' . strlen($payload) . "\r\n\r\n"; + $header['Server'] = SOAP_LIBRARY_NAME; + if (!isset($header['Content-Type'])) + $header['Content-Type'] = "text/xml; charset=$this->response_encoding"; + $header['Content-Length'] = strlen($response); + reset($header); - foreach ($header as $hdr) { - header($hdr); + foreach ($header as $k => $v) { + header("$k: $v"); + $hdrs .= "$k: $v\r\n"; } - $this->response = join("\n", $header) . $payload; - print $payload; + + $this->response = $hdrs . "\r\n" . $response; + print $response; } function callMethod($methodname, &$args) { @@ -195,8 +236,7 @@ // create soap_val object w/ return values from method, use method signature to determine type function buildResult(&$method_response, &$return_type, $return_name='return', $namespace = '') { - $class = get_class($method_response) ; - if ($class == 'soap_value' || $class == 'soap_header') { + if (gettype($method_response) == 'object' && is_a($method_response,'soap_value')) { $return_val = array($method_response); } else { if (is_array($return_type) && is_array($method_response)) { @@ -204,10 +244,11 @@ foreach ($return_type as $key => $type) { if (is_numeric($key)) $key = 'item'; - if (get_class($method_response[$i]) == 'soap_value') { + if (is_a($method_response[$i],'soap_value')) { $return_val[] = $method_response[$i++]; } else { - $return_val[] = new SOAP_Value($key,$type,$method_response[$i++],$namespace); + $qn = new QName($key, $namespace); + $return_val[] = new SOAP_Value($qn->fqn(),$type,$method_response[$i++]); } } } else { @@ -217,39 +258,23 @@ $values = array_values($return_type); $return_type = $values[0]; } - $return_val = array(new SOAP_Value($return_name,$return_type,$method_response, $namespace)); + $qn = new QName($return_name, $namespace); + $return_val = array(new SOAP_Value($qn->fqn(),$return_type,$method_response)); } } return $return_val; } - function parseRequest($data='') + function parseRequest($data='', $attachments=NULL) { - global $_ENV, $_SERVER, $SOAP_Encodings; - - - - $this->request = $dump."\r\n\r\n".$data; // parse response, get soap parser obj - $parser = new SOAP_Parser($data,$this->xml_encoding); + $parser = new SOAP_Parser($data,$this->xml_encoding,$attachments); // if fault occurred during message parsing if ($parser->fault) { - $this->soapfault = $parser->fault->message(); - #$this->makeFault('Server',"error in msg parsing:\n".$fault->serialize."\n\n<pre>$data</pre>\n\n"); - return $parser->fault->message(); + $this->soapfault = $parser->fault; + return NULL; } - /* set namespaces - if ($parser->namespaces['xsd'] != '') { - //print 'got '.$parser->namespaces['xsd']; - global $SOAP_namespaces; - $this->XMLSchemaVersion = $parser->namespaces['xsd']; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - }*/ - //******************************************************* // handle message headers @@ -257,9 +282,9 @@ $header_results = array(); if ($request_headers) { - if (get_class($request_headers) != 'soap_value') { + if (!is_a($request_headers,'soap_value')) { $this->makeFault('Server',"parser did not return SOAP_Value object: $request_headers"); - return $this->getFaultMessage(); + return NULL; } if ($request_headers->value) { // handle headers now @@ -274,7 +299,7 @@ if (!$f_exists && $header_val->mustunderstand && $myactor) { $this->makeFault('Server',"I don't understand header $header_val->name."); - return $this->getFaultMessage(); + return NULL; } // we only handle the header if it's for us @@ -283,13 +308,12 @@ if ($isok) { # call our header now! $header_method = $header_val->name; - $header_data = array($header_val->decode()); + $header_data = array($this->decode($header_val)); // if there are parameters to pass $hr = $this->callMethod($header_method, $header_data); # if they return a fault, then it's all over! - if (get_class($hr) == 'soap_message' && - stristr($hr->value->name,'fault')) { - return $hr; + if (is_a($hr,'soap_value') && stristr($hr->value->name,'fault')) { + return $this->_makeEnvelope($hr, NULL, $this->response_encoding); } $header_results[] = array_shift($this->buildResult($hr, $this->return_type, $header_method, $header_val->namespace)); } @@ -308,63 +332,42 @@ // does method exist? if (!$this->methodname || !$this->validateMethod($this->methodname)) { $this->makeFault('Server',"method '$this->methodname' not defined in service"); - return $this->getFaultMessage(); + return NULL; } if (!$request_val = $parser->getResponse()) { - return $this->getFaultMessage(); + return NULL; } - if (get_class($request_val) != 'soap_value') { + if (!is_a($request_val,'soap_value')) { $this->makeFault('Server',"parser did not return SOAP_Value object: $request_val"); - return $this->getFaultMessage(); + return NULL; } // verify that SOAP_Value objects in request match the methods signature if (!$this->verifyMethod($request_val)) { // verifyMethod creates the fault - return $this->getFaultMessage(); + return NULL; } // need to set special error detection inside the value class // so as to differentiate between no params passed, and an error decoding - $request_data = $request_val->decode(); + $request_data = $this->decode($request_val); $method_response = $this->callMethod($this->methodname, $request_data); - // if return val is SOAP_Message - if (get_class($method_response) == 'soap_message') { - return $method_response; - } - // get the method result if (is_null($method_response)) $return_val = NULL; else $return_val = $this->buildResult($method_response, $this->return_type); - // response object is a soap_msg object - $return_msg = new SOAP_Message(); - - // add response headers - if (count($header_results) > 0) { - foreach($header_results as $hr) { - $return_msg->addHeader($hr); - } - } - - $return_msg->method($this->methodname.'Response',$return_val,$this->method_namespace); - - if ($this->debug_flag) { - $return_msg->debug_flag = true; - } - - return $return_msg; + $qn = new QName($this->methodname.'Response',$this->method_namespace); + $methodValue = new SOAP_Value($qn->fqn(), 'Struct', $return_val); + return $this->_makeEnvelope($methodValue, $header_results, $this->response_encoding); } function verifyMethod($request) { - global $SOAP_typemap; - //return true; $params = $request->value; @@ -401,8 +404,8 @@ // this allows using plain php variables to work (ie. stuff like Decimal would fail otherwise) // we only error if the types exist in our type maps, and they differ if (strcasecmp($sig_t[$i],$p[$i])!=0 && - (isset($SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]]) && - strcasecmp($SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]],$SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$p[$i]])!=0)) { + (isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]]) && + strcasecmp($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]],$this->_typemap[SOAP_XML_SCHEMA_VERSION][$p[$i]])!=0)) { $param = $params[$i]; $this->makeFault('Client',"soap request contained mismatching parameters of name $param->name had type [{$p[$i]}], which did not match signature's type: [{$sig_t[$i]}], matched? ".(strcasecmp($sig_t[$i],$p[$i]))); @@ -481,7 +484,7 @@ { if (!function_exists($methodname)) { $this->makeFault('Server',"error mapping function\n"); - return $this->getFaultMessage(); + return FALSE; } $this->dispatch_map[$methodname]['in'] = $in; $this->dispatch_map[$methodname]['out'] = $out; Index: pear/SOAP/Value.php diff -u pear/SOAP/Value.php:1.28 pear/SOAP/Value.php:1.29 --- pear/SOAP/Value.php:1.28 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Value.php Mon May 13 02:47:09 2002 @@ -17,12 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Value.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +// $Id: Value.php,v 1.29 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Base.php'; -require_once 'SOAP/globals.php'; -require_once 'SOAP/Type/dateTime.php'; -require_once 'SOAP/Type/hexBinary.php'; /** * SOAP::Value @@ -31,39 +28,21 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Value.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Value.php,v 1.29 2002/05/13 06:47:09 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 extends SOAP_Base +class SOAP_Value { /** * - * @var boolean - */ - var $convert_strings = FALSE; - - /** - * * * @var string */ var $value = NULL; /** - * - * @var int - */ - var $type_code = 0; - - /** - * - * @var boolean - */ - var $type_prefix = false; - - /** * * @var string */ @@ -76,29 +55,14 @@ var $type = ''; /** - * - * @var - */ - var $soapTypes; - - /** * Namespace * * @var string */ var $namespace = ''; var $type_namespace = ''; - /** - * - * @var string - */ - var $prefix = ''; - /** - * - * @var - */ - var $wsdl; + var $attributes = array(); /** * @@ -106,638 +70,143 @@ */ var $arrayType = ''; - - /** - * set to true to flatten multidimensional arrays - * @var string - */ - var $flattenArray = FALSE; + var $options = array(); + /** * * - * @param string name of the soap-value <value_name> - * @param mixed soap value type, if not set an automatic - * @param int - * @param mixed - * @param mixed - * @param mixed - * @global $SOAP_typemap, $SOAP_namespaces + * @param string name of the soap-value {namespace}name + * @param mixed soap value {namespace}type, if not set an automatic + * @param mixed value to set */ - function SOAP_Value($name = '', $type = false, $value = -1, $methodNamespace = NULL, $type_namespace = NULL, $wsdl = NULL) + function SOAP_Value($name = '', $type = false, $value) { - global $SOAP_typemap, $SOAP_namespaces; - parent::SOAP_Base('Value'); // detect type if not passed - - $this->name = $name; - $this->wsdl = $wsdl; - $this->type_namespace = $type_namespace; - $this->type = $this->_getSoapType($value, $type, $name, $type_namespace); - $this->namespace = $methodNamespace; - - if (strpos($this->type , ':') !== false) { - $qname = new QName($type); - $this->type = $qname->name; - $this->type_prefix = $qname->ns; - } - - if (array_key_exists($this->type, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION])) { - // scalar - - $this->type_code = SOAP_VALUE_SCALAR; - $this->addScalar($value, $this->type, $name); - - } elseif (strcasecmp('Array', $this->type) == 0 || strcasecmp('ur-type', $this->type) == 0) { - // array - - $this->type_code = SOAP_VALUE_ARRAY; - $this->addArray($value); - - } elseif (stristr($this->type, 'Struct')) { - // struct - - $this->type_code = SOAP_VALUE_STRUCT; - $this->addStruct($value); - - } elseif (is_array($value)) { - - $this->type_code = SOAP_VALUE_STRUCT; - $this->addStruct($value); - - } else { - - $this->type_code = SOAP_VALUE_SCALAR; - $this->addScalar($value, 'string', $name); - - } - } - - /** - * - * - * @param - * @param - * @param - * @return boolean - * @access private - */ - function addScalar($value, $type, $name = '') - { - if ($type == 'string') { - $this->value = !is_null($value)?htmlspecialchars($value):NULL; - } else { - $this->value = $value; - } - return true; + $qn = new QName($name); + $this->name = $qn->name; + $this->namespace = $qn->namespace; + $qn = new QName($type); + $this->type = $qn->name; + $this->type_prefix = $qn->ns; + $this->type_namespace = $qn->namespace; + $this->value = $value; } + /** + * Serialize * - * @param array - * @return boolean - */ - function addArray($vals) - { - $this->value = array(); - - if (is_array($vals) && count($vals) >= 1) { - foreach ($vals as $k => $v) { - // if SOAP_Value, add.. - if (strcasecmp(get_class($v), 'SOAP_Value' ) == 0) { - $this->value[] = $v; - // else make obj and serialize - } else { - #$type = $this->arrayType; - //$type = $this->_getSoapType($v, $type, $k); - $new_val = new SOAP_Value('item', NULL /*$this->arrayType*/, $v); - $this->value[] = $new_val; - } - } - } - return true; - } - - /** - * - * @param array - * @param boolean + * @return string xml representation */ - function addStruct($vals) + function serialize(&$serializer) { - if (is_array($vals) && count($vals) >= 1) { - foreach ($vals as $k => $v) { - // if serialize, if SOAP_Value - if (strcasecmp(get_class($v), 'SOAP_Value') == 0) { - $this->value[] = $v; - // else make obj and serialize - } else { - //$type = NULL; - //$type = $this->_getSoapType($v, $type, $k); - $new_val = new SOAP_Value($k, NULL, $v); - $this->value[] = $new_val; - } - } - } else { - $this->value = array(); - } - return true; + return $serializer->serializeValue($this->value, $this->name, $this->type, $this->namespace, $this->type_namespace, $this->options, $this->attributes); } - - /** - * - * @param - * @param - * @param - * @param - * @return int - */ - function _multiArrayType(&$value, &$type, &$size, &$xml) - { - foreach ($value as $array_val) { - $array_types[$array_val->type] = 1; - #$xml .= $this->serializeval($array_val); - } +} - if ($array_val->type_prefix) { - $type = $array_val->type_prefix . ':' . $array_val->type; - } else { - $type = $array_val->type; - } - $sz = count($value); - $num_types = count($array_types); - if ($num_types == 1) { - if (array_key_exists('Array', $array_types)) { - // seems we have a multi dimensional array, figure it out if we do - foreach ($value as $array_val) { - $numtypes = $this->_multiArrayType($array_val->value, $type, $size, $xml); - if ($numtypes > 1) - return $numtypes; - } +/** + * SOAP::Header + * this class converts values between PHP and SOAP + * it is a simple wrapper around SOAP_Value, adding support for + * soap actor and mustunderstand parameters + * + * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 + * + * @access public + * @version $Id: Value.php,v 1.29 2002/05/13 06:47:09 shane Exp $ + * @package SOAP::Header + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author + */ +class SOAP_Header extends SOAP_Value +{ - if ($sz) { - $size = $sz.','.$size; - } else { - $size = $sz; - } - return 1; - } else { - foreach ($value as $array_val) { - #$array_types[$array_val->type] = 1; - $xml .= $array_val->serialize(); - } - } - } - $size = $sz; - return $num_types; - } - /** - * Turn SOAP_Value's into xml, woohoo! - * - * @param mixed - * @return string xml representation - */ - function serializeval($soapval = false) - { - if (!$soapval) { - $soapval = $this; - } - - if (is_int($soapval->name)) { - $soapval->name = 'item'; - $soapval->prefix = ''; - } - - if ($soapval->prefix && $soapval->type_prefix) { - $xmlout_name = "$soapval->prefix:$soapval->name"; - $xmlout_type = "$soapval->type_prefix:$soapval->type"; - } else - if ($soapval->type_prefix) { - $xmlout_name = $soapval->name; - $xmlout_type = "$soapval->type_prefix:$soapval->type"; - } elseif ($soapval->prefix) { - $xmlout_name = "$soapval->prefix:$soapval->name"; - } else { - $xmlout_name = $soapval->name; - } - $xmlout_value = NULL; - $xmlout_offset = ''; + * Constructor + * + * @param string name of the soap-value <value_name> + * @param mixed soap header value + * @param string namespace + * @param int mustunderstand (zero or one) + * @param string actor + */ + function SOAP_Header($name = '', $type, $value = NULL, + $mustunderstand = 0, + $actor = 'http://schemas.xmlsoap.org/soap/actor/next') + { + parent::SOAP_Value($name, $type, $value); + $this->attributes['SOAP-ENV:actor'] = $actor; + $this->attributes['SOAP-ENV:mustUnderstand'] = (int)$mustunderstand; + } +} - switch ($soapval->type_code) { - case SOAP_VALUE_STRUCT: - // struct - if (is_array($soapval->value)) { - foreach ($soapval->value as $k => $v) { - $xmlout_value .= $v->serialize($v); - } - } - break; - - case SOAP_VALUE_ARRAY: - // array - $xmlout_type = 'SOAP-ENC:Array'; - // XXX this will be slow on larger array's. Basicly, it flattens array's to allow us - // to serialize multi-dimensional array's. We only do this if arrayType is set, - // which will typicaly only happen if we are using WSDL - if ($this->flattenArray || ($this->arrayType && strchr($this->arrayType,','))) { - $numtypes = $this->_multiArrayType($soapval->value, $array_type, $ar_size, $xmlout_value); - } - #$numtypes = 0; - $array_type_prefix = ''; - if ($numtypes != 1) { - foreach ($soapval->value as $array_val) { - $array_types[$array_val->type] = 1; - $xmlout_value .= $array_val->serialize(); - } +/** + * SOAP::Attachment + * this class converts values between PHP and SOAP + * it handles Mime attachements per W3C Note on Soap Attachements at + * http://www.w3.org/TR/SOAP-attachments + * + * + * @access public + * @package SOAP::Attachment + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates + */ +class SOAP_Attachment extends SOAP_Value +{ - $ar_size = count($soapval->value); - $numtypes = count($array_types); - if ($this->arrayType) { - $ch = strpos($this->arrayType, '['); - if ($ch) { - $array_type = substr($this->arrayType,0,$ch); - } else { - $array_type = $this->arrayType; - } - } else { - $array_type = $array_val->type; - } - if ($array_type == 'Struct') { - $array_type = 'anyType'; // should reference what schema we're using - $array_val->type_prefix = 'xsd'; - } - $array_type_prefix = $array_val->type_prefix; - $xmlout_offset = " SOAP-ENC:offset=\"[0]\""; - } - if ($numtypes > 1) { - $array_type = 'xsd:anyType'; // should reference what schema we're using - } 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; - } - } - $xmlout_arrayType = " SOAP-ENC:arrayType=\"".$array_type."[$ar_size]\""; - break; - - case SOAP_VALUE_SCALAR: - $xmlout_value = $soapval->value; - break; - default: - break; - } - - if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\""; - if (is_null($xmlout_value)) { - $xml = "\r\n<{$xmlout_name}{$xmlout_type}/>"; - } else { - $xml = "\r\n<{$xmlout_name}{$xmlout_type}{$xmlout_arrayType}{$xmlout_offset}". - $this->xmlout_extra.">". - $xmlout_value."</$xmlout_name>"; - } - return $xml; - } - /** - * Serialize - * - * @return string xml representation - */ - function serialize() + * Constructor + * + * @param string name of the soap-value <value_name> + * @param mixed soap header value + * @param string namespace + */ + function SOAP_Attachment($name = '', $type = 'application/octet-stream', + $filename, $file=NULL) { - global $SOAP_namespaces; - - if ($this->namespace) { - if (!isset($SOAP_namespaces[$this->namespace])) { - $SOAP_namespaces[$this->namespace] = 'ns' . (count($SOAP_namespaces) + 1); - } - - $this->prefix = $SOAP_namespaces[$this->namespace]; + global $SOAP_options; + if (!isset($SOAP_options['Mime'])) { + return PEAR::raiseError('Mail_mime is not installed, unable to support SOAP Attachements'); } - // get type prefix - if (strpos($this->type , ':') !== false) { - $qname = new QName($type); - $this->type = $qname->name; - $this->type_prefix = $qname->ns; - - } elseif ($this->type_namespace) { - - if (!isset($SOAP_namespaces[$this->type_namespace])) { - $SOAP_namespaces[$this->type_namespace] = 'ns'.(count($SOAP_namespaces)+1); - } - $this->type_prefix = $SOAP_namespaces[$this->type_namespace]; - - // if type namespace was not explicitly passed, and we're not in a method struct: - } elseif (!$this->type_prefix && $this->type != 'Struct' /*!isset($type_namespace)*/) { + parent::SOAP_Value($name, NULL, NULL); - // try to get type prefix from typeMap - if ($ns = $this->verifyType($this->type)) { - $this->type_prefix = $SOAP_namespaces[$ns]; - } else if ($this->namespace) { - // else default to method namespace - $this->type_prefix = $SOAP_namespaces[$this->namespace]; - } + $filedata = ($file === NULL) ? $this->_file2str($filename) : $file; + $filename = basename($filename); + if (PEAR::isError($filedata)) { + return $filedata; } - return $this->serializeval($this); - } - - /** - * - * @param mixed - * @global $SOAP_typemap - */ - function decode($soapval = false) - { - global $SOAP_typemap; - if (!$soapval) { - $soapval = $this; - } + $cid = md5(uniqid(time())); - // scalar decode - if ($soapval->type_code == SOAP_VALUE_SCALAR) { - if ($soapval->type == 'boolean') { - if ($soapval->value != '0' && strcasecmp($soapval->value,'false') !=0) { - $soapval->value = TRUE; - } else { - $soapval->value = FALSE; - } - #} else if ($soapval->type == 'dateTime') { - # # we don't realy know what a user want's in return, - # # but we'll just do unix time stamps for now - # # THOUGHT: we could return a class instead. - # $dt = new SOAP_Type_dateTime($soapval->value); - # $soapval->value = $dt->toUnixtime(); - } else if (array_key_exists($soapval->type, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION])) { - # if we can, lets set php's variable type - settype($soapval->value, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); - } - if (!is_null($soapval->value)) - return $this->un_htmlentities($soapval->value); - return NULL; - // array decode - } elseif ($soapval->type_code == SOAP_VALUE_ARRAY) { - if (is_array($soapval->value)) { - foreach ($soapval->value as $item) { - $return[] = $this->decode($item); - } - return $return; - } - return $soapval->value; - // struct decode - } elseif ($soapval->type_code == SOAP_VALUE_STRUCT) { - if (is_array($soapval->value)) { - $counter = 1; - foreach ($soapval->value as $item) { - if (isset($return[$item->name])) { - // this is realy an array, we need to redirect - $soapval->type_code = SOAP_VALUE_ARRAY; - return $soapval->decode(); - } else { - $return[$item->name] = $this->decode($item); - } - } - return $return; - } - return $soapval->value; - } - # couldn't decode, return a fault! - return $this->raiseSoapFault("couldn't decode response, invalid type_code"); - } - - /** - * pass it a type, and it attempts to return a namespace uri - * - * @param - * @global $SOAP_typemap, $SOAP_namespaces - */ - function verifyType($type) - { - global $SOAP_typemap; - foreach ($SOAP_typemap as $uri => $types) { - if (array_key_exists($type,$types)) return $uri; - } - return FALSE; - } - - /** - * alias for verifyType() - pass it a type, and it returns it's prefix - * - * @brother varityType() - */ - function getPrefix($type) - { - global $SOAP_namespaces; - if ($uri = $this->verifyType($type)) { - return $SOAP_namespaces[$uri]; - } - return NULL; - } - - - /** - * SOAP::Value::_getSoapType - * - * convert php type to soap type - * @param string value - * @param string type - presumed php type - * - * @return string type - soap type - * @access private - */ - function _getSoapType(&$value, &$type, $name, $type_namespace='') { - - $doconvert = FALSE; - if ($this->wsdl) { - # see if it's a complex type so we can deal properly with SOAPENC:arrayType - if (!$type && $name) { - # XXX TODO: - # look up the name in the wsdl and validate the type - if ($this->type) { - foreach ($this->wsdl->complexTypes as $types) { - if (array_key_exists($this->type, $types) && - array_key_exists($name, $types[$this->type]['elements'])) { - $type = $types[$this->type]['elements']['type']; - return $type; - } - } - } - } else if ($type && $type_namespace) { - # XXX TODO: - # this code currently handles only one way of encoding array types in wsdl - # need to do a generalized function to figure out complex types - $p = $this->wsdl->ns[$type_namespace]; - if ($p && - array_key_exists($p, $this->wsdl->complexTypes) && - array_key_exists($type, $this->wsdl->complexTypes[$p])) { - if ($this->arrayType = $this->wsdl->complexTypes[$p][$type]['arrayType']) { - $type = 'Array'; - } else if ($this->wsdl->complexTypes[$p][$type]['order']=='sequence' && - array_key_exists('elements', $this->wsdl->complexTypes[$p][$type])) { - reset($this->wsdl->complexTypes[$p][$type]['elements']); - # assume an array - if (count($this->wsdl->complexTypes[$p][$type]['elements']) == 1) { - $arg = current($this->wsdl->complexTypes[$p][$type]['elements']); - $this->arrayType = $arg['type']; - $type = 'Array'; - } else { - foreach($this->wsdl->complexTypes[$p][$type]['elements'] as $element) { - if ($element['name'] == $type) { - $this->arrayType = $element['type']; - $type = $element['type']; - } - } - } - } - return $type; - } - } - } - if (!$type || !$this->verifyType($type)) { - if (is_object($value)) { - # allows for creating special classes to handle soap types - $type = get_class($value); - # this may return a different type that we process below - $value = $value->toSOAP(); - } elseif ($this->isArray($value)) { - $type = $this->isHash($value)?'Struct':'Array'; - } elseif ($this->isInt($value)) { - $type = 'int'; - } elseif ($this->isFloat($value)) { - $type = 'float'; - } elseif (SOAP_Type_hexBinary::is_hexbin($value)) { - $type = 'hexBinary'; - } elseif ($this->isBase64($value)) { - $type = 'base64Binary'; - } elseif ($this->isBoolean($value)) { - $type = 'boolean'; - } else { - $type = gettype($value); - # php defaults a lot of stuff to string, if we have no - # idea what the type realy is, we have to try to figure it out - # this is the best we can do if the user did not use the SOAP_Value class - if ($type == 'string') $doconvert = TRUE; - elseif ($type == 'NULL') $type = ''; - } - } - # we have the type, handle any value munging we need - if ($doconvert) { - $dt = new SOAP_Type_dateTime($value); - if ($dt->toUnixtime() != -1) { - $type = 'dateTime'; - $value = $dt->toSOAP(); - } - } else - if ($type == 'dateTime') { - # encode a dateTime to ISOE - $dt = new SOAP_Type_dateTime($value); - $value = $dt->toSOAP(); - } else - // php type name mangle - if ($type == 'integer') { - $type = 'int'; - } else - if ($type == 'boolean') { - if (($value != 0 && $value != '0') || strcasecmp($value, 'true') == 0) - $value = 'true'; - else - $value = 'false'; - } - return $type; - } - - // support functions - /** - * - * @param string - * @return string - */ - function isBase64(&$value) - { - return $value[strlen($value)-1]=='=' && preg_match("/[A-Za-z=\/\+]+/",$value); - } - - /** - * - * @param mixed - * @return boolean - */ - function isBoolean(&$value) - { - return gettype($value) == 'boolean' || strcasecmp($value, 'true')==0 || strcasecmp($value, 'false') == 0; - } - - /** - * - * @param mixed - * @return boolean - */ - function isFloat(&$value) - { - return gettype($value) == FLOAT || - $value === 'NaN' || $value === 'INF' || $value === '-INF' || - (is_numeric($value) && strstr($value, '.')); - } - - /** - * - * @param mixed - * @return boolean - */ - function isInt(&$value) - { - return gettype($value) == 'integer' || (is_numeric($value) && !strstr($value,'.')); - } - - /** - * - * @param array - * @return boolean - */ - function isArray(&$value) - { - return is_array($value); # && count($value) >= 1; + $this->attributes['href'] = 'cid:'.$cid; + + $this->options['attachment'] = array( + 'body' => $filedata, + 'disposition' => $filename, + 'content_type' => $type, + 'encoding' => 'base64', + 'cid' => $cid + ); } - /** - * - * @param mixed - * @return boolean + /* + * Returns the contents of the given file name as string + * @param string $file_name + * @return string + * @acces private */ - function isDateTime(&$value) + function & _file2str($file_name) { - $dt = new SOAP_Type_dateTime($value); - return $dt->toUnixtime() != -1; - } - - /** - * - * @param mixed - * @return boolean - */ - function isHash(&$a) { - # XXX I realy dislike having to loop through this in php code, - # realy large arrays will be slow. We need a C function to do this. - $names = array(); - foreach ($a as $k => $v) { - # checking the type is faster than regexp. - if (gettype($k) != 'integer') { - return TRUE; - } else if (gettype($v) == 'object' && get_class($v) == 'soap_value') { - $names[$v->name] = 1; - } + if (!is_readable($file_name)) { + return PEAR::raiseError('File is not readable ' . $file_name); } - return count($names)>1; - } - - function un_htmlentities($string) - { - $trans_tbl = get_html_translation_table (HTML_ENTITIES); - $trans_tbl = array_flip($trans_tbl); - return strtr($string, $trans_tbl); + if (!$fd = fopen($file_name, 'rb')) { + return PEAR::raiseError('Could not open ' . $file_name); + } + $cont = fread($fd, filesize($file_name)); + fclose($fd); + return $cont; } } - -?> +?> \ No newline at end of file Index: pear/SOAP/WSDL.php diff -u pear/SOAP/WSDL.php:1.19 pear/SOAP/WSDL.php:1.20 --- pear/SOAP/WSDL.php:1.19 Wed Apr 24 03:41:18 2002 +++ pear/SOAP/WSDL.php Mon May 13 02:47:09 2002 @@ -17,11 +17,10 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: WSDL.php,v 1.19 2002/04/24 07:41:18 shane Exp $ +// $Id: WSDL.php,v 1.20 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; -require_once 'SOAP/globals.php'; DEFINE("WSDL_CACHE_MAX_AGE",12*60*60); DEFINE("WSDL_CACHE_USE",0); // set to zero to turn off caching @@ -38,7 +37,7 @@ * implement IDL type syntax declaration so we can generate WSDL * * @access public -* @version $Id: WSDL.php,v 1.19 2002/04/24 07:41:18 shane Exp $ +* @version $Id: WSDL.php,v 1.20 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author @@ -374,8 +373,6 @@ // start-element handler function startElement($parser, $name, $attrs) { - global $SOAP_XMLSchema; - // get element prefix $qname = new QName($name); if ($qname->ns) { @@ -476,7 +473,7 @@ $vq = new QName($v); $this->wsdl->complexTypes[$this->schema][$this->currentElement][$q->name] = $vq->name; if ($q->name == 'arrayType') { - $this->wsdl->complexTypes[$this->schema][$this->currentElement]['type'] = $vq->name; + $this->wsdl->complexTypes[$this->schema][$this->currentElement]['type'] = $v; $this->wsdl->complexTypes[$this->schema][$this->currentElement]['namespace'] = $vq->ns; } } @@ -609,7 +606,7 @@ strcasecmp($value,SOAP_SCHEMA)==0) { $this->soapns[] = strtolower($qn->name); } else - if (in_array($value, $SOAP_XMLSchema)) { + if (in_array($value, $this->_XMLSchema)) { $this->wsdl->xsd = $value; } } Index: pear/SOAP/package.xml diff -u pear/SOAP/package.xml:1.11 pear/SOAP/package.xml:1.12 --- pear/SOAP/package.xml:1.11 Sat Apr 27 13:53:18 2002 +++ pear/SOAP/package.xml Mon May 13 02:47:09 2002 @@ -19,7 +19,7 @@ <license>PHP License</license> <release> <state>devel</state> - <version>0.6</version> + <version>0.6.1</version> <date>2002-02-18</date> <notes> This is the initial independent PEAR release. @@ -29,9 +29,6 @@ <file role="php" name="Base.php"/> <file role="php" name="Client.php"/> <file role="php" name="Fault.php"/> - <file role="php" name="globals.php"/> - <file role="php" name="Header.php"/> - <file role="php" name="Message.php"/> <file role="php" name="Parser.php"/> <file role="php" name="Server.php"/> <file role="php" name="Transport.php"/> @@ -94,6 +91,8 @@ <dep type="php" rel="ge" version="4.1"/> <dep type="ext" rel="has">bcmath</dep> <dep type="ext" rel="has">pcre</dep> + <dep type="pkg" rel="has">Mime</dep> + <dep type="pkg" rel="ge" version="0.1">Net_DIME</dep> </deps> </release> </package> Index: pear/SOAP/Server/Email.php diff -u pear/SOAP/Server/Email.php:1.1 pear/SOAP/Server/Email.php:1.2 --- pear/SOAP/Server/Email.php:1.1 Wed Apr 24 03:41:25 2002 +++ pear/SOAP/Server/Email.php Mon May 13 02:47:09 2002 @@ -16,12 +16,12 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: Email.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +// $Id: Email.php,v 1.2 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Server.php'; require_once 'SOAP/Transport.php'; - +require_once 'Mail/mimeDecode.php'; /** * SOAP_Server_Email * SOAP Server Class @@ -36,7 +36,7 @@ * function call * * @access public -* @version $Id: Email.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +* @version $Id: Email.php,v 1.2 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Server * @author Shane Caraveo <shane@php.net> */ @@ -49,57 +49,23 @@ $this->send_response = $send_response; } - /** - * remove http headers from response - * - * TODO: use PEAR email classes - * - * @return boolean - * @access private - */ - function _parseEmail(&$data) - { - if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $data, $match)) { - - if (preg_match_all('/^(.*?):\s+(.*)$/m', $match[1], $matches)) { - $hc = count($matches[0]); - for ($i = 0; $i < $hc; $i++) { - $this->headers[strtolower($matches[1][$i])] = trim($matches[2][$i]); - } - } - - if (!stristr($this->headers['content-type'],'text/xml')) { - $this->makeFault('Client','Invalid Content Type'); - return FALSE; - } - - if (strcasecmp($this->headers['content-transfer-encoding'],'base64')==0) { - // join lines back together - $enctext = preg_replace("/[\r|\n]/", '', $match[2]); - $this->request = base64_decode($enctext); - } else if (strcasecmp($this->headers['content-transfer-encoding'],'quoted-printable')==0) { - $this->request = $match[2]; - } else { - $this->makeFault('Client','Invalid Content-Transfer-Encoding'); - return FALSE; - } - - // if no content, return false - return strlen($this->request) > 0; - } - $this->makeFault('Client','Invalid Email Format'); - return FALSE; - } - - function service(&$data, $endpoint = '', $send_response = TRUE, $dump = FALSE) { $this->endpoint = $endpoint; - - // we have a full set of headers, need to find the first blank line - if (!$this->_parseEmail($data)) { - $response = $this->getFaultMessage(); + $attachments = array(); + $headers = array(); + + # if neither matches, we'll just try it anyway + if (stristr($data,'Content-Type: application/dime')==0) { + $this->decodeDIMEMessage($data,$this->headers,$attachments); + $useEncoding = 'DIME'; + } else if (stristr($data,'Content-Type: multipart/related')) { + // this is a mime message, lets decode it. + $data = 'Content-Type: '.stripslashes($_SERVER['CONTENT_TYPE'])."\r\n\r\n".$data; + $this->decodeMimeMessage($data,$this->headers,$attachments); + $useEncoding = 'Mime'; } + // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set if (!$response && !$this->_getContentEncoding($this->headers['content-type'])) { @@ -109,8 +75,34 @@ $response = $this->getFaultMessage(); } - if (!$response) - $response = $this->parseRequest($this->request); + if (!$this->soapfault) { + $soap_msg = $this->parseRequest($data,$attachments); + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if ($useEncoding == 'Mime') { + $soap_msg = $this->_makeMimeMessage($soap_msg); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg); + $header['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + } + + if (is_array($soap_msg)) { + $response = $soap_msg['body']; + if (count($soap_msg['headers'])) { + $headers = $soap_msg['headers']; + } + } else { + $response = $soap_msg; + } + } if ($this->send_response) { $payload = $response->serialize($this->response_encoding); @@ -123,7 +115,7 @@ $soap_transport = new SOAP_Transport('mailto:'.$from, $this->response_encoding); $from = $this->endpoint ? $this->endpoint : $this->headers['to']; - $headers = array('In-Reply-To'=>$this->headers['message-id']); + $headers['In-Reply-To']=$this->headers['message-id']; $options = array('from' => $from, 'subject'=> $this->headers['subject'], 'headers' => $headers); $soap_transport->send($payload, $options); } Index: pear/SOAP/Server/Email_Gateway.php diff -u pear/SOAP/Server/Email_Gateway.php:1.1 pear/SOAP/Server/Email_Gateway.php:1.2 --- pear/SOAP/Server/Email_Gateway.php:1.1 Wed Apr 24 03:41:25 2002 +++ pear/SOAP/Server/Email_Gateway.php Mon May 13 02:47:09 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: Email_Gateway.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +// $Id: Email_Gateway.php,v 1.2 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Server/Email.php'; @@ -40,11 +40,54 @@ * email * * @access public -* @version $Id: Email_Gateway.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +* @version $Id: Email_Gateway.php,v 1.2 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Server * @author Shane Caraveo <shane@php.net> */ class SOAP_Server_Email_Gateway extends SOAP_Server_Email { + /** + * remove http headers from response + * + * TODO: use PEAR email classes + * + * @return boolean + * @access private + */ + function _parseEmail(&$data) + { + if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $data, $match)) { + + if (preg_match_all('/^(.*?):\s+(.*)$/m', $match[1], $matches)) { + $hc = count($matches[0]); + for ($i = 0; $i < $hc; $i++) { + $this->headers[strtolower($matches[1][$i])] = trim($matches[2][$i]); + } + } + + if (!stristr($this->headers['content-type'],'text/xml')) { + $this->makeFault('Client','Invalid Content Type'); + return FALSE; + } + + if (strcasecmp($this->headers['content-transfer-encoding'],'base64')==0) { + // join lines back together + $enctext = preg_replace("/[\r|\n]/", '', $match[2]); + $this->request = base64_decode($enctext); + } else if (strcasecmp($this->headers['content-transfer-encoding'],'quoted-printable')==0) { + $this->request = $match[2]; + } else { + $this->makeFault('Client','Invalid Content-Transfer-Encoding'); + return FALSE; + } + + // if no content, return false + return strlen($this->request) > 0; + } + $this->makeFault('Client','Invalid Email Format'); + return FALSE; + } + + function service(&$data, $gateway, $endpoint = '', $send_response = TRUE, $dump = FALSE) { $this->endpoint = $endpoint; @@ -75,6 +118,7 @@ // send the message if (!$response) { $options['soapaction'] = $this->headers['soapaction']; + $options['headers']['Content-Type'] = $this->headers['content-type']; $response = $soap_transport->send($this->request, $options); if ($soap_transport->fault) { $fault = $soap_transport->fault->message(); Index: pear/SOAP/Transport/HTTP.php diff -u pear/SOAP/Transport/HTTP.php:1.16 pear/SOAP/Transport/HTTP.php:1.17 --- pear/SOAP/Transport/HTTP.php:1.16 Wed Apr 24 03:41:26 2002 +++ pear/SOAP/Transport/HTTP.php Mon May 13 02:47:10 2002 @@ -16,17 +16,16 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: HTTP.php,v 1.16 2002/04/24 07:41:26 shane Exp $ +// $Id: HTTP.php,v 1.17 2002/05/13 06:47:10 shane Exp $ // -require_once 'SOAP/globals.php'; require_once 'SOAP/Base.php'; - +require_once 'Net_DIME/DIME.php'; /** * HTTP Transport for SOAP * * @access public -* @version $Id: HTTP.php,v 1.16 2002/04/24 07:41:26 shane Exp $ +* @version $Id: HTTP.php,v 1.17 2002/05/13 06:47:10 shane Exp $ * @package SOAP::Transport::HTTP * @author Shane Caraveo <shane@php.net> */ @@ -38,7 +37,7 @@ * * @var string */ - var $credentials = ''; + var $headers = array(); /** * @@ -116,13 +115,13 @@ return $this->fault; } - if ($timeout) + if (isset($options['timeout'])) $this->timeout = (int)$options['timeout']; if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { - return $this->_sendHTTP($msg, $options['soapaction']); + return $this->_sendHTTP($msg, $options); } else if (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { - return $this->_sendHTTPS($msg, $options['soapaction']); + return $this->_sendHTTPS($msg, $options); } return $this->raiseSoapFault('Invalid url scheme '.$this->url); @@ -140,7 +139,7 @@ */ function setCredentials($username, $password) { - $this->credentials = 'Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; + $this->headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password); } // private members @@ -178,8 +177,6 @@ function _parseEncoding($headers) { - global $SOAP_Encodings; - $h = stristr($headers,'Content-Type'); preg_match('/^Content-Type:\s*(.*)$/im',$h,$ct); $this->result_content_type = str_replace("\r","",$ct[1]); @@ -188,7 +185,7 @@ $this->result_content_type = $m[1]; if (count($m) > 2) { $enc = strtoupper(str_replace('"',"",$m[2])); - if (in_array($enc, $SOAP_Encodings)) { + if (in_array($enc, $this->_encodings)) { $this->result_encoding = $enc; } } @@ -215,9 +212,16 @@ return FALSE; } $this->_parseEncoding($match[1]); - if ($this->result_content_type != 'text/xml') { - $this->raiseSoapFault($this->response); - return FALSE; + if ($this->result_content_type == 'application/dime') { + // XXX quick hack insertion of DIME + $this->decodeDIMEMessage($this->response,$this->headers,$this->attachments); + $this->result_content_type = $this->headers['content-type']; + } else if (stristr($this->result_content_type,'multipart/related')) { + $this->response = $this->incoming_payload; + $this->decodeMimeMessage($this->response,$this->headers,$this->attachments); + } else if ($this->result_content_type != 'text/xml') { + $this->raiseSoapFault($this->response); + return FALSE; } // if no content, return false return strlen($this->response) > 0; @@ -232,19 +236,27 @@ * @return string outgoing_payload * @access private */ - function &_getRequest(&$msg, $action) + function &_getRequest(&$msg, $options) { + $action = isset($options['soapaction'])?$options['soapaction']:''; $fullpath = $this->urlparts['path']. - ($this->urlparts['query']?'?'.$this->urlparts['query']:''). - ($this->urlparts['fragment']?'#'.$this->urlparts['fragment']:''); + (isset($this->urlparts['query'])?'?'.$this->urlparts['query']:''). + (isset($this->urlparts['fragment'])?'#'.$this->urlparts['fragment']:''); + $this->headers['User-Agent'] = $this->_userAgent; + $this->headers['Host'] = $this->urlparts['host']; + $this->headers['Content-Type'] = "text/xml; charset=$this->encoding"; + $this->headers['Content-Length'] = strlen($msg); + $this->headers['SOAPAction'] = "\"$action\""; + if (isset($options['headers'])) { + $this->headers = array_merge($this->headers, $options['headers']); + } + $headers = ''; + foreach ($this->headers as $k => $v) { + $headers .= "$k: $v\r\n"; + } $this->outgoing_payload = "POST $fullpath HTTP/1.0\r\n". - "User-Agent: {$this->_userAgent}\r\n". - "Host: {$this->urlparts['host']}\r\n". - $this->credentials. - "Content-Type: text/xml; charset=$this->encoding\r\n". - "Content-Length: ".strlen($msg)."\r\n". - "SOAPAction: \"$action\"\r\n\r\n". + $headers."\r\n". $msg; return $this->outgoing_payload; } @@ -258,9 +270,9 @@ * @return string &$response response data, minus http headers * @access private */ - function &_sendHTTP(&$msg, $action = '') + function &_sendHTTP(&$msg, $options) { - $this->_getRequest($msg, $action); + $this->_getRequest($msg, $options); // send if ($this->timeout > 0) { @@ -298,7 +310,7 @@ * @return string &$response response data, minus http headers * @access private */ - function &_sendHTTPS(&$msg, $action) + function &_sendHTTPS(&$msg, $options) { /* NOTE This function uses the CURL functions * Your php must be compiled with CURL @@ -307,7 +319,7 @@ return $this->raiseSoapFault('CURL Extension is required for HTTPS'); } - $this->_getRequest($msg, $action); + $this->_getRequest($msg, $options); $ch = curl_init(); if ($this->timeout) { Index: pear/SOAP/Transport/SMTP.php diff -u pear/SOAP/Transport/SMTP.php:1.8 pear/SOAP/Transport/SMTP.php:1.9 --- pear/SOAP/Transport/SMTP.php:1.8 Wed Apr 24 03:41:26 2002 +++ pear/SOAP/Transport/SMTP.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: SMTP.php,v 1.8 2002/04/24 07:41:26 shane Exp $ +// $Id: SMTP.php,v 1.9 2002/05/13 06:47:10 shane Exp $ // // Status: rough draft, untested // @@ -27,7 +27,6 @@ // ability to define smtp options (encoding, from, etc.) // -require_once 'SOAP/globals.php'; require_once 'SOAP/Message.php'; require_once 'SOAP/Base.php'; @@ -40,7 +39,7 @@ * TODO: use PEAR smtp and Mime classes * * @access public -* @version $Id: SMTP.php,v 1.8 2002/04/24 07:41:26 shane Exp $ +* @version $Id: SMTP.php,v 1.9 2002/05/13 06:47:10 shane Exp $ * @package SOAP::Transport::SMTP * @author Shane Caraveo <shane@php.net> */ @@ -88,50 +87,57 @@ if (!$options || !array_key_exists('from',$options)) { return $this->raiseSoapFault("No FROM address to send message with"); } - $headers = "From: {$options['from']}\n". - "X-Mailer: $this->_userAgent\n". - "MIME-Version: 1.0\n". - "Content-Disposition: inline\n". - "Content-Type: text/xml; charset=\"$this->encoding\"\n"; - - if (array_key_exists('transfer-encoding', $options)) { - if (strcasecmp($options['transfer-encoding'],'quoted-printable')==0) { - $headers .="Content-Transfer-Encoding: {$options['transfer-encoding']}\n"; - $out = &$msg; - } else if (strcasecmp($options['transfer-encoding'],'base64')==0) { + + $headers = array(); + $headers['From'] = $options['from']; + $headers['X-Mailer'] = $this->_userAgent; + $headers['MIME-Version'] = '1.0'; + if (array_key_exists('soapaction', $options)) { + $headers['Soapaction'] = "\"{$options['soapaction']}\""; + } + + if (isset($options['headers'])) + $headers = array_merge($headers, $options['headers']); + + // if the content type is already set, we assume that Mime encoding + // is already done + if (!isset($headers['Content-Type'])) { + // do an inline Mime encoding + $headers['Content-Disposition'] = 'inline'; + $headers['Content-Type'] = "text/xml; charset=\"$this->encoding\""; + if (array_key_exists('transfer-encoding', $options)) { + if (strcasecmp($options['transfer-encoding'],'quoted-printable')==0) { + $headers .="Content-Transfer-Encoding: {$options['transfer-encoding']}\n"; + $out = &$msg; + } else if (strcasecmp($options['transfer-encoding'],'base64')==0) { + $headers .="Content-Transfer-Encoding: base64\n"; + $out = chunk_split(base64_encode($msg)); + } else { + return $this->raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); + } + } else { + // default to base64 $headers .="Content-Transfer-Encoding: base64\n"; $out = chunk_split(base64_encode($msg)); - } else { - return $this->raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); } - } else { - // default to base64 - $headers .="Content-Transfer-Encoding: base64\n"; - $out = chunk_split(base64_encode($msg)); - } - - if (array_key_exists('soapaction', $options)) { - "Soapaction: \"{$options['soapaction']}\"\n"; } - if (array_key_exists('headers', $options)) { - foreach ($options['headers'] as $key => $value) { - $headers .= "$key: $value\n"; - } + foreach ($headers as $key => $value) { + $header_text .= "$key: $value\n"; } $subject = array_key_exists('subject', $options) ? $options['subject'] : 'SOAP Message'; - $this->outgoing_payload = $headers."\n\n".$this->outgoing_payload; + $this->outgoing_payload = $header_text."\n\n".$this->outgoing_payload; # we want to return a proper XML message - $result = mail($this->urlparts['path'], $subject, $out, $headers); + $result = mail($this->urlparts['path'], $subject, $out, $header_text); if ($result) { $val = new SOAP_Value('return','boolean',TRUE); } else { $val = new SOAP_Value('Fault','Struct',array( - new SOAP_Value('faultcode','string','SOAP-ENV:Transport:SMTP'), - new SOAP_Value('faultstring','string',"couldn't send message to $action") + new SOAP_Value('faultcode','QName','SOAP-ENV:Client'), + new SOAP_Value('faultstring','string',"couldn't send SMTP message to $action") )); } @@ -185,4 +191,4 @@ } } // end SOAP_Transport_HTTP -?> +?> \ No newline at end of file Index: pear/SOAP/interop/client_round2_interop.php diff -u pear/SOAP/interop/client_round2_interop.php:1.10 pear/SOAP/interop/client_round2_interop.php:1.11 --- pear/SOAP/interop/client_round2_interop.php:1.10 Wed Apr 24 03:41:27 2002 +++ pear/SOAP/interop/client_round2_interop.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_interop.php,v 1.10 2002/04/24 07:41:27 shane Exp $ +// $Id: client_round2_interop.php,v 1.11 2002/05/13 06:47:10 shane Exp $ // require_once 'DB.php'; // PEAR/DB require_once 'SOAP/Client.php'; @@ -25,7 +25,7 @@ error_reporting(E_ALL ^ E_NOTICE); -class Interop_Client +class Interop_Client extends SOAP_Base { // database DNS var $DSN = 'mysql://user@localhost/interop'; @@ -90,6 +90,7 @@ // retreive endpoints from the endpoint server $endpointArray = $soapclient->call("GetEndpointInfo",array("groupName"=>$test),"http://soapinterop.org/info/","http://soapinterop.org/info/"); if (PEAR::isError($endpointArray)) { + print $soapclient->wire; print_r($endpointArray); return; } @@ -250,12 +251,13 @@ foreach ($soap_test->headers as $h) { $destination = 0; if (get_class($h) == 'soap_header') { - if ($h->actor == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; - $test_name .= ":{$h->name},$destination,{$h->mustunderstand}"; + if ($h->attributes['SOAP-ENV:actor'] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; + $test_name .= ":{$h->name},$destination,{$h->attributes['SOAP-ENV:mustUnderstand']}"; } else { - if (!$h[4] || $h[4] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; - if (!$h[3]) $h[3] = 0; - $test_name .= ":$h[0],$destination,".(int)$h[3]; + if (!$h[3] || $h[3] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; + if (!$h[2]) $h[2] = 0; + $qn = new QName($h[0]); + $test_name .= ":{$qn->name},$destination,".(int)$h[2]; } } } @@ -300,7 +302,7 @@ if (gettype($soapval) == "object" && (strcasecmp(get_class($soapval),"SOAP_Value") == 0 || strcasecmp(get_class($soapval),"SOAP_Header") == 0)) { - $val = $soapval->decode(); + $val = $this->decode($soapval); } else { $val = $soapval; } @@ -433,7 +435,9 @@ $expect = $soap_test->headers_expect[$header->name]; $header_result[$header->name] = array(); // XXX need to fix need_result to identify the actor correctly - $need_result = $hresult || ($header->actor == 'http://schemas.xmlsoap.org/soap/actor/next' && $header->mustunderstand); + $need_result = $hresult || + ($header->attributes['SOAP-ENV:actor'] == 'http://schemas.xmlsoap.org/soap/actor/next' + && $header->attributes['SOAP-ENV:mustUnderstand']); if ($expect) { $hresult = $soap->headers[key($expect)]; $ok = !$need_result || $this->compareResult($hresult ,$expect[key($expect)]); @@ -555,8 +559,8 @@ foreach ($soap_test->headers as $header) { if (get_class($header) == 'soap_header') { if ($header->name == $m[2]) { - $gotit = $header->actor == ($m[3]?SOAP_TEST_ACTOR_NEXT:SOAP_TEST_ACTOR_OTHER); - $gotit = $gotit && $header->mustunderstand == $m[4]; + $gotit = $header->attributes['SOAP-ENV:actor'] == ($m[3]?SOAP_TEST_ACTOR_NEXT:SOAP_TEST_ACTOR_OTHER); + $gotit = $gotit && $header->attributes['SOAP-ENV:mustUnderstand'] == $m[4]; } } else { if ($header[0] == $m[2]) { Index: pear/SOAP/interop/client_round2_params.php diff -u pear/SOAP/interop/client_round2_params.php:1.6 pear/SOAP/interop/client_round2_params.php:1.7 --- pear/SOAP/interop/client_round2_params.php:1.6 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/client_round2_params.php Mon May 13 02:47:10 2002 @@ -16,9 +16,8 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_params.php,v 1.6 2002/04/17 07:42:53 shane Exp $ +// $Id: client_round2_params.php,v 1.7 2002/05/13 06:47:10 shane Exp $ // -require_once 'SOAP/Header.php'; require_once 'SOAP/Value.php'; define('SOAP_TEST_ACTOR_NEXT','http://schemas.xmlsoap.org/soap/actor/next'); @@ -85,7 +84,8 @@ if ($this->headers) { foreach ($this->headers as $h) { if (get_class($h) == 'soap_header') { - echo "\n {$h->name},{$h->actor},{$h->mustunderstand} : "; + + echo "\n {$h->name},{$h->attributes['SOAP-ENV:actor']},{$h->attributes['SOAP-ENV:mustUnderstand']} : "; } else { if (!$h[4]) $h[4] = SOAP_TEST_ACTOR_NEXT; if (!$h[3]) $h[3] = 0; @@ -199,9 +199,9 @@ array('inputFloatArray' => new SOAP_Value('inputFloatArray','Array', array( #push struct elements into one soap value - new SOAP_Value('nan','float',1.3223), - new SOAP_Value('inf','float',34.2), - new SOAP_Value('neginf','float',325.325) + new SOAP_Value('item','float',1.3223), + new SOAP_Value('item','float',34.2), + new SOAP_Value('item','float',325.325) ) ))); @@ -213,13 +213,12 @@ 'varInt'=>34, 'varFloat'=>325.325))); $soap_tests['base'][] = new SOAP_Test('echoStruct', array('inputStruct' => - new SOAP_Value('inputStruct','Struct', + new SOAP_Value('inputStruct','{http://soapinterop.org/xsd}SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ) - ))); + )))); //*********************************************************** // Base echoStructArray @@ -232,17 +231,17 @@ $soap_tests['base'][] = new SOAP_Test('echoStructArray', array('inputStructArray' => new SOAP_Value('inputStructArray','Array', array( #push struct elements into one soap value - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) )), - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) )), - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) @@ -253,8 +252,8 @@ //*********************************************************** // Base echoVoid -$soap_tests['base'][] = new SOAP_Test('echoVoid', ''); -$test = new SOAP_Test('echoVoid', ''); +$soap_tests['base'][] = new SOAP_Test('echoVoid', NULL); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; $soap_tests['base'][] = $test; @@ -273,14 +272,14 @@ //*********************************************************** // Base echoDecimal -$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => '1234567890')); -$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => new SOAP_Value('inputDecimal','decimal','1234567890'))); +$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => 12345.67890)); +$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => new SOAP_Value('inputDecimal','decimal',12345.67890))); //*********************************************************** // Base echoDate -$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => '2001-04-25T13:31:41-0700')); -$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => new SOAP_Value('inputDate','dateTime','2001-04-25T13:31:41-0700'))); +$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => '2001-05-24T17:31:41Z')); +$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => new SOAP_Value('inputDate','dateTime','2001-05-24T17:31:41Z')));#'2001-04-25T13:31:41-0700' //*********************************************************** // Base echoBoolean @@ -310,13 +309,12 @@ )), $expect); $soap_tests['GroupB'][] = new SOAP_Test('echoStructAsSimpleTypes', array('inputStruct' => - new SOAP_Value('inputStruct','struct', + new SOAP_Value('inputStruct','SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ) - )), $expect); + ))), $expect); //*********************************************************** // GroupB echoSimpleTypesAsStruct @@ -361,7 +359,7 @@ ) ) ); -$multidimarray->flattenArray = TRUE; +$multidimarray->options['flatten'] = TRUE; $soap_tests['GroupB'][] = new SOAP_Test('echo2DStringArray', array('input2DStringArray' => $multidimarray)); @@ -380,7 +378,7 @@ ) ))); $soap_tests['GroupB'][] = new SOAP_Test('echoNestedStruct', - array('input2DStringArray' => + array('inputStruct' => new SOAP_Value('inputStruct','struct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), @@ -392,7 +390,7 @@ new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) ) - ) + /*,NULL,'http://soapinterop.org/xsd'*/) ) ))); @@ -407,7 +405,7 @@ 'varArray' => array('red','blue','green') ))); $soap_tests['GroupB'][] = new SOAP_Test('echoNestedArray', - array('input2DStringArray' => + array('inputStruct' => new SOAP_Value('inputStruct','struct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), @@ -431,27 +429,27 @@ // echoMeStringRequest php val tests // echoMeStringRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 1,SOAP_TEST_ACTOR_NEXT); $this->type = 'soapval'; // force a soapval version of this test $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; @@ -459,39 +457,39 @@ // echoMeStringRequest soapval tests // echoMeStringRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/'); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world'); $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 1); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1); $this->type = 'soapval'; // force a soapval version of this test $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint header destination, must understand, // invalid namespace, should recieve a fault -#$test = new SOAP_Test('echoVoid', ''); +#$test = new SOAP_Test('echoVoid', NULL); #$test->type = 'soapval'; -#$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://unknown.org/', 1); +#$test->headers[] = new SOAP_Header('{http://unknown.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1); #$test->headers_expect['echoMeStringRequest'] = array(); #$test->expect_fault = TRUE; #$soap_tests['GroupC'][] = $test; @@ -499,158 +497,146 @@ //*********************************************************** // php val tests // echoMeStructRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); + 0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); + 1,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); + 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); + 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // soapval tests // echoMeStructRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/'); + )); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 1); + ), 1); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); + ), 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); + ), 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // echoMeUnknown php val tests // echoMeUnknown with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',1,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeUnknown'] = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // echoMeUnknown soapval tests // echoMeUnknown with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/'); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!'); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 1); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!',1); $test->headers_expect['echoMeUnknown'] = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; Index: pear/SOAP/interop/client_round2_run.php diff -u pear/SOAP/interop/client_round2_run.php:1.1 pear/SOAP/interop/client_round2_run.php:1.2 --- pear/SOAP/interop/client_round2_run.php:1.1 Sat Apr 13 23:23:20 2002 +++ pear/SOAP/interop/client_round2_run.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_run.php,v 1.1 2002/04/14 03:23:20 shane Exp $ +// $Id: client_round2_run.php,v 1.2 2002/05/13 06:47:10 shane Exp $ // set_time_limit(0); require_once 'SOAP/interop/client_round2_interop.php'; @@ -37,7 +37,7 @@ $this->nosave = 0; // 1= disable saving results to database // debug output $iop->show = 1; -$iop->debug = 0; +$iop->debug = 1; $iop->showFaults = 0; // used in result table output #$iop->doTest(); // run a single set of tests using above options Index: pear/SOAP/interop/server_round2.php diff -u pear/SOAP/interop/server_round2.php:1.2 pear/SOAP/interop/server_round2.php:1.3 --- pear/SOAP/interop/server_round2.php:1.2 Sun Apr 7 19:22:33 2002 +++ pear/SOAP/interop/server_round2.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: server_round2.php,v 1.2 2002/04/07 23:22:33 shane Exp $ +// $Id: server_round2.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -27,7 +27,7 @@ require_once 'server_round2_groupB.php'; require_once 'server_round2_groupC.php'; -$server->service($HTTP_RAW_POST_DATA); +$server->service(isset($HTTP_RAW_POST_DATA)?$HTTP_RAW_POST_DATA:NULL); #echo "Content-Length is {$_SERVER['CONTENT_LENGTH']}\n\n"; #echo "<!---\n\nlen:".strlen($HTTP_RAW_POST_DATA)."\n\n"; #echo "[$HTTP_RAW_POST_DATA"; Index: pear/SOAP/interop/server_round2_base.php diff -u pear/SOAP/interop/server_round2_base.php:1.4 pear/SOAP/interop/server_round2_base.php:1.5 --- pear/SOAP/interop/server_round2_base.php:1.4 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/server_round2_base.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: server_round2_base.php,v 1.4 2002/04/17 07:42:53 shane Exp $ +// $Id: server_round2_base.php,v 1.5 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -113,13 +113,12 @@ function echoStruct($inputStruct) { - return new SOAP_Value('return','SOAPStruct', + return new SOAP_Value('return','{http://soapinterop.org/xsd}SOAPStruct', array( new SOAP_Value('varInt','int',$inputStruct['varInt']), new SOAP_Value('varFloat','float',$inputStruct['varFloat']), new SOAP_Value('varString','string',$inputStruct['varString']) - ), - 'http://soapinterop.org/xsd'); + )); } function echoStructArray($inputStructArray) @@ -127,13 +126,12 @@ $ra = array(); if ($inputStructArray) { foreach($inputStructArray as $struct) { - $ra[] = new SOAP_Value('item','SOAPStruct', + $ra[] = new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct', array( new SOAP_Value('varInt','int',$struct['varInt']), new SOAP_Value('varFloat','float',$struct['varFloat']), new SOAP_Value('varString','string',$struct['varString']) - ), - 'http://soapinterop.org/xsd'); + )); } } return $ra; @@ -173,6 +171,11 @@ function echoBoolean($boolean) { return new SOAP_Value('return','boolean',$boolean); + } + + function echoMimeAttachment($stuff) + { + return new SOAP_Attachment('return','application/octet-stream',NULL,$stuff); } } Index: pear/SOAP/interop/server_round2_groupB.php diff -u pear/SOAP/interop/server_round2_groupB.php:1.2 pear/SOAP/interop/server_round2_groupB.php:1.3 --- pear/SOAP/interop/server_round2_groupB.php:1.2 Mon Apr 15 02:46:09 2002 +++ pear/SOAP/interop/server_round2_groupB.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: server_round2_groupB.php,v 1.2 2002/04/15 06:46:09 shane Exp $ +// $Id: server_round2_groupB.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -53,7 +53,7 @@ function echoSimpleTypesAsStruct($string, $int, $float) { # convert a input into struct - $ret = new SOAP_Value('return','Struct', + $ret = new SOAP_Value('return','{http://soapinterop.org/xsd}SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string',$string), new SOAP_Value('varInt','int',(int)$int), @@ -71,7 +71,7 @@ function echo2DStringArray($ary) { $ret = new SOAP_Value('return','Array',$ary); - $ret->flattenArray = TRUE; + $ret->options['flatten'] = TRUE; return $ret; } Index: pear/SOAP/interop/server_round2_groupC.php diff -u pear/SOAP/interop/server_round2_groupC.php:1.2 pear/SOAP/interop/server_round2_groupC.php:1.3 --- pear/SOAP/interop/server_round2_groupC.php:1.2 Mon Apr 15 02:46:09 2002 +++ pear/SOAP/interop/server_round2_groupC.php Mon May 13 02:47:10 2002 @@ -16,10 +16,10 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: server_round2_groupC.php,v 1.2 2002/04/15 06:46:09 shane Exp $ +// $Id: server_round2_groupC.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; -require_once 'SOAP/Header.php'; +require_once 'SOAP/Value.php'; class SOAP_Interop_GroupC { var $method_namespace = 'http://soapinterop.org/echoheader/'; Index: pear/SOAP/interop/server_round2_test.php diff -u pear/SOAP/interop/server_round2_test.php:1.4 pear/SOAP/interop/server_round2_test.php:1.5 --- pear/SOAP/interop/server_round2_test.php:1.4 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/server_round2_test.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: server_round2_test.php,v 1.4 2002/04/17 07:42:53 shane Exp $ +// $Id: server_round2_test.php,v 1.5 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -124,41 +124,135 @@ </SOAP-ENV:Body> </SOAP-ENV:Envelope>'; -$test = "<S:Envelope -S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' -xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' -xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' -xmlns:a='http://soapinterop.org/' -xmlns:b='http://soapinterop.org/xsd' -xmlns:XS='http://www.w3.org/2001/XMLSchema' -xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> -<S:Body> -<b:SOAPStruct Enc:root='0' id='21b56c4' XI:type='b:SOAPStruct'> -<varInt XI:type='XS:int'>1</varInt> -<varFloat XI:type='XS:float'>2</varFloat> -<varString XI:type='XS:string'>wilma</varString> -</b:SOAPStruct> -<a:echoStructArray> -<inputStructArray XI:type='Enc:Array' Enc:arrayType='XS:anyType[3]'> -<fred href='#21b56c4'/> -<i href='#21b56c4'/> -<i href='#21b56c4'/> -</inputStructArray> -</a:echoStructArray> -</S:Body></S:Envelope>"; +#$test = "<S:Envelope +#S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' +#xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' +#xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' +#xmlns:a='http://soapinterop.org/' +#xmlns:b='http://soapinterop.org/xsd' +#xmlns:XS='http://www.w3.org/2001/XMLSchema' +#xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> +#<S:Body> +#<b:SOAPStruct Enc:root='0' id='21b56c4' XI:type='b:SOAPStruct'> +#<varInt XI:type='XS:int'>1</varInt> +#<varFloat XI:type='XS:float'>2</varFloat> +#<varString XI:type='XS:string'>wilma</varString> +#</b:SOAPStruct> +#<a:echoStructArray> +#<inputStructArray XI:type='Enc:Array' Enc:arrayType='XS:anyType[3]'> +#<fred href='#21b56c4'/> +#<i href='#21b56c4'/> +#<i href='#21b56c4'/> +#</inputStructArray> +#</a:echoStructArray> +#</S:Body></S:Envelope>"; #$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructArray><inputStructArray XI:type='Enc:Array' Enc:arrayType='b:SOAPStruct[2]'><inputStruct href='#213e654'/> <inputStruct href='#21b8c4c'/> </inputStructArray> </a:echoStructArray> <b:SOAPStruct Enc:root='0' id='21b8c4c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>-1</varInt> <varFloat XI:type='XS:float'>-1</varFloat> <varString XI:type='XS:string'>lean on into the groove y'all</varString> </b:SOAPStruct> <b:SOAPStruct Enc:root='0' id='213e654' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>1073741824</varInt> <varFloat XI:type='XS:float'>-42.24</varFloat> <varString XI:type='XS:string'>pocketSOAP rocks!<g></varString> </b:SOAPStruct> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction S:mustUnderstand='1' XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructAsSimpleTypes><inputStruct href='#213e59c'/> </a:echoStructAsSimpleTypes> <b:SOAPStruct Enc:root='0' id='213e59c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>42</varInt> <varString XI:type='XS:string'>Orbital</varString> <varFloat XI:type='XS:float'>-42.42</varFloat> </b:SOAPStruct> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction S:mustUnderstand='1' XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructAsSimpleTypes><inputStruct href='#213e59c'/> </a:echoStructAsSimpleTypes> <b:SOAPStruct Enc:root='0' id='213e59c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>42</varInt> <varString XI:type='XS:string'>Orbital</varString> <varFloat XI:type='XS:float'>-42.42</varFloat> </b:SOAPStruct> </S:Body></S:Envelope>"; // white mesa failures /*$test = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><h:echoMeStringRequest SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:mustUnderstand="1" xmlns:h="http://unknown.org/">White Mesa Test Header String.</h:echoMeStringRequest></SOAP-ENV:Header><SOAP-ENV:Body><m:echoVoid SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m="http://soapinterop.org/" /></SOAP-ENV:Body></SOAP-ENV:Envelope>'; */ +/* $test = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><h:echoMeStringRequest SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:mustUnderstand="1" xmlns:h="http://unknown.org/">White Mesa Test Header String.</h:echoMeStringRequest></SOAP-ENV:Header><SOAP-ENV:Body><m:echoVoid SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m="http://soapinterop.org/" /></SOAP-ENV:Body></SOAP-ENV:Envelope>'; +*/ +//$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoIntegerArray><inputIntegerArray XI:nil='true'></inputIntegerArray> </a:echoIntegerArray> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoIntegerArray><inputIntegerArray XI:nil='true'></inputIntegerArray> </a:echoIntegerArray> </S:Body></S:Envelope>"; -$server->service($test, '',TRUE); +$test = '<?xml version="1.0" encoding="UTF-8"?> + +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" + xmlns:ns4="http://soapinterop.org/" + SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> +<SOAP-ENV:Body> + +<ns4:echo2DStringArray> +<input2DStringArray xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2,3]"> +<item xsi:type="xsd:string">row0col0</item> +<item xsi:type="xsd:string">row0col1</item> +<item xsi:type="xsd:string">row0col2</item> +<item xsi:type="xsd:string">row1col0</item> +<item xsi:type="xsd:string">row1col1</item> +<item xsi:type="xsd:string">row1col2</item></input2DStringArray></ns4:echo2DStringArray> +</SOAP-ENV:Body> +</SOAP-ENV:Envelope>'; + +$_SERVER['REQUEST_METHOD'] = "POST"; +$_SERVER['CONTENT_TYPE'] = 'multipart/related; type=text/xml; boundary="=_d624611fe466a88d956a205651c74fdb"'; + +$test = '--=_d624611fe466a88d956a205651c74fdb +Content-Type: text/xml; charset="UTF-8" +Content-Transfer-Encoding: base64 + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPFNPQVAtRU5WOkVudmVs +b3BlICB4bWxuczpTT0FQLUVOVj0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvc29hcC9lbnZl +bG9wZS8iDQogIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiDQog +IHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiDQog +IHhtbG5zOlNPQVAtRU5DPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy9zb2FwL2VuY29kaW5n +LyINCiAgU09BUC1FTlY6ZW5jb2RpbmdTdHlsZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcv +c29hcC9lbmNvZGluZy8iPg0KPFNPQVAtRU5WOkJvZHk+DQoNCjxlY2hvTWltZUF0dGFjaG1lbnQ+ +DQo8dGVzdCBocmVmPSJjaWQ6ZTZiOTg0M2JiYzUxY2JiMDAzOTk0MGVmN2VlNzY2MDMiLz48L2Vj +aG9NaW1lQXR0YWNobWVudD4NCjwvU09BUC1FTlY6Qm9keT4NCjwvU09BUC1FTlY6RW52ZWxvcGU+ +DQo= +--=_d624611fe466a88d956a205651c74fdb +Content-Disposition: attachment.php +Content-Type: text/plain +Content-Transfer-Encoding: base64 +Content-ID: <e6b9843bbc51cbb0039940ef7ee76603> + +PD9waHANCnJlcXVpcmVfb25jZSgiU09BUC9DbGllbnQucGhwIik7DQpyZXF1aXJlX29uY2UoIlNP +QVAvdGVzdC90ZXN0LnV0aWxpdHkucGhwIik7DQpyZXF1aXJlX29uY2UoIlNPQVAvVmFsdWUucGhw +Iik7DQokc29hcF9iYXNlID0gbmV3IFNPQVBfQmFzZSgpOw0KDQokdiA9ICBuZXcgU09BUF9BdHRh +Y2htZW50KCd0ZXN0JywndGV4dC9wbGFpbicsJ2F0dGFjaG1lbnQucGhwJyk7DQokbWV0aG9kVmFs +dWUgPSBuZXcgU09BUF9WYWx1ZSgndGVzdGF0dGFjaCcsICdTdHJ1Y3QnLCBhcnJheSgkdikpOw0K +DQovLyBzZWUgdGhlIG1pbWUgYXJyYXkNCi8vJHZhbCA9ICRzb2FwX2Jhc2UtPl9tYWtlRW52ZWxv +cGUoJG1ldGhvZFZhbHVlKTsNCi8vcHJpbnRfcigkdmFsKTsNCg0KJGNsaWVudCA9IG5ldyBTT0FQ +X0NsaWVudCgnaHR0cDovL2xvY2FsaG9zdC9zb2FwX2ludGVyb3Avc2VydmVyX3JvdW5kMi5waHAn +KTsNCiRyZXNwID0gJGNsaWVudC0+Y2FsbCgnZWNob01pbWVBdHRhY2htZW50JyxhcnJheSgkdikp +Ow0KcHJpbnRfcigkcmVzcCk7DQpwcmludCAkY2xpZW50LT53aXJlOw0KPz4= +--=_d624611fe466a88d956a205651c74fdb--'; + +$_SERVER['CONTENT_TYPE'] = 'multipart/related; type=text/xml; boundary="=_a2cbb051424cc43e72d3c8c8d0b8f70e"'; +$test='--=_a2cbb051424cc43e72d3c8c8d0b8f70e +Content-Type: text/xml; charset="UTF-8" +<?xml version="1.0" encoding="UTF-8"?> + +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" + SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> +<SOAP-ENV:Body> + +<echoMimeAttachment> +<test href="cid:a223fea3c35b5f0e6dedf8da75efd6b3"/></echoMimeAttachment> +</SOAP-ENV:Body> +</SOAP-ENV:Envelope> + +--=_a2cbb051424cc43e72d3c8c8d0b8f70e +Content-Disposition: attachment.php +Content-Type: text/plain +Content-Transfer-Encoding: base64 +Content-ID: <a223fea3c35b5f0e6dedf8da75efd6b3> + +PD9waHANCnJlcXVpcmVfb25jZSgiU09BUC9DbGllbnQucGhwIik7DQpyZXF1aXJlX29uY2UoIlNP +QVAvdGVzdC90ZXN0LnV0aWxpdHkucGhwIik7DQpyZXF1aXJlX29uY2UoIlNPQVAvVmFsdWUucGhw +Iik7DQokc29hcF9iYXNlID0gbmV3IFNPQVBfQmFzZSgpOw0KDQokdiA9ICBuZXcgU09BUF9BdHRh +Y2htZW50KCd0ZXN0JywndGV4dC9wbGFpbicsJ2F0dGFjaG1lbnQucGhwJyk7DQokbWV0aG9kVmFs +dWUgPSBuZXcgU09BUF9WYWx1ZSgndGVzdGF0dGFjaCcsICdTdHJ1Y3QnLCBhcnJheSgkdikpOw0K +DQovLyBzZWUgdGhlIG1pbWUgYXJyYXkNCi8vJHZhbCA9ICRzb2FwX2Jhc2UtPl9tYWtlRW52ZWxv +cGUoJG1ldGhvZFZhbHVlKTsNCi8vcHJpbnRfcigkdmFsKTsNCg0KJGNsaWVudCA9IG5ldyBTT0FQ +X0NsaWVudCgnaHR0cDovL2xvY2FsaG9zdC9zb2FwX2ludGVyb3Avc2VydmVyX3JvdW5kMi5waHAn +KTsNCiRyZXNwID0gJGNsaWVudC0+Y2FsbCgnZWNob01pbWVBdHRhY2htZW50JyxhcnJheSgkdikp +Ow0KI3ByaW50X3IoJHJlc3ApOw0KcHJpbnQgJGNsaWVudC0+d2lyZTsNCj8+ +--=_a2cbb051424cc43e72d3c8c8d0b8f70e-- +'; +$server->service($test, '',TRUE); +print $server->response; ?> Index: pear/SOAP/test/5.2.1.simpletypes.string.php diff -u pear/SOAP/test/5.2.1.simpletypes.string.php:1.1 pear/SOAP/test/5.2.1.simpletypes.string.php:1.2 --- pear/SOAP/test/5.2.1.simpletypes.string.php:1.1 Sun Feb 24 21:55:13 2002 +++ pear/SOAP/test/5.2.1.simpletypes.string.php Mon May 13 02:47:10 2002 @@ -1,5 +1,7 @@ <?php require_once("SOAP/test/test.utility.php"); +require_once("SOAP/Base.php"); +$soap_base = new SOAP_Base(); $prefix = "5.2.1 String"; $msg = '<?xml version="1.0" encoding="UTF-8"?> @@ -24,7 +26,7 @@ # serialize a soap value $expect = '<inputString xsi:type="xsd:string">hello world</inputString>'; $v = new SOAP_Value("inputString","string","hello world"); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare($expect, $val)) { print "$prefix Serialize Type OK\n"; } else { @@ -32,7 +34,7 @@ } # serialize a soap value with unknown type $expect = "hello world"; -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize known SOAP_Value OK\n"; } else { @@ -42,7 +44,7 @@ # serialize a soap value with unknown type $expect = '<inputString xsi:type="xsd:string">hello world</inputString>'; $v = new SOAP_Value("inputString","","hello world"); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare($expect, $val)) { print "$prefix Serialize Unknown Type OK\n"; } else { @@ -51,7 +53,7 @@ # serialize a soap value with unknown type $expect = "hello world"; -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize Unknown SOAP_Value OK\n"; } else { Index: pear/SOAP/test/5.2.simpletypes.php diff -u pear/SOAP/test/5.2.simpletypes.php:1.5 pear/SOAP/test/5.2.simpletypes.php:1.6 --- pear/SOAP/test/5.2.simpletypes.php:1.5 Mon Apr 15 02:46:11 2002 +++ pear/SOAP/test/5.2.simpletypes.php Mon May 13 02:47:10 2002 @@ -1,6 +1,9 @@ <?php +require_once("SOAP/Base.php"); require_once("SOAP/test/test.utility.php"); require_once("SOAP/Fault.php"); +$soap_base = new SOAP_Base(); + $prefix = "5.2 Simple Types"; $msg = '<?xml version="1.0" encoding="UTF-8"?> @@ -55,7 +58,8 @@ new SOAP_Value("displacement","negativeInteger",-450), new SOAP_Value("color","string","Blue") )); -$val = $v->serialize(); + +$val = $v->serialize($soap_base); if (string_compare(str_replace("\r\n","",$expect), str_replace("\r\n","",$val))) { print "$prefix Serialize Type OK\n"; } else { @@ -64,7 +68,7 @@ # deserialize a soap value $expect = array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue'); -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize known SOAP_Value OK\n"; } else { @@ -80,7 +84,7 @@ </inputString> '; $v = new SOAP_Value("inputString","Struct",array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue')); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare(str_replace("\r\n","",$expect), str_replace("\r\n","",$val))) { print "$prefix Serialize Unknown Type OK\n"; } else { @@ -89,8 +93,8 @@ # serialize a soap value with unknown type $expect = array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue'); -$val = $v->decode(); -if (string_compare($expect, $val)) { +$val = $soap_base->decode($v); +if (array_compare($expect, $val)) { print "$prefix Deserialize Unknown SOAP_Value OK\n"; } else { print "$prefix Deserialize Unknown SOAP_Value FAILED\n"; Index: pear/SOAP/test/test.utility.php diff -u pear/SOAP/test/test.utility.php:1.4 pear/SOAP/test/test.utility.php:1.5 --- pear/SOAP/test/test.utility.php:1.4 Mon Apr 15 02:46:12 2002 +++ pear/SOAP/test/test.utility.php Mon May 13 02:47:10 2002 @@ -1,7 +1,6 @@ <?php require_once("SOAP/Parser.php"); require_once("SOAP/Value.php"); -require_once("SOAP/Message.php"); function number_compare($f1, $f2) { @@ -10,7 +9,7 @@ preg_match('/.*?\.(.*)/',$f2,$m2); #print_r($m1); # always use at least 2 digits of precision - $d = max(min(strlen($m1[1]),strlen($m2[1])),2); + $d = max(min(strlen(count($m1)?$m1[1]:'0'),strlen(count($m2)?$m2[1]:'0')),2); $f1 = round($f1, $d); $f2 = round($f2, $d); return bccomp($f1, $f2, $d) == 0; @@ -71,7 +70,7 @@ return $response->fault->getFault(); } $return = $response->getResponse(); - $v = $return->decode(); + $v = $response->decode($return); if (gettype($v) == 'array' && count($v)==1) { return array_shift($v); } Index: pear/SOAP/example/attachment.php +++ pear/SOAP/example/attachment.php <?php require_once("SOAP/Client.php"); require_once("SOAP/test/test.utility.php"); require_once("SOAP/Value.php"); $filename = 'attachment.php'; $v = new SOAP_Attachment('test','text/plain',$filename); $methodValue = new SOAP_Value('testattach', 'Struct', array($v)); $client = new SOAP_Client('http://localhost/soap_interop/server_round2.php'); # calling with mime $resp = $client->call('echoMimeAttachment',array($v),array('Mime'=>1)); print $client->wire."\n\n\n"; print_r($resp); # calling with DIME $resp = $client->call('echoMimeAttachment',array($v)); # DIME has null spaces, change them so we can see the wire $wire = str_replace("\0",'*',$client->wire); print $wire."\n\n\n"; print_r($resp); ?>
Index: pear/SOAP/Base.php diff -u pear/SOAP/Base.php:1.7 pear/SOAP/Base.php:1.8 --- pear/SOAP/Base.php:1.7 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Base.php Mon May 13 02:47:09 2002 @@ -17,23 +17,163 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +// $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ // require_once 'PEAR.php'; #require_once 'SOAP/Fault.php'; +require_once 'SOAP/Type/dateTime.php'; +require_once 'SOAP/Type/hexBinary.php'; + +// optional features +$SOAP_options = array(); + +include_once 'Mail/mimePart.php'; +include_once 'Mail/mimeDecode.php'; +if (class_exists('Mail_mimePart')) { + $SOAP_options['Mime'] = 1; +} + +include_once 'Net/DIME.php'; +if (class_exists('DIME_Message')) { + $SOAP_options['DIME'] = 1; +} + +#error_reporting(E_ALL & ~E_NOTICE); + +/** +* Enable debugging informations? +* +* @const SOAP_DEBUG +*/ +define('SOAP_DEBUG', false); + +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'); +} else { + 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('SOAP_LIBRARY_NAME', 'PEAR-SOAP 0.6.1'); +// set schema version +define('SOAP_XML_SCHEMA_VERSION', 'http://www.w3.org/2001/XMLSchema'); +define('SOAP_XML_SCHEMA_INSTANCE', 'http://www.w3.org/2001/XMLSchema-instance'); +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_DEFAULT_ENCODING', 'UTF-8'); + +if (!function_exists('is_a')) +{ + function is_a($object, $class_name) + { + if (get_class($object) == $class_name) return TRUE; + else return is_subclass_of($object, $class_name); + } +} /** * SOAP_Base * Common base class of all Soap lclasses * * @access public -* @version $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates */ class SOAP_Base extends PEAR { + var $_XMLSchema = array('http://www.w3.org/2001/XMLSchema', 'http://www.w3.org/1999/XMLSchema'); + var $_XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; + + // load types into typemap array + var $_typemap = array( + 'http://www.w3.org/2001/XMLSchema' => array( + 'string' => 'string', + 'boolean' => 'boolean', + 'float' => FLOAT, + 'double' => FLOAT, + 'decimal' => FLOAT, + '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', + 'anyType' => 'string', + 'anyURI' => 'string', + 'QName' => 'string' + ), + 'http://www.w3.org/1999/XMLSchema' => array( + 'i4' => 'integer', + 'int' => 'integer', + 'boolean' => 'boolean', + 'string' => 'string', + 'double' => FLOAT, + 'float' => FLOAT, + 'dateTime' => 'string', + 'timeInstant' => 'string', + 'base64Binary' => 'string', + 'base64' => 'string', + 'ur-type' => 'string' + ), + 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64' => 'string','array' => 'array','Array' => 'array', 'Struct'=>'array') + ); + + // load namespace uris into an array of uri => prefix + var $_namespaces; + var $_ns_count = 0; + # supported encodings, limited by XML extension + var $_encodings = array('ISO-8859-1','US-ASCII','UTF-8'); + + var $_xmlEntities = array ( '&' => '&', '<' => '<', '>' => '>', "'" => ''', '"' => '"' ); + + var $doconversion = TRUE; + + var $attachments = array(); /** * Store debugging information in $debug_data? @@ -66,19 +206,49 @@ */ var $fault = NULL; - + var $wsdl = NULL; /** * Constructor * * @param string error code * @see $debug_data, debug() */ - function SOAP_Base($faultcode) + function SOAP_Base($faultcode = 'Client') { $this->myfaultcode = $faultcode; + $this->resetNamespaces(); parent::PEAR('SOAP_Fault'); } + function resetNamespaces() + { + $this->_namespaces = array( + 'http://schemas.xmlsoap.org/soap/envelope/' => 'SOAP-ENV', + 'http://www.w3.org/2001/XMLSchema' => 'xsd', + 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', + 'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC'); + } + + /** + * setSchemaVersion + * + * sets the schema version used in the soap message + * + * @param string (see globals.php) + * + * @access private + */ + function setSchemaVersion($schemaVersion) + { + if (!in_array($schemaVersion, $this->_XMLSchema)) { + return $this->raiseSoapFault("unsuported XMLSchema $schemaVersion"); + } + $this->_XMLSchemaVersion = $schemaVersion; + $tmpNS = array_flip($this->_namespaces); + $tmpNS['xsd'] = $this->_XMLSchemaVersion; + $tmpNS['xsi'] = $this->_XMLSchemaVersion.'-instance'; + $this->_namespaces = array_flip($tmpNS); + } /** * Raise a soap error @@ -127,6 +297,513 @@ } } + function getNamespacePrefix($ns) + { + if (array_key_exists($ns,$this->_namespaces)) { + return $this->_namespaces[$ns]; + } + $prefix = 'ns'.count($this->_namespaces); + $this->_namespaces[$ns] = $prefix; + return $prefix; + return NULL; + } + + function serializeValue($value, $name = '', $type = false, $elNamespace = NULL, $typeNamespace=NULL, $options=array(), $attributes = array()) + { + $namespaces = array(); + $xmlout_value = NULL; + $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = $xmlout_type = $xmlns = ''; + + if (!$name || is_numeric($name)) $name = 'item'; + + if (!is_null($value)) { + list($ptype,$arrayType,$array_type_ns) = $this->_getSchemaType($type, $name, $typeNamespace); + if (!$ptype) $ptype = $this->_getType($value); + if (!$type) $type = $ptype; + + #if ($ptype == 'object') { + # return $value->serialize($this); + #} else + if (strcasecmp($ptype,'Struct')==0 || strcasecmp($type,'Struct')==0) { + // struct + foreach ($value as $k => $v) { + if (is_object($v)) + $xmlout_value .= $v->serialize($this); + else + $xmlout_value .= $this->serializeValue($v,$k); + } + } else if (strcasecmp($ptype,'Array')==0 || strcasecmp($type,'Array')==0) { + // array + $typeNamespace = SOAP_SCHEMA_ENCODING; + $type = 'Array'; + $numtypes = 0; + // XXX this will be slow on larger array's. Basicly, it flattens array's to allow us + // to serialize multi-dimensional array's. We only do this if arrayType is set, + // which will typicaly only happen if we are using WSDL + if (isset($options['flatten']) || ($arrayType && strchr($arrayType,','))) { + $numtypes = $this->_multiArrayType($value, $arrayType, $ar_size, $xmlout_value); + } + + $array_type = $array_type_prefix = ''; + if ($numtypes != 1) { + $array_types = array(); + $array_val = NULL; + + // serialize each array element + foreach ($value as $array_val) { + if (is_object($array_val)) { + $array_type = $array_val->type; + $array_types[$array_type] = 1; + $array_type_ns = $array_val->type_namespace; + $xmlout_value .= $array_val->serialize($this); + } else { + $array_type = $this->_getType($array_val); + $array_types[$array_type] = 1; + $xmlout_value .= $this->serializeValue($array_val,'item', $array_type); + } + } + + $ar_size = count($value); + $numtypes = count($array_types); + $xmlout_offset = " SOAP-ENC:offset=\"[0]\""; + if ($numtypes == 1) $arrayType = $array_type; + // using anyType is more interoperable + if ($array_type == 'Struct') { + $array_type = ''; + } else if ($array_type == 'Array') { + $arrayType = 'anyType'; + $array_type_prefix = 'xsd'; + } else + if (!$arrayType) $arrayType = $array_type; + } + if (!isset($arrayType) || $numtypes > 1) { + $arrayType = 'xsd:anyType'; // should reference what schema we're using + } else { + if ($array_type_ns) { + $array_type_prefix = $this->getNamespacePrefix($array_type_ns); + } else if (array_key_exists($arrayType, $this->_typemap[$this->_XMLSchemaVersion])) { + $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; + } + if ($array_type_prefix) + $arrayType = $array_type_prefix.':'.$arrayType; + } + $xmlout_arrayType = " SOAP-ENC:arrayType=\"".$arrayType."[$ar_size]\""; + + } else if ($type == 'string') { + $xmlout_value = htmlspecialchars($value); + } else { + $xmlout_value = $value; + } + } + // add namespaces + if ($elNamespace) { + $elPrefix = $this->getNamespacePrefix($elNamespace); + $xmlout_name = "$elPrefix:$name"; + } else { + $xmlout_name = $name; + } + + if ($typeNamespace) { + $typePrefix = $this->getNamespacePrefix($typeNamespace); + $xmlout_type = "$typePrefix:$type"; + } else if ($type && array_key_exists($type, $this->_typemap[$this->_XMLSchemaVersion])) { + $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; + $xmlout_type = "$typePrefix:$type"; + } + + // handle additional attributes + $xml_attr = ''; + if (count($attributes)) { + foreach ($attributes as $k => $v) { + $kqn = new QName($k); + $vqn = new QName($v); + $xml_attr .= ' '.$kqn->fqn().'="'.$vqn->fqn().'"'; + } + } + + // store the attachement for mime encoding + if (isset($options['attachment'])) + $this->attachments[] = $options['attachment']; + + if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\""; + if (is_null($xmlout_value)) { + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xml_attr/>"; + } else { + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType$xmlout_offset$xml_attr>". + $xmlout_value."</$xmlout_name>"; + } + return $xml; + } + + function _getSchemaType($type, $name, $type_namespace) + { + if ($this->wsdl) { + # see if it's a complex type so we can deal properly with SOAPENC:arrayType + if ($name && $type) { + # XXX TODO: + # look up the name in the wsdl and validate the type + foreach ($this->wsdl->complexTypes as $ns=> $types) { + if (array_key_exists($type, $types)) { + if (array_key_exists('base', $types[$type])) { + return array($types[$type]['base'],$types[$type]['type'],$this->wsdl->namespaces[$types[$type]['namespace']]); + } + if (array_key_exists('arrayType', $types[$type])) { + return array('Array',$types[$type]['arrayType'],$this->wsdl->namespaces[$types[$type]['namespace']]); + } + if (array_key_exists('elements', $types[$type]) && + array_key_exists($name, $types[$type]['elements'])) { + $type = $types[$this->type]['elements']['type']; + return array($type,NULL,$this->wsdl->namespaces[$types[$type]['namespace']]); + } + } + } + } + if ($type && $type_namespace) { + $arrayType = NULL; + # XXX TODO: + # this code currently handles only one way of encoding array types in wsdl + # need to do a generalized function to figure out complex types + $p = $this->wsdl->ns[$type_namespace]; + if ($p && + array_key_exists($p, $this->wsdl->complexTypes) && + array_key_exists($type, $this->wsdl->complexTypes[$p])) { + if ($arrayType = $this->wsdl->complexTypes[$p][$type]['arrayType']) { + $type = 'Array'; + } else if ($this->wsdl->complexTypes[$p][$type]['order']=='sequence' && + array_key_exists('elements', $this->wsdl->complexTypes[$p][$type])) { + reset($this->wsdl->complexTypes[$p][$type]['elements']); + # assume an array + if (count($this->wsdl->complexTypes[$p][$type]['elements']) == 1) { + $arg = current($this->wsdl->complexTypes[$p][$type]['elements']); + $arrayType = $arg['type']; + $type = 'Array'; + } else { + foreach($this->wsdl->complexTypes[$p][$type]['elements'] as $element) { + if ($element['name'] == $type) { + $arrayType = $element['type']; + $type = $element['type']; + } + } + } + } else { + $type = 'Struct'; + } + return array($type,$arrayType,$type_namespace); + } + } + } + return array(NULL,NULL,NULL); + } + + /** + * SOAP::Value::_getType + * + * convert php type to soap type + * @param string value + * + * @return string type - soap type + * @access private + */ + function _getType(&$value) { + $type = gettype($value); + switch ($type) { + case 'object': + if (is_a($value,'soap_value')) { + $type = $value->type; + } + break; + case 'array': + $type = $this->isHash($value)?'Struct':'Array'; + break; + case 'integer': + case 'long': + $type = 'int'; + break; + case 'boolean': + $value = $value?'true':'false'; + break; + case 'double': + $type = 'float'; // double is deprecated in 4.2 and later + break; + case 'NULL': + $type = ''; + break; + case 'string': + if ($this->doconversion) { + if (is_numeric($value)) { + if (strstr($value,'.')) $type = 'float'; + else $type = 'int'; + } else + if (SOAP_Type_hexBinary::is_hexbin($value)) { + $type = 'hexBinary'; + } else + if ($this->isBase64($value)) { + $type = 'base64Binary'; + } else { + $dt = new SOAP_Type_dateTime($value); + if ($dt->toUnixtime() != -1) { + $type = 'dateTime'; + #$value = $dt->toSOAP(); + } + } + } + default: + break; + } + return $type; + } + + function _multiArrayType(&$value, &$type, &$size, &$xml) + { + $sz = count($value); + if ($sz > 1) { + // seems we have a multi dimensional array, figure it out if we do + foreach ($value as $array_val) { + $this->_multiArrayType($array_val, $type, $size, $xml); + } + + if ($size) { + $size = $sz.','.$size; + } else { + $size = $sz; + } + return 1; + } else { + if (is_object($value)) { + $type = $value->type; + $xml .= $value->serialize($this); + } else { + $type = $this->_getType($value); + $xml .= $this->serializeValue($value,'item',$type); + } + } + $size = NULL; + return 1; + } + // support functions + /** + * + * @param string + * @return string + */ + function isBase64(&$value) + { + $l = strlen($value); + if ($l > 0) + return $value[$l-1] == '=' && preg_match("/[A-Za-z=\/\+]+/",$value); + return FALSE; + } + + /** + * + * @param mixed + * @return boolean + */ + function isHash(&$a) { + # XXX I realy dislike having to loop through this in php code, + # realy large arrays will be slow. We need a C function to do this. + $names = array(); + $it = 0; + foreach ($a as $k => $v) { + # checking the type is faster than regexp. + $t = gettype($k); + if ($t != 'integer') { + return TRUE; + } else if (gettype($v) == 'object' && is_a($v,'soap_value')) { + $names[$v->name] = 1; + } + // if someone has a large hash they should realy be defining the type + if ($it++ > 10) return FALSE; + } + return count($names)>1; + } + + function un_htmlentities($string) + { + $trans_tbl = get_html_translation_table (HTML_ENTITIES); + $trans_tbl = array_flip($trans_tbl); + return strtr($string, $trans_tbl); + } + + /** + * + * @param mixed + */ + function decode($soapval) + { + if (!is_object($soapval)) { + return $soapval; + } else if (is_array($soapval->value)) { + $return = array(); + $counter = 1; + $isstruct = TRUE; // assume it's a struct + foreach ($soapval->value as $item) { + if (!$isstruct) { + $return[] = $this->decode($item); + } else if (isset($return[$item->name])) { + // this is realy an array, we need to redirect + $isstruct = FALSE; + $return = array($return[$item->name], $this->decode($item)); + } else { + $return[$item->name] = $this->decode($item); + } + } + return $return; + } + + if ($soapval->type == 'boolean') { + if ($soapval->value != '0' && strcasecmp($soapval->value,'false') !=0) { + $soapval->value = TRUE; + } else { + $soapval->value = FALSE; + } + } else if ($soapval->type && array_key_exists($soapval->type, $this->_typemap[SOAP_XML_SCHEMA_VERSION])) { + # if we can, lets set php's variable type + settype($soapval->value, $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); + } + return $soapval->value; + } + + /** + * creates the soap envelope with the soap envelop data + * + * @param string $payload soap data (in xml) + * @return associative array (headers,body) + * @access private + */ + function _makeEnvelope($method, $headers=NULL, $encoding = SOAP_DEFAULT_ENCODING) + { + $header_xml = $ns_string = ''; + + if ($headers) { + foreach ($headers as $header) { + $header_xml .= $header->serialize($this); + } + $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n"; + } + $body = "<SOAP-ENV:Body>\r\n".$method->serialize($this)."\r\n</SOAP-ENV:Body>\r\n"; + + foreach ($this->_namespaces as $k => $v) { + $ns_string .= " xmlns:$v=\"$k\"\r\n "; + } + + $xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n". + "<SOAP-ENV:Envelope $ns_string SOAP-ENV:encodingStyle=\"" . SOAP_SCHEMA_ENCODING . "\">\r\n". + "$header_xml$body</SOAP-ENV:Envelope>\r\n"; + + return $xml; + } + + function _makeMimeMessage($xml, $encoding = SOAP_DEFAULT_ENCODING) + { + global $SOAP_options; + + if (!isset($SOAP_options['Mime'])) { + return $this->raiseSoapFault('Mime is not installed'); + } + + // encode any attachments + // see http://www.w3.org/TR/SOAP-attachments + // now we have to mime encode the message + $params = array('content_type' => 'multipart/related; type=text/xml'); + $msg = new Mail_mimePart('', $params); + // add the xml part + $params['content_type'] = 'text/xml'; + $params['charset'] = $encoding; + $params['encoding'] = 'base64'; + $msg->addSubPart($xml, $params); + + // add the attachements + foreach ($this->attachments as $attachment) { + $msg->addSubPart($attachment['body'],$attachment); + } + return $msg->encode(); + } + + // XXX this needs to be used from the Transport system + function _makeDIMEMessage($xml) + { + global $SOAP_options; + + if (!isset($SOAP_options['DIME'])) { + return $this->raiseSoapFault('DIME is not installed'); + } + + // encode any attachments + // see http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt + // now we have to DIME encode the message + $dime = new DIME_Message(); + $msg = $dime->encodeData($xml,SOAP_ENVELOP,NULL,DIME_TYPE_URI); + + // add the attachements + foreach ($this->attachments as $attachment) { + $msg .= $dime->encodeData($attachment['body'],$attachment['content_type'],$attachment['cid'],DIME_TYPE_MEDIA); + } + $msg .= $dime->endMessage(); + return $msg; + } + + function decodeMimeMessage(&$data, &$headers, &$attachments) + { + global $SOAP_options; + if (!isset($SOAP_options['Mime'])) { + $this->makeFault('Server','Mime Unsupported, install PEAR::Mail::Mime'); + return; + } + + $params['include_bodies'] = TRUE; + $params['decode_bodies'] = TRUE; + $params['decode_headers'] = TRUE; + + $decoder = new Mail_mimeDecode($data); + $structure = $decoder->decode($params); + + if (isset($structure->body)) { + $data = $structure->body; + $headers = $structure->headers; + return; + } else if (isset($structure->parts)) { + $data = $structure->parts[0]->body; + $headers = $structure->parts[0]->headers; + if (count($structure->parts) > 1) { + $mime_parts = array_splice($structure->parts,1); + // prepare the parts for the soap parser + + foreach ($mime_parts as $p) { + if (isset($p->headers['content-location'])) { + // XXX TODO: modify location per SwA note section 3 + // http://www.w3.org/TR/SOAP-attachments + $attachments[$p->headers['content-location']] = $p->body; + } else { + $cid = 'cid:'.substr($p->headers['content-id'],1,strlen($p->headers['content-id'])-2); + $attachments[$cid] = $p->body; + } + } + } + return; + } + $this->makeFault('Server','Mime parsing error'); + } + + function decodeDIMEMessage(&$data, &$headers, &$attachments) + { + // XXX this SHOULD be moved to the transport layer, e.g. PHP itself + // should handle parsing DIME ;) + $dime = new DIME_Message(); + $dime->decodeData($data); + if (strcasecmp($dime->parts[0]['type'],SOAP_ENVELOP) !=0 || + strcasecmp($dime->parts[0]['type'],SOAP_ENVELOP) !=0) { + $this->makeFault('Server','Dime record 1 is not a SOAP envelop!'); + } else { + $data = $dime->parts[0]['data']; + $headers['content-type'] = 'text/xml'; // fake it for now + foreach ($dime->parts as $part) { + // XXX we need to handle URI's better + $attachments['cid:'.$part['id']] = $part['data']; + } + } + } + } /** @@ -134,7 +811,7 @@ * class used to handle QNAME values in XML * * @access public -* @version $Id: Base.php,v 1.7 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Base.php,v 1.8 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates */ @@ -142,26 +819,44 @@ { var $name = ''; var $ns = ''; + var $namespace=''; #var $arrayInfo = ''; - function QName($name) { - if (strpos($name, ':') != FALSE) { + function QName($name, $namespace = '') { + if ($name && $name[0] == '{') { + preg_match('/\{(.*?)\}(.*)/',$name, $m); + $this->name = $m[2]; + $this->namespace = $m[1]; + } else if (strpos($name, ':') != FALSE) { $s = split(':',$name); $s = array_reverse($s); $this->name = $s[0]; $this->ns = $s[1]; + $this->namespace = $namespace; } else { $this->name = $name; + $this->namespace = $namespace; } # a little more magic than should be in a qname - #$p = strpos($this->name, '['); - #if ($p) { - # # XXX need to re-examine this logic later - # # chop off [] - # $this->arrayInfo = substr($this->name, $p); - # $this->name = substr($this->name, 0, $p); - #} + $p = strpos($this->name, '['); + if ($p) { + # XXX need to re-examine this logic later + # chop off [] + $this->arraySize = split(',',substr($this->name,$p+1, strlen($this->name)-$p-2)); + $this->arrayInfo = substr($this->name, $p); + $this->name = substr($this->name, 0, $p); + } + } + + function fqn() + { + if ($this->namespace) { + return '{'.$this->namespace.'}'.$this->name; + } else if ($this->ns) { + return $this->ns.':'.$this->name; + } + return $this->name; } } -?> +?> \ No newline at end of file Index: pear/SOAP/Client.php diff -u pear/SOAP/Client.php:1.28 pear/SOAP/Client.php:1.29 --- pear/SOAP/Client.php:1.28 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Client.php Mon May 13 02:47:09 2002 @@ -17,13 +17,12 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Client.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +// $Id: Client.php,v 1.29 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Value.php'; require_once 'SOAP/Base.php'; require_once 'SOAP/Transport.php'; -require_once 'SOAP/Message.php'; require_once 'SOAP/WSDL.php'; require_once 'SOAP/Fault.php'; @@ -38,7 +37,7 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Client.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Client.php,v 1.29 2002/05/13 06:47:09 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 @@ -105,6 +104,8 @@ * @var string Contains the character encoding used for XML parser, etc. */ var $encoding = SOAP_DEFAULT_ENCODING; + + var $headers = NULL; /** * SOAP_Client constructor * @@ -142,8 +143,7 @@ */ function setEncoding($encoding) { - global $SOAP_Encodings; - if (in_array($encoding, $SOAP_Encodings)) { + if (in_array($encoding, $this->_encodings)) { $this->encoding = $encoding; return NULL; } @@ -162,17 +162,14 @@ */ function addHeader($soap_value) { - if (!$this->soapmsg) { - soap_reset_namespaces(); - $this->soapmsg = new SOAP_Message(NULL, $this->wsdl); - } # add a new header to the message - if (get_class($soap_value) == 'soap_header') { - $this->soapmsg->addHeader($soap_value); + if (is_a($soap_value,'soap_header')) { + #$this->soapmsg->addHeader($soap_value); + $this->headers[] = $soap_value; } else if (gettype($soap_value) == 'array') { // name, value, namespace, mustunderstand, actor - $h = new SOAP_Header($soap_value[0], NULL, $soap_value[1], $soap_value[2], $soap_value[3], $soap_value[4]); - $this->soapmsg->addHeader($h); + $h = new SOAP_Header($soap_value[0], NULL, $soap_value[1], $soap_value[2], $soap_value[3]); + $this->headers[] = $h; } else { $this->raiseSoapFault("Don't understand the header info you provided. Must be array or SOAP_Header."); } @@ -211,15 +208,10 @@ $this->fault = null; $options = array(); - // make message - if (!$this->soapmsg) { - soap_reset_namespaces(); - $this->soapmsg = new SOAP_Message(NULL, $this->wsdl); - } - if (gettype($namespace) == 'array') { $options = $namespace; - $namespace = $options['namespace']; + if (isset($options['namespace'])) $namespace = $options['namespace']; + else $namespace = false; } else { // we'll place soapaction into our array for usage in the transport $options['soapaction'] = $soapAction; @@ -264,16 +256,17 @@ $nparams[$name] = current($params); next($params); } - if (gettype($nparams[$name]) != 'object' && - get_class($nparams[$name]) != 'soap_value') { + if (gettype($nparams[$name]) != 'object' || + !is_a($nparams[$name],'soap_value')) { // type is a qname likely, split it apart, and get the type namespace from wsdl $qname = new QName($type); if ($qname->ns) $type_namespace = $this->wsdl->namespaces[$qname->ns]; else $type_namespace = NULL; + $qname->namespace = $type_namespace; $type = $qname->name; - $nparams[$name] = new SOAP_Value($name, $qname->name, $nparams[$name], NULL, $type_namespace, $this->wsdl); + $nparams[$name] = new SOAP_Value($name, $qname->fqn(), $nparams[$name]); } } } @@ -282,21 +275,50 @@ $this->setSchemaVersion(SOAP_XML_SCHEMA_VERSION); } - $this->soapmsg->method($method, $params, $namespace); - if ($this->soapmsg->fault) { - return $this->raiseSoapFault($this->soapmsg->fault); - } - // serialize the message - $soap_data = $this->soapmsg->serialize($this->encoding); - - if (PEAR::isError($soap_data)) { - return $this->raiseSoapFault($soap_data); + $mqname = new QName($method, $namespace); + $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params); + $soap_msg = $this->_makeEnvelope($methodValue, $this->headers, $this->encoding); + + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if (isset($options['Mime'])) { + $soap_msg = $this->_makeMimeMessage($soap_msg, $this->encoding); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg, $this->encoding); + $options['headers']['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } } // instantiate client - $dbg = "calling server at '$this->endpoint'..."; - + if (is_array($soap_msg)) { + $soap_data = $soap_msg['body']; + if (count($soap_msg['headers'])) { + if (isset($options['headers'])) { + $options['headers'] = array_merge($options['headers'],$soap_msg['headers']); + } else { + $options['headers'] = $soap_msg['headers']; + } + } + } else { + $soap_data = $soap_msg; + } + #$f = fopen('/tmp/dime.data','wb+'); + #if ($f) { + # fwrite($f,$soap_data); + # fclose($f); + # return; + #} $soap_transport = new SOAP_Transport($this->endpoint, $this->encoding); if ($soap_transport->fault) { @@ -319,7 +341,7 @@ } // parse the response - $this->response = new SOAP_Parser($this->response, $soap_transport->result_encoding); + $this->response = new SOAP_Parser($this->response, $soap_transport->result_encoding,$soap_transport->transport->attachments); if ($this->response->fault) { return $this->raiseSoapFault($this->response->fault); } @@ -327,20 +349,20 @@ $return = $this->response->getResponse(); $headers = $this->response->getHeaders(); if ($headers) { - $this->headers = $headers->decode(); + $this->headers = $this->decode($headers); } - $this->soapmsg = NULL; + #$this->soapmsg = NULL; // check for valid response if (PEAR::isError($return)) { return $this->raiseSoapFault($return); - } else if (strcasecmp(get_class($return), 'SOAP_Value') != 0) { + } else if (!is_a($return,'soap_value')) { return $this->raiseSoapFault("didn't get SOAP_Value object back from client"); } // decode to native php datatype - $returnArray = $return->decode(); + $returnArray = $this->decode($return); // fault? if (PEAR::isError($returnArray)) { return $this->raiseSoapFault($returnArray); @@ -364,25 +386,6 @@ return $returnArray; } - /** - * setSchemaVersion - * - * sets the schema version used in the soap message - * - * @param string (see globals.php) - * - * @access private - */ - function setSchemaVersion($schemaVersion) - { - global $SOAP_namespaces; - $this->XMLSchemaVersion = $schemaVersion; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - } - /** * SOAP_Client::__call * Index: pear/SOAP/Fault.php diff -u pear/SOAP/Fault.php:1.6 pear/SOAP/Fault.php:1.7 --- pear/SOAP/Fault.php:1.6 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Fault.php Mon May 13 02:47:09 2002 @@ -17,10 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Fault.php,v 1.6 2002/04/27 18:33:25 shane Exp $ +// $Id: Fault.php,v 1.7 2002/05/13 06:47:09 shane Exp $ // require_once('PEAR.php'); -require_once('SOAP/Message.php'); /** * SOAP_Fault @@ -30,7 +29,7 @@ * @access public * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more * @author Dietrich Ayala <dietrich@ganx4.com> Original Author - * @version $Id: Fault.php,v 1.6 2002/04/27 18:33:25 shane Exp $ + * @version $Id: Fault.php,v 1.7 2002/05/13 06:47:09 shane Exp $ */ class SOAP_Fault extends PEAR_Error { @@ -70,17 +69,15 @@ */ function message() { - $msg = new SOAP_Message(); - $msg->method('Fault', - array( + $msg = new SOAP_Base(); + $params = array( new SOAP_Value('faultcode', 'QName', 'SOAP-ENV:'.$this->code), new SOAP_Value('faultstring', 'string', $this->message), new SOAP_Value('faultactor', 'anyURI', $this->error_message_prefix), new SOAP_Value('detail', 'string', $this->userinfo) - ), - SOAP_ENVELOP - ); - return $msg; + ); + $methodValue = new SOAP_Value('{'.SOAP_ENVELOP.'}Fault', 'Struct', $params); + return $msg->_makeEnvelope($methodValue); } /** Index: pear/SOAP/Parser.php diff -u pear/SOAP/Parser.php:1.21 pear/SOAP/Parser.php:1.22 --- pear/SOAP/Parser.php:1.21 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Parser.php Mon May 13 02:47:09 2002 @@ -17,10 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Parser.php,v 1.21 2002/04/27 18:33:25 shane Exp $ +// $Id: Parser.php,v 1.22 2002/05/13 06:47:09 shane Exp $ // -require_once 'SOAP/globals.php'; require_once 'SOAP/Base.php'; require_once 'SOAP/Value.php'; @@ -31,7 +30,7 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Parser.php,v 1.21 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Parser.php,v 1.22 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Parser * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author @@ -43,11 +42,11 @@ var $pos_stat = 0; var $depth = 0; var $default_namespace = ''; - var $namespaces = array(); var $message = array(); var $depth_array = array(); var $previous_element = ''; var $soapresponse = NULL; + var $soapheaders = NULL; var $parent = 0; var $root_struct_name = array(); var $header_struct_name = array(); @@ -69,14 +68,15 @@ * @param string xml content * @param string xml character encoding, defaults to 'UTF-8' */ - function SOAP_Parser($xml, $encoding = SOAP_DEFAULT_ENCODING) + function SOAP_Parser($xml, $encoding = SOAP_DEFAULT_ENCODING, $attachments=NULL) { parent::SOAP_Base('Parser'); $this->setSchemaVersion(SOAP_XML_SCHEMA_VERSION); $this->xml = $xml; $this->xml_encoding = $encoding; - + $this->attachments = $attachments; + // check the xml tag for encoding if (preg_match('/<\?xml.*?encoding=(?:[\'|"])([\w\d-]*)?.*?(?:[\'|"])\?>/',$xml,$m)) { $this->xml_encoding = strtoupper($m[1]); @@ -113,23 +113,7 @@ } } - /** - * setSchemaVersion - * sets the schema for the resulting message - * - * @param string schema version - * @access private - */ - function setSchemaVersion($schemaVersion) - { - global $SOAP_namespaces; - $this->XMLSchemaVersion = $schemaVersion; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - } - + /** * domulti * recurse to build a multi-dim array, used by buildResponse @@ -157,7 +141,7 @@ { $response = NULL; - if ($this->message[$pos]['children'] != '') { + if (isset($this->message[$pos]['children'])) { $children = explode('|',$this->message[$pos]['children']); foreach ($children as $c => $child_pos) { @@ -189,7 +173,8 @@ } } $response = $newresp; - } else if ($this->message[$pos]['arrayOffset'][0] > 0) { + } else if (isset($this->message[$pos]['arrayOffset']) && + $this->message[$pos]['arrayOffset'][0] > 0) { # check for padding $pad = $this->message[$pos]['arrayOffset'][0]+count($response)*-1; $response = array_pad($response,$pad,NULL); @@ -198,9 +183,13 @@ } // add current node's value if ($response) { - $response = new SOAP_Value($this->message[$pos]["name"], $this->message[$pos]["type"] , $response, $this->message[$pos]["namespace"], $this->message[$pos]['type_namespace']); + $nqn = new Qname($this->message[$pos]["name"],$this->message[$pos]["namespace"]); + $tqn = new Qname($this->message[$pos]["type"],$this->message[$pos]["type_namespace"]); + $response = new SOAP_Value($nqn->fqn(), $nqn->fqn(), $response); } else { - $response = new SOAP_Value($this->message[$pos]['name'], $this->message[$pos]['type'] , $this->message[$pos]['cdata'], $this->message[$pos]["namespace"], $this->message[$pos]['type_namespace']); + $nqn = new Qname($this->message[$pos]["name"],$this->message[$pos]["namespace"]); + $tqn = new Qname($this->message[$pos]["type"],$this->message[$pos]["type_namespace"]); + $response = new SOAP_Value($nqn->fqn(), $nqn->fqn(), $this->message[$pos]['cdata']); } // handle header attribute that we need if (array_key_exists('actor',$this->message[$pos])) { @@ -220,13 +209,15 @@ */ function startElement($parser, $name, $attrs) { - global $SOAP_XMLSchema; // position in a total number of elements, starting from 0 // update class level pos $pos = $this->position++; // and set mine $this->message[$pos] = array(); + $this->message[$pos]['type'] = ''; + $this->message[$pos]['type_namespace'] = ''; + $this->message[$pos]['cdata'] = ''; $this->message[$pos]['pos'] = $pos; $this->message[$pos]['id'] = ''; @@ -238,7 +229,10 @@ // else add self as child to whoever the current parent is if ($pos != 0) { - $this->message[$this->parent]['children'] .= "|$pos"; + if (isset($this->message[$this->parent]['children'])) + $this->message[$this->parent]['children'] .= "|$pos"; + else + $this->message[$this->parent]['children'] = $pos; } // set my parent @@ -290,16 +284,6 @@ // set attrs $this->message[$pos]['attrs'] = $attrs; - // see if namespace is defined in tag - if (array_key_exists('xmlns:'.$qname->ns,$attrs)) { - $namespace = $attrs['xmlns:'.$qname->ns]; - } else { - // get namespace - $namespace = $qname->ns?$this->namespaces[$qname->ns]:$this->default_namespace; - } - $this->message[$pos]['namespace'] = $namespace; - $this->default_namespace = $namespace; - // loop through atts, logging ns and type declarations foreach ($attrs as $key => $value) { // if ns declarations, add to class level array of valid namespaces @@ -307,11 +291,11 @@ if ($kqn->ns == 'xmlns') { $prefix = $kqn->name; - if (in_array($value, $SOAP_XMLSchema)) { + if (in_array($value, $this->_XMLSchema)) { $this->setSchemaVersion($value); } - $this->namespaces[$prefix] = $value; + $this->_namespaces[$prefix] = $value; // set method namespace # XXX unused??? @@ -328,20 +312,21 @@ } elseif ($kqn->name == 'type') { $vqn = new QName($value); $this->message[$pos]['type'] = $vqn->name; - $this->message[$pos]['type_namespace'] = $this->namespaces[$vqn->ns]; + $this->message[$pos]['type_namespace'] = $this->_namespaces[$vqn->ns]; #print "set type for {$this->message[$pos]['name']} to {$this->message[$pos]['type']}\n"; // should do something here with the namespace of specified type? } elseif ($kqn->name == 'arrayType') { $vqn = new QName($value); $this->message[$pos]['type'] = 'Array'; - $type = $vqn->name; - $sa = strpos($type,'['); - if ($sa > 0) { - $this->message[$pos]['arraySize'] = split(',',substr($type,$sa+1, strlen($type)-$sa-2)); - $type = substr($type, 0, $sa); - } - $this->message[$pos]['arrayType'] = $type; + #$type = $vqn->name; + $this->message[$pos]['arraySize'] = $vqn->arraySize; + #$sa = strpos($type,'['); + #if ($sa > 0) { + # $this->message[$pos]['arraySize'] = split(',',substr($type,$sa+1, strlen($type)-$sa-2)); + # $type = substr($type, 0, $sa); + #} + $this->message[$pos]['arrayType'] = $vqn->name; } elseif ($kqn->name == 'offset') { $this->message[$pos]['arrayOffset'] = split(',',substr($value, 1, strlen($value)-2)); @@ -351,23 +336,36 @@ $this->references[$value] = $pos; $this->message[$pos]['id'] = $value; - } elseif ($kqn->name == 'href' && $value[0] == '#') { - $ref = substr($value, 1); - if (array_key_exists($ref,$this->references)) { - # cdata, type, inval - $ref_pos = $this->references[$ref]; - $this->message[$pos]['children'] = &$this->message[$ref_pos]['children']; - $this->message[$pos]['cdata'] = &$this->message[$ref_pos]['cdata']; - $this->message[$pos]['type'] = &$this->message[$ref_pos]['type']; - $this->message[$pos]['arraySize'] = &$this->message[$ref_pos]['arraySize']; - $this->message[$pos]['arrayType'] = &$this->message[$ref_pos]['arrayType']; - } else { - # reverse reference, store in 'need reference' - if (!is_array($this->need_references[$ref])) $this->need_references[$ref] = array(); - $this->need_references[$ref][] = $pos; + } elseif ($kqn->name == 'href') { + if ($value[0] == '#') { + $ref = substr($value, 1); + if (array_key_exists($ref,$this->references)) { + # cdata, type, inval + $ref_pos = $this->references[$ref]; + $this->message[$pos]['children'] = &$this->message[$ref_pos]['children']; + $this->message[$pos]['cdata'] = &$this->message[$ref_pos]['cdata']; + $this->message[$pos]['type'] = &$this->message[$ref_pos]['type']; + $this->message[$pos]['arraySize'] = &$this->message[$ref_pos]['arraySize']; + $this->message[$pos]['arrayType'] = &$this->message[$ref_pos]['arrayType']; + } else { + # reverse reference, store in 'need reference' + if (!isset($this->need_references[$ref])) $this->need_references[$ref] = array(); + $this->need_references[$ref][] = $pos; + } + } else if (isset($this->attachments[$value])) { + $this->message[$pos]['cdata'] = $this->attachments[$value]; } } } + // see if namespace is defined in tag + if (array_key_exists('xmlns:'.$qname->ns,$attrs)) { + $namespace = $attrs['xmlns:'.$qname->ns]; + } else { + // get namespace + $namespace = $qname->ns?$this->_namespaces[$qname->ns]:$this->default_namespace; + } + $this->message[$pos]['namespace'] = $namespace; + $this->default_namespace = $namespace; } /** @@ -387,7 +385,7 @@ // get type if not explicitly declared in an xsi:type attribute // XXX check on integrating wsdl validation here if ($this->message[$pos]['type'] == '') { - if ($this->message[$pos]['children'] != '') { + if (isset($this->message[$pos]['children'])) { /* this is slow, need to look at some faster method $children = explode('|',$this->message[$pos]['children']); if (count($children) > 2 && @@ -444,7 +442,10 @@ function characterData($parser, $data) { $pos = $this->depth_array[$this->depth]; - $this->message[$pos]['cdata'] .= $data; + if (isset($this->message[$pos]['cdata'])) + $this->message[$pos]['cdata'] .= $data; + else + $this->message[$pos]['cdata'] = $data; } /** @@ -499,4 +500,4 @@ } } -?> +?> \ No newline at end of file Index: pear/SOAP/Server.php diff -u pear/SOAP/Server.php:1.20 pear/SOAP/Server.php:1.21 --- pear/SOAP/Server.php:1.20 Wed Apr 24 03:41:18 2002 +++ pear/SOAP/Server.php Mon May 13 02:47:09 2002 @@ -17,18 +17,14 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Server.php,v 1.20 2002/04/24 07:41:18 shane Exp $ +// $Id: Server.php,v 1.21 2002/05/13 06:47:09 shane Exp $ // -require_once 'SOAP/globals.php'; +require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; require_once 'SOAP/Parser.php'; -require_once 'SOAP/Message.php'; require_once 'SOAP/Value.php'; -// make errors handle properly in windows -#error_reporting(2039); - $soap_server_fault = NULL; function SOAP_ServerErrorHandler($errno, $errmsg, $filename, $linenum, $vars) { global $soap_server_fault; @@ -44,12 +40,13 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Server.php,v 1.20 2002/04/24 07:41:18 shane Exp $ +* @version $Id: Server.php,v 1.21 2002/05/13 06:47:09 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_Server { +class SOAP_Server extends SOAP_Base +{ /** * @@ -92,17 +89,17 @@ function SOAP_Server() { ini_set('track_errors',1); + parent::SOAP_Base('Server'); } function _getContentEncoding($content_type) { - global $SOAP_Encodings; // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set $this->xml_encoding = 'UTF-8'; - if (!$test && strpos($content_type,'=')) { + if (strpos($content_type,'=')) { $enc = strtoupper(str_replace('"',"",substr(strstr($content_type,'='),1))); - if (!in_array($enc, $SOAP_Encodings)) { + if (!in_array($enc, $this->_encodings)) { return FALSE; } $this->xml_encoding = $enc; @@ -110,60 +107,104 @@ return TRUE; } + // parses request and posts response function service($data, $endpoint = '', $test = FALSE) { - global $_ENV, $_SERVER; + $response = NULL; + $attachments = array(); + $headers = array(); + $useEncoding = 'DIME'; // figure out our endpoint $this->endpoint = $endpoint; - if (!$this->endpoint) { + if (!$test && !$this->endpoint) { // we'll try to build our endpoint $this->endpoint = 'http://'.$_SERVER['SERVER_NAME']; if ($_SERVER['SERVER_PORT']) $this->endpoint .= ':'.$_SERVER['SERVER_PORT']; - $this->endpoint .= $PHP_SELF; + $this->endpoint .= $_SERVER['SCRIPT_NAME']; } // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set - if (!$this->_getContentEncoding($_SERVER['CONTENT_TYPE'])) { - $this->xml_encoding = SOAP_DEFAULT_ENCODING; - // an encoding we don't understand, return a fault - $this->makeFault('Server','Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8'); - $response = $this->getFaultMessage(); + if (isset($_SERVER['CONTENT_TYPE'])) { + if (strcasecmp($_SERVER['CONTENT_TYPE'],'application/dime')==0) { + $this->decodeDIMEMessage($data,$headers,$attachments); + $useEncoding = 'DIME'; + } else if (stristr($_SERVER['CONTENT_TYPE'],'multipart/related')) { + // this is a mime message, lets decode it. + $data = 'Content-Type: '.stripslashes($_SERVER['CONTENT_TYPE'])."\r\n\r\n".$data; + $this->decodeMimeMessage($data,$headers,$attachments); + $useEncoding = 'Mime'; + } + if (!isset($headers['content-type'])) { + $headers['content-type'] = $_SERVER['CONTENT_TYPE']; + } + if (!$this->soapfault && + !$this->_getContentEncoding($headers['content-type'])) { + $this->xml_encoding = SOAP_DEFAULT_ENCODING; + // an encoding we don't understand, return a fault + $this->makeFault('Server','Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8'); + } } // if this is not a POST with Content-Type text/xml, try to return a WSDL file - if (!$response && !$test && ($_SERVER['REQUEST_METHOD'] != 'POST' || - strncmp($_SERVER['CONTENT_TYPE'],'text/xml',8) != 0)) { + if (!$this->soapfault && !$test && ($_SERVER['REQUEST_METHOD'] != 'POST' || + strncmp($headers['content-type'],'text/xml',8) != 0)) { // this is not possibly a valid soap request, try to return a WSDL file - $this->makeFault('Server',"Invalid SOAP request, must be POST with content-type: text/xml"); - $response = $this->getFaultMessage(); + $this->makeFault('Server',"Invalid SOAP request, must be POST with content-type: text/xml, got: {$headers['content-type']}"); } - if (!$response) { + if (!$this->soapfault) { // $response is a soap_msg object - $response = $this->parseRequest($data); + $soap_msg = $this->parseRequest($data, $attachments); + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if ($useEncoding == 'Mime') { + $soap_msg = $this->_makeMimeMessage($soap_msg); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg); + $header['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + } + + if (is_array($soap_msg)) { + $response = $soap_msg['body']; + if (count($soap_msg['headers'])) { + $header = $soap_msg['headers']; + } + } else { + $response = $soap_msg; + } } - $payload = $response->serialize($this->response_encoding); - // print headers if ($this->soapfault) { - #$header[] = "Status: 500 Internal Server Error\r\n"; - $header[] = "HTTP/1.1 500 Soap Fault\r\n"; + $hdrs = "HTTP/1.1 500 Soap Fault\r\n"; + $response = $this->getFaultMessage(); } else { - #$header[] = "Status: 200 OK\r\n"; - $header[] = "HTTP/1.1 200 OK\r\n"; + $hdrs = "HTTP/1.1 200 OK\r\n"; } + header($hdrs); - $header[] = 'Server: ' . SOAP_LIBRARY_NAME . "\r\n"; - $header[] = "Content-Type: text/xml; charset=$this->response_encoding\r\n"; - $header[] = 'Content-Length: ' . strlen($payload) . "\r\n\r\n"; + $header['Server'] = SOAP_LIBRARY_NAME; + if (!isset($header['Content-Type'])) + $header['Content-Type'] = "text/xml; charset=$this->response_encoding"; + $header['Content-Length'] = strlen($response); + reset($header); - foreach ($header as $hdr) { - header($hdr); + foreach ($header as $k => $v) { + header("$k: $v"); + $hdrs .= "$k: $v\r\n"; } - $this->response = join("\n", $header) . $payload; - print $payload; + + $this->response = $hdrs . "\r\n" . $response; + print $response; } function callMethod($methodname, &$args) { @@ -195,8 +236,7 @@ // create soap_val object w/ return values from method, use method signature to determine type function buildResult(&$method_response, &$return_type, $return_name='return', $namespace = '') { - $class = get_class($method_response) ; - if ($class == 'soap_value' || $class == 'soap_header') { + if (gettype($method_response) == 'object' && is_a($method_response,'soap_value')) { $return_val = array($method_response); } else { if (is_array($return_type) && is_array($method_response)) { @@ -204,10 +244,11 @@ foreach ($return_type as $key => $type) { if (is_numeric($key)) $key = 'item'; - if (get_class($method_response[$i]) == 'soap_value') { + if (is_a($method_response[$i],'soap_value')) { $return_val[] = $method_response[$i++]; } else { - $return_val[] = new SOAP_Value($key,$type,$method_response[$i++],$namespace); + $qn = new QName($key, $namespace); + $return_val[] = new SOAP_Value($qn->fqn(),$type,$method_response[$i++]); } } } else { @@ -217,39 +258,23 @@ $values = array_values($return_type); $return_type = $values[0]; } - $return_val = array(new SOAP_Value($return_name,$return_type,$method_response, $namespace)); + $qn = new QName($return_name, $namespace); + $return_val = array(new SOAP_Value($qn->fqn(),$return_type,$method_response)); } } return $return_val; } - function parseRequest($data='') + function parseRequest($data='', $attachments=NULL) { - global $_ENV, $_SERVER, $SOAP_Encodings; - - - - $this->request = $dump."\r\n\r\n".$data; // parse response, get soap parser obj - $parser = new SOAP_Parser($data,$this->xml_encoding); + $parser = new SOAP_Parser($data,$this->xml_encoding,$attachments); // if fault occurred during message parsing if ($parser->fault) { - $this->soapfault = $parser->fault->message(); - #$this->makeFault('Server',"error in msg parsing:\n".$fault->serialize."\n\n<pre>$data</pre>\n\n"); - return $parser->fault->message(); + $this->soapfault = $parser->fault; + return NULL; } - /* set namespaces - if ($parser->namespaces['xsd'] != '') { - //print 'got '.$parser->namespaces['xsd']; - global $SOAP_namespaces; - $this->XMLSchemaVersion = $parser->namespaces['xsd']; - $tmpNS = array_flip($SOAP_namespaces); - $tmpNS['xsd'] = $this->XMLSchemaVersion; - $tmpNS['xsi'] = $this->XMLSchemaVersion.'-instance'; - $SOAP_namespaces = array_flip($tmpNS); - }*/ - //******************************************************* // handle message headers @@ -257,9 +282,9 @@ $header_results = array(); if ($request_headers) { - if (get_class($request_headers) != 'soap_value') { + if (!is_a($request_headers,'soap_value')) { $this->makeFault('Server',"parser did not return SOAP_Value object: $request_headers"); - return $this->getFaultMessage(); + return NULL; } if ($request_headers->value) { // handle headers now @@ -274,7 +299,7 @@ if (!$f_exists && $header_val->mustunderstand && $myactor) { $this->makeFault('Server',"I don't understand header $header_val->name."); - return $this->getFaultMessage(); + return NULL; } // we only handle the header if it's for us @@ -283,13 +308,12 @@ if ($isok) { # call our header now! $header_method = $header_val->name; - $header_data = array($header_val->decode()); + $header_data = array($this->decode($header_val)); // if there are parameters to pass $hr = $this->callMethod($header_method, $header_data); # if they return a fault, then it's all over! - if (get_class($hr) == 'soap_message' && - stristr($hr->value->name,'fault')) { - return $hr; + if (is_a($hr,'soap_value') && stristr($hr->value->name,'fault')) { + return $this->_makeEnvelope($hr, NULL, $this->response_encoding); } $header_results[] = array_shift($this->buildResult($hr, $this->return_type, $header_method, $header_val->namespace)); } @@ -308,63 +332,42 @@ // does method exist? if (!$this->methodname || !$this->validateMethod($this->methodname)) { $this->makeFault('Server',"method '$this->methodname' not defined in service"); - return $this->getFaultMessage(); + return NULL; } if (!$request_val = $parser->getResponse()) { - return $this->getFaultMessage(); + return NULL; } - if (get_class($request_val) != 'soap_value') { + if (!is_a($request_val,'soap_value')) { $this->makeFault('Server',"parser did not return SOAP_Value object: $request_val"); - return $this->getFaultMessage(); + return NULL; } // verify that SOAP_Value objects in request match the methods signature if (!$this->verifyMethod($request_val)) { // verifyMethod creates the fault - return $this->getFaultMessage(); + return NULL; } // need to set special error detection inside the value class // so as to differentiate between no params passed, and an error decoding - $request_data = $request_val->decode(); + $request_data = $this->decode($request_val); $method_response = $this->callMethod($this->methodname, $request_data); - // if return val is SOAP_Message - if (get_class($method_response) == 'soap_message') { - return $method_response; - } - // get the method result if (is_null($method_response)) $return_val = NULL; else $return_val = $this->buildResult($method_response, $this->return_type); - // response object is a soap_msg object - $return_msg = new SOAP_Message(); - - // add response headers - if (count($header_results) > 0) { - foreach($header_results as $hr) { - $return_msg->addHeader($hr); - } - } - - $return_msg->method($this->methodname.'Response',$return_val,$this->method_namespace); - - if ($this->debug_flag) { - $return_msg->debug_flag = true; - } - - return $return_msg; + $qn = new QName($this->methodname.'Response',$this->method_namespace); + $methodValue = new SOAP_Value($qn->fqn(), 'Struct', $return_val); + return $this->_makeEnvelope($methodValue, $header_results, $this->response_encoding); } function verifyMethod($request) { - global $SOAP_typemap; - //return true; $params = $request->value; @@ -401,8 +404,8 @@ // this allows using plain php variables to work (ie. stuff like Decimal would fail otherwise) // we only error if the types exist in our type maps, and they differ if (strcasecmp($sig_t[$i],$p[$i])!=0 && - (isset($SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]]) && - strcasecmp($SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]],$SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$p[$i]])!=0)) { + (isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]]) && + strcasecmp($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]],$this->_typemap[SOAP_XML_SCHEMA_VERSION][$p[$i]])!=0)) { $param = $params[$i]; $this->makeFault('Client',"soap request contained mismatching parameters of name $param->name had type [{$p[$i]}], which did not match signature's type: [{$sig_t[$i]}], matched? ".(strcasecmp($sig_t[$i],$p[$i]))); @@ -481,7 +484,7 @@ { if (!function_exists($methodname)) { $this->makeFault('Server',"error mapping function\n"); - return $this->getFaultMessage(); + return FALSE; } $this->dispatch_map[$methodname]['in'] = $in; $this->dispatch_map[$methodname]['out'] = $out; Index: pear/SOAP/Value.php diff -u pear/SOAP/Value.php:1.28 pear/SOAP/Value.php:1.29 --- pear/SOAP/Value.php:1.28 Sat Apr 27 14:33:25 2002 +++ pear/SOAP/Value.php Mon May 13 02:47:09 2002 @@ -17,12 +17,9 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: Value.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +// $Id: Value.php,v 1.29 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Base.php'; -require_once 'SOAP/globals.php'; -require_once 'SOAP/Type/dateTime.php'; -require_once 'SOAP/Type/hexBinary.php'; /** * SOAP::Value @@ -31,39 +28,21 @@ * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 * * @access public -* @version $Id: Value.php,v 1.28 2002/04/27 18:33:25 shane Exp $ +* @version $Id: Value.php,v 1.29 2002/05/13 06:47:09 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 extends SOAP_Base +class SOAP_Value { /** * - * @var boolean - */ - var $convert_strings = FALSE; - - /** - * * * @var string */ var $value = NULL; /** - * - * @var int - */ - var $type_code = 0; - - /** - * - * @var boolean - */ - var $type_prefix = false; - - /** * * @var string */ @@ -76,29 +55,14 @@ var $type = ''; /** - * - * @var - */ - var $soapTypes; - - /** * Namespace * * @var string */ var $namespace = ''; var $type_namespace = ''; - /** - * - * @var string - */ - var $prefix = ''; - /** - * - * @var - */ - var $wsdl; + var $attributes = array(); /** * @@ -106,638 +70,143 @@ */ var $arrayType = ''; - - /** - * set to true to flatten multidimensional arrays - * @var string - */ - var $flattenArray = FALSE; + var $options = array(); + /** * * - * @param string name of the soap-value <value_name> - * @param mixed soap value type, if not set an automatic - * @param int - * @param mixed - * @param mixed - * @param mixed - * @global $SOAP_typemap, $SOAP_namespaces + * @param string name of the soap-value {namespace}name + * @param mixed soap value {namespace}type, if not set an automatic + * @param mixed value to set */ - function SOAP_Value($name = '', $type = false, $value = -1, $methodNamespace = NULL, $type_namespace = NULL, $wsdl = NULL) + function SOAP_Value($name = '', $type = false, $value) { - global $SOAP_typemap, $SOAP_namespaces; - parent::SOAP_Base('Value'); // detect type if not passed - - $this->name = $name; - $this->wsdl = $wsdl; - $this->type_namespace = $type_namespace; - $this->type = $this->_getSoapType($value, $type, $name, $type_namespace); - $this->namespace = $methodNamespace; - - if (strpos($this->type , ':') !== false) { - $qname = new QName($type); - $this->type = $qname->name; - $this->type_prefix = $qname->ns; - } - - if (array_key_exists($this->type, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION])) { - // scalar - - $this->type_code = SOAP_VALUE_SCALAR; - $this->addScalar($value, $this->type, $name); - - } elseif (strcasecmp('Array', $this->type) == 0 || strcasecmp('ur-type', $this->type) == 0) { - // array - - $this->type_code = SOAP_VALUE_ARRAY; - $this->addArray($value); - - } elseif (stristr($this->type, 'Struct')) { - // struct - - $this->type_code = SOAP_VALUE_STRUCT; - $this->addStruct($value); - - } elseif (is_array($value)) { - - $this->type_code = SOAP_VALUE_STRUCT; - $this->addStruct($value); - - } else { - - $this->type_code = SOAP_VALUE_SCALAR; - $this->addScalar($value, 'string', $name); - - } - } - - /** - * - * - * @param - * @param - * @param - * @return boolean - * @access private - */ - function addScalar($value, $type, $name = '') - { - if ($type == 'string') { - $this->value = !is_null($value)?htmlspecialchars($value):NULL; - } else { - $this->value = $value; - } - return true; + $qn = new QName($name); + $this->name = $qn->name; + $this->namespace = $qn->namespace; + $qn = new QName($type); + $this->type = $qn->name; + $this->type_prefix = $qn->ns; + $this->type_namespace = $qn->namespace; + $this->value = $value; } + /** + * Serialize * - * @param array - * @return boolean - */ - function addArray($vals) - { - $this->value = array(); - - if (is_array($vals) && count($vals) >= 1) { - foreach ($vals as $k => $v) { - // if SOAP_Value, add.. - if (strcasecmp(get_class($v), 'SOAP_Value' ) == 0) { - $this->value[] = $v; - // else make obj and serialize - } else { - #$type = $this->arrayType; - //$type = $this->_getSoapType($v, $type, $k); - $new_val = new SOAP_Value('item', NULL /*$this->arrayType*/, $v); - $this->value[] = $new_val; - } - } - } - return true; - } - - /** - * - * @param array - * @param boolean + * @return string xml representation */ - function addStruct($vals) + function serialize(&$serializer) { - if (is_array($vals) && count($vals) >= 1) { - foreach ($vals as $k => $v) { - // if serialize, if SOAP_Value - if (strcasecmp(get_class($v), 'SOAP_Value') == 0) { - $this->value[] = $v; - // else make obj and serialize - } else { - //$type = NULL; - //$type = $this->_getSoapType($v, $type, $k); - $new_val = new SOAP_Value($k, NULL, $v); - $this->value[] = $new_val; - } - } - } else { - $this->value = array(); - } - return true; + return $serializer->serializeValue($this->value, $this->name, $this->type, $this->namespace, $this->type_namespace, $this->options, $this->attributes); } - - /** - * - * @param - * @param - * @param - * @param - * @return int - */ - function _multiArrayType(&$value, &$type, &$size, &$xml) - { - foreach ($value as $array_val) { - $array_types[$array_val->type] = 1; - #$xml .= $this->serializeval($array_val); - } +} - if ($array_val->type_prefix) { - $type = $array_val->type_prefix . ':' . $array_val->type; - } else { - $type = $array_val->type; - } - $sz = count($value); - $num_types = count($array_types); - if ($num_types == 1) { - if (array_key_exists('Array', $array_types)) { - // seems we have a multi dimensional array, figure it out if we do - foreach ($value as $array_val) { - $numtypes = $this->_multiArrayType($array_val->value, $type, $size, $xml); - if ($numtypes > 1) - return $numtypes; - } +/** + * SOAP::Header + * this class converts values between PHP and SOAP + * it is a simple wrapper around SOAP_Value, adding support for + * soap actor and mustunderstand parameters + * + * originaly based on SOAPx4 by Dietrich Ayala http://dietrich.ganx4.com/soapx4 + * + * @access public + * @version $Id: Value.php,v 1.29 2002/05/13 06:47:09 shane Exp $ + * @package SOAP::Header + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author + */ +class SOAP_Header extends SOAP_Value +{ - if ($sz) { - $size = $sz.','.$size; - } else { - $size = $sz; - } - return 1; - } else { - foreach ($value as $array_val) { - #$array_types[$array_val->type] = 1; - $xml .= $array_val->serialize(); - } - } - } - $size = $sz; - return $num_types; - } - /** - * Turn SOAP_Value's into xml, woohoo! - * - * @param mixed - * @return string xml representation - */ - function serializeval($soapval = false) - { - if (!$soapval) { - $soapval = $this; - } - - if (is_int($soapval->name)) { - $soapval->name = 'item'; - $soapval->prefix = ''; - } - - if ($soapval->prefix && $soapval->type_prefix) { - $xmlout_name = "$soapval->prefix:$soapval->name"; - $xmlout_type = "$soapval->type_prefix:$soapval->type"; - } else - if ($soapval->type_prefix) { - $xmlout_name = $soapval->name; - $xmlout_type = "$soapval->type_prefix:$soapval->type"; - } elseif ($soapval->prefix) { - $xmlout_name = "$soapval->prefix:$soapval->name"; - } else { - $xmlout_name = $soapval->name; - } - $xmlout_value = NULL; - $xmlout_offset = ''; + * Constructor + * + * @param string name of the soap-value <value_name> + * @param mixed soap header value + * @param string namespace + * @param int mustunderstand (zero or one) + * @param string actor + */ + function SOAP_Header($name = '', $type, $value = NULL, + $mustunderstand = 0, + $actor = 'http://schemas.xmlsoap.org/soap/actor/next') + { + parent::SOAP_Value($name, $type, $value); + $this->attributes['SOAP-ENV:actor'] = $actor; + $this->attributes['SOAP-ENV:mustUnderstand'] = (int)$mustunderstand; + } +} - switch ($soapval->type_code) { - case SOAP_VALUE_STRUCT: - // struct - if (is_array($soapval->value)) { - foreach ($soapval->value as $k => $v) { - $xmlout_value .= $v->serialize($v); - } - } - break; - - case SOAP_VALUE_ARRAY: - // array - $xmlout_type = 'SOAP-ENC:Array'; - // XXX this will be slow on larger array's. Basicly, it flattens array's to allow us - // to serialize multi-dimensional array's. We only do this if arrayType is set, - // which will typicaly only happen if we are using WSDL - if ($this->flattenArray || ($this->arrayType && strchr($this->arrayType,','))) { - $numtypes = $this->_multiArrayType($soapval->value, $array_type, $ar_size, $xmlout_value); - } - #$numtypes = 0; - $array_type_prefix = ''; - if ($numtypes != 1) { - foreach ($soapval->value as $array_val) { - $array_types[$array_val->type] = 1; - $xmlout_value .= $array_val->serialize(); - } +/** + * SOAP::Attachment + * this class converts values between PHP and SOAP + * it handles Mime attachements per W3C Note on Soap Attachements at + * http://www.w3.org/TR/SOAP-attachments + * + * + * @access public + * @package SOAP::Attachment + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates + */ +class SOAP_Attachment extends SOAP_Value +{ - $ar_size = count($soapval->value); - $numtypes = count($array_types); - if ($this->arrayType) { - $ch = strpos($this->arrayType, '['); - if ($ch) { - $array_type = substr($this->arrayType,0,$ch); - } else { - $array_type = $this->arrayType; - } - } else { - $array_type = $array_val->type; - } - if ($array_type == 'Struct') { - $array_type = 'anyType'; // should reference what schema we're using - $array_val->type_prefix = 'xsd'; - } - $array_type_prefix = $array_val->type_prefix; - $xmlout_offset = " SOAP-ENC:offset=\"[0]\""; - } - if ($numtypes > 1) { - $array_type = 'xsd:anyType'; // should reference what schema we're using - } 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; - } - } - $xmlout_arrayType = " SOAP-ENC:arrayType=\"".$array_type."[$ar_size]\""; - break; - - case SOAP_VALUE_SCALAR: - $xmlout_value = $soapval->value; - break; - default: - break; - } - - if ($xmlout_type) $xmlout_type = " xsi:type=\"$xmlout_type\""; - if (is_null($xmlout_value)) { - $xml = "\r\n<{$xmlout_name}{$xmlout_type}/>"; - } else { - $xml = "\r\n<{$xmlout_name}{$xmlout_type}{$xmlout_arrayType}{$xmlout_offset}". - $this->xmlout_extra.">". - $xmlout_value."</$xmlout_name>"; - } - return $xml; - } - /** - * Serialize - * - * @return string xml representation - */ - function serialize() + * Constructor + * + * @param string name of the soap-value <value_name> + * @param mixed soap header value + * @param string namespace + */ + function SOAP_Attachment($name = '', $type = 'application/octet-stream', + $filename, $file=NULL) { - global $SOAP_namespaces; - - if ($this->namespace) { - if (!isset($SOAP_namespaces[$this->namespace])) { - $SOAP_namespaces[$this->namespace] = 'ns' . (count($SOAP_namespaces) + 1); - } - - $this->prefix = $SOAP_namespaces[$this->namespace]; + global $SOAP_options; + if (!isset($SOAP_options['Mime'])) { + return PEAR::raiseError('Mail_mime is not installed, unable to support SOAP Attachements'); } - // get type prefix - if (strpos($this->type , ':') !== false) { - $qname = new QName($type); - $this->type = $qname->name; - $this->type_prefix = $qname->ns; - - } elseif ($this->type_namespace) { - - if (!isset($SOAP_namespaces[$this->type_namespace])) { - $SOAP_namespaces[$this->type_namespace] = 'ns'.(count($SOAP_namespaces)+1); - } - $this->type_prefix = $SOAP_namespaces[$this->type_namespace]; - - // if type namespace was not explicitly passed, and we're not in a method struct: - } elseif (!$this->type_prefix && $this->type != 'Struct' /*!isset($type_namespace)*/) { + parent::SOAP_Value($name, NULL, NULL); - // try to get type prefix from typeMap - if ($ns = $this->verifyType($this->type)) { - $this->type_prefix = $SOAP_namespaces[$ns]; - } else if ($this->namespace) { - // else default to method namespace - $this->type_prefix = $SOAP_namespaces[$this->namespace]; - } + $filedata = ($file === NULL) ? $this->_file2str($filename) : $file; + $filename = basename($filename); + if (PEAR::isError($filedata)) { + return $filedata; } - return $this->serializeval($this); - } - - /** - * - * @param mixed - * @global $SOAP_typemap - */ - function decode($soapval = false) - { - global $SOAP_typemap; - if (!$soapval) { - $soapval = $this; - } + $cid = md5(uniqid(time())); - // scalar decode - if ($soapval->type_code == SOAP_VALUE_SCALAR) { - if ($soapval->type == 'boolean') { - if ($soapval->value != '0' && strcasecmp($soapval->value,'false') !=0) { - $soapval->value = TRUE; - } else { - $soapval->value = FALSE; - } - #} else if ($soapval->type == 'dateTime') { - # # we don't realy know what a user want's in return, - # # but we'll just do unix time stamps for now - # # THOUGHT: we could return a class instead. - # $dt = new SOAP_Type_dateTime($soapval->value); - # $soapval->value = $dt->toUnixtime(); - } else if (array_key_exists($soapval->type, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION])) { - # if we can, lets set php's variable type - settype($soapval->value, $SOAP_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); - } - if (!is_null($soapval->value)) - return $this->un_htmlentities($soapval->value); - return NULL; - // array decode - } elseif ($soapval->type_code == SOAP_VALUE_ARRAY) { - if (is_array($soapval->value)) { - foreach ($soapval->value as $item) { - $return[] = $this->decode($item); - } - return $return; - } - return $soapval->value; - // struct decode - } elseif ($soapval->type_code == SOAP_VALUE_STRUCT) { - if (is_array($soapval->value)) { - $counter = 1; - foreach ($soapval->value as $item) { - if (isset($return[$item->name])) { - // this is realy an array, we need to redirect - $soapval->type_code = SOAP_VALUE_ARRAY; - return $soapval->decode(); - } else { - $return[$item->name] = $this->decode($item); - } - } - return $return; - } - return $soapval->value; - } - # couldn't decode, return a fault! - return $this->raiseSoapFault("couldn't decode response, invalid type_code"); - } - - /** - * pass it a type, and it attempts to return a namespace uri - * - * @param - * @global $SOAP_typemap, $SOAP_namespaces - */ - function verifyType($type) - { - global $SOAP_typemap; - foreach ($SOAP_typemap as $uri => $types) { - if (array_key_exists($type,$types)) return $uri; - } - return FALSE; - } - - /** - * alias for verifyType() - pass it a type, and it returns it's prefix - * - * @brother varityType() - */ - function getPrefix($type) - { - global $SOAP_namespaces; - if ($uri = $this->verifyType($type)) { - return $SOAP_namespaces[$uri]; - } - return NULL; - } - - - /** - * SOAP::Value::_getSoapType - * - * convert php type to soap type - * @param string value - * @param string type - presumed php type - * - * @return string type - soap type - * @access private - */ - function _getSoapType(&$value, &$type, $name, $type_namespace='') { - - $doconvert = FALSE; - if ($this->wsdl) { - # see if it's a complex type so we can deal properly with SOAPENC:arrayType - if (!$type && $name) { - # XXX TODO: - # look up the name in the wsdl and validate the type - if ($this->type) { - foreach ($this->wsdl->complexTypes as $types) { - if (array_key_exists($this->type, $types) && - array_key_exists($name, $types[$this->type]['elements'])) { - $type = $types[$this->type]['elements']['type']; - return $type; - } - } - } - } else if ($type && $type_namespace) { - # XXX TODO: - # this code currently handles only one way of encoding array types in wsdl - # need to do a generalized function to figure out complex types - $p = $this->wsdl->ns[$type_namespace]; - if ($p && - array_key_exists($p, $this->wsdl->complexTypes) && - array_key_exists($type, $this->wsdl->complexTypes[$p])) { - if ($this->arrayType = $this->wsdl->complexTypes[$p][$type]['arrayType']) { - $type = 'Array'; - } else if ($this->wsdl->complexTypes[$p][$type]['order']=='sequence' && - array_key_exists('elements', $this->wsdl->complexTypes[$p][$type])) { - reset($this->wsdl->complexTypes[$p][$type]['elements']); - # assume an array - if (count($this->wsdl->complexTypes[$p][$type]['elements']) == 1) { - $arg = current($this->wsdl->complexTypes[$p][$type]['elements']); - $this->arrayType = $arg['type']; - $type = 'Array'; - } else { - foreach($this->wsdl->complexTypes[$p][$type]['elements'] as $element) { - if ($element['name'] == $type) { - $this->arrayType = $element['type']; - $type = $element['type']; - } - } - } - } - return $type; - } - } - } - if (!$type || !$this->verifyType($type)) { - if (is_object($value)) { - # allows for creating special classes to handle soap types - $type = get_class($value); - # this may return a different type that we process below - $value = $value->toSOAP(); - } elseif ($this->isArray($value)) { - $type = $this->isHash($value)?'Struct':'Array'; - } elseif ($this->isInt($value)) { - $type = 'int'; - } elseif ($this->isFloat($value)) { - $type = 'float'; - } elseif (SOAP_Type_hexBinary::is_hexbin($value)) { - $type = 'hexBinary'; - } elseif ($this->isBase64($value)) { - $type = 'base64Binary'; - } elseif ($this->isBoolean($value)) { - $type = 'boolean'; - } else { - $type = gettype($value); - # php defaults a lot of stuff to string, if we have no - # idea what the type realy is, we have to try to figure it out - # this is the best we can do if the user did not use the SOAP_Value class - if ($type == 'string') $doconvert = TRUE; - elseif ($type == 'NULL') $type = ''; - } - } - # we have the type, handle any value munging we need - if ($doconvert) { - $dt = new SOAP_Type_dateTime($value); - if ($dt->toUnixtime() != -1) { - $type = 'dateTime'; - $value = $dt->toSOAP(); - } - } else - if ($type == 'dateTime') { - # encode a dateTime to ISOE - $dt = new SOAP_Type_dateTime($value); - $value = $dt->toSOAP(); - } else - // php type name mangle - if ($type == 'integer') { - $type = 'int'; - } else - if ($type == 'boolean') { - if (($value != 0 && $value != '0') || strcasecmp($value, 'true') == 0) - $value = 'true'; - else - $value = 'false'; - } - return $type; - } - - // support functions - /** - * - * @param string - * @return string - */ - function isBase64(&$value) - { - return $value[strlen($value)-1]=='=' && preg_match("/[A-Za-z=\/\+]+/",$value); - } - - /** - * - * @param mixed - * @return boolean - */ - function isBoolean(&$value) - { - return gettype($value) == 'boolean' || strcasecmp($value, 'true')==0 || strcasecmp($value, 'false') == 0; - } - - /** - * - * @param mixed - * @return boolean - */ - function isFloat(&$value) - { - return gettype($value) == FLOAT || - $value === 'NaN' || $value === 'INF' || $value === '-INF' || - (is_numeric($value) && strstr($value, '.')); - } - - /** - * - * @param mixed - * @return boolean - */ - function isInt(&$value) - { - return gettype($value) == 'integer' || (is_numeric($value) && !strstr($value,'.')); - } - - /** - * - * @param array - * @return boolean - */ - function isArray(&$value) - { - return is_array($value); # && count($value) >= 1; + $this->attributes['href'] = 'cid:'.$cid; + + $this->options['attachment'] = array( + 'body' => $filedata, + 'disposition' => $filename, + 'content_type' => $type, + 'encoding' => 'base64', + 'cid' => $cid + ); } - /** - * - * @param mixed - * @return boolean + /* + * Returns the contents of the given file name as string + * @param string $file_name + * @return string + * @acces private */ - function isDateTime(&$value) + function & _file2str($file_name) { - $dt = new SOAP_Type_dateTime($value); - return $dt->toUnixtime() != -1; - } - - /** - * - * @param mixed - * @return boolean - */ - function isHash(&$a) { - # XXX I realy dislike having to loop through this in php code, - # realy large arrays will be slow. We need a C function to do this. - $names = array(); - foreach ($a as $k => $v) { - # checking the type is faster than regexp. - if (gettype($k) != 'integer') { - return TRUE; - } else if (gettype($v) == 'object' && get_class($v) == 'soap_value') { - $names[$v->name] = 1; - } + if (!is_readable($file_name)) { + return PEAR::raiseError('File is not readable ' . $file_name); } - return count($names)>1; - } - - function un_htmlentities($string) - { - $trans_tbl = get_html_translation_table (HTML_ENTITIES); - $trans_tbl = array_flip($trans_tbl); - return strtr($string, $trans_tbl); + if (!$fd = fopen($file_name, 'rb')) { + return PEAR::raiseError('Could not open ' . $file_name); + } + $cont = fread($fd, filesize($file_name)); + fclose($fd); + return $cont; } } - -?> +?> \ No newline at end of file Index: pear/SOAP/WSDL.php diff -u pear/SOAP/WSDL.php:1.19 pear/SOAP/WSDL.php:1.20 --- pear/SOAP/WSDL.php:1.19 Wed Apr 24 03:41:18 2002 +++ pear/SOAP/WSDL.php Mon May 13 02:47:09 2002 @@ -17,11 +17,10 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: WSDL.php,v 1.19 2002/04/24 07:41:18 shane Exp $ +// $Id: WSDL.php,v 1.20 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; -require_once 'SOAP/globals.php'; DEFINE("WSDL_CACHE_MAX_AGE",12*60*60); DEFINE("WSDL_CACHE_USE",0); // set to zero to turn off caching @@ -38,7 +37,7 @@ * implement IDL type syntax declaration so we can generate WSDL * * @access public -* @version $Id: WSDL.php,v 1.19 2002/04/24 07:41:18 shane Exp $ +* @version $Id: WSDL.php,v 1.20 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Client * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author @@ -374,8 +373,6 @@ // start-element handler function startElement($parser, $name, $attrs) { - global $SOAP_XMLSchema; - // get element prefix $qname = new QName($name); if ($qname->ns) { @@ -476,7 +473,7 @@ $vq = new QName($v); $this->wsdl->complexTypes[$this->schema][$this->currentElement][$q->name] = $vq->name; if ($q->name == 'arrayType') { - $this->wsdl->complexTypes[$this->schema][$this->currentElement]['type'] = $vq->name; + $this->wsdl->complexTypes[$this->schema][$this->currentElement]['type'] = $v; $this->wsdl->complexTypes[$this->schema][$this->currentElement]['namespace'] = $vq->ns; } } @@ -609,7 +606,7 @@ strcasecmp($value,SOAP_SCHEMA)==0) { $this->soapns[] = strtolower($qn->name); } else - if (in_array($value, $SOAP_XMLSchema)) { + if (in_array($value, $this->_XMLSchema)) { $this->wsdl->xsd = $value; } } Index: pear/SOAP/package.xml diff -u pear/SOAP/package.xml:1.11 pear/SOAP/package.xml:1.12 --- pear/SOAP/package.xml:1.11 Sat Apr 27 13:53:18 2002 +++ pear/SOAP/package.xml Mon May 13 02:47:09 2002 @@ -19,7 +19,7 @@ <license>PHP License</license> <release> <state>devel</state> - <version>0.6</version> + <version>0.6.1</version> <date>2002-02-18</date> <notes> This is the initial independent PEAR release. @@ -29,9 +29,6 @@ <file role="php" name="Base.php"/> <file role="php" name="Client.php"/> <file role="php" name="Fault.php"/> - <file role="php" name="globals.php"/> - <file role="php" name="Header.php"/> - <file role="php" name="Message.php"/> <file role="php" name="Parser.php"/> <file role="php" name="Server.php"/> <file role="php" name="Transport.php"/> @@ -94,6 +91,8 @@ <dep type="php" rel="ge" version="4.1"/> <dep type="ext" rel="has">bcmath</dep> <dep type="ext" rel="has">pcre</dep> + <dep type="pkg" rel="has">Mime</dep> + <dep type="pkg" rel="ge" version="0.1">Net_DIME</dep> </deps> </release> </package> Index: pear/SOAP/Server/Email.php diff -u pear/SOAP/Server/Email.php:1.1 pear/SOAP/Server/Email.php:1.2 --- pear/SOAP/Server/Email.php:1.1 Wed Apr 24 03:41:25 2002 +++ pear/SOAP/Server/Email.php Mon May 13 02:47:09 2002 @@ -16,12 +16,12 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: Email.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +// $Id: Email.php,v 1.2 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Server.php'; require_once 'SOAP/Transport.php'; - +require_once 'Mail/mimeDecode.php'; /** * SOAP_Server_Email * SOAP Server Class @@ -36,7 +36,7 @@ * function call * * @access public -* @version $Id: Email.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +* @version $Id: Email.php,v 1.2 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Server * @author Shane Caraveo <shane@php.net> */ @@ -49,57 +49,23 @@ $this->send_response = $send_response; } - /** - * remove http headers from response - * - * TODO: use PEAR email classes - * - * @return boolean - * @access private - */ - function _parseEmail(&$data) - { - if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $data, $match)) { - - if (preg_match_all('/^(.*?):\s+(.*)$/m', $match[1], $matches)) { - $hc = count($matches[0]); - for ($i = 0; $i < $hc; $i++) { - $this->headers[strtolower($matches[1][$i])] = trim($matches[2][$i]); - } - } - - if (!stristr($this->headers['content-type'],'text/xml')) { - $this->makeFault('Client','Invalid Content Type'); - return FALSE; - } - - if (strcasecmp($this->headers['content-transfer-encoding'],'base64')==0) { - // join lines back together - $enctext = preg_replace("/[\r|\n]/", '', $match[2]); - $this->request = base64_decode($enctext); - } else if (strcasecmp($this->headers['content-transfer-encoding'],'quoted-printable')==0) { - $this->request = $match[2]; - } else { - $this->makeFault('Client','Invalid Content-Transfer-Encoding'); - return FALSE; - } - - // if no content, return false - return strlen($this->request) > 0; - } - $this->makeFault('Client','Invalid Email Format'); - return FALSE; - } - - function service(&$data, $endpoint = '', $send_response = TRUE, $dump = FALSE) { $this->endpoint = $endpoint; - - // we have a full set of headers, need to find the first blank line - if (!$this->_parseEmail($data)) { - $response = $this->getFaultMessage(); + $attachments = array(); + $headers = array(); + + # if neither matches, we'll just try it anyway + if (stristr($data,'Content-Type: application/dime')==0) { + $this->decodeDIMEMessage($data,$this->headers,$attachments); + $useEncoding = 'DIME'; + } else if (stristr($data,'Content-Type: multipart/related')) { + // this is a mime message, lets decode it. + $data = 'Content-Type: '.stripslashes($_SERVER['CONTENT_TYPE'])."\r\n\r\n".$data; + $this->decodeMimeMessage($data,$this->headers,$attachments); + $useEncoding = 'Mime'; } + // get the character encoding of the incoming request // treat incoming data as UTF-8 if no encoding set if (!$response && !$this->_getContentEncoding($this->headers['content-type'])) { @@ -109,8 +75,34 @@ $response = $this->getFaultMessage(); } - if (!$response) - $response = $this->parseRequest($this->request); + if (!$this->soapfault) { + $soap_msg = $this->parseRequest($data,$attachments); + + // handle Mime or DIME encoding + // XXX DIME Encoding should move to the transport, do it here for now + // and for ease of getting it done + if (count($this->attachments)) { + if ($useEncoding == 'Mime') { + $soap_msg = $this->_makeMimeMessage($soap_msg); + } else { + // default is dime + $soap_msg = $this->_makeDIMEMessage($soap_msg); + $header['Content-Type'] = 'application/dime'; + } + if (PEAR::isError($soap_msg)) { + return $this->raiseSoapFault($soap_msg); + } + } + + if (is_array($soap_msg)) { + $response = $soap_msg['body']; + if (count($soap_msg['headers'])) { + $headers = $soap_msg['headers']; + } + } else { + $response = $soap_msg; + } + } if ($this->send_response) { $payload = $response->serialize($this->response_encoding); @@ -123,7 +115,7 @@ $soap_transport = new SOAP_Transport('mailto:'.$from, $this->response_encoding); $from = $this->endpoint ? $this->endpoint : $this->headers['to']; - $headers = array('In-Reply-To'=>$this->headers['message-id']); + $headers['In-Reply-To']=$this->headers['message-id']; $options = array('from' => $from, 'subject'=> $this->headers['subject'], 'headers' => $headers); $soap_transport->send($payload, $options); } Index: pear/SOAP/Server/Email_Gateway.php diff -u pear/SOAP/Server/Email_Gateway.php:1.1 pear/SOAP/Server/Email_Gateway.php:1.2 --- pear/SOAP/Server/Email_Gateway.php:1.1 Wed Apr 24 03:41:25 2002 +++ pear/SOAP/Server/Email_Gateway.php Mon May 13 02:47:09 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: Email_Gateway.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +// $Id: Email_Gateway.php,v 1.2 2002/05/13 06:47:09 shane Exp $ // require_once 'SOAP/Server/Email.php'; @@ -40,11 +40,54 @@ * email * * @access public -* @version $Id: Email_Gateway.php,v 1.1 2002/04/24 07:41:25 shane Exp $ +* @version $Id: Email_Gateway.php,v 1.2 2002/05/13 06:47:09 shane Exp $ * @package SOAP::Server * @author Shane Caraveo <shane@php.net> */ class SOAP_Server_Email_Gateway extends SOAP_Server_Email { + /** + * remove http headers from response + * + * TODO: use PEAR email classes + * + * @return boolean + * @access private + */ + function _parseEmail(&$data) + { + if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $data, $match)) { + + if (preg_match_all('/^(.*?):\s+(.*)$/m', $match[1], $matches)) { + $hc = count($matches[0]); + for ($i = 0; $i < $hc; $i++) { + $this->headers[strtolower($matches[1][$i])] = trim($matches[2][$i]); + } + } + + if (!stristr($this->headers['content-type'],'text/xml')) { + $this->makeFault('Client','Invalid Content Type'); + return FALSE; + } + + if (strcasecmp($this->headers['content-transfer-encoding'],'base64')==0) { + // join lines back together + $enctext = preg_replace("/[\r|\n]/", '', $match[2]); + $this->request = base64_decode($enctext); + } else if (strcasecmp($this->headers['content-transfer-encoding'],'quoted-printable')==0) { + $this->request = $match[2]; + } else { + $this->makeFault('Client','Invalid Content-Transfer-Encoding'); + return FALSE; + } + + // if no content, return false + return strlen($this->request) > 0; + } + $this->makeFault('Client','Invalid Email Format'); + return FALSE; + } + + function service(&$data, $gateway, $endpoint = '', $send_response = TRUE, $dump = FALSE) { $this->endpoint = $endpoint; @@ -75,6 +118,7 @@ // send the message if (!$response) { $options['soapaction'] = $this->headers['soapaction']; + $options['headers']['Content-Type'] = $this->headers['content-type']; $response = $soap_transport->send($this->request, $options); if ($soap_transport->fault) { $fault = $soap_transport->fault->message(); Index: pear/SOAP/Transport/HTTP.php diff -u pear/SOAP/Transport/HTTP.php:1.16 pear/SOAP/Transport/HTTP.php:1.17 --- pear/SOAP/Transport/HTTP.php:1.16 Wed Apr 24 03:41:26 2002 +++ pear/SOAP/Transport/HTTP.php Mon May 13 02:47:10 2002 @@ -16,17 +16,16 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: HTTP.php,v 1.16 2002/04/24 07:41:26 shane Exp $ +// $Id: HTTP.php,v 1.17 2002/05/13 06:47:10 shane Exp $ // -require_once 'SOAP/globals.php'; require_once 'SOAP/Base.php'; - +require_once 'Net_DIME/DIME.php'; /** * HTTP Transport for SOAP * * @access public -* @version $Id: HTTP.php,v 1.16 2002/04/24 07:41:26 shane Exp $ +* @version $Id: HTTP.php,v 1.17 2002/05/13 06:47:10 shane Exp $ * @package SOAP::Transport::HTTP * @author Shane Caraveo <shane@php.net> */ @@ -38,7 +37,7 @@ * * @var string */ - var $credentials = ''; + var $headers = array(); /** * @@ -116,13 +115,13 @@ return $this->fault; } - if ($timeout) + if (isset($options['timeout'])) $this->timeout = (int)$options['timeout']; if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { - return $this->_sendHTTP($msg, $options['soapaction']); + return $this->_sendHTTP($msg, $options); } else if (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { - return $this->_sendHTTPS($msg, $options['soapaction']); + return $this->_sendHTTPS($msg, $options); } return $this->raiseSoapFault('Invalid url scheme '.$this->url); @@ -140,7 +139,7 @@ */ function setCredentials($username, $password) { - $this->credentials = 'Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; + $this->headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password); } // private members @@ -178,8 +177,6 @@ function _parseEncoding($headers) { - global $SOAP_Encodings; - $h = stristr($headers,'Content-Type'); preg_match('/^Content-Type:\s*(.*)$/im',$h,$ct); $this->result_content_type = str_replace("\r","",$ct[1]); @@ -188,7 +185,7 @@ $this->result_content_type = $m[1]; if (count($m) > 2) { $enc = strtoupper(str_replace('"',"",$m[2])); - if (in_array($enc, $SOAP_Encodings)) { + if (in_array($enc, $this->_encodings)) { $this->result_encoding = $enc; } } @@ -215,9 +212,16 @@ return FALSE; } $this->_parseEncoding($match[1]); - if ($this->result_content_type != 'text/xml') { - $this->raiseSoapFault($this->response); - return FALSE; + if ($this->result_content_type == 'application/dime') { + // XXX quick hack insertion of DIME + $this->decodeDIMEMessage($this->response,$this->headers,$this->attachments); + $this->result_content_type = $this->headers['content-type']; + } else if (stristr($this->result_content_type,'multipart/related')) { + $this->response = $this->incoming_payload; + $this->decodeMimeMessage($this->response,$this->headers,$this->attachments); + } else if ($this->result_content_type != 'text/xml') { + $this->raiseSoapFault($this->response); + return FALSE; } // if no content, return false return strlen($this->response) > 0; @@ -232,19 +236,27 @@ * @return string outgoing_payload * @access private */ - function &_getRequest(&$msg, $action) + function &_getRequest(&$msg, $options) { + $action = isset($options['soapaction'])?$options['soapaction']:''; $fullpath = $this->urlparts['path']. - ($this->urlparts['query']?'?'.$this->urlparts['query']:''). - ($this->urlparts['fragment']?'#'.$this->urlparts['fragment']:''); + (isset($this->urlparts['query'])?'?'.$this->urlparts['query']:''). + (isset($this->urlparts['fragment'])?'#'.$this->urlparts['fragment']:''); + $this->headers['User-Agent'] = $this->_userAgent; + $this->headers['Host'] = $this->urlparts['host']; + $this->headers['Content-Type'] = "text/xml; charset=$this->encoding"; + $this->headers['Content-Length'] = strlen($msg); + $this->headers['SOAPAction'] = "\"$action\""; + if (isset($options['headers'])) { + $this->headers = array_merge($this->headers, $options['headers']); + } + $headers = ''; + foreach ($this->headers as $k => $v) { + $headers .= "$k: $v\r\n"; + } $this->outgoing_payload = "POST $fullpath HTTP/1.0\r\n". - "User-Agent: {$this->_userAgent}\r\n". - "Host: {$this->urlparts['host']}\r\n". - $this->credentials. - "Content-Type: text/xml; charset=$this->encoding\r\n". - "Content-Length: ".strlen($msg)."\r\n". - "SOAPAction: \"$action\"\r\n\r\n". + $headers."\r\n". $msg; return $this->outgoing_payload; } @@ -258,9 +270,9 @@ * @return string &$response response data, minus http headers * @access private */ - function &_sendHTTP(&$msg, $action = '') + function &_sendHTTP(&$msg, $options) { - $this->_getRequest($msg, $action); + $this->_getRequest($msg, $options); // send if ($this->timeout > 0) { @@ -298,7 +310,7 @@ * @return string &$response response data, minus http headers * @access private */ - function &_sendHTTPS(&$msg, $action) + function &_sendHTTPS(&$msg, $options) { /* NOTE This function uses the CURL functions * Your php must be compiled with CURL @@ -307,7 +319,7 @@ return $this->raiseSoapFault('CURL Extension is required for HTTPS'); } - $this->_getRequest($msg, $action); + $this->_getRequest($msg, $options); $ch = curl_init(); if ($this->timeout) { Index: pear/SOAP/Transport/SMTP.php diff -u pear/SOAP/Transport/SMTP.php:1.8 pear/SOAP/Transport/SMTP.php:1.9 --- pear/SOAP/Transport/SMTP.php:1.8 Wed Apr 24 03:41:26 2002 +++ pear/SOAP/Transport/SMTP.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: SMTP.php,v 1.8 2002/04/24 07:41:26 shane Exp $ +// $Id: SMTP.php,v 1.9 2002/05/13 06:47:10 shane Exp $ // // Status: rough draft, untested // @@ -27,7 +27,6 @@ // ability to define smtp options (encoding, from, etc.) // -require_once 'SOAP/globals.php'; require_once 'SOAP/Message.php'; require_once 'SOAP/Base.php'; @@ -40,7 +39,7 @@ * TODO: use PEAR smtp and Mime classes * * @access public -* @version $Id: SMTP.php,v 1.8 2002/04/24 07:41:26 shane Exp $ +* @version $Id: SMTP.php,v 1.9 2002/05/13 06:47:10 shane Exp $ * @package SOAP::Transport::SMTP * @author Shane Caraveo <shane@php.net> */ @@ -88,50 +87,57 @@ if (!$options || !array_key_exists('from',$options)) { return $this->raiseSoapFault("No FROM address to send message with"); } - $headers = "From: {$options['from']}\n". - "X-Mailer: $this->_userAgent\n". - "MIME-Version: 1.0\n". - "Content-Disposition: inline\n". - "Content-Type: text/xml; charset=\"$this->encoding\"\n"; - - if (array_key_exists('transfer-encoding', $options)) { - if (strcasecmp($options['transfer-encoding'],'quoted-printable')==0) { - $headers .="Content-Transfer-Encoding: {$options['transfer-encoding']}\n"; - $out = &$msg; - } else if (strcasecmp($options['transfer-encoding'],'base64')==0) { + + $headers = array(); + $headers['From'] = $options['from']; + $headers['X-Mailer'] = $this->_userAgent; + $headers['MIME-Version'] = '1.0'; + if (array_key_exists('soapaction', $options)) { + $headers['Soapaction'] = "\"{$options['soapaction']}\""; + } + + if (isset($options['headers'])) + $headers = array_merge($headers, $options['headers']); + + // if the content type is already set, we assume that Mime encoding + // is already done + if (!isset($headers['Content-Type'])) { + // do an inline Mime encoding + $headers['Content-Disposition'] = 'inline'; + $headers['Content-Type'] = "text/xml; charset=\"$this->encoding\""; + if (array_key_exists('transfer-encoding', $options)) { + if (strcasecmp($options['transfer-encoding'],'quoted-printable')==0) { + $headers .="Content-Transfer-Encoding: {$options['transfer-encoding']}\n"; + $out = &$msg; + } else if (strcasecmp($options['transfer-encoding'],'base64')==0) { + $headers .="Content-Transfer-Encoding: base64\n"; + $out = chunk_split(base64_encode($msg)); + } else { + return $this->raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); + } + } else { + // default to base64 $headers .="Content-Transfer-Encoding: base64\n"; $out = chunk_split(base64_encode($msg)); - } else { - return $this->raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); } - } else { - // default to base64 - $headers .="Content-Transfer-Encoding: base64\n"; - $out = chunk_split(base64_encode($msg)); - } - - if (array_key_exists('soapaction', $options)) { - "Soapaction: \"{$options['soapaction']}\"\n"; } - if (array_key_exists('headers', $options)) { - foreach ($options['headers'] as $key => $value) { - $headers .= "$key: $value\n"; - } + foreach ($headers as $key => $value) { + $header_text .= "$key: $value\n"; } $subject = array_key_exists('subject', $options) ? $options['subject'] : 'SOAP Message'; - $this->outgoing_payload = $headers."\n\n".$this->outgoing_payload; + $this->outgoing_payload = $header_text."\n\n".$this->outgoing_payload; # we want to return a proper XML message - $result = mail($this->urlparts['path'], $subject, $out, $headers); + $result = mail($this->urlparts['path'], $subject, $out, $header_text); if ($result) { $val = new SOAP_Value('return','boolean',TRUE); } else { $val = new SOAP_Value('Fault','Struct',array( - new SOAP_Value('faultcode','string','SOAP-ENV:Transport:SMTP'), - new SOAP_Value('faultstring','string',"couldn't send message to $action") + new SOAP_Value('faultcode','QName','SOAP-ENV:Client'), + new SOAP_Value('faultstring','string',"couldn't send SMTP message to $action") )); } @@ -185,4 +191,4 @@ } } // end SOAP_Transport_HTTP -?> +?> \ No newline at end of file Index: pear/SOAP/interop/client_round2_interop.php diff -u pear/SOAP/interop/client_round2_interop.php:1.10 pear/SOAP/interop/client_round2_interop.php:1.11 --- pear/SOAP/interop/client_round2_interop.php:1.10 Wed Apr 24 03:41:27 2002 +++ pear/SOAP/interop/client_round2_interop.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_interop.php,v 1.10 2002/04/24 07:41:27 shane Exp $ +// $Id: client_round2_interop.php,v 1.11 2002/05/13 06:47:10 shane Exp $ // require_once 'DB.php'; // PEAR/DB require_once 'SOAP/Client.php'; @@ -25,7 +25,7 @@ error_reporting(E_ALL ^ E_NOTICE); -class Interop_Client +class Interop_Client extends SOAP_Base { // database DNS var $DSN = 'mysql://user@localhost/interop'; @@ -90,6 +90,7 @@ // retreive endpoints from the endpoint server $endpointArray = $soapclient->call("GetEndpointInfo",array("groupName"=>$test),"http://soapinterop.org/info/","http://soapinterop.org/info/"); if (PEAR::isError($endpointArray)) { + print $soapclient->wire; print_r($endpointArray); return; } @@ -250,12 +251,13 @@ foreach ($soap_test->headers as $h) { $destination = 0; if (get_class($h) == 'soap_header') { - if ($h->actor == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; - $test_name .= ":{$h->name},$destination,{$h->mustunderstand}"; + if ($h->attributes['SOAP-ENV:actor'] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; + $test_name .= ":{$h->name},$destination,{$h->attributes['SOAP-ENV:mustUnderstand']}"; } else { - if (!$h[4] || $h[4] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; - if (!$h[3]) $h[3] = 0; - $test_name .= ":$h[0],$destination,".(int)$h[3]; + if (!$h[3] || $h[3] == 'http://schemas.xmlsoap.org/soap/actor/next') $destination = 1; + if (!$h[2]) $h[2] = 0; + $qn = new QName($h[0]); + $test_name .= ":{$qn->name},$destination,".(int)$h[2]; } } } @@ -300,7 +302,7 @@ if (gettype($soapval) == "object" && (strcasecmp(get_class($soapval),"SOAP_Value") == 0 || strcasecmp(get_class($soapval),"SOAP_Header") == 0)) { - $val = $soapval->decode(); + $val = $this->decode($soapval); } else { $val = $soapval; } @@ -433,7 +435,9 @@ $expect = $soap_test->headers_expect[$header->name]; $header_result[$header->name] = array(); // XXX need to fix need_result to identify the actor correctly - $need_result = $hresult || ($header->actor == 'http://schemas.xmlsoap.org/soap/actor/next' && $header->mustunderstand); + $need_result = $hresult || + ($header->attributes['SOAP-ENV:actor'] == 'http://schemas.xmlsoap.org/soap/actor/next' + && $header->attributes['SOAP-ENV:mustUnderstand']); if ($expect) { $hresult = $soap->headers[key($expect)]; $ok = !$need_result || $this->compareResult($hresult ,$expect[key($expect)]); @@ -555,8 +559,8 @@ foreach ($soap_test->headers as $header) { if (get_class($header) == 'soap_header') { if ($header->name == $m[2]) { - $gotit = $header->actor == ($m[3]?SOAP_TEST_ACTOR_NEXT:SOAP_TEST_ACTOR_OTHER); - $gotit = $gotit && $header->mustunderstand == $m[4]; + $gotit = $header->attributes['SOAP-ENV:actor'] == ($m[3]?SOAP_TEST_ACTOR_NEXT:SOAP_TEST_ACTOR_OTHER); + $gotit = $gotit && $header->attributes['SOAP-ENV:mustUnderstand'] == $m[4]; } } else { if ($header[0] == $m[2]) { Index: pear/SOAP/interop/client_round2_params.php diff -u pear/SOAP/interop/client_round2_params.php:1.6 pear/SOAP/interop/client_round2_params.php:1.7 --- pear/SOAP/interop/client_round2_params.php:1.6 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/client_round2_params.php Mon May 13 02:47:10 2002 @@ -16,9 +16,8 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_params.php,v 1.6 2002/04/17 07:42:53 shane Exp $ +// $Id: client_round2_params.php,v 1.7 2002/05/13 06:47:10 shane Exp $ // -require_once 'SOAP/Header.php'; require_once 'SOAP/Value.php'; define('SOAP_TEST_ACTOR_NEXT','http://schemas.xmlsoap.org/soap/actor/next'); @@ -85,7 +84,8 @@ if ($this->headers) { foreach ($this->headers as $h) { if (get_class($h) == 'soap_header') { - echo "\n {$h->name},{$h->actor},{$h->mustunderstand} : "; + + echo "\n {$h->name},{$h->attributes['SOAP-ENV:actor']},{$h->attributes['SOAP-ENV:mustUnderstand']} : "; } else { if (!$h[4]) $h[4] = SOAP_TEST_ACTOR_NEXT; if (!$h[3]) $h[3] = 0; @@ -199,9 +199,9 @@ array('inputFloatArray' => new SOAP_Value('inputFloatArray','Array', array( #push struct elements into one soap value - new SOAP_Value('nan','float',1.3223), - new SOAP_Value('inf','float',34.2), - new SOAP_Value('neginf','float',325.325) + new SOAP_Value('item','float',1.3223), + new SOAP_Value('item','float',34.2), + new SOAP_Value('item','float',325.325) ) ))); @@ -213,13 +213,12 @@ 'varInt'=>34, 'varFloat'=>325.325))); $soap_tests['base'][] = new SOAP_Test('echoStruct', array('inputStruct' => - new SOAP_Value('inputStruct','Struct', + new SOAP_Value('inputStruct','{http://soapinterop.org/xsd}SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ) - ))); + )))); //*********************************************************** // Base echoStructArray @@ -232,17 +231,17 @@ $soap_tests['base'][] = new SOAP_Test('echoStructArray', array('inputStructArray' => new SOAP_Value('inputStructArray','Array', array( #push struct elements into one soap value - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) )), - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) )), - new SOAP_Value('item','SOAPStruct',array( + new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct',array( new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) @@ -253,8 +252,8 @@ //*********************************************************** // Base echoVoid -$soap_tests['base'][] = new SOAP_Test('echoVoid', ''); -$test = new SOAP_Test('echoVoid', ''); +$soap_tests['base'][] = new SOAP_Test('echoVoid', NULL); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; $soap_tests['base'][] = $test; @@ -273,14 +272,14 @@ //*********************************************************** // Base echoDecimal -$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => '1234567890')); -$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => new SOAP_Value('inputDecimal','decimal','1234567890'))); +$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => 12345.67890)); +$soap_tests['base'][] = new SOAP_Test('echoDecimal', array('inputDecimal' => new SOAP_Value('inputDecimal','decimal',12345.67890))); //*********************************************************** // Base echoDate -$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => '2001-04-25T13:31:41-0700')); -$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => new SOAP_Value('inputDate','dateTime','2001-04-25T13:31:41-0700'))); +$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => '2001-05-24T17:31:41Z')); +$soap_tests['base'][] = new SOAP_Test('echoDate', array('inputDate' => new SOAP_Value('inputDate','dateTime','2001-05-24T17:31:41Z')));#'2001-04-25T13:31:41-0700' //*********************************************************** // Base echoBoolean @@ -310,13 +309,12 @@ )), $expect); $soap_tests['GroupB'][] = new SOAP_Test('echoStructAsSimpleTypes', array('inputStruct' => - new SOAP_Value('inputStruct','struct', + new SOAP_Value('inputStruct','SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ) - )), $expect); + ))), $expect); //*********************************************************** // GroupB echoSimpleTypesAsStruct @@ -361,7 +359,7 @@ ) ) ); -$multidimarray->flattenArray = TRUE; +$multidimarray->options['flatten'] = TRUE; $soap_tests['GroupB'][] = new SOAP_Test('echo2DStringArray', array('input2DStringArray' => $multidimarray)); @@ -380,7 +378,7 @@ ) ))); $soap_tests['GroupB'][] = new SOAP_Test('echoNestedStruct', - array('input2DStringArray' => + array('inputStruct' => new SOAP_Value('inputStruct','struct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), @@ -392,7 +390,7 @@ new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) ) - ) + /*,NULL,'http://soapinterop.org/xsd'*/) ) ))); @@ -407,7 +405,7 @@ 'varArray' => array('red','blue','green') ))); $soap_tests['GroupB'][] = new SOAP_Test('echoNestedArray', - array('input2DStringArray' => + array('inputStruct' => new SOAP_Value('inputStruct','struct', array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), @@ -431,27 +429,27 @@ // echoMeStringRequest php val tests // echoMeStringRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 1,SOAP_TEST_ACTOR_NEXT); $this->type = 'soapval'; // force a soapval version of this test $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStringRequest', 'hello world', 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'hello world', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; @@ -459,39 +457,39 @@ // echoMeStringRequest soapval tests // echoMeStringRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/'); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world'); $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 1); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1); $this->type = 'soapval'; // force a soapval version of this test $test->headers_expect['echoMeStringRequest'] = array('echoMeStringResponse'=>'hello world'); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStringRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStringRequest with endpoint header destination, must understand, // invalid namespace, should recieve a fault -#$test = new SOAP_Test('echoVoid', ''); +#$test = new SOAP_Test('echoVoid', NULL); #$test->type = 'soapval'; -#$test->headers[] = new SOAP_Header('echoMeStringRequest', 'string', 'hello world', 'http://unknown.org/', 1); +#$test->headers[] = new SOAP_Header('{http://unknown.org/echoheader/}echoMeStringRequest', 'string', 'hello world', 1); #$test->headers_expect['echoMeStringRequest'] = array(); #$test->expect_fault = TRUE; #$soap_tests['GroupC'][] = $test; @@ -499,158 +497,146 @@ //*********************************************************** // php val tests // echoMeStructRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); + 0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); + 1,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); + 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeStructRequest', +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeStructRequest', array('varString'=>'arg', 'varInt'=>34, 'varFloat'=>325.325), - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); + 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // soapval tests // echoMeStructRequest with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/'); + )); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 1); + ), 1); $test->headers_expect['echoMeStructRequest'] = array('echoMeStructResponse'=> array('varString'=>'arg','varInt'=>34,'varFloat'=>325.325)); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); + ), 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; // echoMeStructRequest with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeStructRequest',NULL, +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeStructRequest',NULL, array( #push struct elements into one soap value new SOAP_Value('varString','string','arg'), new SOAP_Value('varInt','int',34), new SOAP_Value('varFloat','float',325.325) - ), - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); + ), 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeStructRequest'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // echoMeUnknown php val tests // echoMeUnknown with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/',0,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',0,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 1,SOAP_TEST_ACTOR_NEXT); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',1,SOAP_TEST_ACTOR_NEXT); $test->headers_expect['echoMeUnknown'] = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!',0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); -$test->headers[] = array('echoMeUnknown', 'nobody understands me!', - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test = new SOAP_Test('echoVoid', NULL); +$test->headers[] = array('{http://soapinterop.org/echoheader/}echoMeUnknown', 'nobody understands me!', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; //*********************************************************** // echoMeUnknown soapval tests // echoMeUnknown with endpoint as header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/'); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!'); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint as header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 1); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!',1); $test->headers_expect['echoMeUnknown'] = array(); $test->expect_fault = TRUE; $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, doesn't have to understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 0, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!', 0, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; // echoMeUnknown with endpoint NOT header destination, must understand -$test = new SOAP_Test('echoVoid', ''); +$test = new SOAP_Test('echoVoid', NULL); $test->type = 'soapval'; -$test->headers[] = new SOAP_Header('echoMeUnknown','string','nobody understands me!', - 'http://soapinterop.org/echoheader/', 1, SOAP_TEST_ACTOR_OTHER); +$test->headers[] = new SOAP_Header('{http://soapinterop.org/echoheader/}echoMeUnknown','string','nobody understands me!', 1, SOAP_TEST_ACTOR_OTHER); $test->headers_expect['echoMeUnknown'] = array(); $soap_tests['GroupC'][] = $test; Index: pear/SOAP/interop/client_round2_run.php diff -u pear/SOAP/interop/client_round2_run.php:1.1 pear/SOAP/interop/client_round2_run.php:1.2 --- pear/SOAP/interop/client_round2_run.php:1.1 Sat Apr 13 23:23:20 2002 +++ pear/SOAP/interop/client_round2_run.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: client_round2_run.php,v 1.1 2002/04/14 03:23:20 shane Exp $ +// $Id: client_round2_run.php,v 1.2 2002/05/13 06:47:10 shane Exp $ // set_time_limit(0); require_once 'SOAP/interop/client_round2_interop.php'; @@ -37,7 +37,7 @@ $this->nosave = 0; // 1= disable saving results to database // debug output $iop->show = 1; -$iop->debug = 0; +$iop->debug = 1; $iop->showFaults = 0; // used in result table output #$iop->doTest(); // run a single set of tests using above options Index: pear/SOAP/interop/server_round2.php diff -u pear/SOAP/interop/server_round2.php:1.2 pear/SOAP/interop/server_round2.php:1.3 --- pear/SOAP/interop/server_round2.php:1.2 Sun Apr 7 19:22:33 2002 +++ pear/SOAP/interop/server_round2.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: server_round2.php,v 1.2 2002/04/07 23:22:33 shane Exp $ +// $Id: server_round2.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -27,7 +27,7 @@ require_once 'server_round2_groupB.php'; require_once 'server_round2_groupC.php'; -$server->service($HTTP_RAW_POST_DATA); +$server->service(isset($HTTP_RAW_POST_DATA)?$HTTP_RAW_POST_DATA:NULL); #echo "Content-Length is {$_SERVER['CONTENT_LENGTH']}\n\n"; #echo "<!---\n\nlen:".strlen($HTTP_RAW_POST_DATA)."\n\n"; #echo "[$HTTP_RAW_POST_DATA"; Index: pear/SOAP/interop/server_round2_base.php diff -u pear/SOAP/interop/server_round2_base.php:1.4 pear/SOAP/interop/server_round2_base.php:1.5 --- pear/SOAP/interop/server_round2_base.php:1.4 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/server_round2_base.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: server_round2_base.php,v 1.4 2002/04/17 07:42:53 shane Exp $ +// $Id: server_round2_base.php,v 1.5 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -113,13 +113,12 @@ function echoStruct($inputStruct) { - return new SOAP_Value('return','SOAPStruct', + return new SOAP_Value('return','{http://soapinterop.org/xsd}SOAPStruct', array( new SOAP_Value('varInt','int',$inputStruct['varInt']), new SOAP_Value('varFloat','float',$inputStruct['varFloat']), new SOAP_Value('varString','string',$inputStruct['varString']) - ), - 'http://soapinterop.org/xsd'); + )); } function echoStructArray($inputStructArray) @@ -127,13 +126,12 @@ $ra = array(); if ($inputStructArray) { foreach($inputStructArray as $struct) { - $ra[] = new SOAP_Value('item','SOAPStruct', + $ra[] = new SOAP_Value('item','{http://soapinterop.org/xsd}SOAPStruct', array( new SOAP_Value('varInt','int',$struct['varInt']), new SOAP_Value('varFloat','float',$struct['varFloat']), new SOAP_Value('varString','string',$struct['varString']) - ), - 'http://soapinterop.org/xsd'); + )); } } return $ra; @@ -173,6 +171,11 @@ function echoBoolean($boolean) { return new SOAP_Value('return','boolean',$boolean); + } + + function echoMimeAttachment($stuff) + { + return new SOAP_Attachment('return','application/octet-stream',NULL,$stuff); } } Index: pear/SOAP/interop/server_round2_groupB.php diff -u pear/SOAP/interop/server_round2_groupB.php:1.2 pear/SOAP/interop/server_round2_groupB.php:1.3 --- pear/SOAP/interop/server_round2_groupB.php:1.2 Mon Apr 15 02:46:09 2002 +++ pear/SOAP/interop/server_round2_groupB.php Mon May 13 02:47:10 2002 @@ -17,7 +17,7 @@ // | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | // +----------------------------------------------------------------------+ // -// $Id: server_round2_groupB.php,v 1.2 2002/04/15 06:46:09 shane Exp $ +// $Id: server_round2_groupB.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -53,7 +53,7 @@ function echoSimpleTypesAsStruct($string, $int, $float) { # convert a input into struct - $ret = new SOAP_Value('return','Struct', + $ret = new SOAP_Value('return','{http://soapinterop.org/xsd}SOAPStruct', array( #push struct elements into one soap value new SOAP_Value('varString','string',$string), new SOAP_Value('varInt','int',(int)$int), @@ -71,7 +71,7 @@ function echo2DStringArray($ary) { $ret = new SOAP_Value('return','Array',$ary); - $ret->flattenArray = TRUE; + $ret->options['flatten'] = TRUE; return $ret; } Index: pear/SOAP/interop/server_round2_groupC.php diff -u pear/SOAP/interop/server_round2_groupC.php:1.2 pear/SOAP/interop/server_round2_groupC.php:1.3 --- pear/SOAP/interop/server_round2_groupC.php:1.2 Mon Apr 15 02:46:09 2002 +++ pear/SOAP/interop/server_round2_groupC.php Mon May 13 02:47:10 2002 @@ -16,10 +16,10 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> | // +----------------------------------------------------------------------+ // -// $Id: server_round2_groupC.php,v 1.2 2002/04/15 06:46:09 shane Exp $ +// $Id: server_round2_groupC.php,v 1.3 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; -require_once 'SOAP/Header.php'; +require_once 'SOAP/Value.php'; class SOAP_Interop_GroupC { var $method_namespace = 'http://soapinterop.org/echoheader/'; Index: pear/SOAP/interop/server_round2_test.php diff -u pear/SOAP/interop/server_round2_test.php:1.4 pear/SOAP/interop/server_round2_test.php:1.5 --- pear/SOAP/interop/server_round2_test.php:1.4 Wed Apr 17 03:42:53 2002 +++ pear/SOAP/interop/server_round2_test.php Mon May 13 02:47:10 2002 @@ -16,7 +16,7 @@ // | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | // +----------------------------------------------------------------------+ // -// $Id: server_round2_test.php,v 1.4 2002/04/17 07:42:53 shane Exp $ +// $Id: server_round2_test.php,v 1.5 2002/05/13 06:47:10 shane Exp $ // require_once 'SOAP/Server.php'; @@ -124,41 +124,135 @@ </SOAP-ENV:Body> </SOAP-ENV:Envelope>'; -$test = "<S:Envelope -S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' -xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' -xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' -xmlns:a='http://soapinterop.org/' -xmlns:b='http://soapinterop.org/xsd' -xmlns:XS='http://www.w3.org/2001/XMLSchema' -xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> -<S:Body> -<b:SOAPStruct Enc:root='0' id='21b56c4' XI:type='b:SOAPStruct'> -<varInt XI:type='XS:int'>1</varInt> -<varFloat XI:type='XS:float'>2</varFloat> -<varString XI:type='XS:string'>wilma</varString> -</b:SOAPStruct> -<a:echoStructArray> -<inputStructArray XI:type='Enc:Array' Enc:arrayType='XS:anyType[3]'> -<fred href='#21b56c4'/> -<i href='#21b56c4'/> -<i href='#21b56c4'/> -</inputStructArray> -</a:echoStructArray> -</S:Body></S:Envelope>"; +#$test = "<S:Envelope +#S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' +#xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' +#xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' +#xmlns:a='http://soapinterop.org/' +#xmlns:b='http://soapinterop.org/xsd' +#xmlns:XS='http://www.w3.org/2001/XMLSchema' +#xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> +#<S:Body> +#<b:SOAPStruct Enc:root='0' id='21b56c4' XI:type='b:SOAPStruct'> +#<varInt XI:type='XS:int'>1</varInt> +#<varFloat XI:type='XS:float'>2</varFloat> +#<varString XI:type='XS:string'>wilma</varString> +#</b:SOAPStruct> +#<a:echoStructArray> +#<inputStructArray XI:type='Enc:Array' Enc:arrayType='XS:anyType[3]'> +#<fred href='#21b56c4'/> +#<i href='#21b56c4'/> +#<i href='#21b56c4'/> +#</inputStructArray> +#</a:echoStructArray> +#</S:Body></S:Envelope>"; #$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructArray><inputStructArray XI:type='Enc:Array' Enc:arrayType='b:SOAPStruct[2]'><inputStruct href='#213e654'/> <inputStruct href='#21b8c4c'/> </inputStructArray> </a:echoStructArray> <b:SOAPStruct Enc:root='0' id='21b8c4c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>-1</varInt> <varFloat XI:type='XS:float'>-1</varFloat> <varString XI:type='XS:string'>lean on into the groove y'all</varString> </b:SOAPStruct> <b:SOAPStruct Enc:root='0' id='213e654' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>1073741824</varInt> <varFloat XI:type='XS:float'>-42.24</varFloat> <varString XI:type='XS:string'>pocketSOAP rocks!<g></varString> </b:SOAPStruct> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction S:mustUnderstand='1' XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructAsSimpleTypes><inputStruct href='#213e59c'/> </a:echoStructAsSimpleTypes> <b:SOAPStruct Enc:root='0' id='213e59c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>42</varInt> <varString XI:type='XS:string'>Orbital</varString> <varFloat XI:type='XS:float'>-42.42</varFloat> </b:SOAPStruct> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction S:mustUnderstand='1' XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:b='http://soapinterop.org/' xmlns:a='http://soapinterop.org/headers/' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Header> <a:Transaction XI:type='XS:short'>5</a:Transaction> </S:Header> <S:Body><b:echoString><inputString XI:type='XS:string'>Opps, should never see me</inputString> </b:echoString> </S:Body></S:Envelope>"; +#$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:Enc='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:b='http://soapinterop.org/xsd' xmlns:XS='http://www.w3.org/2001/XMLSchema' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoStructAsSimpleTypes><inputStruct href='#213e59c'/> </a:echoStructAsSimpleTypes> <b:SOAPStruct Enc:root='0' id='213e59c' XI:type='b:SOAPStruct'><varInt XI:type='XS:int'>42</varInt> <varString XI:type='XS:string'>Orbital</varString> <varFloat XI:type='XS:float'>-42.42</varFloat> </b:SOAPStruct> </S:Body></S:Envelope>"; // white mesa failures /*$test = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><h:echoMeStringRequest SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:mustUnderstand="1" xmlns:h="http://unknown.org/">White Mesa Test Header String.</h:echoMeStringRequest></SOAP-ENV:Header><SOAP-ENV:Body><m:echoVoid SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m="http://soapinterop.org/" /></SOAP-ENV:Body></SOAP-ENV:Envelope>'; */ +/* $test = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><h:echoMeStringRequest SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:mustUnderstand="1" xmlns:h="http://unknown.org/">White Mesa Test Header String.</h:echoMeStringRequest></SOAP-ENV:Header><SOAP-ENV:Body><m:echoVoid SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:m="http://soapinterop.org/" /></SOAP-ENV:Body></SOAP-ENV:Envelope>'; +*/ +//$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoIntegerArray><inputIntegerArray XI:nil='true'></inputIntegerArray> </a:echoIntegerArray> </S:Body></S:Envelope>"; -$test = "<S:Envelope S:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:a='http://soapinterop.org/' xmlns:XI='http://www.w3.org/2001/XMLSchema-instance'> <S:Body><a:echoIntegerArray><inputIntegerArray XI:nil='true'></inputIntegerArray> </a:echoIntegerArray> </S:Body></S:Envelope>"; -$server->service($test, '',TRUE); +$test = '<?xml version="1.0" encoding="UTF-8"?> + +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" + xmlns:ns4="http://soapinterop.org/" + SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> +<SOAP-ENV:Body> + +<ns4:echo2DStringArray> +<input2DStringArray xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2,3]"> +<item xsi:type="xsd:string">row0col0</item> +<item xsi:type="xsd:string">row0col1</item> +<item xsi:type="xsd:string">row0col2</item> +<item xsi:type="xsd:string">row1col0</item> +<item xsi:type="xsd:string">row1col1</item> +<item xsi:type="xsd:string">row1col2</item></input2DStringArray></ns4:echo2DStringArray> +</SOAP-ENV:Body> +</SOAP-ENV:Envelope>'; + +$_SERVER['REQUEST_METHOD'] = "POST"; +$_SERVER['CONTENT_TYPE'] = 'multipart/related; type=text/xml; boundary="=_d624611fe466a88d956a205651c74fdb"'; + +$test = '--=_d624611fe466a88d956a205651c74fdb +Content-Type: text/xml; charset="UTF-8" +Content-Transfer-Encoding: base64 + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCg0KPFNPQVAtRU5WOkVudmVs +b3BlICB4bWxuczpTT0FQLUVOVj0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvc29hcC9lbnZl +bG9wZS8iDQogIHhtbG5zOnhzZD0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiDQog +IHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiDQog +IHhtbG5zOlNPQVAtRU5DPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy9zb2FwL2VuY29kaW5n +LyINCiAgU09BUC1FTlY6ZW5jb2RpbmdTdHlsZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcv +c29hcC9lbmNvZGluZy8iPg0KPFNPQVAtRU5WOkJvZHk+DQoNCjxlY2hvTWltZUF0dGFjaG1lbnQ+ +DQo8dGVzdCBocmVmPSJjaWQ6ZTZiOTg0M2JiYzUxY2JiMDAzOTk0MGVmN2VlNzY2MDMiLz48L2Vj +aG9NaW1lQXR0YWNobWVudD4NCjwvU09BUC1FTlY6Qm9keT4NCjwvU09BUC1FTlY6RW52ZWxvcGU+ +DQo= +--=_d624611fe466a88d956a205651c74fdb +Content-Disposition: attachment.php +Content-Type: text/plain +Content-Transfer-Encoding: base64 +Content-ID: <e6b9843bbc51cbb0039940ef7ee76603> + +PD9waHANCnJlcXVpcmVfb25jZSgiU09BUC9DbGllbnQucGhwIik7DQpyZXF1aXJlX29uY2UoIlNP +QVAvdGVzdC90ZXN0LnV0aWxpdHkucGhwIik7DQpyZXF1aXJlX29uY2UoIlNPQVAvVmFsdWUucGhw +Iik7DQokc29hcF9iYXNlID0gbmV3IFNPQVBfQmFzZSgpOw0KDQokdiA9ICBuZXcgU09BUF9BdHRh +Y2htZW50KCd0ZXN0JywndGV4dC9wbGFpbicsJ2F0dGFjaG1lbnQucGhwJyk7DQokbWV0aG9kVmFs +dWUgPSBuZXcgU09BUF9WYWx1ZSgndGVzdGF0dGFjaCcsICdTdHJ1Y3QnLCBhcnJheSgkdikpOw0K +DQovLyBzZWUgdGhlIG1pbWUgYXJyYXkNCi8vJHZhbCA9ICRzb2FwX2Jhc2UtPl9tYWtlRW52ZWxv +cGUoJG1ldGhvZFZhbHVlKTsNCi8vcHJpbnRfcigkdmFsKTsNCg0KJGNsaWVudCA9IG5ldyBTT0FQ +X0NsaWVudCgnaHR0cDovL2xvY2FsaG9zdC9zb2FwX2ludGVyb3Avc2VydmVyX3JvdW5kMi5waHAn +KTsNCiRyZXNwID0gJGNsaWVudC0+Y2FsbCgnZWNob01pbWVBdHRhY2htZW50JyxhcnJheSgkdikp +Ow0KcHJpbnRfcigkcmVzcCk7DQpwcmludCAkY2xpZW50LT53aXJlOw0KPz4= +--=_d624611fe466a88d956a205651c74fdb--'; + +$_SERVER['CONTENT_TYPE'] = 'multipart/related; type=text/xml; boundary="=_a2cbb051424cc43e72d3c8c8d0b8f70e"'; +$test='--=_a2cbb051424cc43e72d3c8c8d0b8f70e +Content-Type: text/xml; charset="UTF-8" +<?xml version="1.0" encoding="UTF-8"?> + +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" + SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> +<SOAP-ENV:Body> + +<echoMimeAttachment> +<test href="cid:a223fea3c35b5f0e6dedf8da75efd6b3"/></echoMimeAttachment> +</SOAP-ENV:Body> +</SOAP-ENV:Envelope> + +--=_a2cbb051424cc43e72d3c8c8d0b8f70e +Content-Disposition: attachment.php +Content-Type: text/plain +Content-Transfer-Encoding: base64 +Content-ID: <a223fea3c35b5f0e6dedf8da75efd6b3> + +PD9waHANCnJlcXVpcmVfb25jZSgiU09BUC9DbGllbnQucGhwIik7DQpyZXF1aXJlX29uY2UoIlNP +QVAvdGVzdC90ZXN0LnV0aWxpdHkucGhwIik7DQpyZXF1aXJlX29uY2UoIlNPQVAvVmFsdWUucGhw +Iik7DQokc29hcF9iYXNlID0gbmV3IFNPQVBfQmFzZSgpOw0KDQokdiA9ICBuZXcgU09BUF9BdHRh +Y2htZW50KCd0ZXN0JywndGV4dC9wbGFpbicsJ2F0dGFjaG1lbnQucGhwJyk7DQokbWV0aG9kVmFs +dWUgPSBuZXcgU09BUF9WYWx1ZSgndGVzdGF0dGFjaCcsICdTdHJ1Y3QnLCBhcnJheSgkdikpOw0K +DQovLyBzZWUgdGhlIG1pbWUgYXJyYXkNCi8vJHZhbCA9ICRzb2FwX2Jhc2UtPl9tYWtlRW52ZWxv +cGUoJG1ldGhvZFZhbHVlKTsNCi8vcHJpbnRfcigkdmFsKTsNCg0KJGNsaWVudCA9IG5ldyBTT0FQ +X0NsaWVudCgnaHR0cDovL2xvY2FsaG9zdC9zb2FwX2ludGVyb3Avc2VydmVyX3JvdW5kMi5waHAn +KTsNCiRyZXNwID0gJGNsaWVudC0+Y2FsbCgnZWNob01pbWVBdHRhY2htZW50JyxhcnJheSgkdikp +Ow0KI3ByaW50X3IoJHJlc3ApOw0KcHJpbnQgJGNsaWVudC0+d2lyZTsNCj8+ +--=_a2cbb051424cc43e72d3c8c8d0b8f70e-- +'; +$server->service($test, '',TRUE); +print $server->response; ?> Index: pear/SOAP/test/5.2.1.simpletypes.string.php diff -u pear/SOAP/test/5.2.1.simpletypes.string.php:1.1 pear/SOAP/test/5.2.1.simpletypes.string.php:1.2 --- pear/SOAP/test/5.2.1.simpletypes.string.php:1.1 Sun Feb 24 21:55:13 2002 +++ pear/SOAP/test/5.2.1.simpletypes.string.php Mon May 13 02:47:10 2002 @@ -1,5 +1,7 @@ <?php require_once("SOAP/test/test.utility.php"); +require_once("SOAP/Base.php"); +$soap_base = new SOAP_Base(); $prefix = "5.2.1 String"; $msg = '<?xml version="1.0" encoding="UTF-8"?> @@ -24,7 +26,7 @@ # serialize a soap value $expect = '<inputString xsi:type="xsd:string">hello world</inputString>'; $v = new SOAP_Value("inputString","string","hello world"); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare($expect, $val)) { print "$prefix Serialize Type OK\n"; } else { @@ -32,7 +34,7 @@ } # serialize a soap value with unknown type $expect = "hello world"; -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize known SOAP_Value OK\n"; } else { @@ -42,7 +44,7 @@ # serialize a soap value with unknown type $expect = '<inputString xsi:type="xsd:string">hello world</inputString>'; $v = new SOAP_Value("inputString","","hello world"); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare($expect, $val)) { print "$prefix Serialize Unknown Type OK\n"; } else { @@ -51,7 +53,7 @@ # serialize a soap value with unknown type $expect = "hello world"; -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize Unknown SOAP_Value OK\n"; } else { Index: pear/SOAP/test/5.2.simpletypes.php diff -u pear/SOAP/test/5.2.simpletypes.php:1.5 pear/SOAP/test/5.2.simpletypes.php:1.6 --- pear/SOAP/test/5.2.simpletypes.php:1.5 Mon Apr 15 02:46:11 2002 +++ pear/SOAP/test/5.2.simpletypes.php Mon May 13 02:47:10 2002 @@ -1,6 +1,9 @@ <?php +require_once("SOAP/Base.php"); require_once("SOAP/test/test.utility.php"); require_once("SOAP/Fault.php"); +$soap_base = new SOAP_Base(); + $prefix = "5.2 Simple Types"; $msg = '<?xml version="1.0" encoding="UTF-8"?> @@ -55,7 +58,8 @@ new SOAP_Value("displacement","negativeInteger",-450), new SOAP_Value("color","string","Blue") )); -$val = $v->serialize(); + +$val = $v->serialize($soap_base); if (string_compare(str_replace("\r\n","",$expect), str_replace("\r\n","",$val))) { print "$prefix Serialize Type OK\n"; } else { @@ -64,7 +68,7 @@ # deserialize a soap value $expect = array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue'); -$val = $v->decode(); +$val = $soap_base->decode($v); if (string_compare($expect, $val)) { print "$prefix Deserialize known SOAP_Value OK\n"; } else { @@ -80,7 +84,7 @@ </inputString> '; $v = new SOAP_Value("inputString","Struct",array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue')); -$val = $v->serialize(); +$val = $v->serialize($soap_base); if (string_compare(str_replace("\r\n","",$expect), str_replace("\r\n","",$val))) { print "$prefix Serialize Unknown Type OK\n"; } else { @@ -89,8 +93,8 @@ # serialize a soap value with unknown type $expect = array('age'=>45, 'height'=> 5.9, 'displacement' => -450, 'color' => 'Blue'); -$val = $v->decode(); -if (string_compare($expect, $val)) { +$val = $soap_base->decode($v); +if (array_compare($expect, $val)) { print "$prefix Deserialize Unknown SOAP_Value OK\n"; } else { print "$prefix Deserialize Unknown SOAP_Value FAILED\n"; Index: pear/SOAP/test/test.utility.php diff -u pear/SOAP/test/test.utility.php:1.4 pear/SOAP/test/test.utility.php:1.5 --- pear/SOAP/test/test.utility.php:1.4 Mon Apr 15 02:46:12 2002 +++ pear/SOAP/test/test.utility.php Mon May 13 02:47:10 2002 @@ -1,7 +1,6 @@ <?php require_once("SOAP/Parser.php"); require_once("SOAP/Value.php"); -require_once("SOAP/Message.php"); function number_compare($f1, $f2) { @@ -10,7 +9,7 @@ preg_match('/.*?\.(.*)/',$f2,$m2); #print_r($m1); # always use at least 2 digits of precision - $d = max(min(strlen($m1[1]),strlen($m2[1])),2); + $d = max(min(strlen(count($m1)?$m1[1]:'0'),strlen(count($m2)?$m2[1]:'0')),2); $f1 = round($f1, $d); $f2 = round($f2, $d); return bccomp($f1, $f2, $d) == 0; @@ -71,7 +70,7 @@ return $response->fault->getFault(); } $return = $response->getResponse(); - $v = $return->decode(); + $v = $response->decode($return); if (gettype($v) == 'array' && count($v)==1) { return array_shift($v); } Index: pear/SOAP/example/attachment.php +++ pear/SOAP/example/attachment.php <?php require_once("SOAP/Client.php"); require_once("SOAP/test/test.utility.php"); require_once("SOAP/Value.php"); $filename = 'attachment.php'; $v = new SOAP_Attachment('test','text/plain',$filename); $methodValue = new SOAP_Value('testattach', 'Struct', array($v)); $client = new SOAP_Client('http://localhost/soap_interop/server_round2.php'); # calling with mime $resp = $client->call('echoMimeAttachment',array($v),array('Mime'=>1)); print $client->wire."\n\n\n"; print_r($resp); # calling with DIME $resp = $client->call('echoMimeAttachment',array($v)); # DIME has null spaces, change them so we can see the wire $wire = str_replace("\0",'*',$client->wire); print $wire."\n\n\n"; print_r($resp); ?>