pax_global_header00006660000000000000000000000064121422267050014513gustar00rootroot0000000000000052 comment=3c6d582ac0aadd3323e80a1f11b069cfe1dc0ee1 php-soap-0.13.0/000077500000000000000000000000001214222670500133235ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/000077500000000000000000000000001214222670500146025ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/000077500000000000000000000000001214222670500153445ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/Base.php000066400000000000000000001166331214222670500167410ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** Define linebreak sequence for the Mail_Mime package. */ define('MAIL_MIMEPART_CRLF', "\r\n"); require_once 'PEAR.php'; if (!defined('INF')) { define('INF', 1.8e307); } if (!defined('NAN')) { define('NAN', 0.0); } define('SOAP_LIBRARY_VERSION', '@version@'); define('SOAP_LIBRARY_NAME', 'PEAR-SOAP @version@-beta'); // 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('SCHEMA_DISCO', 'http://schemas.xmlsoap.org/disco/'); define('SCHEMA_DISCO_SCL', 'http://schemas.xmlsoap.org/disco/scl/'); define('SCHEMA_SOAP', 'http://schemas.xmlsoap.org/wsdl/soap/'); define('SCHEMA_SOAP12', 'http://schemas.xmlsoap.org/wsdl/soap12/'); define('SCHEMA_SOAP_HTTP', 'http://schemas.xmlsoap.org/soap/http'); define('SCHEMA_WSDL_HTTP', 'http://schemas.xmlsoap.org/wsdl/http/'); define('SCHEMA_MIME', 'http://schemas.xmlsoap.org/wsdl/mime/'); define('SCHEMA_WSDL', 'http://schemas.xmlsoap.org/wsdl/'); define('SCHEMA_DIME', 'http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/'); define('SCHEMA_CONTENT', 'http://schemas.xmlsoap.org/ws/2002/04/content-type/'); define('SCHEMA_REF', 'http://schemas.xmlsoap.org/ws/2002/04/reference/'); define('SOAP_DEFAULT_ENCODING', 'UTF-8'); /** * @package SOAP */ class SOAP_Base_Object extends PEAR { /** * Supported encodings, limited by XML extension. * * @var array $_encodings */ var $_encodings = array('ISO-8859-1', 'US-ASCII', 'UTF-8'); /** * Fault code. * * @var string $_myfaultcode */ var $_myfaultcode = ''; /** * Recent PEAR_Error object. * * @var PEAR_Error $fault */ var $fault = null; /** * Constructor. * * @param string $faultcode Error code. */ function SOAP_Base_Object($faultcode = 'Client') { $this->_myfaultcode = $faultcode; parent::PEAR('SOAP_Fault'); } /** * Raises a SOAP error. * * Please refer to the SOAP definition for an impression of what a certain * parameter stands for. * * @param string|object $str Error message or object. * @param string $detail Detailed error message. * @param string $actorURI * @param mixed $code * @param mixed $mode * @param mixed $options * @param boolean $skipmsg */ function &_raiseSoapFault($str, $detail = '', $actorURI = '', $code = null, $mode = null, $options = null, $skipmsg = false) { // Pass through previous faults. $is_instance = isset($this) && is_a($this, 'SOAP_Base_Object'); if (is_object($str)) { $fault = $str; } else { if (!$code) { $code = $is_instance ? $this->_myfaultcode : 'Client'; } require_once 'SOAP/Fault.php'; $fault = new SOAP_Fault($str, $code, $actorURI, $detail, $mode, $options); } if ($is_instance) { $this->fault = $fault; } return $fault; } function _isfault() { return $this->fault != null; } function &_getfault() { return $this->fault; } } /** * Common base class of all SOAP classes. * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates */ class SOAP_Base extends SOAP_Base_Object { 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', // longs (64bit ints) are not supported cross-platform. 'long' => 'string', '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') ); /** * Default class name to use for decoded response objects. * * @var string $_defaultObjectClassname */ var $_defaultObjectClassname = 'stdClass'; /** * Hash with used namespaces. * * @var array */ var $_namespaces; /** * The default namespace. * * @var string */ var $_namespace; var $_xmlEntities = array('&' => '&', '<' => '<', '>' => '>', "'" => ''', '"' => '"'); var $_doconversion = false; var $_attachments = array(); var $_wsdl = null; /** * True if we use section 5 encoding, or false if this is literal. * * @var boolean $_section5 */ var $_section5 = true; // Handle type to class mapping. var $_auto_translation = false; var $_type_translation = array(); /** * Constructor. * * @param string $faultcode Error code. */ function SOAP_Base($faultcode = 'Client') { parent::SOAP_Base_Object($faultcode); $this->_resetNamespaces(); } /** * Sets the SOAP-ENV prefix and returns the current value. * * @access public * * @param string SOAP-ENV prefix * * @return string current SOAP-ENV prefix. */ function SOAPENVPrefix($prefix = null) { static $_soapenv_prefix = 'SOAP-ENV'; if (!is_null($prefix)) { $_soapenv_prefix = $prefix; } return $_soapenv_prefix; } /** * Sets the SOAP-ENC prefix and returns the current value. * * @access public * * @param string SOAP-ENC prefix * * @return string current SOAP-ENC prefix. */ function SOAPENCPrefix($prefix = null) { static $_soapenv_prefix = 'SOAP-ENC'; if (!is_null($prefix)) { $_soapenv_prefix = $prefix; } return $_soapenv_prefix; } /** * Sets the default namespace. * * @param string $namespace The default namespace. */ function setDefaultNamespace($namespace) { $this->_namespace = $namespace; } function _resetNamespaces() { $this->_namespaces = array( 'http://schemas.xmlsoap.org/soap/envelope/' => SOAP_BASE::SOAPENVPrefix(), 'http://www.w3.org/2001/XMLSchema' => 'xsd', 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', 'http://schemas.xmlsoap.org/soap/encoding/' => SOAP_BASE::SOAPENCPrefix()); } /** * Sets the schema version used in the SOAP message. * * @access private * @see $_XMLSchema * * @param string $schemaVersion The schema version. */ 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); } function _getNamespacePrefix($ns) { if ($this->_namespace && $ns == $this->_namespace) { return ''; } if (isset($this->_namespaces[$ns])) { return $this->_namespaces[$ns]; } $prefix = 'ns' . count($this->_namespaces); $this->_namespaces[$ns] = $prefix; return $prefix; } function _getNamespaceForPrefix($prefix) { $flipped = array_flip($this->_namespaces); if (isset($flipped[$prefix])) { return $flipped[$prefix]; } return null; } /** * Serializes a value, array or object according to the rules set by this * object. * * @see SOAP_Value * * @param mixed $value The actual value. * @param QName $name The value name. * @param QName $type The value type. * @param array $options A list of encoding and serialization options. * @param array $attributes A hash of additional attributes. * @param string $artype The type of any array elements. */ function _serializeValue($value, $name = null, $type = null, $options = array(), $attributes = array(), $artype = '') { $namespaces = array(); $arrayType = $array_depth = $xmlout_value = null; $typePrefix = $elPrefix = $xmlout_arrayType = ''; $xmlout_type = $xmlns = $ptype = $array_type_ns = ''; if (!$name->name || is_numeric($name->name)) { $name->name = 'item'; } if ($this->_wsdl) { list($ptype, $arrayType, $array_type_ns, $array_depth) = $this->_wsdl->getSchemaType($type, $name); } if (!$arrayType) { $arrayType = $artype; } if (!$ptype) { $ptype = $this->_getType($value); } if (!$type) { $type = new QName($ptype); } if (strcasecmp($ptype, 'Struct') == 0 || strcasecmp($type->name, 'Struct') == 0) { // Struct $vars = is_object($value) ? get_object_vars($value) : $value; if (is_array($vars)) { foreach (array_keys($vars) as $k) { // Hide private vars. if ($k[0] == '_') { continue; } if (is_object($vars[$k])) { if (is_a($vars[$k], 'SOAP_Value')) { $xmlout_value .= $vars[$k]->serialize($this); } else { // XXX get the members and serialize them instead // converting to an array is more overhead than we // should really do. $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), new QName($k, $this->_section5 ? null : $name->namepace), null, $options); } } else { $xmlout_value .= $this->_serializeValue($vars[$k], new QName($k, $this->_section5 ? null : $name->namespace), false, $options); } } } } elseif (strcasecmp($ptype, 'Array') == 0 || strcasecmp($type->name, 'Array') == 0) { // Array. $type = new QName('Array', SOAP_SCHEMA_ENCODING); $numtypes = 0; $value = (array)$value; // XXX this will be slow on larger arrays. Basically, it flattens // arrays to allow us to serialize multi-dimensional arrays. We // only do this if arrayType is set, which will typically only // happen if we are using WSDL if (isset($options['flatten']) || ($arrayType && (strchr($arrayType, ',') || strstr($arrayType, '][')))) { $numtypes = $this->_multiArrayType($value, $arrayType, $ar_size, $xmlout_value); } $array_type = $array_type_prefix = ''; if ($numtypes != 1) { $arrayTypeQName = new QName($arrayType); $arrayType = $arrayTypeQName->name; $array_types = array(); $array_val = null; // Serialize each array element. $ar_size = count($value); foreach ($value as $array_val) { if (is_a($array_val, 'SOAP_Value')) { $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; if (empty($options['keep_arrays_flat'])) { $xmlout_value .= $this->_serializeValue($array_val, new QName('item', $this->_section5 ? null : $name->namespace), new QName($array_type), $options); } else { $xmlout_value .= $this->_serializeValue($array_val, $name, new QName($array_type), $options, $attributes); } } } if (!$arrayType) { $numtypes = count($array_types); if ($numtypes == 1) { $arrayType = $array_type; } // Using anyType is more interoperable. if ($array_type == 'Struct') { $array_type = ''; } elseif ($array_type == 'Array') { $arrayType = 'anyType'; $array_type_prefix = 'xsd'; } else { if (!$arrayType) { $arrayType = $array_type; } } } } if (!$arrayType || $numtypes > 1) { // Should reference what schema we're using. $arrayType = 'xsd:anyType'; } else { if ($array_type_ns) { $array_type_prefix = $this->_getNamespacePrefix($array_type_ns); } elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) { $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; } elseif (isset($this->_typemap[SOAP_SCHEMA_ENCODING][$arrayType])) { $array_type_prefix = SOAP_BASE::SOAPENCPrefix(); } if ($array_type_prefix) { $arrayType = $array_type_prefix . ':' . $arrayType; } } $xmlout_arrayType = ' ' . SOAP_BASE::SOAPENCPrefix() . ':arrayType="' . $arrayType; if ($array_depth != null) { for ($i = 0; $i < $array_depth; $i++) { $xmlout_arrayType .= '[]'; } } $xmlout_arrayType .= "[$ar_size]\""; } elseif (is_a($value, 'SOAP_Value')) { $xmlout_value = $value->serialize($this); } elseif ($type->name == 'string') { $xmlout_value = htmlspecialchars($value); } elseif ($type->name == 'rawstring') { $xmlout_value = $value; } elseif ($type->name == 'boolean') { $xmlout_value = $value ? 'true' : 'false'; } else { $xmlout_value = $value; } // Add namespaces. if ($name->namespace) { $elPrefix = $this->_getNamespacePrefix($name->namespace); if ($elPrefix) { $xmlout_name = $elPrefix . ':' . $name->name; } else { $xmlout_name = $name->name; } } else { $xmlout_name = $name->name; } if ($type->namespace) { $typePrefix = false; if (empty($options['no_type_prefix'])) { $typePrefix = $this->_getNamespacePrefix($type->namespace); } if ($typePrefix) { $xmlout_type = $typePrefix . ':' . $type->name; } else { $xmlout_type = $type->name; } } elseif ($type->name && isset($this->_typemap[$this->_XMLSchemaVersion][$type->name])) { $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; if ($typePrefix) { $xmlout_type = $typePrefix . ':' . $type->name; } else { $xmlout_type = $type->name; } } // 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 attachment for mime encoding. if (isset($options['attachment']) && !PEAR::isError($options['attachment'])) { $this->_attachments[] = $options['attachment']; } if ($this->_section5) { if ($xmlout_type) { $xmlout_type = " xsi:type=\"$xmlout_type\""; } if (is_null($xmlout_value)) { $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . "$xml_attr xsi:nil=\"true\"/>"; } else { $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . "$xml_attr>$xmlout_value"; } } elseif ($type->name == 'Array' && !empty($options['keep_arrays_flat'])) { $xml = $xmlout_value; } else { if (is_null($xmlout_value)) { $xml = "\r\n<$xmlout_name$xmlns$xml_attr/>"; } else { $xml = "\r\n<$xmlout_name$xmlns$xml_attr>" . $xmlout_value . ""; } } return $xml; } /** * Converts a PHP type to a SOAP type. * * @param mixed $value The value to inspect. * * @return string The value's SOAP type. */ function _getType($value) { $type = gettype($value); switch ($type) { case 'object': if (is_a($value, 'soap_value')) { $type = $value->type; } else { $type = 'Struct'; } break; case 'array': // Hashes are always handled as structs. if ($this->_isHash($value)) { $type = 'Struct'; break; } if (count($value) > 1) { // For non-wsdl structs that are all the same type reset($value); $value1 = next($value); $value2 = next($value); if (is_a($value1, 'SOAP_Value') && is_a($value2, 'SOAP_Value') && $value1->name != $value2->name) { // This is a struct, not an array. $type = 'Struct'; break; } } $type = 'Array'; break; case 'integer': case 'long': $type = 'int'; break; case 'boolean': break; case 'double': // double is deprecated in PHP 4.2 and later. $type = 'float'; break; case 'null': $type = ''; break; case 'string': default: break; } return $type; } function _multiArrayType($value, &$type, &$size, &$xml) { if (is_array($value)) { // Seems we have a multi dimensional array, figure it out if we // do. for ($i = 0, $c = count($value); $i < $c; ++$i) { $this->_multiArrayType($value[$i], $type, $size, $xml); } $sz = count($value); if ($size) { $size = $sz . ',' . $size; } else { $size = $sz; } return 1; } elseif (is_object($value)) { $type = $value->type; $xml .= $value->serialize($this); } else { $type = $this->_getType($value); $xml .= $this->_serializeValue($value, new QName('item'), new QName($type)); } $size = null; return 1; } /** * Returns whether a type is a base64 type. * * @param string $type A type name. * * @return boolean True if the type name is a base64 type. */ function _isBase64Type($type) { return $type == 'base64' || $type == 'base64Binary'; } /** * Returns whether an array is a hash. * * @param array $a An array to check. * * @return boolean True if the specified array is a hash. */ function _isHash($a) { foreach (array_keys($a) as $k) { // Checking the type is faster than regexp. if (!is_int($k)) { return true; } } return false; } function _un_htmlentities($string) { $trans_tbl = get_html_translation_table(HTML_ENTITIES); $trans_tbl = array_flip($trans_tbl); return strtr($string, $trans_tbl); } /** * Converts a SOAP_Value object into a PHP value. */ function _decode($soapval) { if (!is_a($soapval, 'SOAP_Value')) { return $soapval; } if (is_array($soapval->value)) { $isstruct = $soapval->type != 'Array'; if ($isstruct) { $classname = $this->_defaultObjectClassname; if (isset($this->_type_translation[$soapval->tqn->fqn()])) { // This will force an error in PHP if the class does not // exist. $classname = $this->_type_translation[$soapval->tqn->fqn()]; } elseif (isset($this->_type_translation[$soapval->type])) { // This will force an error in PHP if the class does not // exist. $classname = $this->_type_translation[$soapval->type]; } elseif ($this->_auto_translation) { if (class_exists($soapval->type)) { $classname = $soapval->type; } elseif ($this->_wsdl) { $t = $this->_wsdl->getComplexTypeNameForElement($soapval->name, $soapval->namespace); if ($t && class_exists($t)) { $classname = $t; } } } $return = new $classname; } else { $return = array(); } foreach ($soapval->value as $item) { if ($isstruct) { if ($this->_wsdl) { // Get this child's WSDL information. // /$soapval->prefix/$soapval->type/$item->prefix/$item->name $child_type = $this->_wsdl->getComplexTypeChildType( $soapval->namespace, $soapval->name, $item->namespace, $item->name); if ($child_type) { $item->type = $child_type; } } if ($item->type == 'Array') { if (isset($return->{$item->name}) && is_object($return->{$item->name})) { $return->{$item->name} = $this->_decode($item); } elseif (isset($return->{$item->name}) && is_array($return->{$item->name})) { $return->{$item->name}[] = $this->_decode($item); } elseif (isset($return->{$item->name})) { $return->{$item->name} = array( $return->{$item->name}, $this->_decode($item) ); } elseif (is_array($return)) { $return[] = $this->_decode($item); } else { $return->{$item->name} = $this->_decode($item); } } elseif (isset($return->{$item->name})) { $d = $this->_decode($item); if (count(get_object_vars($return)) == 1) { $isstruct = false; $return = array($return->{$item->name}, $d); } else { if (is_array($return->{$item->name})) { $return->{$item->name} = array_merge($return->{$item->name}, array($d)); } else { $return->{$item->name} = array($return->{$item->name}, $d); } } } else { $return->{$item->name} = $this->_decode($item); } // Set the attributes as members in the class. if (method_exists($return, '__set_attribute')) { foreach ($soapval->attributes as $key => $value) { call_user_func_array(array(&$return, '__set_attribute'), array($key, $value)); } } } else { if ($soapval->arrayType && is_a($item, 'SOAP_Value')) { if ($this->_isBase64Type($item->type) && !$this->_isBase64Type($soapval->arrayType)) { // Decode the value if we're losing the base64 // type information. $item->value = base64_decode($item->value); } $item->type = $soapval->arrayType; } $return[] = $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; } } elseif ($soapval->type && isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type])) { // If we can, set variable type. settype($soapval->value, $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); } elseif ($soapval->type == 'Struct') { $soapval->value = null; } return $soapval->value; } /** * Creates the SOAP envelope with the SOAP envelop data. * * @param SOAP_Value $method SOAP_Value instance with the method name as * the name, and the method arguments as the * value. * @param array $headers A list of additional SOAP_Header objects. * @param string $encoding The charset of the SOAP message. * @param array $options A list of encoding/serialization options. * * @return string The complete SOAP message. */ function makeEnvelope($method, $headers, $encoding = SOAP_DEFAULT_ENCODING, $options = array()) { $smsg = $header_xml = $ns_string = ''; if ($headers) { for ($i = 0, $c = count($headers); $i < $c; $i++) { $header_xml .= $headers[$i]->serialize($this); } $header_xml = sprintf("<%s:Header>\r\n%s\r\n\r\n", SOAP_BASE::SOAPENVPrefix(), $header_xml, SOAP_BASE::SOAPENVPrefix()); } if (!isset($options['input']) || $options['input'] == 'parse') { if (is_array($method)) { for ($i = 0, $c = count($method); $i < $c; $i++) { $smsg .= $method[$i]->serialize($this); } } else { $smsg = $method->serialize($this); } } else { $smsg = $method; } $body = sprintf("<%s:Body>%s\r\n\r\n", SOAP_BASE::SOAPENVPrefix(), $smsg, SOAP_BASE::SOAPENVPrefix()); foreach ($this->_namespaces as $k => $v) { $ns_string .= "\r\n " . sprintf('xmlns:%s="%s"', $v, $k); } if ($this->_namespace) { $ns_string .= "\r\n " . sprintf('xmlns="%s"', $this->_namespace); } /* If 'use' == 'literal', do not put in the encodingStyle. This is * denoted by $this->_section5 being false. 'use' can be defined at a * more granular level than we are dealing with here, so this does not * work for all services. */ $xml = sprintf('%s<%s:Envelope%s', $encoding, "\r\n", SOAP_BASE::SOAPENVPrefix(), $ns_string); if ($this->_section5) { $xml .= "\r\n " . sprintf('%s:encodingStyle="%s"', SOAP_BASE::SOAPENVPrefix(), SOAP_SCHEMA_ENCODING); } $xml .= sprintf('>%s%s%s' . "\r\n", "\r\n", $header_xml, $body, SOAP_BASE::SOAPENVPrefix()); return $xml; } function _makeMimeMessage($xml, $encoding = SOAP_DEFAULT_ENCODING) { if (!@include_once 'Mail/mimePart.php') { return $this->_raiseSoapFault('MIME messages are unsupported, the Mail_Mime package 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; $msg->addSubPart($xml, $params); // Add the attachements for ($i = 0, $c = count($this->_attachments); $i < $c; ++$i) { $msg->addSubPart($this->_attachments[$i]['body'], $this->_attachments[$i]); } return $msg->encode(); } // TODO: this needs to be used from the Transport system. function _makeDIMEMessage($xml) { if (!@include_once 'Net/DIME.php') { return $this->_raiseSoapFault('DIME messages are unsupported, the Net_DIME package 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 Net_DIME_Message(); $msg = $dime->encodeData($xml, SOAP_ENVELOP, null, NET_DIME_TYPE_URI); // Add the attachments. $c = count($this->_attachments); for ($i = 0; $i < $c; $i++) { $msg .= $dime->encodeData($this->_attachments[$i]['body'], $this->_attachments[$i]['content_type'], $this->_attachments[$i]['cid'], NET_DIME_TYPE_MEDIA); } $msg .= $dime->endMessage(); return $msg; } function _decodeMimeMessage(&$data, &$headers, &$attachments) { if (!@include_once 'Mail/mimeDecode.php') { return $this->_raiseSoapFault('MIME messages are unsupported, the Mail_Mime package is not installed'); } $params['include_bodies'] = true; $params['decode_bodies'] = true; $params['decode_headers'] = true; // Lame thing to have to do for decoding. $decoder = new Mail_mimeDecode($data); $structure = $decoder->decode($params); if (isset($structure->body)) { $data = $structure->body; $headers = $structure->headers; unset($headers['']); return; } elseif (isset($structure->parts)) { $data = $structure->parts[0]->body; $headers = array_merge($structure->headers, $structure->parts[0]->headers); unset($headers['']); if (count($structure->parts) <= 1) { return; } $mime_parts = array_splice($structure->parts, 1); // Prepare the parts for the SOAP parser. for ($i = 0, $c = count($mime_parts); $i < $c; $i++) { $p = $mime_parts[$i]; if (isset($p->headers['content-location'])) { // 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, -1); $attachments[$cid] = $p->body; } } return; } $this->_raiseSoapFault('Mime parsing error', '', '', 'Server'); } function _decodeDIMEMessage(&$data, &$headers, &$attachments) { if (!@include_once 'Net/DIME.php') { return $this->_raiseSoapFault('DIME messages are unsupported, the Net_DIME package is not installed'); } // This SHOULD be moved to the transport layer, e.g. PHP itself should // handle parsing DIME ;) $dime = new Net_DIME_Message(); $err = $dime->decodeData($data); if (PEAR::isError($err)) { $this->_raiseSoapFault('Failed to decode the DIME message!', '', '', 'Server'); return; } if (strcasecmp($dime->parts[0]['type'], SOAP_ENVELOP) != 0) { $this->_raiseSoapFault('DIME record 1 is not a SOAP envelop!', '', '', 'Server'); return; } $data = $dime->parts[0]['data']; // Fake it for now. $headers['content-type'] = 'text/xml'; $c = count($dime->parts); for ($i = 0; $i < $c; $i++) { $part =& $dime->parts[$i]; // We need to handle URI's better. $id = strncmp($part['id'], 'cid:', 4) ? 'cid:' . $part['id'] : $part['id']; $attachments[$id] = $part['data']; } } /** * Explicitly sets the translation for a specific class. * * Auto translation works for all cases, but opens ANY class in the script * to be used as a data type, and may not be desireable. * * @param string $type A SOAP type. * @param string $class A PHP class name. */ function setTypeTranslation($type, $class = null) { $tq = new QName($type); if (!$class) { $class = $tq->name; } $this->_type_translation[$type]=$class; } } /** * Class used to handle QNAME values in XML. * * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates */ class QName { var $name = ''; var $prefix = ''; var $namespace = ''; function QName($name, $namespace = '') { if ($name && $name[0] == '{') { preg_match('/\{(.*?)\}(.*)/', $name, $m); $this->name = $m[2]; $this->namespace = $m[1]; } elseif (substr_count($name, ':') == 1) { $s = explode(':', $name); $this->prefix = $s[0]; $this->name = $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) { // TODO: Need to re-examine this logic later. // Chop off []. $this->arraySize = explode(',', substr($this->name, $p + 1, -$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; } elseif ($this->prefix) { return $this->prefix . ':' . $this->name; } return $this->name; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Client.php000066400000000000000000000701631214222670500173020ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Value */ require_once 'SOAP/Value.php'; require_once 'SOAP/Base.php'; require_once 'SOAP/Transport.php'; require_once 'SOAP/WSDL.php'; require_once 'SOAP/Fault.php'; require_once 'SOAP/Parser.php'; // Arnaud: the following code was taken from DataObject and adapted to suit // this will be horrifically slow!!!! // NOTE: Overload SEGFAULTS ON PHP4 + Zend Optimizer // these two are BC/FC handlers for call in PHP4/5 /** * @package SOAP */ if (!class_exists('SOAP_Client_Overload')) { if (substr(zend_version(), 0, 1) > 1) { class SOAP_Client_Overload extends SOAP_Base { function __call($method, $args) { $return = null; $this->_call($method, $args, $return); return $return; } } } else { if (!function_exists('clone')) { eval('function clone($t) { return $t; }'); } eval(' class SOAP_Client_Overload extends SOAP_Base { function __call($method, $args, &$return) { return $this->_call($method, $args, $return); } }'); } } /** * SOAP Client Class * * This class is the main interface for making soap requests. * * basic usage: * $soapclient = new SOAP_Client( string path [ , boolean wsdl] ); * echo $soapclient->call( string methodname [ , array parameters] ); * * or, if using PHP 5+ or the overload extension: * $soapclient = new SOAP_Client( string path [ , boolean wsdl] ); * echo $soapclient->methodname( [ array parameters] ); * * * Originally based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Stig Bakken Conversion to PEAR * @author Dietrich Ayala Original Author */ class SOAP_Client extends SOAP_Client_Overload { /** * Communication endpoint. * * Currently the following transport formats are supported: * - HTTP * - SMTP * * Example endpoints: * http://www.example.com/soap/server.php * https://www.example.com/soap/server.php * mailto:soap@example.com * * @see SOAP_Client() * @var string */ var $_endpoint = ''; /** * The SOAP PORT name that is used by the client. * * @var string */ var $_portName = ''; /** * Endpoint type e.g. 'wdsl'. * * @var string */ var $_endpointType = ''; /** * The received xml. * * @var string */ var $xml; /** * The outgoing and incoming data stream for debugging. * * @var string */ var $wire; /** * The outgoing data stream for debugging. * * @var string */ var $_last_request = null; /** * The incoming data stream for debugging. * * @var string */ var $_last_response = null; /** * Options. * * @var array */ var $_options = array('trace' => false); /** * The character encoding used for XML parser, etc. * * @var string */ var $_encoding = SOAP_DEFAULT_ENCODING; /** * The array of SOAP_Headers that we are sending. * * @var array */ var $headersOut = null; /** * The headers we recieved back in the response. * * @var array */ var $headersIn = null; /** * Options for the HTTP_Request class (see HTTP/Request.php). * * @var array */ var $_proxy_params = array(); /** * The SOAP_Transport instance. * * @var SOAP_Transport */ var $_soap_transport = null; /** * Constructor. * * @access public * * @param string $endpoint An URL. * @param boolean $wsdl Whether the endpoint is a WSDL file. * @param string $portName The service's port name to use. * @param array $proxy_params Options for the HTTP_Request class * @see HTTP_Request * @param boolean|string $cache Use WSDL caching? The cache directory if * a string. */ function SOAP_Client($endpoint, $wsdl = false, $portName = false, $proxy_params = array(), $cache = false) { parent::SOAP_Base('Client'); $this->_endpoint = $endpoint; $this->_portName = $portName; $this->_proxy_params = $proxy_params; // This hack should perhaps be removed as it might cause unexpected // behaviour. $wsdl = $wsdl ? $wsdl : strtolower(substr($endpoint, -4)) == 'wsdl'; // make values if ($wsdl) { $this->_endpointType = 'wsdl'; // instantiate wsdl class $this->_wsdl = new SOAP_WSDL($this->_endpoint, $this->_proxy_params, $cache); if ($this->_wsdl->fault) { $this->_raiseSoapFault($this->_wsdl->fault); } } } function _reset() { $this->xml = null; $this->wire = null; $this->_last_request = null; $this->_last_response = null; $this->headersIn = null; $this->headersOut = null; } /** * Sets the character encoding. * * Limited to 'UTF-8', 'US_ASCII' and 'ISO-8859-1'. * * @access public * * @param string encoding * * @return mixed SOAP_Fault on error. */ function setEncoding($encoding) { if (in_array($encoding, $this->_encodings)) { $this->_encoding = $encoding; return; } return $this->_raiseSoapFault('Invalid Encoding'); } /** * Adds a header to the envelope. * * @access public * * @param SOAP_Header $soap_value A SOAP_Header or an array with the * elements 'name', 'namespace', * 'mustunderstand', and 'actor' to send * as a header. */ function addHeader($soap_value) { // Add a new header to the message. if (is_a($soap_value, 'SOAP_Header')) { $this->headersOut[] = $soap_value; } elseif (is_array($soap_value)) { // name, value, namespace, mustunderstand, actor $this->headersOut[] = new SOAP_Header($soap_value[0], null, $soap_value[1], $soap_value[2], $soap_value[3]); } else { $this->_raiseSoapFault('Invalid parameter provided to addHeader(). Must be an array or a SOAP_Header.'); } } /** * Calls a method on the SOAP endpoint. * * The namespace parameter is overloaded to accept an array of options * that can contain data necessary for various transports if it is used as * an array, it MAY contain a namespace value and a soapaction value. If * it is overloaded, the soapaction parameter is ignored and MUST be * placed in the options array. This is done to provide backwards * compatibility with current clients, but may be removed in the future. * The currently supported values are: * - 'namespace' * - 'soapaction' * - 'timeout': HTTP socket timeout * - 'transfer-encoding': SMTP transport, Content-Transfer-Encoding: header * - 'from': SMTP transport, From: header * - 'subject': SMTP transport, Subject: header * - 'headers': SMTP transport, hash of extra SMTP headers * - 'attachments': what encoding to use for attachments (Mime, Dime) * - 'trace': whether to trace the SOAP communication * - 'style': 'document' or 'rpc'; when set to 'document' the parameters * are not wrapped inside a tag with the SOAP action name * - 'use': 'literal' for literal encoding, anything else for section 5 * encoding; when set to 'literal' SOAP types will be omitted. * - 'keep_arrays_flat': use the tag name multiple times for each element * when passing in an array in literal mode * - 'no_type_prefix': supress adding of the namespace prefix * * @access public * * @param string $method The method to call. * @param array $params The method parameters. * @param string|array $namespace Namespace or hash with options. Note: * most options need to be repeated for * SOAP_Value instances. * @param string $soapAction * * @return mixed The method result or a SOAP_Fault on error. */ function call($method, $params, $namespace = false, $soapAction = false) { $this->headersIn = null; $this->_last_request = null; $this->_last_response = null; $this->wire = null; $this->xml = null; $soap_data = $this->_generate($method, $params, $namespace, $soapAction); if (PEAR::isError($soap_data)) { $fault = $this->_raiseSoapFault($soap_data); return $fault; } // _generate() may have changed the endpoint if the WSDL has more // than one service, so we need to see if we need to generate a new // transport to hook to a different URI. Since the transport protocol // can also change, we need to get an entirely new object. This could // probably be optimized. if (!$this->_soap_transport || $this->_endpoint != $this->_soap_transport->url) { $this->_soap_transport = SOAP_Transport::getTransport($this->_endpoint); if (PEAR::isError($this->_soap_transport)) { $fault = $this->_raiseSoapFault($this->_soap_transport); $this->_soap_transport = null; return $fault; } } $this->_soap_transport->encoding = $this->_encoding; // Send the message. $transport_options = array_merge_recursive($this->_proxy_params, $this->_options); $this->xml = $this->_soap_transport->send($soap_data, $transport_options); // Save the wire information for debugging. if ($this->_options['trace']) { $this->_last_request = $this->_soap_transport->outgoing_payload; $this->_last_response = $this->_soap_transport->incoming_payload; $this->wire = $this->getWire(); } if ($this->_soap_transport->fault) { $fault = $this->_raiseSoapFault($this->xml); return $fault; } if (isset($this->_options['result']) && $this->_options['result'] != 'parse') { return $this->xml; } $this->__result_encoding = $this->_soap_transport->result_encoding; $result = $this->parseResponse($this->xml, $this->__result_encoding, $this->_soap_transport->attachments); return $result; } /** * Sets an option to use with the transport layers. * * For example: * * $soapclient->setOpt('curl', CURLOPT_VERBOSE, 1) * * to pass a specific option to curl if using an SSL connection. * * @access public * * @param string $category Category to which the option applies or option * name. * @param string $option An option name if $category is a category name, * an option value if $category is an option name. * @param string $value An option value if $category is a category * name. */ function setOpt($category, $option, $value = null) { if (!is_null($value)) { if (!isset($this->_options[$category])) { $this->_options[$category] = array(); } $this->_options[$category][$option] = $value; } else { $this->_options[$category] = $option; } } /** * Call method supporting the overload extension. * * If the overload extension is loaded, you can call the client class with * a soap method name: * * $soap = new SOAP_Client(....); * $value = $soap->getStockQuote('MSFT'); * * * @access public * * @param string $method The method to call. * @param array $params The method parameters. * @param mixed $return_value Will get the method's return value * assigned. * * @return boolean Always true. */ function _call($method, $params, &$return_value) { // Overloading lowercases the method name, we need to look into the // WSDL and try to find the correct method name to get the correct // case for the call. if ($this->_wsdl) { $this->_wsdl->matchMethod($method); } $return_value = $this->call($method, $params); return true; } /** * Returns the XML content of the last SOAP request. * * @return string The last request. */ function getLastRequest() { return $this->_last_request; } /** * Returns the XML content of the last SOAP response. * * @return string The last response. */ function getLastResponse() { return $this->_last_response; } /** * Sets the SOAP encoding. * * The default encoding is section 5 encoded. * * @param string $use Either 'literal' or 'encoded' (section 5). */ function setUse($use) { $this->_options['use'] = $use; } /** * Sets the SOAP encoding style. * * The default style is rpc. * * @param string $style Either 'document' or 'rpc'. */ function setStyle($style) { $this->_options['style'] = $style; } /** * Sets whether to trace the traffic on the transport level. * * @see getWire() * * @param boolean $trace */ function setTrace($trace) { $this->_options['trace'] = $trace; } /** * Generates the complete XML SOAP message for an RPC call. * * @see call() * * @param string $method The method to call. * @param array $params The method parameters. * @param string|array $namespace Namespace or hash with options. Note: * most options need to be repeated for * SOAP_Value instances. * @param string $soapAction * * @return string The SOAP message including envelope. */ function _generate($method, $params, $namespace = false, $soapAction = false) { $this->fault = null; $this->_options['input'] = 'parse'; $this->_options['result'] = 'parse'; $this->_options['parameters'] = false; if ($params && !is_array($params)) { $params = array($params); } if (is_array($namespace)) { // Options passed as a hash. foreach ($namespace as $optname => $opt) { $this->_options[strtolower($optname)] = $opt; } } else { // We'll place $soapAction into our array for usage in the // transport. if ($soapAction) { $this->_options['soapaction'] = $soapAction; } if ($namespace) { $this->_options['namespace'] = $namespace; } } if (isset($this->_options['namespace'])) { $namespace = $this->_options['namespace']; } else { $namespace = false; } if ($this->_endpointType == 'wsdl') { $this->_setSchemaVersion($this->_wsdl->xsd); // Get port name. if (!$this->_portName) { $this->_portName = $this->_wsdl->getPortName($method); } if (PEAR::isError($this->_portName)) { return $this->_raiseSoapFault($this->_portName); } // Get endpoint. $this->_endpoint = $this->_wsdl->getEndpoint($this->_portName); if (PEAR::isError($this->_endpoint)) { return $this->_raiseSoapFault($this->_endpoint); } // Get operation data. $opData = $this->_wsdl->getOperationData($this->_portName, $method); if (PEAR::isError($opData)) { return $this->_raiseSoapFault($opData); } $namespace = $opData['namespace']; $this->_options['style'] = $opData['style']; $this->_options['use'] = $opData['input']['use']; $this->_options['soapaction'] = $opData['soapAction']; // Set input parameters. if ($this->_options['input'] == 'parse') { $this->_options['parameters'] = $opData['parameters']; $nparams = array(); if (isset($opData['input']['parts']) && count($opData['input']['parts'])) { foreach ($opData['input']['parts'] as $name => $part) { $xmlns = ''; $attrs = array(); // Is the name a complex type? if (isset($part['element'])) { $xmlns = $this->_wsdl->namespaces[$part['namespace']]; $part = $this->_wsdl->elements[$part['namespace']][$part['type']]; $name = $part['name']; } if (isset($params[$name]) || $this->_wsdl->getDataHandler($name, $part['namespace'])) { $nparams[$name] =& $params[$name]; } else { // We now force an associative array for // parameters if using WSDL. return $this->_raiseSoapFault("The named parameter $name is not in the call parameters."); } if (gettype($nparams[$name]) != 'object' || !is_a($nparams[$name], 'SOAP_Value')) { // Type is likely a qname, split it apart, and get // the type namespace from WSDL. $qname = new QName($part['type']); if ($qname->prefix) { $type_namespace = $this->_wsdl->namespaces[$qname->prefix]; } elseif (isset($part['namespace'])) { $type_namespace = $this->_wsdl->namespaces[$part['namespace']]; } else { $type_namespace = null; } $qname->namespace = $type_namespace; $pqname = $name; if ($xmlns) { $pqname = '{' . $xmlns . '}' . $name; } $nparams[$name] = new SOAP_Value($pqname, $qname->fqn(), $nparams[$name], $attrs); } else { // WSDL fixups to the SOAP value. } } } $params =& $nparams; unset($nparams); } } else { $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); } // Serialize the message. $this->_section5 = (!isset($this->_options['use']) || $this->_options['use'] != 'literal'); if (!isset($this->_options['style']) || $this->_options['style'] == 'rpc') { $this->_options['style'] = 'rpc'; $this->docparams = true; $mqname = new QName($method, $namespace); $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params, array(), $this->_options); $soap_msg = $this->makeEnvelope($methodValue, $this->headersOut, $this->_encoding, $this->_options); } else { if (!$params) { $mqname = new QName($method, $namespace); $params = new SOAP_Value($mqname->fqn(), 'Struct', null); } elseif ($this->_options['input'] == 'parse') { if (is_array($params)) { $nparams = array(); $keys = array_keys($params); foreach ($keys as $k) { if (gettype($params[$k]) != 'object') { $nparams[] = new SOAP_Value($k, false, $params[$k]); } else { $nparams[] =& $params[$k]; } } $params =& $nparams; } if ($this->_options['parameters']) { $mqname = new QName($method, $namespace); $params = new SOAP_Value($mqname->fqn(), 'Struct', $params); } } $soap_msg = $this->makeEnvelope($params, $this->headersOut, $this->_encoding, $this->_options); } $this->headersOut = null; if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } // Handle MIME or DIME encoding. // TODO: 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($this->_options['attachments']) && $this->_options['attachments'] == 'Mime') || isset($this->_options['Mime'])) { $soap_msg = $this->_makeMimeMessage($soap_msg, $this->_encoding); } else { // default is dime $soap_msg = $this->_makeDIMEMessage($soap_msg, $this->_encoding); $this->_options['headers']['Content-Type'] = 'application/dime'; } if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } } // Instantiate client. if (is_array($soap_msg)) { $soap_data = $soap_msg['body']; if (count($soap_msg['headers'])) { if (isset($this->_options['headers'])) { $this->_options['headers'] = array_merge($this->_options['headers'], $soap_msg['headers']); } else { $this->_options['headers'] = $soap_msg['headers']; } } } else { $soap_data = $soap_msg; } return $soap_data; } /** * Parses a SOAP response. * * @see SOAP_Parser:: * * @param string $response XML content of SOAP response. * @param string $encoding Character set encoding, defaults to 'UTF-8'. * @param array $attachments List of attachments. */ function parseResponse($response, $encoding, $attachments) { // Parse the response. $response = new SOAP_Parser($response, $encoding, $attachments); if ($response->fault) { $fault = $this->_raiseSoapFault($response->fault); return $fault; } // Return array of parameters. $return = $response->getResponse(); $headers = $response->getHeaders(); if ($headers) { $this->headersIn = $this->_decodeResponse($headers, false); } $decoded = $this->_decodeResponse($return); return $decoded; } /** * Converts a complex SOAP_Value into a PHP Array * * @param SOAP_Value $response Value object. * @param boolean $shift * * @return array */ function _decodeResponse($response, $shift = true) { if (!$response) { $decoded = null; return $decoded; } // Check for valid response. if (PEAR::isError($response)) { $fault = $this->_raiseSoapFault($response); return $fault; } elseif (!is_a($response, 'soap_value')) { $fault = $this->_raiseSoapFault("Didn't get SOAP_Value object back from client"); return $fault; } // Decode to native php datatype. $returnArray = $this->_decode($response); // Fault? if (PEAR::isError($returnArray)) { $fault = $this->_raiseSoapFault($returnArray); return $fault; } if (is_object($returnArray) && strcasecmp(get_class($returnArray), 'stdClass') == 0) { $returnArray = get_object_vars($returnArray); } if (is_array($returnArray)) { if (isset($returnArray['faultcode']) || isset($returnArray[SOAP_BASE::SOAPENVPrefix().':faultcode'])) { $faultcode = $faultstring = $faultdetail = $faultactor = ''; foreach ($returnArray as $k => $v) { if (stristr($k, 'faultcode')) $faultcode = $v; if (stristr($k, 'faultstring')) $faultstring = $v; if (stristr($k, 'detail')) $faultdetail = $v; if (stristr($k, 'faultactor')) $faultactor = $v; } $fault = $this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); return $fault; } // Return array of return values. if ($shift && count($returnArray) == 1) { $decoded = array_shift($returnArray); return $decoded; } return $returnArray; } return $returnArray; } /** * Returns the outgoing and incoming traffic on the transport level. * * Tracing has to be enabled. * * @see setTrace() * * @return string The complete traffic between the client and the server. */ function getWire() { if ($this->_options['trace'] && ($this->_last_request || $this->_last_response)) { return "OUTGOING:\n\n" . $this->_last_request . "\n\nINCOMING\n\n" . preg_replace("/>\r\n<", $this->_last_response); } return null; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Disco.php000066400000000000000000000364621214222670500171310ustar00rootroot00000000000000 * @author Chuck Hagenbuch * @author Jan Schneider * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Base */ require_once 'SOAP/Base.php'; /** * @package SOAP */ class SOAP_DISCO_Server extends SOAP_Base_Object { var $namespaces = array(SCHEMA_WSDL => 'wsdl', SCHEMA_SOAP => 'soap'); var $import_ns = array(); var $wsdl = ''; var $disco = ''; var $_wsdl = array(); var $_disco = array(); var $_service_name = ''; var $_service_ns = ''; var $_service_desc = ''; var $_portname = ''; var $_bindingname = ''; var $soap_server = NULL; function SOAP_DISCO_Server($soap_server, $service_name, $service_desc = '', $import_ns = null) { parent::SOAP_Base_Object('Server'); if ( !is_object($soap_server) || !get_class($soap_server) == 'soap_server') return; $this->_service_name = $service_name; $this->_service_ns = "urn:$service_name"; $this->_service_desc = $service_desc; $this->import_ns = isset($import_ns) ? $import_ns : $this->import_ns; $this->soap_server = $soap_server; $this->host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'; } function getDISCO() { $this->_generate_DISCO(); return $this->disco; } function getWSDL() { $this->_generate_WSDL(); return $this->wsdl; } function _generate_DISCO() { // DISCO $this->_disco['disco:discovery']['attr']['xmlns:disco'] = SCHEMA_DISCO; $this->_disco['disco:discovery']['attr']['xmlns:scl'] = SCHEMA_DISCO_SCL; $this->_disco['disco:discovery']['scl:contractRef']['attr']['ref'] = (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl' : 'http://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl'; // generate disco xml $this->_generate_DISCO_XML($this->_disco); } function _generate_WSDL() { // WSDL if (is_array($this->soap_server->_namespaces)) { // need to get: typens, xsd & SOAP-ENC $flipped = array_flip($this->soap_server->_namespaces); $this->namespaces[$this->_service_ns] = 'tns'; $this->namespaces[$flipped['xsd']] = 'xsd'; $this->namespaces[$flipped[SOAP_BASE::SOAPENCPrefix()]] = SOAP_BASE::SOAPENCPrefix(); } // DEFINITIONS $this->_wsdl['definitions']['attr']['name'] = $this->_service_name; $this->_wsdl['definitions']['attr']['targetNamespace'] = $this->_service_ns; foreach ($this->namespaces as $ns => $prefix) { $this->_wsdl['definitions']['attr']['xmlns:' . $prefix] = $ns; } $this->_wsdl['definitions']['attr']['xmlns'] = SCHEMA_WSDL; // Import namespaces. Seems to not work yet: wsdl.exe fom .NET can't // handle imported complete wsdl-definitions. if (count($this->import_ns)) { $i = 0; foreach ($this->import_ns as $_ns => $_location) { $this->_wsdl['definitions']['import'][$i]['attr']['location'] = $_location; $this->_wsdl['definitions']['import'][$i]['attr']['namespace'] = $_ns; $i++; } } $this->_wsdl['definitions']['types']['attr']['xmlns']='http://schemas.xmlsoap.org/wsdl/'; $this->_wsdl['definitions']['types']['schema']=array(); // Placeholder for messages $this->_wsdl['definitions']['message'] = array(); // PORTTYPE-NAME $this->_portname = $this->_service_name . 'Port'; $this->_wsdl['definitions']['portType']['attr']['name'] = $this->_portname; // BINDING-NAME $this->_bindingname = $this->_service_name . 'Binding'; $this->_wsdl['definitions']['binding']['attr']['name'] = $this->_bindingname; $this->_wsdl['definitions']['binding']['attr']['type'] = 'tns:' . $this->_portname; $this->_wsdl['definitions']['binding']['soap:binding']['attr']['style'] = 'rpc'; $this->_wsdl['definitions']['binding']['soap:binding']['attr']['transport'] = SCHEMA_SOAP_HTTP; // SERVICE $this->_wsdl['definitions']['service']['attr']['name'] = $this->_service_name . 'Service'; $this->_wsdl['definitions']['service']['documentation']['attr'] = ''; $this->_wsdl['definitions']['service']['documentation'] = htmlentities($this->_service_desc); $this->_wsdl['definitions']['service']['port']['attr']['name'] = $this->_portname; $this->_wsdl['definitions']['service']['port']['attr']['binding'] = 'tns:' . $this->_bindingname; $this->_wsdl['definitions']['service']['port']['soap:address']['attr']['location'] = (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') ? 'https://' . $this->host . $_SERVER['PHP_SELF'] : 'http://' . $this->host . $_SERVER['PHP_SELF']; // $dispatch_keys = array_keys($this->soap_server->dispatch_objects); $dc = count($dispatch_keys); for ($di = 0; $di < $dc; $di++) { $namespace = $dispatch_keys[$di]; $namespace_objects =& $this->soap_server->dispatch_objects[$namespace]; $oc = count($namespace_objects); for ($oi = 0; $oi < $oc; $oi++) { $object = $namespace_objects[$oi]; // types definitions $this->addSchemaFromMap($object->__typedef); // MESSAGES $this->addMethodsFromMap($object->__dispatch_map, $namespace, get_class($object)); } } if (isset($this->soap_server->dispatch_map)) { $this->addMethodsFromMap($this->soap_server->dispatch_map, $namespace); } // generate wsdl $this->_generate_WSDL_XML(); } function &_getSchema($namespace) { // SCHEMA $c = count($this->_wsdl['definitions']['types']['schema']); for($i = 0; $i < $c; $i++) { if ($this->_wsdl['definitions']['types']['schema'][$i]['attr']['targetNamespace'] == $namespace) { return $this->_wsdl['definitions']['types']['schema'][$i]; } } // don't have this namespace $schema = array(); $schema['attr'] = array(); $schema['complexType'] = array(); $schema['attr']['xmlns'] = array_search('xsd',$this->namespaces); $schema['attr']['targetNamespace'] = $namespace; $this->_wsdl['definitions']['types']['schema'][] =& $schema; return $schema; } function addSchemaFromMap(&$map) { if (!$map) { return; } foreach ($map as $_type_name => $_type_def) { list($typens,$type) = $this->_getTypeNs($_type_name); if ($typens == 'xsd') { // cannot add to xsd, lets use method_namespace $typens = 'tns'; } $schema =& $this->_getSchema(array_search($typens, $this->namespaces)); if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) { $ctype =& $schema['complexType'][]; $ctype['attr']['name'] = $type; foreach ($_type_def as $_varname => $_vartype) { if (!is_int($_varname)) { list($_vartypens,$_vartype) = $this->_getTypeNs($_vartype); $ctype['all']['attr'] = ''; $el =& $ctype['all']['element'][]; $el['attr']['name'] = $_varname; $el['attr']['type'] = $_vartypens . ':' . $_vartype; } else { $ctype['complexContent']['attr'] = ''; $ctype['complexContent']['restriction']['attr']['base'] = SOAP_BASE::SOAPENCPrefix().':Array'; foreach ($_vartype as $array_type) { list($_vartypens, $_vartype) = $this->_getTypeNs($array_type); $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = SOAP_BASE::SOAPENCPrefix().':arrayType'; $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]'; } } } } } } function addMethodsFromMap(&$map, $namespace, $classname = null) { if (!$map) { return; } foreach ($map as $method_name => $method_types) { if (array_key_exists('namespace', $method_types)) { $method_namespace = $method_types['namespace']; } else { $method_namespace = $namespace; } // INPUT $input_message = array('attr' => array('name' => $method_name . 'Request')); if (isset($method_types['in']) && is_array($method_types['in'])) { foreach ($method_types['in'] as $name => $type) { list($typens, $type) = $this->_getTypeNs($type); $part = array(); $part['attr']['name'] = $name; $part['attr']['type'] = $typens . ':' . $type; $input_message['part'][] = $part; } } $this->_wsdl['definitions']['message'][] = $input_message; // OUTPUT $output_message = array('attr' => array('name' => $method_name . 'Response')); if (isset($method_types['out']) && is_array($method_types['out'])) { foreach ($method_types['out'] as $name => $type) { list($typens, $type) = $this->_getTypeNs($type); $part = array(); $part['attr']['name'] = $name; $part['attr']['type'] = $typens . ':' . $type; $output_message['part'][] = $part; } } $this->_wsdl['definitions']['message'][] = $output_message; // PORTTYPES $operation = array(); $operation['attr']['name'] = $method_name; // INPUT $operation['input']['attr']['message'] = 'tns:' . $input_message['attr']['name']; // OUTPUT $operation['output']['attr']['message'] = 'tns:' . $output_message['attr']['name']; $this->_wsdl['definitions']['portType']['operation'][] = $operation; // BINDING $binding = array(); $binding['attr']['name'] = $method_name; $action = $method_namespace . '#' . ($classname ? $classname . '#' : '') . $method_name; $binding['soap:operation']['attr']['soapAction'] = $action; // INPUT $binding['input']['attr'] = ''; $binding['input']['soap:body']['attr']['use'] = 'encoded'; $binding['input']['soap:body']['attr']['namespace'] = $method_namespace; $binding['input']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING; // OUTPUT $binding['output']['attr'] = ''; $binding['output']['soap:body']['attr']['use'] = 'encoded'; $binding['output']['soap:body']['attr']['namespace'] = $method_namespace; $binding['output']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING; $this->_wsdl['definitions']['binding']['operation'][] = $binding; } } function _generate_DISCO_XML($disco_array) { $disco = ''; foreach ($disco_array as $key => $val) { $disco .= $this->_arrayToNode($key,$val); } $this->disco = $disco; } function _generate_WSDL_XML() { $wsdl = ''; foreach ($this->_wsdl as $key => $val) { $wsdl .= $this->_arrayToNode($key, $val); } $this->wsdl = $wsdl; } function _arrayToNode($node_name = '', $array) { $return = ''; if (is_array($array)) { // we have a node if there's key 'attr' if (array_key_exists('attr',$array)) { $return .= "<$node_name"; if (is_array($array['attr'])) { foreach ($array['attr'] as $attr_name => $attr_value) { $return .= " $attr_name=\"$attr_value\""; } } // unset 'attr' and proceed other childs... unset($array['attr']); if (count($array) > 0) { $i = 0; foreach ($array as $child_node_name => $child_node_value) { $return .= $i == 0 ? ">\n" : ''; $return .= $this->_arrayToNode($child_node_name,$child_node_value); $i++; } $return .= "\n"; } else { $return .= " />\n"; } } else { // we have no 'attr' key in array - so it's list of nodes with // the same name ... foreach ($array as $child_node_name => $child_node_value) { $return .= $this->_arrayToNode($node_name,$child_node_value); } } } else { // $array is not an array if ($array !='') { // and its not empty $return .= "<$node_name>$array\n"; } else { // and its empty... $return .= "<$node_name />\n"; } } return $return; } function _getTypeNs($type) { preg_match_all("'\{(.*)\}'sm", $type, $m); if (isset($m[1][0]) && $m[1][0] != '') { if (!array_key_exists($m[1][0],$this->namespaces)) { $ns_pref = 'ns' . count($this->namespaces); $this->namespaces[$m[1][0]] = $ns_pref; $this->_wsdl['definitions']['attr']['xmlns:' . $ns_pref] = $m[1][0]; } $typens = $this->namespaces[$m[1][0]]; $type = preg_replace('/'.$m[0][0].'/', '', $type); } else { $typens = 'xsd'; } return array($typens,$type); } function _ifComplexTypeExists($typesArray, $type_name) { if (is_array($typesArray)) { foreach ($typesArray as $type_data) { if ($type_data['attr']['name'] == $type_name) { return true; } } } return false; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Fault.php000066400000000000000000000102121214222670500171240ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2006 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** PEAR_Error */ require_once 'PEAR.php'; /** * PEAR::Error wrapper used to match SOAP Faults to PEAR Errors * * SOAP_Fault can provide a complete backtrace of the error. Revealing these * details in a public web services is a bad idea because it can be used by * attackers. Thus you have to enable backtrace information in SOAP_Fault * responses by putting the following code in your script after your * "require_once 'SOAP/Server.php';" line: * * * $backtrace =& PEAR::getStaticProperty('SOAP_Fault', 'backtrace'); * $backtrace = true; * * * @package SOAP * @access public * @author Shane Caraveo Port to PEAR and more * @author Dietrich Ayala Original Author */ class SOAP_Fault extends PEAR_Error { /** * Constructor. * * @param string $faultstring Message string for fault. * @param mixed $faultcode The faultcode. * @param mixed $faultactor * @param mixed $detail @see PEAR_Error * @param array $mode @see PEAR_Error * @param array $options @see PEAR_Error */ function SOAP_Fault($faultstring = 'unknown error', $faultcode = 'Client', $faultactor = null, $detail = null, $mode = null, $options = null) { parent::PEAR_Error($faultstring, $faultcode, $mode, $options, $detail); if ($faultactor) { $this->error_message_prefix = $faultactor; } } /** * Returns a SOAP XML message that can be sent as a server response. * * @return string */ function message($encoding = SOAP_DEFAULT_ENCODING) { $msg = new SOAP_Base(); $params = array(); $params[] = new SOAP_Value('faultcode', 'QName', SOAP_BASE::SOAPENVPrefix().':' . $this->code); $params[] = new SOAP_Value('faultstring', 'string', $this->message); $params[] = new SOAP_Value('faultactor', 'anyURI', $this->error_message_prefix); if (PEAR::getStaticProperty('SOAP_Fault', 'backtrace') && isset($this->backtrace)) { $params[] = new SOAP_Value('detail', 'string', $this->backtrace); } else { $params[] = new SOAP_Value('detail', 'string', $this->userinfo); } $methodValue = new SOAP_Value('{' . SOAP_ENVELOP . '}Fault', 'Struct', $params); $headers = null; return $msg->makeEnvelope($methodValue, $headers, $encoding); } /** * Returns a simple native PHP array containing the fault data. * * @return array */ function getFault() { $fault = new stdClass(); $fault->faultcode = $this->code; $fault->faultstring = $this->message; $fault->faultactor = $this->error_message_prefix; $fault->detail = $this->userinfo; return $fault; } /** * Returns the SOAP actor for the fault. * * @return string */ function getActor() { return $this->error_message_prefix; } /** * Returns the fault detail. * * @return string */ function getDetail() { return $this->userinfo; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Parser.php000066400000000000000000000453041214222670500173170ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Base.php'; require_once 'SOAP/Value.php'; /** * SOAP Parser * * This class is used by SOAP::Message and SOAP::Server to parse soap * packets. Originally based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Dietrich Ayala Original Author */ class SOAP_Parser extends SOAP_Base { var $status = ''; var $position = 0; var $depth = 0; var $default_namespace = ''; var $message = array(); var $depth_array = array(); var $parent = 0; var $root_struct_name = array(); var $header_struct_name = array(); var $curent_root_struct_name = ''; var $root_struct = array(); var $header_struct = array(); var $curent_root_struct = 0; var $references = array(); var $need_references = array(); /** * Used to handle non-root elements before root body element. * * @var integer */ var $bodyDepth; /** * Constructor. * * @param string $xml XML content. * @param string $encoding Character set encoding, defaults to 'UTF-8'. * @param array $attachments List of attachments. */ function SOAP_Parser($xml, $encoding = SOAP_DEFAULT_ENCODING, $attachments = null) { parent::SOAP_Base('Parser'); $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); $this->attachments = $attachments; // Check the XML tag for encoding. if (preg_match('/<\?xml[^>]+encoding\s*?=\s*?(\'([^\']*)\'|"([^"]*)")[^>]*?[\?]>/', $xml, $m)) { $encoding = strtoupper($m[2] ? $m[2] : $m[3]); } // Determine where in the message we are (envelope, header, body, // method). Check whether content has been read. if (!empty($xml)) { // Prepare the XML parser. $parser = xml_parser_create($encoding); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($parser, $this); xml_set_element_handler($parser, '_startElement', '_endElement'); xml_set_character_data_handler($parser, '_characterData'); // Some lame SOAP implementations add nul bytes at the end of the // SOAP stream, and expat chokes on that. if ($xml[strlen($xml) - 1] == 0) { $xml = trim($xml); } // Parse the XML file. if (!xml_parse($parser, $xml, true)) { $err = sprintf('XML error on line %d col %d byte %d %s', xml_get_current_line_number($parser), xml_get_current_column_number($parser), xml_get_current_byte_index($parser), xml_error_string(xml_get_error_code($parser))); $this->_raiseSoapFault($err, htmlspecialchars($xml)); } xml_parser_free($parser); } } /** * Returns an array of responses. * * After parsing a SOAP message, use this to get the response. * * @return array */ function getResponse() { if (!empty($this->root_struct[0])) { return $this->_buildResponse($this->root_struct[0]); } else { return $this->_raiseSoapFault('Cannot build response'); } } /** * Returns an array of header responses. * * After parsing a SOAP message, use this to get the response. * * @return array */ function getHeaders() { if (!empty($this->header_struct[0])) { return $this->_buildResponse($this->header_struct[0]); } else { // We don't fault if there are no headers; that can be handled by // the application if necessary. return null; } } /** * Recurses to build a multi dimensional array. * * @see _buildResponse() */ function _domulti($d, &$ar, &$r, &$v, $ad = 0) { if ($d) { $this->_domulti($d - 1, $ar, $r[$ar[$ad]], $v, $ad + 1); } else { $r = $v; } } /** * Loops through the message, building response structures. * * @param integer $pos Position. * * @return SOAP_Value */ function _buildResponse($pos) { $response = null; if (isset($this->message[$pos]['children'])) { $children = explode('|', $this->message[$pos]['children']); foreach ($children as $c => $child_pos) { if ($this->message[$child_pos]['type'] != null) { $response[] = $this->_buildResponse($child_pos); } } if (isset($this->message[$pos]['arraySize'])) { $ardepth = count($this->message[$pos]['arraySize']); if ($ardepth > 1) { $ar = array_pad(array(), $ardepth, 0); if (isset($this->message[$pos]['arrayOffset'])) { for ($i = 0; $i < $ardepth; $i++) { $ar[$i] += $this->message[$pos]['arrayOffset'][$i]; } } $elc = count($response); for ($i = 0; $i < $elc; $i++) { // Recurse to build a multi dimensional array. $this->_domulti($ardepth, $ar, $newresp, $response[$i]); // Increment our array pointers. $ad = $ardepth - 1; $ar[$ad]++; while ($ad > 0 && $ar[$ad] >= $this->message[$pos]['arraySize'][$ad]) { $ar[$ad] = 0; $ad--; $ar[$ad]++; } } $response = $newresp; } elseif (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); } } } // Build attributes. $attrs = array(); foreach ($this->message[$pos]['attrs'] as $atn => $atv) { if (!strstr($atn, 'xmlns') && !strpos($atn, ':')) { $attrs[$atn] = $atv; } } // Add current node's value. $nqn = new QName($this->message[$pos]['name'], $this->message[$pos]['namespace']); $tqn = new QName($this->message[$pos]['type'], $this->message[$pos]['type_namespace']); if ($response) { $response = new SOAP_Value($nqn->fqn(), $tqn->fqn(), $response, $attrs); if (isset($this->message[$pos]['arrayType'])) { $response->arrayType = $this->message[$pos]['arrayType']; } } else { // Check if value is an empty array if ($tqn->name == 'Array') { $response = new SOAP_Value($nqn->fqn(), $tqn->fqn(), array(), $attrs); //if ($pos == 4) var_dump($this->message[$pos], $response); } else { $response = new SOAP_Value($nqn->fqn(), $tqn->fqn(), $this->message[$pos]['cdata'], $attrs); } } // Handle header attribute that we need. if (array_key_exists('actor', $this->message[$pos])) { $response->actor = $this->message[$pos]['actor']; } if (array_key_exists('mustUnderstand', $this->message[$pos])) { $response->mustunderstand = $this->message[$pos]['mustUnderstand']; } return $response; } /** * Start element handler used with the XML parser. */ function _startElement($parser, $name, $attrs) { // Position in a total number of elements, starting from 0. // Update class level position. $pos = $this->position++; // And set mine. $this->message[$pos] = array( 'type' => '', 'type_namespace' => '', 'cdata' => '', 'pos' => $pos, 'id' => ''); // Parent/child/depth determinations. // depth = How many levels removed from root? // Set mine as current global depth and increment global depth value. $this->message[$pos]['depth'] = $this->depth++; // Else add self as child to whoever the current parent is. if ($pos != 0) { if (isset($this->message[$this->parent]['children'])) { $this->message[$this->parent]['children'] .= '|' . $pos; } else { $this->message[$this->parent]['children'] = $pos; } } // Set my parent. $this->message[$pos]['parent'] = $this->parent; // Set self as current value for this depth. $this->depth_array[$this->depth] = $pos; // Set self as current parent. $this->parent = $pos; $qname = new QName($name); // Set status. if (strcasecmp('envelope', $qname->name) == 0) { $this->status = 'envelope'; } elseif (strcasecmp('header', $qname->name) == 0) { $this->status = 'header'; $this->header_struct_name[] = $this->curent_root_struct_name = $qname->name; $this->header_struct[] = $this->curent_root_struct = $pos; $this->message[$pos]['type'] = 'Struct'; } elseif (strcasecmp('body', $qname->name) == 0) { $this->status = 'body'; $this->bodyDepth = $this->depth; // Set method } elseif ($this->status == 'body') { // Is this element allowed to be a root? // TODO: this needs to be optimized, we loop through $attrs twice // now. $can_root = $this->depth == $this->bodyDepth + 1; if ($can_root) { foreach ($attrs as $key => $value) { if (stristr($key, ':root') && !$value) { $can_root = false; } } } if ($can_root) { $this->status = 'method'; $this->root_struct_name[] = $this->curent_root_struct_name = $qname->name; $this->root_struct[] = $this->curent_root_struct = $pos; $this->message[$pos]['type'] = 'Struct'; } } // Set my status. $this->message[$pos]['status'] = $this->status; // Set name. $this->message[$pos]['name'] = htmlspecialchars($qname->name); // Set attributes. $this->message[$pos]['attrs'] = $attrs; // Loop through attributes, logging ns and type declarations. foreach ($attrs as $key => $value) { // If ns declarations, add to class level array of valid // namespaces. $kqn = new QName($key); if ($kqn->prefix == 'xmlns') { $prefix = $kqn->name; if (in_array($value, $this->_XMLSchema)) { $this->_setSchemaVersion($value); } $this->_namespaces[$value] = $prefix; // Set method namespace. } elseif ($key == 'xmlns') { $qname->prefix = $this->_getNamespacePrefix($value); $qname->namespace = $value; } elseif ($kqn->name == 'actor') { $this->message[$pos]['actor'] = $value; } elseif ($kqn->name == 'mustUnderstand') { $this->message[$pos]['mustUnderstand'] = $value; // If it's a type declaration, set type. } elseif ($kqn->name == 'type') { $vqn = new QName($value); $this->message[$pos]['type'] = $vqn->name; $this->message[$pos]['type_namespace'] = $this->_getNamespaceForPrefix($vqn->prefix); // Should do something here with the namespace of specified // type? } elseif ($kqn->name == 'arrayType') { $vqn = new QName($value); $this->message[$pos]['type'] = 'Array'; if (isset($vqn->arraySize)) { $this->message[$pos]['arraySize'] = $vqn->arraySize; } $this->message[$pos]['arrayType'] = $vqn->name; } elseif ($kqn->name == 'offset') { $this->message[$pos]['arrayOffset'] = explode(',', substr($value, 1, strlen($value) - 2)); } elseif ($kqn->name == 'id') { // Save id to reference array. $this->references[$value] = $pos; $this->message[$pos]['id'] = $value; } elseif ($kqn->name == 'href') { if ($value[0] == '#') { $ref = substr($value, 1); if (isset($this->references[$ref])) { // 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; } } elseif (isset($this->attachments[$value])) { $this->message[$pos]['cdata'] = $this->attachments[$value]; } } } // See if namespace is defined in tag. if (isset($attrs['xmlns:' . $qname->prefix])) { $namespace = $attrs['xmlns:' . $qname->prefix]; } elseif ($qname->prefix && !$qname->namespace) { $namespace = $this->_getNamespaceForPrefix($qname->prefix); } else { // Get namespace. $namespace = $qname->namespace ? $qname->namespace : $this->default_namespace; } $this->message[$pos]['namespace'] = $namespace; $this->default_namespace = $namespace; } /** * End element handler used with the XML parser. */ function _endElement($parser, $name) { // Position of current element is equal to the last value left in // depth_array for my depth. $pos = $this->depth_array[$this->depth]; // Bring depth down a notch. $this->depth--; $qname = new QName($name); // Get type if not explicitly declared in an xsi:type attribute. // TODO: check on integrating WSDL validation here. if ($this->message[$pos]['type'] == '') { 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 && $this->message[$children[1]]['name'] == $this->message[$children[2]]['name']) { $this->message[$pos]['type'] = 'Array'; } else { $this->message[$pos]['type'] = 'Struct'; }*/ $this->message[$pos]['type'] = 'Struct'; } else { $parent = $this->message[$pos]['parent']; if ($this->message[$parent]['type'] == 'Array' && isset($this->message[$parent]['arrayType'])) { $this->message[$pos]['type'] = $this->message[$parent]['arrayType']; } else { $this->message[$pos]['type'] = 'string'; } } } // If tag we are currently closing is the method wrapper. if ($pos == $this->curent_root_struct) { $this->status = 'body'; } elseif ($qname->name == 'Body' || $qname->name == 'Header') { $this->status = 'envelope'; } // Set parent back to my parent. $this->parent = $this->message[$pos]['parent']; // Handle any reverse references now. $idref = $this->message[$pos]['id']; if ($idref != '' && isset($this->need_references[$idref])) { foreach ($this->need_references[$idref] as $ref_pos) { // XXX is this stuff there already? $this->message[$ref_pos]['children'] = &$this->message[$pos]['children']; $this->message[$ref_pos]['cdata'] = &$this->message[$pos]['cdata']; $this->message[$ref_pos]['type'] = &$this->message[$pos]['type']; $this->message[$ref_pos]['arraySize'] = &$this->message[$pos]['arraySize']; $this->message[$ref_pos]['arrayType'] = &$this->message[$pos]['arrayType']; } } } /** * Element content handler used with the XML parser. */ function _characterData($parser, $data) { $pos = $this->depth_array[$this->depth]; if (isset($this->message[$pos]['cdata'])) { $this->message[$pos]['cdata'] .= $data; } else { $this->message[$pos]['cdata'] = $data; } } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Server.php000066400000000000000000000763501214222670500173360ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; require_once 'SOAP/Parser.php'; require_once 'SOAP/Value.php'; require_once 'SOAP/WSDL.php'; /** * SOAP Server Class * * Originaly based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Dietrich Ayala Original Author */ class SOAP_Server extends SOAP_Base { /** * * @var array */ var $dispatch_map = array(); // create empty dispatch map var $dispatch_objects = array(); var $soapobject = null; var $call_methodname = null; var $callHandler = null; var $callValidation = true; /** * A list of headers that are going to be sent back to the client. * * @var array */ var $headers = array(); /** * * @var string */ var $request = ''; /** * * @var string XML-Encoding */ var $xml_encoding = SOAP_DEFAULT_ENCODING; var $response_encoding = 'UTF-8'; var $result = 'successful'; // for logging interop results to db var $endpoint = ''; // the uri to ME! var $service = ''; //soapaction header var $method_namespace = null; /** * Options. * * @var array */ var $_options = array('use' => 'encoded', 'style' => 'rpc', 'parameters' => 0, 'http_status_success' => '200 OK', 'http_status_fault' => '500 SOAP Fault'); function SOAP_Server($options = null) { ini_set('track_errors', 1); parent::SOAP_Base('Server'); if (is_array($options)) { if (isset($options['use'])) { $this->_options['use'] = $options['use']; } if (isset($options['style'])) { $this->_options['style'] = $options['style']; } if (isset($options['parameters'])) { $this->_options['parameters'] = $options['parameters']; } } // assume we encode with section 5 $this->_section5 = true; if ($this->_options['use'] == 'literal') { $this->_section5 = false; } } /** * Error handler for errors that happen in proxied methods. * * To always return a valid SOAP response even on errors that don't happen * in this code, the errors are catched, transformed to a SOAP fault and * immediately sent to the client. * * @see http://www.php.net/set_error_handler */ function _errorHandler($errno, $errmsg, $filename, $linenum) { /* The error handler should ignore '0' errors, eg. hidden by @ - see * the set_error_handler manual page. (thanks to Alan Knowles). */ if (!$errno || !error_reporting() || $errno == E_NOTICE || (defined('E_STRICT') && $errno == constant('E_STRICT'))) { return false; } $this->fault = new SOAP_Fault($errmsg, 'Server', 'PHP', "Errno: $errno\nFilename: $filename\nLineno: $linenum\n"); $this->_sendResponse(); exit; } function _getContentEncoding($content_type) { /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ $this->xml_encoding = 'UTF-8'; if (strpos($content_type, '=')) { $enc = strtoupper(str_replace('"', '', substr(strstr($content_type, '='), 1))); if (!in_array($enc, $this->_encodings)) { return false; } $this->xml_encoding = $enc; } return true; } /** * Parses the request and posts or returns the response. * * @param string $data The SOAP request data. * @param string $endpoint The service endpoint. Determined automatically * if left empty. * @param boolean $test * @param boolean $return Whether to return the SOAP response data * instead of sending it to the client. */ function service($data, $endpoint = '', $test = false, $return = false) { $response = null; $attachments = array(); $useEncoding = 'DIME'; /* Figure out our endpoint. */ $this->endpoint = $endpoint; if (!$test && !$this->endpoint) { /* We'll try to build our endpoint. */ $this->endpoint = 'http://' . $_SERVER['SERVER_NAME']; if (isset($_SERVER['SERVER_PORT'])) { $this->endpoint .= ':' . $_SERVER['SERVER_PORT']; } $this->endpoint .= $_SERVER['SCRIPT_NAME']; } /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ if (isset($_SERVER['CONTENT_TYPE'])) { if (strcasecmp($_SERVER['CONTENT_TYPE'], 'application/dime') == 0) { $this->_decodeDIMEMessage($data, $this->headers, $attachments); $useEncoding = 'DIME'; } elseif (stristr($_SERVER['CONTENT_TYPE'], 'multipart/related')) { /* This is a mime message, let's decode it. */ $data = 'Content-Type: ' . stripslashes($_SERVER['CONTENT_TYPE']) . "\r\n\r\n" . $data; $this->_decodeMimeMessage($data, $this->headers, $attachments); $useEncoding = 'Mime'; } if (!isset($this->headers['content-type'])) { $this->headers['content-type'] = stripslashes($_SERVER['CONTENT_TYPE']); } if (!$this->fault && !$this->_getContentEncoding($this->headers['content-type'])) { $this->xml_encoding = SOAP_DEFAULT_ENCODING; /* Found encoding we don't understand; return a fault. */ $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); } } /* If this is not a POST with Content-Type text/xml, try to return a * WSDL file. */ if (!$this->fault && !$test && ((isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'POST') || (isset($this->headers['content-type']) && strncmp($this->headers['content-type'], 'text/xml', 8) != 0))) { /* This is not possibly a valid SOAP request, try to return a WSDL * file. */ $got = isset($this->headers['content-type']) ? $this->headers['content-type'] : 'Nothing!'; $this->_raiseSoapFault('Invalid SOAP request, must be POST with content-type: text/xml, got: ' . $got, '', '', 'Server'); } if (!$this->fault) { /* $response is a SOAP_Msg object. */ $soap_msg = $this->parseRequest($data, $attachments); /* Handle Mime or DIME encoding. */ /* TODO: DIME decoding 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); $this->headers['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'])) { $this->headers = $soap_msg['headers']; } } else { $response = $soap_msg; } } if ($return) { if ($this->fault) { $response = $this->fault->message(); } return $response; } $this->_sendResponse($response); } /** * Sends the final HTTP response to the client, including the HTTP header * and the HTTP body. * * If an error happened, it returns a SOAP fault instead of the response * body. * * @param string $response The response body. */ function _sendResponse($response = '') { /* Make distinction between the different SAPIs, running PHP as CGI or * as a module. */ if (stristr(php_sapi_name(), 'cgi') === 0) { $hdrs_type = 'Status:'; } else { $hdrs_type = 'HTTP/1.1'; } if ($this->fault) { $hdrs = $hdrs_type . ' ' . $this->_options['http_status_fault'] . "\r\n"; $response = $this->fault->message($this->response_encoding); } else { $hdrs = $hdrs_type . ' ' . $this->_options['http_status_success'] . "\r\n"; } header($hdrs); $this->headers['Server'] = SOAP_LIBRARY_NAME; if (!isset($this->headers['Content-Type'])) { $this->headers['Content-Type'] = 'text/xml; charset=' . $this->response_encoding; } $this->headers['Content-Length'] = strlen($response); foreach ($this->headers as $k => $v) { $v = str_replace(array("\r", "\n"), '', $v); header("$k: $v"); $hdrs .= "$k: $v\r\n"; } $this->response = $hdrs . "\r\n" . $response; print $response; } function &callMethod($methodname, &$args) { if ($this->callHandler) { $ret = @call_user_func_array($this->callHandler, array($methodname, $args)); return $ret; } set_error_handler(array($this, '_errorHandler')); if ($args) { /* Call method with parameters. */ if (isset($this->soapobject) && is_object($this->soapobject)) { $ret = call_user_func_array(array(&$this->soapobject, $methodname), $args); } else { $ret = call_user_func_array($methodname, $args); } } else { /* Call method withour parameters. */ if (is_object($this->soapobject)) { $ret = call_user_func(array(&$this->soapobject, $methodname)); } else { $ret = call_user_func($methodname); } } restore_error_handler(); return $ret; } /** * Creates SOAP_Value objects with return values from method. * Uses method signature to determine type. * * @param mixed $method_response The result(s). * @param array|string $type The type(s) of the return value(s). * @param string $return_name The name of the return value. * @param string $namespace The namespace of the return value. * * @return array List of SOAP_Value objects. */ function buildResult(&$method_response, &$return_type, $return_name = 'return', $namespace = '') { if (is_a($method_response, 'SOAP_Value')) { $return_val = array($method_response); } else { if (is_array($return_type) && is_array($method_response)) { $i = 0; foreach ($return_type as $key => $type) { if (is_numeric($key)) { $key = 'item'; } if (is_a($method_response[$i], 'SOAP_Value')) { $return_val[] =& $method_response[$i++]; } else { $qn = new QName($key, $namespace); $return_val[] = new SOAP_Value($qn->fqn(), $type, $method_response[$i++]); } } } else { if (is_array($return_type)) { $keys = array_keys($return_type); if (!is_numeric($keys[0])) { $return_name = $keys[0]; } $values = array_values($return_type); $return_type = $values[0]; } $qn = new QName($return_name, $namespace); $return_val = array(new SOAP_Value($qn->fqn(), $return_type, $method_response)); } } return $return_val; } function parseRequest($data = '', $attachments = null) { /* Parse response, get SOAP_Parser object. */ $parser = new SOAP_Parser($data, $this->xml_encoding, $attachments); if ($parser->fault) { /* Fault occurred during message parsing. */ $this->fault = $parser->fault; return null; } if (!count($parser->root_struct_name)) { /* No method specified. */ $this->_raiseSoapFault('No method specified in request.'); return null; } /* Handle message headers. */ $request_headers = $parser->getHeaders(); $header_results = array(); if ($request_headers) { if (!is_a($request_headers, 'SOAP_Value')) { $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_headers, '', '', 'Server'); return null; } if ($request_headers->value) { /* Handle headers now. */ foreach ($request_headers->value as $header_val) { $f_exists = $this->validateMethod($header_val->name, $header_val->namespace); /* TODO: this does not take into account message routing * yet. */ $myactor = !$header_val->actor || $header_val->actor == 'http://schemas.xmlsoap.org/soap/actor/next' || $header_val->actor == $this->endpoint; if (!$f_exists && $header_val->mustunderstand && $myactor) { $this->_raiseSoapFault('I don\'t understand header ' . $header_val->name, '', '', 'MustUnderstand'); return null; } /* We only handle the header if it's for us. */ $isok = $f_exists && $myactor; if ($isok) { /* Call our header now! */ $header_method = $header_val->name; $header_data = array($this->_decode($header_val)); /* If there are parameters to pass. */ $hr =& $this->callMethod($header_method, $header_data); if (PEAR::isError($hr)) { $this->_raiseSoapFault($hr); return null; } $results = $this->buildResult($hr, $this->return_type, $header_method, $header_val->namespace); $header_results[] = $results[0]; } } } } /* Handle the method call. */ /* Evaluate message, getting back a SOAP_Value object. */ $this->call_methodname = $this->methodname = $parser->root_struct_name[0]; /* Figure out the method namespace. */ $this->method_namespace = $parser->message[$parser->root_struct[0]]['namespace']; if ($this->_wsdl) { $this->_setSchemaVersion($this->_wsdl->xsd); $dataHandler = $this->_wsdl->getDataHandler($this->methodname, $this->method_namespace); if ($dataHandler) $this->call_methodname = $this->methodname = $dataHandler; $this->_portName = $this->_wsdl->getPortName($this->methodname); if (PEAR::isError($this->_portName)) { $this->_raiseSoapFault($this->_portName); return null; } $opData = $this->_wsdl->getOperationData($this->_portName, $this->methodname); if (PEAR::isError($opData)) { $this->_raiseSoapFault($opData); return null; } $this->_options['style'] = $opData['style']; $this->_options['use'] = $opData['output']['use']; $this->_options['parameters'] = $opData['parameters']; } /* Does method exist? */ if (!$this->methodname || !$this->validateMethod($this->methodname, $this->method_namespace)) { $this->_raiseSoapFault('method "' . $this->method_namespace . $this->methodname . '" not defined in service', '', '', 'Server'); return null; } if (!$request_val = $parser->getResponse()) { return null; } if (!is_a($request_val, 'SOAP_Value')) { $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_val, '', '', 'Server'); return null; } /* Verify that SOAP_Value objects in request match the methods * signature. */ if (!$this->verifyMethod($request_val)) { /* verifyMethod() creates the fault. */ return null; } /* Need to set special error detection inside the value class to * differentiate between no params passed, and an error decoding. */ $request_data = $this->__decodeRequest($request_val); if (PEAR::isError($request_data)) { $this->_raiseSoapFault($request_data); return null; } $method_response =& $this->callMethod($this->call_methodname, $request_data); if (PEAR::isError($method_response)) { $this->_raiseSoapFault($method_response); return null; } if ($this->_options['parameters'] || !$method_response || $this->_options['style'] == 'rpc') { /* Get the method result. */ if (is_null($method_response)) { $return_val = null; } else { $return_val = $this->buildResult($method_response, $this->return_type); } $qn = new QName($this->methodname . 'Response', $this->method_namespace); $methodValue = new SOAP_Value($qn->fqn(), 'Struct', $return_val); } else { $methodValue =& $method_response; } return $this->makeEnvelope($methodValue, $header_results, $this->response_encoding); } function &__decodeRequest($request, $shift = false) { if (!$request) { $decoded = null; return $decoded; } /* Check for valid response. */ if (PEAR::isError($request)) { $fault = &$this->_raiseSoapFault($request); return $fault; } else if (!is_a($request, 'SOAP_Value')) { $fault = &$this->_raiseSoapFault('Invalid data in server::__decodeRequest'); return $fault; } /* Decode to native php datatype. */ $requestArray = $this->_decode($request); /* Fault? */ if (PEAR::isError($requestArray)) { $fault = &$this->_raiseSoapFault($requestArray); return $fault; } if (is_object($requestArray) && get_class($requestArray) == 'stdClass') { $requestArray = get_object_vars($requestArray); } elseif ($this->_options['style'] == 'document') { $requestArray = array($requestArray); } if (is_array($requestArray)) { if (isset($requestArray['faultcode']) || isset($requestArray[SOAP_BASE::SOAPENVPrefix().':faultcode'])) { $faultcode = $faultstring = $faultdetail = $faultactor = ''; foreach ($requestArray as $k => $v) { if (stristr($k, 'faultcode')) { $faultcode = $v; } if (stristr($k, 'faultstring')) { $faultstring = $v; } if (stristr($k, 'detail')) { $faultdetail = $v; } if (stristr($k, 'faultactor')) { $faultactor = $v; } } $fault = &$this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); return $fault; } /* Return array of return values. */ if ($shift && count($requestArray) == 1) { $decoded = array_shift($requestArray); return $decoded; } return $requestArray; } return $requestArray; } function verifyMethod($request) { if (!$this->callValidation) { return true; } $params = $request->value; /* Get the dispatch map if one exists. */ $map = null; if (array_key_exists($this->methodname, $this->dispatch_map)) { $map = $this->dispatch_map[$this->methodname]; } elseif (isset($this->soapobject)) { if (method_exists($this->soapobject, '__dispatch')) { $map = $this->soapobject->__dispatch($this->methodname); } elseif (method_exists($this->soapobject, $this->methodname)) { if (isset($this->soapobject->__dispatch_map[$this->methodname])) { // pdp - 2011-04-29 - declared output will be copied to return_type and use in buildResult $map = $this->soapobject->__dispatch_map[$this->methodname]; } else { /* No map, all public functions are SOAP functions. */ return true; } } } if (!$map) { $this->_raiseSoapFault('SOAP request specified an unhandled method "' . $this->methodname . '"', '', '', 'Client'); return false; } /* If we aliased the SOAP method name to a PHP function, change * call_methodname so we do the right thing. */ if (array_key_exists('alias', $map) && !empty($map['alias'])) { $this->call_methodname = $map['alias']; } /* If there are input parameters required. */ if ($map['in']) { $this->input_value = count($map['in']); $this->return_type = false; if (is_array($map['out'])) { $this->return_type = count($map['out']) > 1 ? $map['out'] : array_shift($map['out']); } if (is_array($params)) { /* Validate the number of parameters. */ if (count($params) == count($map['in'])) { /* Make array of param types. */ foreach ($params as $param) { $p[] = strtolower($param->type); } $sig_t = array_values($map['in']); /* Validate each param's type. */ for ($i = 0; $i < count($p); $i++) { /* If SOAP types do not match, it's still fine if the * mapped php types match this allows using plain PHP * variables to work (i.e. stuff like Decimal would * fail otherwise). We consider this only error if the * types exist in our type maps, and they differ. */ if (strcasecmp($sig_t[$i], $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->_raiseSoapFault("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])), '', '', 'Client'); return false; } } return true; } else { /* Wrong number of params. */ $this->_raiseSoapFault('SOAP request contained incorrect number of parameters. method "' . $this->methodname . '" required ' . count($map['in']) . ' and request provided ' . count($params), '', '', 'Client'); return false; } } else { /* No params. */ $this->_raiseSoapFault('SOAP request contained incorrect number of parameters. method "' . $this->methodname . '" requires ' . count($map['in']) . ' parameters, and request provided none.', '', '', 'Client'); return false; } } /* We'll try it anyway. */ return true; } function validateMethod($methodname, $namespace = null) { unset($this->soapobject); if (!$this->callValidation) { return true; } /* No SOAP access to private functions. */ if ($methodname[0] == '_') { return false; } /* if it's in our function list, ok */ if (array_key_exists($methodname, $this->dispatch_map) && (!$namespace || !array_key_exists('namespace', $this->dispatch_map[$methodname]) || $namespace == $this->dispatch_map[$methodname]['namespace'])) { if (array_key_exists('namespace', $this->dispatch_map[$methodname])) $this->method_namespace = $this->dispatch_map[$methodname]['namespace']; return true; } /* if it's in an object, it's ok */ if (isset($this->dispatch_objects[$namespace])) { $c = count($this->dispatch_objects[$namespace]); for ($i = 0; $i < $c; $i++) { $obj =& $this->dispatch_objects[$namespace][$i]; /* If we have a dispatch map, and the function is not in the * dispatch map, then it is not callable! */ if (method_exists($obj, '__dispatch')) { if ($obj->__dispatch($methodname)) { $this->method_namespace = $namespace; $this->soapobject =& $obj; return true; } } elseif (method_exists($obj, $methodname)) { $this->method_namespace = $namespace; $this->soapobject =& $obj; return true; } } } return false; } function addObjectMap(&$obj, $namespace = null, $service_name = 'Default', $service_desc = '') { if (!$namespace) { if (isset($obj->namespace)) { // XXX a bit of backwards compatibility $namespace = $obj->namespace; } else { $this->_raiseSoapFault('No namespace provided for class!', '', '', 'Server'); return false; } } if (!isset($this->dispatch_objects[$namespace])) { $this->dispatch_objects[$namespace] = array(); } $this->dispatch_objects[$namespace][] =& $obj; // Create internal WSDL structures for object // XXX Because some internal workings of PEAR::SOAP decide whether to // do certain things by the presence or absence of _wsdl, we should // only create a _wsdl structure if we know we can fill it; if // __dispatch_map or __typedef for the object is missing, we should // avoid creating it. Later, when we are using PHP 5 introspection, we // will be able to make the data for all objects without any extra // information from the developers, and this condition should be // dropped. // XXX Known issue: if imported WSDL (bindWSDL) or another WSDL source // is used to add _wsdl structure information, then addObjectWSDL is // used, there is a high possibility of _wsdl data corruption; // therefore you should avoid using __dispatch_map/__typedef // definitions AND other WSDL data sources in the same service. We // exclude classes that don't have __typedefs to allow external WSDL // files to be used with classes with no internal type definitions // (the types are defined in the WSDL file). When addObjectWSDL is // refactored to not cause corruption, this restriction can be // relaxed. // In summary, if you add an object with both a dispatch map and type // definitions, then previous WSDL file operation and type definitions // will be overwritten. if (isset($obj->__dispatch_map) && isset($obj->__typedef)) { $this->addObjectWSDL($obj, $namespace, $service_name, $service_desc); } return true; } /** * Adds a method to the dispatch map. */ function addToMap($methodname, $in, $out, $namespace = null, $alias = null) { if (!$this->callHandler && !function_exists($methodname)) { $this->_raiseSoapFault('Error mapping function', '', '', 'Server'); return false; } $this->dispatch_map[$methodname]['in'] = $in; $this->dispatch_map[$methodname]['out'] = $out; $this->dispatch_map[$methodname]['alias'] = $alias; if ($namespace) { $this->dispatch_map[$methodname]['namespace'] = $namespace; } return true; } function setCallHandler($callHandler, $validation = true) { $this->callHandler = $callHandler; $this->callValidation = $validation; } /** * @deprecated use bindWSDL from now on */ function bind($wsdl_url) { $this->bindWSDL($wsdl_url); } /** * @param string a url to a WSDL resource * @return void */ function bindWSDL($wsdl_url) { /* Instantiate WSDL class. */ $this->_wsdl = new SOAP_WSDL($wsdl_url); if ($this->_wsdl->fault) { $this->_raiseSoapFault($this->_wsdl->fault); } } /** * @return void */ function addObjectWSDL($wsdl_obj, $targetNamespace, $service_name, $service_desc = '') { if (!isset($this->_wsdl)) { $this->_wsdl = new SOAP_WSDL; } $this->_wsdl->parseObject($wsdl_obj, $targetNamespace, $service_name, $service_desc); if ($this->_wsdl->fault) { $this->_raiseSoapFault($this->_wsdl->fault); } } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/000077500000000000000000000000001214222670500166125ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/Email.php000066400000000000000000000164231214222670500203600ustar00rootroot00000000000000 Port to PEAR and more * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Server */ require_once 'SOAP/Server.php'; require_once 'SOAP/Client.php'; require_once 'SOAP/Transport.php'; require_once 'Mail/mimeDecode.php'; /** * SOAP Server Class that implements an email SOAP server. * http://www.pocketsoap.com/specs/smtpbinding/ * * This class overrides the default HTTP server, providing the ability to * parse an email message and execute SOAP calls. This class DOES NOT pop the * message; the message, complete with headers, must be passed in as a * parameter to the service function call. * * @access public * @package SOAP * @author Shane Caraveo */ class SOAP_Server_Email extends SOAP_Server { var $headers = array(); function SOAP_Server_Email($send_response = true) { parent::SOAP_Server(); $this->send_response = $send_response; } /** * Removes 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->_raiseSoapFault('Invalid Content Type', '', '', 'Client'); return false; } if (strcasecmp($this->headers['content-transfer-encoding'], 'base64')==0) { /* Unfold lines. */ $enctext = preg_replace("/[\r|\n]/", '', $match[2]); $data = base64_decode($enctext); } else { $data = $match[2]; } /* If no content, return false. */ return strlen($this->request) > 0; } $this->_raiseSoapFault('Invalid Email Format', '', '', 'Client'); return false; } function client(&$data) { $attachments = array(); /* If neither matches, we'll just try it anyway. */ if (stristr($data, 'Content-Type: application/dime')) { $this->_decodeDIMEMessage($data, $this->headers, $attachments); } elseif (stristr($data, 'MIME-Version:')) { /* This is a mime message, let's decode it. */ $this->_decodeMimeMessage($data, $this->headers, $attachments); } else { /* The old fallback, but decodeMimeMessage handles things fine. */ $this->_parseEmail($data); } /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ if (!$this->soapfault && !$this->_getContentEncoding($this->headers['content-type'])) { $this->xml_encoding = SOAP_DEFAULT_ENCODING; /* An encoding we don't understand, return a fault. */ $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); } if ($this->soapfault) { return $this->soapfault->getFault(); } $client = new SOAP_Client(null); return $client->parseResponse($data, $this->xml_encoding, $this->attachments); } function service(&$data, $endpoint = '', $send_response = true, $dump = false) { $this->endpoint = $endpoint; $attachments = array(); $headers = array(); /* If neither matches, we'll just try it anyway. */ if (stristr($data, 'Content-Type: application/dime')) { $this->_decodeDIMEMessage($data, $this->headers, $attachments); $useEncoding = 'DIME'; } elseif (stristr($data, 'MIME-Version:')) { /* This is a mime message, let's decode it. */ $this->_decodeMimeMessage($data, $this->headers, $attachments); $useEncoding = 'Mime'; } else { /* The old fallback, but decodeMimeMessage handles things fine. */ $this->_parseEmail($data); } /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ if (!$this->_getContentEncoding($this->headers['content-type'])) { $this->xml_encoding = SOAP_DEFAULT_ENCODING; /* An encoding we don't understand, return a fault. */ $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); $response = $this->getFaultMessage(); } if ($this->soapfault) { $response = $this->soapfault->message(); } else { $soap_msg = $this->parseRequest($data,$attachments); /* Handle Mime or DIME encoding. */ /* TODO: 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); $soap_msg['headers']['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) { if ($dump) { print $response; } else { $from = array_key_exists('reply-to', $this->headers) ? $this->headers['reply-to'] : $this->headers['from']; $soap_transport =& SOAP_Transport::getTransport('mailto:' . $from, $this->response_encoding); $from = $this->endpoint ? $this->endpoint : $this->headers['to']; $headers['In-Reply-To'] = $this->headers['message-id']; $options = array('from' => $from, 'subject' => $this->headers['subject'], 'headers' => $headers); $soap_transport->send($response, $options); } } } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/Email_Gateway.php000066400000000000000000000126061214222670500220400ustar00rootroot00000000000000 Port to PEAR and more * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Server_Email */ require_once 'SOAP/Server/Email.php'; require_once 'SOAP/Transport.php'; /** * SOAP Server Class that implements an email SOAP server. * http://www.pocketsoap.com/specs/smtpbinding/ * * This class overrides the default HTTP server, providing the ability to * parse an email message and execute soap calls. This class DOES NOT pop the * message; the message, complete with headers, must be passed in as a * parameter to the service function call. * * This class calls a provided HTTP SOAP server, forwarding the email request, * then sending the HTTP response out as an email. * * @access public * @package SOAP * @author Shane Caraveo */ class SOAP_Server_Email_Gateway extends SOAP_Server_Email { var $gateway = null; var $dump = false; function SOAP_Server_Email_Gateway($gateway = '', $send_response = true, $dump = false) { parent::SOAP_Server(); $this->send_response = $send_response; $this->gateway = $gateway; $this->dump = $dump; } function service(&$data, $gateway = '', $endpoint = '', $send_response = true, $dump = false) { $this->endpoint = $endpoint; $response = ''; $useEncoding = 'Mime'; $options = array(); if (!$gateway) { $gateway = $this->gateway; } /* We have a full set of headers, need to find the first blank * line. */ $this->_parseEmail($data); if ($this->fault) { $response = $this->fault->message(); } if ($this->headers['content-type'] == 'application/dime') $useEncoding = 'DIME'; /* Call the HTTP Server. */ if (!$response) { $soap_transport =& SOAP_Transport::getTransport($gateway, $this->xml_encoding); if ($soap_transport->fault) { $response = $soap_transport->fault->message(); } } /* Send the message. */ if (!$response) { $options['soapaction'] = $this->headers['soapaction']; $options['headers']['Content-Type'] = $this->headers['content-type']; $response = $soap_transport->send($data, $options); if (isset($this->headers['mime-version'])) $options['headers']['MIME-Version'] = $this->headers['mime-version']; if ($soap_transport->fault) { $response = $soap_transport->fault->message(); } else { foreach ($soap_transport->transport->attachments as $cid => $body) { $this->attachments[] = array('body' => $body, 'cid' => $cid, 'encoding' => 'base64'); } if (count($this->_attachments)) { if ($useEncoding == 'Mime') { $soap_msg = $this->_makeMimeMessage($response); $options['headers']['MIME-Version'] = '1.0'; } else { /* Default is DIME. */ $soap_msg = $this->_makeDIMEMessage($response); $options['headers']['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'])) { if (isset($options['headers'])) { $options['headers'] = array_merge($options['headers'], $soap_msg['headers']); } else { $options['headers'] = $soap_msg['headers']; } } } } } } if ($this->send_response) { if ($this->dump || $dump) { print $response; } else { $from = array_key_exists('reply-to', $this->headers) ? $this->headers['reply-to'] : $this->headers['from']; $soap_transport =& SOAP_Transport::getTransport('mailto:' . $from, $this->response_encoding); $from = $this->endpoint ? $this->endpoint : $this->headers['to']; $headers = array('In-Reply-To' => $this->headers['message-id']); $options = array('from' => $from, 'subject'=> $this->headers['subject'], 'headers' => $headers); $soap_transport->send($response, $options); } } } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/TCP.php000066400000000000000000000052341214222670500177550ustar00rootroot00000000000000 Port to PEAR and more * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Server.php'; require_once 'SOAP/Server/TCP/Handler.php'; /** * SOAP Server Class that implements a TCP SOAP Server. * http://www.pocketsoap.com/specs/smtpbinding/ * * This class overrides the default HTTP server, providing the ability to * accept socket connections and execute SOAP calls. * * TODO: * use Net_Socket * implement some security scheme * implement support for attachments * * @access public * @package SOAP * @author Shane Caraveo */ class SOAP_Server_TCP extends SOAP_Server { var $headers = array(); var $localaddr; var $port; var $type; function SOAP_Server_TCP($localaddr = '127.0.0.1', $port = 10000, $type = 'sequential') { parent::SOAP_Server(); $this->localaddr = $localaddr; $this->port = $port; $this->type = $type; } function run($idleTimeout = null) { $server = &Net_Server::create($this->type, $this->localaddr, $this->port); if (PEAR::isError($server)) { echo $server->getMessage()."\n"; } $handler = &new SOAP_Server_TCP_Handler; $handler->setSOAPServer($this); // hand over the object that handles server events $server->setCallbackObject($handler); $server->readEndCharacter = ''; $server->setIdleTimeout($idleTimeout); // start the server $server->start(); } function service(&$data) { /* TODO: we need to handle attachments somehow. */ $response = $this->parseRequest($data); if ($this->fault) { $response = $this->fault->message($this->response_encoding); } return $response; } function onStart() { } function onIdle() { } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/TCP/000077500000000000000000000000001214222670500172405ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/Server/TCP/Handler.php000066400000000000000000000036671214222670500213420ustar00rootroot00000000000000 * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** * server base class */ require_once 'Net/Server.php'; /** * base class for the handler */ require_once 'Net/Server/Handler.php'; /** * SOAP Server Class that implements a TCP SOAP Server. * http://www.pocketsoap.com/specs/smtpbinding/ * * This class overrides the default HTTP server, providing the ability to * accept socket connections and execute SOAP calls. * * @access public * @package SOAP * @author Tomasz Rup */ class SOAP_Server_TCP_Handler extends Net_Server_Handler { var $_SOAP_Server; function setSOAPServer(&$server) { $this->_SOAP_Server =& $server; } /** * If the user sends data, send it back to him * * @access public * @param integer $clientId * @param string $data */ function onReceiveData($clientId = 0, $data = '') { if (trim($data) <> '') { $response = $this->_SOAP_Server->service($data); $this->_server->sendData($clientId, $response); } } function onStart() { $this->_SOAP_Server->onStart(); } function onIdle() { $this->_SOAP_Server->onIdle(); } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport.php000066400000000000000000000072201214222670500200520ustar00rootroot00000000000000 * @author Shane Caraveo * @author Jan Schneider * @copyright 2003-2006 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Base.php'; /** * SOAP Transport Layer * * This layer can use different protocols dependant on the endpoint url * provided. * * No knowlege of the SOAP protocol is available at this level. * No knowlege of the transport protocols is available at this level. * * @access public * @package SOAP * @author Shane Caraveo * @author Jan Schneider */ class SOAP_Transport extends SOAP_Base { /** * Connection endpoint URL. * * @var string */ var $url = ''; /** * Array containing urlparts. * * @see parse_url() * * @var mixed */ var $urlparts = null; /** * Incoming payload. * * @var string */ var $incoming_payload = ''; /** * Outgoing payload. * * @var string */ var $outgoing_payload = ''; /** * Request encoding. * * @var string */ var $encoding = SOAP_DEFAULT_ENCODING; /** * Response encoding. * * We assume UTF-8 if no encoding is set. * * @var string */ var $result_encoding = 'UTF-8'; /** * Decoded attachments from the reponse. * * @var array */ var $attachments; /** * Request User-Agent. * * @var string */ var $_userAgent = SOAP_LIBRARY_NAME; /** * Sends and receives SOAP data. * * @access public * @abstract * * @param string Outgoing SOAP data. * @param array Options. * * @return string|SOAP_Fault */ function send($msg, $options = null) { return $this->_raiseSoapFault('SOAP_Transport::send() not implemented.'); } function getTransport($url, $encoding = SOAP_DEFAULT_ENCODING) { $urlparts = @parse_url($url); if (!$urlparts['scheme']) { return SOAP_Base_Object::_raiseSoapFault("Invalid transport URI: $url"); } if (strcasecmp($urlparts['scheme'], 'mailto') == 0) { $transport_type = 'SMTP'; } elseif (strcasecmp($urlparts['scheme'], 'https') == 0) { $transport_type = 'HTTP'; } else { /* Handle other transport types */ $transport_type = strtoupper($urlparts['scheme']); } $transport_class = "SOAP_Transport_$transport_type"; if (!class_exists($transport_class)) { if (!(@include_once('SOAP/Transport/' . basename($transport_type) . '.php'))) { return SOAP_Base_Object::_raiseSoapFault("No Transport for {$urlparts['scheme']}"); } } if (!class_exists($transport_class)) { return SOAP_Base_Object::_raiseSoapFault("No Transport class $transport_class"); } return new $transport_class($url, $encoding); } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport/000077500000000000000000000000001214222670500173405ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport/HTTP.php000066400000000000000000000477601214222670500206460ustar00rootroot00000000000000 * @author Jan Schneider * @copyright 2003-2006 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** * HTTP Transport class * * @package SOAP * @category Web Services */ /** * Needed Classes */ require_once 'SOAP/Transport.php'; /** * HTTP Transport for SOAP * * @access public * @package SOAP * @author Shane Caraveo * @author Jan Schneider */ class SOAP_Transport_HTTP extends SOAP_Transport { /** * Basic Auth string. * * @var array */ var $headers = array(); /** * Cookies. * * @var array */ var $cookies; /** * Connection timeout in seconds. 0 = none. * * @var integer */ var $timeout = 4; /** * HTTP-Response Content-Type. */ var $result_content_type; var $result_headers = array(); var $result_cookies = array(); /** * SOAP_Transport_HTTP Constructor * * @access public * * @param string $url HTTP url to SOAP endpoint. * @param string $encoding Encoding to use. */ function SOAP_Transport_HTTP($url, $encoding = SOAP_DEFAULT_ENCODING) { parent::SOAP_Base('HTTP'); $this->urlparts = @parse_url($url); $this->url = $url; $this->encoding = $encoding; } /** * Sends and receives SOAP data. * * @access public * * @param string Outgoing SOAP data. * @param array Options. * * @return string|SOAP_Fault */ function send($msg, $options = array()) { $this->fault = null; if (!$this->_validateUrl()) { return $this->fault; } if (isset($options['timeout'])) { $this->timeout = (int)$options['timeout']; } if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { return $this->_sendHTTP($msg, $options); } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { return $this->_sendHTTPS($msg, $options); } return $this->_raiseSoapFault('Invalid url scheme ' . $this->url); } /** * Sets data for HTTP authentication, creates authorization header. * * @param string $username Username. * @param string $password Response data, minus HTTP headers. * * @access public */ function setCredentials($username, $password) { $this->headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password); } /** * Adds a cookie. * * @access public * @param string $name Cookie name. * @param mixed $value Cookie value. */ function addCookie($name, $value) { $this->cookies[$name] = $value; } /** * Generates the correct headers for the cookies. * * @access private * * @param array $options Cookie options. If 'nocookies' is set and true * the cookies from the last response are added * automatically. 'cookies' is name-value-hash with * a list of cookies to add. * * @return string The cookie header value. */ function _generateCookieHeader($options) { $this->cookies = array(); if (empty($options['nocookies']) && isset($this->result_cookies)) { // Add the cookies we got from the last request. foreach ($this->result_cookies as $cookie) { if ($cookie['domain'] == $this->urlparts['host']) { $this->cookies[$cookie['name']] = $cookie['value']; } } } // Add cookies the user wants to set. if (isset($options['cookies'])) { foreach ($options['cookies'] as $cookie) { if ($cookie['domain'] == $this->urlparts['host']) { $this->cookies[$cookie['name']] = $cookie['value']; } } } $cookies = ''; foreach ($this->cookies as $name => $value) { if (!empty($cookies)) { $cookies .= '; '; } $cookies .= urlencode($name) . '=' . urlencode($value); } return $cookies; } /** * Validate url data passed to constructor. * * @access private * @return boolean */ function _validateUrl() { if (!is_array($this->urlparts) ) { $this->_raiseSoapFault('Unable to parse URL ' . $this->url); return false; } if (!isset($this->urlparts['host'])) { $this->_raiseSoapFault('No host in URL ' . $this->url); return false; } if (!isset($this->urlparts['port'])) { if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { $this->urlparts['port'] = 80; } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { $this->urlparts['port'] = 443; } } if (isset($this->urlparts['user'])) { $this->setCredentials(urldecode($this->urlparts['user']), urldecode($this->urlparts['pass'])); } if (!isset($this->urlparts['path']) || !$this->urlparts['path']) { $this->urlparts['path'] = '/'; } return true; } /** * Finds out what the encoding is. * Sets the object property accordingly. * * @access private * @param array $headers Headers. */ function _parseEncoding($headers) { $h = stristr($headers, 'Content-Type'); preg_match_all('/^Content-Type:\s*(.*)$/im', $h, $ct, PREG_SET_ORDER); $n = count($ct); $ct = $ct[$n - 1]; // Strip the string of \r. $this->result_content_type = str_replace("\r", '', $ct[1]); if (preg_match('/(.*?)(?:;\s?charset=)(.*)/i', $this->result_content_type, $m)) { $this->result_content_type = $m[1]; if (count($m) > 2) { $enc = strtoupper(str_replace('"', '', $m[2])); if (in_array($enc, $this->_encodings)) { $this->result_encoding = $enc; } } } // Deal with broken servers that don't set content type on faults. if (!$this->result_content_type) { $this->result_content_type = 'text/xml'; } } /** * Parses the headers. * * @param array $headers The headers. */ function _parseHeaders($headers) { /* Largely borrowed from HTTP_Request. */ $this->result_headers = array(); $headers = preg_split("/\r?\n/", $headers); foreach ($headers as $value) { if (strpos($value, ':') === false) { $this->result_headers[0] = $value; continue; } list($name, $value) = explode(':', $value); $headername = strtolower($name); $headervalue = trim($value); $this->result_headers[$headername] = $headervalue; if ($headername == 'set-cookie') { // Parse a SetCookie header to fill _cookies array. $cookie = array('expires' => null, 'domain' => $this->urlparts['host'], 'path' => null, 'secure' => false); if (!strpos($headervalue, ';')) { // Only a name=value pair. list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $headervalue)); $cookie['name'] = urldecode($cookie['name']); $cookie['value'] = urldecode($cookie['value']); } else { // Some optional parameters are supplied. $elements = explode(';', $headervalue); list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $elements[0])); $cookie['name'] = urldecode($cookie['name']); $cookie['value'] = urldecode($cookie['value']); for ($i = 1; $i < count($elements);$i++) { list($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); if ('secure' == $elName) { $cookie['secure'] = true; } elseif ('expires' == $elName) { $cookie['expires'] = str_replace('"', '', $elValue); } elseif ('path' == $elName OR 'domain' == $elName) { $cookie[$elName] = urldecode($elValue); } else { $cookie[$elName] = $elValue; } } } $this->result_cookies[] = $cookie; } } } /** * Removes HTTP headers from response. * * @return boolean * @access private */ function _parseResponse() { if (!preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $this->incoming_payload, $match)) { $this->_raiseSoapFault('Invalid HTTP Response'); return false; } $this->response = $match[2]; // Find the response error, some servers response with 500 for // SOAP faults. $this->_parseHeaders($match[1]); list(, $code, $msg) = sscanf($this->result_headers[0], '%s %s %s'); unset($this->result_headers[0]); switch($code) { // Continue case 100: $this->incoming_payload = $match[2]; return $this->_parseResponse(); case 200: case 202: if (!strlen(trim($match[2]))) { /* Valid one-way message response. */ return true; } break; case 400: $this->_raiseSoapFault("HTTP Response $code Bad Request"); return false; case 401: $this->_raiseSoapFault("HTTP Response $code Authentication Failed"); return false; case 403: $this->_raiseSoapFault("HTTP Response $code Forbidden"); return false; case 404: $this->_raiseSoapFault("HTTP Response $code Not Found"); return false; case 407: $this->_raiseSoapFault("HTTP Response $code Proxy Authentication Required"); return false; case 408: $this->_raiseSoapFault("HTTP Response $code Request Timeout"); return false; case 410: $this->_raiseSoapFault("HTTP Response $code Gone"); return false; default: if ($code >= 400 && $code < 500) { $this->_raiseSoapFault("HTTP Response $code Not Found, Server message: $msg"); return false; } break; } $this->_parseEncoding($match[1]); if ($this->result_content_type == 'application/dime') { // XXX quick hack insertion of DIME if (PEAR::isError($this->_decodeDIMEMessage($this->response, $this->headers, $this->attachments))) { // _decodeDIMEMessage already raised $this->fault return false; } $this->result_content_type = $this->headers['content-type']; } elseif (stristr($this->result_content_type, 'multipart/related')) { $this->response = $this->incoming_payload; if (PEAR::isError($this->_decodeMimeMessage($this->response, $this->headers, $this->attachments))) { // _decodeMimeMessage already raised $this->fault return false; } } elseif ($this->result_content_type != 'text/xml') { $this->_raiseSoapFault($this->response); return false; } // if no content, return false return strlen($this->response) > 0; } /** * Creates an HTTP request, including headers, for the outgoing request. * * @access private * * @param string $msg Outgoing SOAP package. * @param array $options Options. * * @return string Outgoing payload. */ function _getRequest($msg, $options) { $this->headers = array(); $action = isset($options['soapaction']) ? $options['soapaction'] : ''; $fullpath = $this->urlparts['path']; if (isset($this->urlparts['query'])) { $fullpath .= '?' . $this->urlparts['query']; } if (isset($this->urlparts['fragment'])) { $fullpath .= '#' . $this->urlparts['fragment']; } if (isset($options['proxy_host'])) { $fullpath = 'http://' . $this->urlparts['host'] . ':' . $this->urlparts['port'] . $fullpath; } if (isset($options['proxy_user'])) { $this->headers['Proxy-Authorization'] = 'Basic ' . base64_encode($options['proxy_user'] . ':' . $options['proxy_pass']); } if (isset($options['user'])) { $this->setCredentials($options['user'], $options['pass']); } $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 . '"'; $this->headers['Connection'] = 'close'; if (isset($options['headers'])) { $this->headers = array_merge($this->headers, $options['headers']); } $cookies = $this->_generateCookieHeader($options); if ($cookies) { $this->headers['Cookie'] = $cookies; } $headers = ''; foreach ($this->headers as $k => $v) { $headers .= "$k: $v\r\n"; } $this->outgoing_payload = "POST $fullpath HTTP/1.0\r\n" . $headers . "\r\n" . $msg; return $this->outgoing_payload; } /** * Sends the outgoing HTTP request and reads and parses the response. * * @access private * * @param string $msg Outgoing SOAP package. * @param array $options Options. * * @return string Response data without HTTP headers. */ function _sendHTTP($msg, $options) { $this->incoming_payload = ''; $this->_getRequest($msg, $options); $host = $this->urlparts['host']; $port = $this->urlparts['port']; if (isset($options['proxy_host'])) { $host = $options['proxy_host']; $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; } // Send. if ($this->timeout > 0) { $fp = @fsockopen($host, $port, $this->errno, $this->errmsg, $this->timeout); } else { $fp = @fsockopen($host, $port, $this->errno, $this->errmsg); } if (!$fp) { return $this->_raiseSoapFault("Connect Error to $host:$port"); } if ($this->timeout > 0) { // some builds of PHP do not support this, silence the warning @socket_set_timeout($fp, $this->timeout); } if (!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { return $this->_raiseSoapFault("Error POSTing Data to $host"); } // get reponse // XXX time consumer do { $data = fread($fp, 4096); $_tmp_status = socket_get_status($fp); if ($_tmp_status['timed_out']) { return $this->_raiseSoapFault("Timed out read from $host"); } else { $this->incoming_payload .= $data; } } while (!$_tmp_status['eof']); fclose($fp); if (!$this->_parseResponse()) { return $this->fault; } return $this->response; } /** * Sends the outgoing HTTPS request and reads and parses the response. * * @access private * * @param string $msg Outgoing SOAP package. * @param array $options Options. * * @return string Response data without HTTP headers. */ function _sendHTTPS($msg, $options) { /* Check if the required curl extension is installed. */ if (!extension_loaded('curl')) { return $this->_raiseSoapFault('CURL Extension is required for HTTPS'); } $ch = curl_init(); if (isset($options['proxy_host'])) { $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; curl_setopt($ch, CURLOPT_PROXY, $options['proxy_host'] . ':' . $port); } if (isset($options['proxy_user'])) { curl_setopt($ch, CURLOPT_PROXYUSERPWD, $options['proxy_user'] . ':' . $options['proxy_pass']); } if (isset($options['user'])) { curl_setopt($ch, CURLOPT_USERPWD, $options['user'] . ':' . $options['pass']); } $headers = array(); $action = isset($options['soapaction']) ? $options['soapaction'] : ''; $headers['Content-Type'] = "text/xml; charset=$this->encoding"; $headers['SOAPAction'] = '"' . $action . '"'; if (isset($options['headers'])) { $headers = array_merge($headers, $options['headers']); } foreach ($headers as $header => $value) { $headers[$header] = $header . ': ' . $value; } curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_USERAGENT, $this->_userAgent); if ($this->timeout) { curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); } curl_setopt($ch, CURLOPT_POSTFIELDS, $msg); curl_setopt($ch, CURLOPT_URL, $this->url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_FAILONERROR, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); if (defined('CURLOPT_HTTP_VERSION')) { curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); } if (!ini_get('safe_mode') && !ini_get('open_basedir')) { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); } $cookies = $this->_generateCookieHeader($options); if ($cookies) { curl_setopt($ch, CURLOPT_COOKIE, $cookies); } if (isset($options['curl'])) { foreach ($options['curl'] as $key => $val) { curl_setopt($ch, $key, $val); } } // Save the outgoing XML. This doesn't quite match _sendHTTP as CURL // generates the headers, but having the XML is usually the most // important part for tracing/debugging. $this->outgoing_payload = $msg; $this->incoming_payload = curl_exec($ch); if (!$this->incoming_payload) { $m = 'curl_exec error ' . curl_errno($ch) . ' ' . curl_error($ch); curl_close($ch); return $this->_raiseSoapFault($m); } curl_close($ch); if (!$this->_parseResponse()) { return $this->fault; } return $this->response; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport/SMTP.php000066400000000000000000000157161214222670500206460ustar00rootroot00000000000000 * @author Jan Schneider * @copyright 2003-2006 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Transport.php'; require_once 'Mail/smtp.php'; /** * SMTP Transport for SOAP * * Implements SOAP-SMTP as defined at * http://www.pocketsoap.com/specs/smtpbinding/ * * @todo use PEAR smtp and Mime classes * * @access public * @package SOAP * @author Shane Caraveo * @author Jan Schneider */ class SOAP_Transport_SMTP extends SOAP_Transport { var $credentials = ''; var $timeout = 4; // connect timeout var $host = '127.0.0.1'; var $port = 25; var $auth = null; /** * SOAP_Transport_SMTP Constructor * * @param string $url mailto: address. * * @access public */ function SOAP_Transport_SMTP($url, $encoding = 'US-ASCII') { parent::SOAP_Base('SMTP'); $this->encoding = $encoding; $this->urlparts = @parse_url($url); $this->url = $url; } /** * Sends and receives SOAP data. * * @access public * * @param string Outgoing SOAP data. * @param array Options. * * @return string|SOAP_Fault */ function send($msg, $options = array()) { $this->fault = null; $this->incoming_payload = ''; $this->outgoing_payload = $msg; if (!$this->_validateUrl()) { return $this->fault; } if (!$options || !isset($options['from'])) { return $this->_raiseSoapFault('No From: address to send message with'); } if (isset($options['host'])) $this->host = $options['host']; if (isset($options['port'])) $this->port = $options['port']; if (isset($options['auth'])) $this->auth = $options['auth']; if (isset($options['username'])) $this->username = $options['username']; if (isset($options['password'])) $this->password = $options['password']; $headers = array(); $headers['From'] = $options['from']; $headers['X-Mailer'] = $this->_userAgent; $headers['MIME-Version'] = '1.0'; $headers['Message-ID'] = md5(time()) . '.soap@' . $this->host; $headers['To'] = $this->urlparts['path']; if (isset($options['soapaction'])) { $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'])) { $out = $msg; } else { // Do a simple inline MIME encoding. $headers['Content-Disposition'] = 'inline'; $headers['Content-Type'] = "text/xml; charset=\"$this->encoding\""; if (isset($options['transfer-encoding'])) { if (strcasecmp($options['transfer-encoding'], 'quoted-printable') == 0) { $headers['Content-Transfer-Encoding'] = $options['transfer-encoding']; $out = $msg; } elseif (strcasecmp($options['transfer-encoding'],'base64') == 0) { $headers['Content-Transfer-Encoding'] = 'base64'; $out = chunk_split(base64_encode($msg), 76, "\n"); } else { return $this->_raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); } } else { // Default to base64. $headers['Content-Transfer-Encoding'] = 'base64'; $out = chunk_split(base64_encode($msg)); } } $headers['Subject'] = isset($options['subject']) ? $options['subject'] : 'SOAP Message'; foreach ($headers as $key => $value) { $header_text .= "$key: $value\n"; } $this->outgoing_payload = $header_text . "\r\n" . $this->outgoing_payload; $mailer_params = array( 'host' => $this->host, 'port' => $this->port, 'username' => $this->username, 'password' => $this->password, 'auth' => $this->auth ); $mailer = new Mail_smtp($mailer_params); $result = $mailer->send($this->urlparts['path'], $headers, $out); if (!PEAR::isError($result)) { $val = new SOAP_Value('Message-ID', 'string', $headers['Message-ID']); } else { $sval[] = new SOAP_Value('faultcode', 'QName', SOAP_BASE::SOAPENVPrefix().':Client'); $sval[] = new SOAP_Value('faultstring', 'string', "couldn't send SMTP message to {$this->urlparts['path']}"); $val = new SOAP_Value('Fault', 'Struct', $sval); } $methodValue = new SOAP_Value('Response', 'Struct', array($val)); $this->incoming_payload = $this->makeEnvelope($methodValue, $this->headers, $this->encoding); return $this->incoming_payload; } /** * Sets data for HTTP authentication, creates Authorization header. * * @param string $username Username. * @param string $password Response data, minus HTTP headers. * * @access public */ function setCredentials($username, $password) { $this->username = $username; $this->password = $password; } /** * Validates url data passed to constructor. * * @return boolean * @access private */ function _validateUrl() { if (!is_array($this->urlparts)) { $this->_raiseSoapFault("Unable to parse URL $this->url"); return false; } if (!isset($this->urlparts['scheme']) || strcasecmp($this->urlparts['scheme'], 'mailto') != 0) { $this->_raiseSoapFault("Unable to parse URL $this->url"); return false; } if (!isset($this->urlparts['path'])) { $this->_raiseSoapFault("Unable to parse URL $this->url"); return false; } return true; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport/TCP.php000066400000000000000000000110051214222670500204740ustar00rootroot00000000000000 * @author Jan Schneider * @copyright 2003-2006 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Transport.php'; /** * TCP transport for SOAP. * * @todo use Net_Socket; implement some security scheme; implement support * for attachments * @access public * @package SOAP * @author Shane Hanna * @author Jan Schneider */ class SOAP_Transport_TCP extends SOAP_Transport { /** * Socket. */ var $socket = null; /** * Constructor. * * @param string $url HTTP url to SOAP endpoint. * * @access public */ function SOAP_Transport_TCP($url, $encoding = SOAP_DEFAULT_ENCODING) { parent::SOAP_Base_Object('TCP'); $this->urlparts = @parse_url($url); $this->url = $url; $this->encoding = $encoding; } function _socket_ping() { // XXX how do we restart after socket_shutdown? //if (!$this->socket) { // Create socket resource. $this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if ($this->socket < 0) { return 0; } // Connect. $result = socket_connect($this->socket, $this->urlparts['host'], $this->urlparts['port']); if ($result < 0) { return 0; } //} return 1; } /** * Sends and receives SOAP data. * * @access public * * @param string Outgoing SOAP data. * @param array Options. * * @return string|SOAP_Fault */ function send($msg, $options = array()) { $this->fault = null; $this->incoming_payload = ''; $this->outgoing_payload = $msg; if (!$this->_validateUrl()) { return $this->fault; } // Check for TCP scheme. if (strcasecmp($this->urlparts['scheme'], 'TCP') == 0) { // Check connection. if (!$this->_socket_ping()) { return $this->_raiseSoapFault('Error connecting to ' . $this->url . '; reason: ' . socket_strerror(socket_last_error($this->socket))); } // Write to the socket. if (!@socket_write($this->socket, $this->outgoing_payload, strlen($this->outgoing_payload))) { return $this->_raiseSoapFault('Error sending data to ' . $this->url . '; reason: ' . socket_strerror(socket_last_error($this->socket))); } // Shutdown writing. if(!socket_shutdown($this->socket, 1)) { return $this->_raiseSoapFault('Cannot change socket mode to read.'); } // Read everything we can. while ($buf = @socket_read($this->socket, 1024, PHP_BINARY_READ)) { $this->incoming_payload .= $buf; } // Return payload or die. if ($this->incoming_payload) { return $this->incoming_payload; } return $this->_raiseSoapFault('Error reveiving data from ' . $this->url); } return $this->_raiseSoapFault('Invalid url scheme ' . $this->url); } /** * Validates the url data passed to the constructor. * * @return boolean * @access private */ function _validateUrl() { if (!is_array($this->urlparts) ) { $this->_raiseSoapFault("Unable to parse URL $this->url"); return false; } if (!isset($this->urlparts['host'])) { $this->_raiseSoapFault("No host in URL $this->url"); return false; } if (!isset($this->urlparts['path']) || !$this->urlparts['path']) { $this->urlparts['path'] = '/'; } return true; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Transport/TEST.php000066400000000000000000000030071214222670500206300ustar00rootroot00000000000000 * @copyright 2008 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Transport.php'; /** * Test transport for SOAP. * * @access public * @package SOAP * @author Jan Schneider */ class SOAP_Transport_TEST extends SOAP_Transport { /** * Sends and receives SOAP data. * * @param string $msg Outgoing SOAP data. * @param array $options Options. * * @return string|SOAP_Fault */ function send($msg, $options = array()) { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->outgoing_payload = $msg; ob_start(); $server = clone($options['server']); $server->service($msg); $this->incoming_payload = ob_get_contents(); ob_end_clean(); return $this->incoming_payload; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Type/000077500000000000000000000000001214222670500162655ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/SOAP/Type/dateTime.php000066400000000000000000000166141214222670500205420ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** * This class converts from and to unix timestamps and ISO 8601 date/time. * * @access public * @package SOAP * @author Dietrich Ayala Original Author * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance */ class SOAP_Type_dateTime { var $_iso8601 = '# 1: centuries & years CCYY- (-?[0-9]{4})- # 2: months MM- ([0-9]{2})- # 3: days DD ([0-9]{2}) # 4: separator T T # 5: hours hh: ([0-9]{2}): # 6: minutes mm: ([0-9]{2}): # 7: seconds ss.ss... ([0-9]{2})(\.[0-9]*)? # 8: Z to indicate UTC, -+HH:MM:SS.SS... for local zones (Z|[+\-][0-9]{4}|[+\-][0-9]{2}:[0-9]{2})?'; var $timestamp = -1; /** * Constructor. * * @param string|integer $date The timestamp or ISO 8601 formatted * date and time this object is going to * represent. */ function SOAP_Type_dateTime($date = -1) { if ($date == -1) { $this->timestamp = time(); } elseif (is_int($date)) { $this->timestamp = $date; } else { $this->timestamp = $this->toUnixtime($date); } } /** * Alias of {@link SOAP_Type_dateTime::toUTC}. */ function toSOAP($date = NULL) { return $this->toUTC($date); } /** * Converts this object or a timestamp to an ISO 8601 date/time string. * * @param integer $timestamp A unix timestamp * * @return string An ISO 8601 formatted date/time string. */ function toString($timestamp = 0) { if (!$timestamp) { $timestamp = $this->timestamp; } if ($timestamp < 0) { return 0; } //simulate PHP5's P parameter $zone = date('O', $timestamp); if (strlen($zone) === 5) { $zone = substr($zone, 0, 3) . ':' . substr($zone, 3); } return date('Y-m-d\TH:i:s', $timestamp) . $zone; } /** * Splits a date/time into its components. * * @param string|integer $datestr A unix timestamp or ISO 8601 date/time * string. If empty, this object is used. * * @return boolean|array An array with the date and time components or * false on failure. */ function _split($datestr) { if (!$datestr) { $datestr = $this->toString(); } elseif (is_int($datestr)) { $datestr = $this->toString($datestr); } if (preg_match('/' . $this->_iso8601 . '/x', $datestr, $regs)) { if (empty($regs[8])) { $timestamp = strtotime(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6])); $regs[8] = date('O', $timestamp); } if ($regs[8] != 'Z') { $op = substr($regs[8], 0, 1); $h = substr($regs[8], 1, 2); if (strstr($regs[8], ':')) { $m = substr($regs[8], 4, 2); } else { $m = substr($regs[8], 3, 2); } if ($op == '+') { $regs[4] = $regs[4] - $h; if ($regs[4] < 0) { $regs[4] += 24; } $regs[5] = $regs[5] - $m; if ($regs[5] < 0) { $regs[5] += 60; } } else { $regs[4] = $regs[4] + $h; if ($regs[4] > 23) { $regs[4] -= 24; } $regs[5] = $regs[5] + $m; if ($regs[5] > 59) { $regs[5] -= 60; } } } return $regs; } return false; } /** * Returns an ISO 8601 formatted UTC date/time string. * * @param string|integer $datestr @see SOAP_Type_dateTime::_split * * @return string The ISO 8601 formatted UTC date/time string. */ function toUTC($datestr = null) { $regs = $this->_split($datestr); if ($regs) { return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]); } return ''; } /** * Returns a unix timestamp. * * @param string|integer $datestr @see SOAP_Type_dateTime::_split * * @return integer The unix timestamp. */ function toUnixtime($datestr = null) { $regs = $this->_split($datestr); if ($regs) { return strtotime(sprintf('%04d-%02d-%02d %02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6])); } return -1; } /** * Compares two dates or this object with a second date. * * @param string|integer $date1 A unix timestamp or ISO 8601 date/time * string. * @param string|integer $date2 A unix timestamp or ISO 8601 date/time * string. If empty, this object is used. * * @return integer The difference between the first and the second date. */ function compare($date1, $date2 = null) { if (is_null($date2)) { $date2 = $date1; $date1 = $this->timestamp; } if (!is_int($date1)) { $date1 = $this->toUnixtime($date1); } if (!is_int($date2)) { $date2 = $this->toUnixtime($date2); } if ($date1 != -1 && $date2 != -1) { return $date1 - $date2; } return -1; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Type/duration.php000066400000000000000000000155441214222670500206340ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** * This is only an aproximation of duration, more work still to do. See the * schema url for more info on duration. * * http://www.w3.org/TR/xmlschema-2/ * * [Definition:] duration represents a duration of time. The value space of * duration is a six-dimensional space where the coordinates designate the * Gregorian year, month, day, hour, minute, and second components * defined in 5.5.3.2 of [ISO 8601], respectively. These components are * ordered in their significance by their order of appearance i.e. as year, * month, day, hour, minute, and second. * * 3.2.6.1 Lexical representation * The lexical representation for duration is the [ISO 8601] extended * format PnYn MnDTnH nMnS, where nY represents the number of * years, nM the number of months, nD the number of days, 'T' is the * date/time separator, nH the number of hours, nM the number of * minutes and nS the number of seconds. The number of seconds * can include decimal digits to arbitrary precision. * * The values of the Year, Month, Day, Hour and Minutes components * are not restricted but allow an arbitrary integer. Similarly, the * value of the Seconds component allows an arbitrary decimal. * Thus, the lexical representation of duration does not follow the * alternative format of 5.5.3.2.1 of [ISO 8601]. * * An optional preceding minus sign ('-') is allowed, to indicate a * negative duration. If the sign is omitted a positive duration is * indicated. See also ISO 8601 Date and Time Formats (D). * * For example, to indicate a duration of 1 year, 2 months, 3 days, * 10 hours, and 30 minutes, one would write: P1Y2M3DT10H30M. * One could also indicate a duration of minus 120 days as: -P120D. * * Reduced precision and truncated representations of this format * are allowed provided they conform to the following: * * If the number of years, months, days, hours, minutes, or seconds * in any expression equals zero, the number and its corresponding * designator *may* be omitted. However, at least one number and * its designator *must* be present. * The seconds part *may* have a decimal fraction. * The designator 'T' shall be absent if all of the time items are absent. * The designator 'P' must always be present. * For example, P1347Y, P1347M and P1Y2MT2H are all allowed; P0Y1347M * and P0Y1347M0D are allowed. P-1347M is not allowed although -P1347M * is allowed. P1Y2MT is not allowed. * * @access public * @package SOAP * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance * @todo Figure out best aproximation for year and month conversion to * seconds */ class SOAP_Type_duration { // format PnYnMnDTnHnMnS function unix_to_duration($seconds) { return SOAP_Type_duration::getduration($seconds); } function mod($a, $b, &$d, &$r) { $d = floor($a / $b); $r = $a % $b; } function getduration($seconds) { $neg = ''; if ($seconds < 0) { $neg = '-'; $seconds = $seconds * -1; } $_mi = 60; $_h = $_mi * 60; $_d = $_h * 24; // XXX how do we properly handle month and year values? $_m = $_d * 30; $_y = $_d * 365; SOAP_Type_duration::mod($seconds, $_y, $y, $seconds); SOAP_Type_duration::mod($seconds, $_m, $m, $seconds); SOAP_Type_duration::mod($seconds, $_d, $d, $seconds); SOAP_Type_duration::mod($seconds, $_h, $h, $seconds); SOAP_Type_duration::mod($seconds, $_mi, $mi, $s); $duration = $neg.'P'; if ($y) $duration .= $y.'Y'; if ($m) $duration .= $m.'M'; if ($d) $duration .= $d.'D'; if ($h || $mi || $s) $duration .='T'; if ($h) $duration .= $h.'H'; if ($mi) $duration .= $mi.'M'; if ($s) $duration .= $s.'S'; if ($duration == 'P' || $duration == '-P') $duration = 'PT0S'; return $duration; } function mkduration($n, $Y, $Mo, $D, $H, $Mi, $S) { $_mi = 60; $_h = $_mi * 60; $_d = $_h * 24; // XXX how do we properly handle month and year values? $_m = $_d * 30; $_y = $_d * 365; $sec = $Y * $_y + $Mo * $_m + $D * $_d + $H * $_h + $Mi * $_mi + $S; if ($n == '-') $sec = $sec * -1; return $sec; } function duration_to_unix($duration) { if (preg_match('/(-)?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T?([0-9]+H)?([0-9]+M)?([0-9]+S)?/', $duration, $regs)) { return SOAP_Type_duration::mkduration($regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6], $regs[7]); } return false; } function is_duration($duration) { return preg_match('/(-)?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T?([0-9]+H)?([0-9]+M)?([0-9]+S)?/', $duration, $regs); } function _test($time) { if (SOAP_Type_duration::is_duration($time)) { $t = SOAP_Type_duration::duration_to_unix($time); echo "Duration: $time is ".$t." seconds\n"; } else { $t = SOAP_Type_duration::unix_to_duration($time); echo "Seconds: $time is ".$t." duration\n"; } return $t; } function add($d1, $d2) { $s1 = SOAP_Type_duration::duration_to_unix($d1); $s2 = SOAP_Type_duration::duration_to_unix($d2); return SOAP_Type_duration::unix_to_duration($s1 + $s2); } function subtract($d1, $d2) { $s1 = SOAP_Type_duration::duration_to_unix($d1); $s2 = SOAP_Type_duration::duration_to_unix($d2); return SOAP_Type_duration::unix_to_duration($s1 - $s2); } } /* Tests. */ $t = SOAP_Type_duration::_test('P1Y2M3DT10H30M'); SOAP_Type_duration::_test($t); $t = SOAP_Type_duration::_test('-P120D'); SOAP_Type_duration::_test($t); /* Duration since 1970. */ $t = SOAP_Type_duration::_test(time()); SOAP_Type_duration::_test($t); echo 'Add should be PT0S: ' . SOAP_Type_duration::add('-P120D','P4M') . "\n"; echo 'Subtract should be PT0S: ' . SOAP_Type_duration::subtract('P120D','P4M') . "\n"; php-soap-0.13.0/SOAP-0.13.0/SOAP/Type/hexBinary.php000066400000000000000000000026061214222670500207330ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ class SOAP_Type_hexBinary { function to_bin($value) { return pack('H' . strlen($value), $value); } function to_hex($value) { return bin2hex($value); } function is_hexbin($value) { // First see if there are any invalid chars. if (!strlen($value) || preg_match('/[^A-Fa-f0-9]/', $value)) { return false; } return strcasecmp($value, SOAP_Type_hexBinary::to_hex(SOAP_Type_hexBinary::to_bin($value))) == 0; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/Value.php000066400000000000000000000212611214222670500171330ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Base.php'; /** * SOAP::Value * * This class converts values between PHP and SOAP. * * Originally based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Dietrich Ayala Original Author */ class SOAP_Value { /** * The actual value. * * @var mixed */ var $value = null; /** * QName instance representing the value name. * * @var QName */ var $nqn; /** * The value name, without namespace information. * * @var string */ var $name = ''; /** * The namespace of the value name. * * @var string */ var $namespace = ''; /** * QName instance representing the value type. * * @var QName */ var $tqn; /** * The value type, without namespace information. * * @var string */ var $type = ''; /** * The namespace of the value type. * * @var string */ var $type_namespace = ''; /** * The type of the array elements, if this value is an array. * * @var string */ var $arrayType = ''; /** * A hash of additional attributes. * * @see SOAP_Value() * @var array */ var $attributes = array(); /** * List of encoding and serialization options. * * @see SOAP_Value() * @var array */ var $options = array(); /** * Constructor. * * @param string $name Name of the SOAP value {namespace}name. * @param mixed $type SOAP value {namespace}type. Determined * automatically if not set. * @param mixed $value Value to set. * @param array $attributes A has of additional XML attributes to be * added to the serialized value. * @param array $options A list of encoding and serialization options: * - 'attachment': array with information about * the attachment * - 'soap_encoding': defines encoding for SOAP * message part of a MIME encoded SOAP request * (default: base64) * - 'keep_arrays_flat': use the tag name * multiple times for each element when * passing in an array in literal mode * - 'no_type_prefix': supress adding of the * namespace prefix */ function SOAP_Value($name = '', $type = false, $value = null, $attributes = array(), $options = array()) { $this->nqn = new QName($name); $this->name = $this->nqn->name; $this->namespace = $this->nqn->namespace; $this->tqn = new QName($type); $this->type = $this->tqn->name; $this->type_namespace = $this->tqn->namespace; $this->value = $value; $this->attributes = $attributes; $this->options = $options; } /** * Serializes this value. * * @param SOAP_Base $serializer A SOAP_Base instance or subclass to * serialize with. * * @return string XML representation of $this. */ function serialize(&$serializer) { return $serializer->_serializeValue($this->value, $this->nqn, $this->tqn, $this->options, $this->attributes, $this->arrayType); } } /** * This class converts values between PHP and SOAP. It is a simple wrapper * around SOAP_Value, adding support for SOAP actor and mustunderstand * parameters. * * Originally based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Dietrich Ayala Original Author */ class SOAP_Header extends SOAP_Value { /** * Constructor * * @param string $name Name of the SOAP value {namespace}name. * @param mixed $type SOAP value {namespace}type. Determined * automatically if not set. * @param mixed $value Value to set * @param integer $mustunderstand Zero or one. * @param mixed $attributes Attributes. */ function SOAP_Header($name = '', $type, $value, $mustunderstand = 0, $attributes = array()) { if (!is_array($attributes)) { $actor = $attributes; $attributes = array(); } parent::SOAP_Value($name, $type, $value, $attributes); if (isset($actor)) { $this->attributes[SOAP_BASE::SOAPENVPrefix().':actor'] = $actor; } elseif (!isset($this->attributes[SOAP_BASE::SOAPENVPrefix().':actor'])) { $this->attributes[SOAP_BASE::SOAPENVPrefix().':actor'] = 'http://schemas.xmlsoap.org/soap/actor/next'; } $this->attributes[SOAP_BASE::SOAPENVPrefix().':mustUnderstand'] = (int)$mustunderstand; } } /** * This class handles MIME attachements per W3C's Note on Soap Attachements at * http://www.w3.org/TR/SOAP-attachments * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates */ class SOAP_Attachment extends SOAP_Value { /** * Constructor. * * @param string $name Name of the SOAP value * @param string $type The attachment's MIME type. * @param string $filename The attachment's file name. Ignored if $file * is provide. * @param string $file The attachment data. * @param array $attributes Attributes. */ function SOAP_Attachment($name = '', $type = 'application/octet-stream', $filename, $file = null, $attributes = null) { parent::SOAP_Value($name, null, null); $filedata = $file === null ? $this->_file2str($filename) : $file; $filename = basename($filename); if (PEAR::isError($filedata)) { $this->options['attachment'] = $filedata; return; } $cid = md5(uniqid(time())); $this->attributes = $attributes; $this->attributes['href'] = 'cid:' . $cid; $this->options['attachment'] = array('body' => $filedata, 'disposition' => $filename, 'content_type' => $type, 'encoding' => 'base64', 'cid' => $cid); } /** * Returns the contents of the given file name as string. * * @access private * * @param string $file_name The file location. * * @return string The file data or a PEAR_Error. */ function _file2str($file_name) { if (!is_readable($file_name)) { return PEAR::raiseError('File is not readable: ' . $file_name); } if (function_exists('file_get_contents')) { return file_get_contents($file_name); } if (!$fd = fopen($file_name, 'rb')) { return PEAR::raiseError('Could not open ' . $file_name); } $cont = fread($fd, filesize($file_name)); fclose($fd); return $cont; } } php-soap-0.13.0/SOAP-0.13.0/SOAP/WSDL.php000066400000000000000000002603651214222670500166420ustar00rootroot00000000000000 Original Author * @author Shane Caraveo Port to PEAR and more * @author Chuck Hagenbuch Maintenance * @author Jan Schneider Maintenance * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Base.php'; require_once 'SOAP/Fault.php'; require_once 'HTTP/Request.php'; define('WSDL_CACHE_MAX_AGE', 43200); /** * This class parses WSDL files, and can be used by SOAP::Client to properly * register soap values for services. * * Originally based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @todo * - refactor namespace handling ($namespace/$ns) * - implement IDL type syntax declaration so we can generate WSDL * * @access public * @package SOAP * @author Shane Caraveo Conversion to PEAR and updates * @author Dietrich Ayala Original Author */ class SOAP_WSDL extends SOAP_Base { var $tns = null; var $definition = array(); var $namespaces = array(); var $ns = array(); var $xsd = SOAP_XML_SCHEMA_VERSION; var $complexTypes = array(); var $elements = array(); var $messages = array(); var $portTypes = array(); var $bindings = array(); var $imports = array(); var $services = array(); var $service = ''; /** * URL to WSDL file. * * @var string */ var $uri; /** * Parse documentation in the WSDL? * * @var boolean */ var $docs; /** * Proxy parameters. * * @var array */ var $proxy; /** * Enable tracing in the generated proxy class? * * @var boolean */ var $trace = false; /** * Use WSDL cache? * * @var boolean */ var $cacheUse; /** * WSDL cache directory. * * @var string */ var $cacheDir; /** * Cache maximum lifetime (in seconds). * * @var integer */ var $cacheMaxAge; /** * Class to use for WSDL parsing. Can be overridden for special cases, * subclasses, etc. * * @var string */ var $wsdlParserClass = 'SOAP_WSDL_Parser'; /** * Reserved PHP keywords. * * @link http://www.php.net/manual/en/reserved.php * * @var array */ var $_reserved = array('abstract', 'and', 'array', 'as', 'break', 'case', 'catch', 'cfunction', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exception', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'if', 'implements', 'include', 'include_once', 'interface', 'isset', 'list', 'new', 'old_function', 'or', 'php_user_filter', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'this', 'throw', 'try', 'unset', 'use', 'var', 'while', 'xor'); /** * Regular expressions for invalid PHP labels. * * @link http://www.php.net/manual/en/language.variables.php. * * @var string */ var $_invalid = array('/^[^a-zA-Z_\x7f-\xff]/', '/[^a-zA-Z0-9_\x7f-\xff]/'); /** * SOAP_WSDL constructor. * * @param string $wsdl_uri URL to WSDL file. * @param array $proxy Options for HTTP_Request class * @see HTTP_Request. * @param boolean|string $cacheUse Use WSDL caching? The cache directory * if a string. * @param integer $cacheMaxAge Cache maximum lifetime (in seconds). * @param boolean $docs Parse documentation in the WSDL? * * @access public */ function SOAP_WSDL($wsdl_uri = false, $proxy = array(), $cacheUse = false, $cacheMaxAge = WSDL_CACHE_MAX_AGE, $docs = false) { parent::SOAP_Base('WSDL'); $this->uri = $wsdl_uri; $this->proxy = $proxy; $this->cacheUse = !empty($cacheUse); $this->cacheMaxAge = $cacheMaxAge; $this->docs = $docs; if (is_string($cacheUse)) { $this->cacheDir = $cacheUse; } if ($wsdl_uri) { if (!PEAR::isError($this->parseURL($wsdl_uri))) { reset($this->services); $this->service = key($this->services); } } } /** * @deprecated Use setService(). */ function set_service($service) { $this->setService($service); } /** * Sets the service currently to be used. * * @param string $service An (existing) service name. */ function setService($service) { if (array_key_exists($service, $this->services)) { $this->service = $service; } } /** * Fills the WSDL array tree with data from a WSDL file. * * @param string $wsdl_uri URL to WSDL file. */ function parseURL($wsdl_uri) { $parser = new $this->wsdlParserClass($wsdl_uri, $this, $this->docs); if ($parser->fault) { $this->_raiseSoapFault($parser->fault); } } /** * Fills the WSDL array tree with data from one or more PHP class objects. * * @param mixed $wsdl_obj An object or array of objects to add to * the internal WSDL tree. * @param string $targetNamespace The target namespace of schema types * etc. * @param string $service_name Name of the WSDL service. * @param string $service_desc Optional description of the WSDL * service. */ function parseObject($wsdl_obj, $targetNamespace, $service_name, $service_desc = '') { $parser = new SOAP_WSDL_ObjectParser($wsdl_obj, $this, $targetNamespace, $service_name, $service_desc); if ($parser->fault) { $this->_raiseSoapFault($parser->fault); } } function getEndpoint($portName) { if ($this->_isfault()) { return $this->_getfault(); } return (isset($this->services[$this->service]['ports'][$portName]['address']['location'])) ? $this->services[$this->service]['ports'][$portName]['address']['location'] : $this->_raiseSoapFault("No endpoint for port for $portName", $this->uri); } function _getPortName($operation, $service) { if (isset($this->services[$service]['ports'])) { $ports = $this->services[$service]['ports']; foreach ($ports as $port => $portAttrs) { $type = $ports[$port]['type']; if ($type == 'soap' && isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) { return $port; } } } return null; } /** * Finds the name of the first port that contains an operation of name * $operation. Always returns a SOAP portName. */ function getPortName($operation, $service = null) { if ($this->_isfault()) { return $this->_getfault(); } if (!$service) { $service = $this->service; } if (isset($this->services[$service]['ports'])) { if ($portName = $this->_getPortName($operation, $service)) { return $portName; } } // Try any service in the WSDL. foreach ($this->services as $serviceName => $service) { if (isset($this->services[$serviceName]['ports'])) { if ($portName = $this->_getPortName($operation, $serviceName)) { $this->service = $serviceName; return $portName; } } } return $this->_raiseSoapFault("No operation $operation in WSDL.", $this->uri); } function getOperationData($portName, $operation) { if ($this->_isfault()) { return $this->_getfault(); } if (!isset($this->services[$this->service]['ports'][$portName]['binding']) || !($binding = $this->services[$this->service]['ports'][$portName]['binding'])) { return $this->_raiseSoapFault("No binding for port $portName in WSDL.", $this->uri); } // Get operation data from binding. if (is_array($this->bindings[$binding]['operations'][$operation])) { $opData = $this->bindings[$binding]['operations'][$operation]; } // Get operation data from porttype. $portType = $this->bindings[$binding]['type']; if (!$portType) { return $this->_raiseSoapFault("No port type for binding $binding in WSDL.", $this->uri); } if (is_array($type = $this->portTypes[$portType][$operation])) { if (isset($type['parameterOrder'])) { $opData['parameterOrder'] = $type['parameterOrder']; } $opData['input'] = array_merge($opData['input'], $type['input']); $opData['output'] = array_merge($opData['output'], $type['output']); } if (!$opData) return $this->_raiseSoapFault("No operation $operation for port $portName in WSDL.", $this->uri); $opData['parameters'] = false; if (isset($this->bindings[$binding]['operations'][$operation]['input']['namespace'])) $opData['namespace'] = $this->bindings[$binding]['operations'][$operation]['input']['namespace']; // Message data from messages. $inputMsg = $opData['input']['message']; if (isset($opData['input']['parts']) && !is_array($opData['input']['parts'])) { $opData['input']['parts'] = array($opData['input']['parts'] => ''); } if (is_array($this->messages[$inputMsg])) { foreach ($this->messages[$inputMsg] as $pname => $pattrs) { if ($opData['style'] == 'document' && $opData['input']['use'] == 'literal' && $pname == 'parameters') { $opData['parameters'] = true; $opData['namespace'] = $this->namespaces[$pattrs['namespace']]; $el = $this->elements[$pattrs['namespace']][$pattrs['type']]; if (isset($el['elements'])) { foreach ($el['elements'] as $elname => $elattrs) { $opData['input']['parts'][$elname] = $elattrs; } } } else { $opData['input']['parts'][$pname] = $pattrs; } } } $outputMsg = $opData['output']['message']; if (isset($opData['output']['parts']) && !is_array($opData['output']['parts'])) { $opData['output']['parts'] = array($opData['output']['parts'] => ''); } if (is_array($this->messages[$outputMsg])) { foreach ($this->messages[$outputMsg] as $pname => $pattrs) { if ($opData['style'] == 'document' && $opData['output']['use'] == 'literal' && $pname == 'parameters') { $el = $this->elements[$pattrs['namespace']][$pattrs['type']]; if (isset($el['elements'])) { foreach ($el['elements'] as $elname => $elattrs) { $opData['output']['parts'][$elname] = $elattrs; } } } else { $opData['output']['parts'][$pname] = $pattrs; } } } return $opData; } function matchMethod(&$operation) { if ($this->_isfault()) { return $this->_getfault(); } // Overloading lowercases function names :( foreach ($this->services[$this->service]['ports'] as $portAttrs) { foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) { if (strcasecmp($op, $operation) == 0) { $operation = $op; } } } } /** * Given a datatype, what function handles the processing? * * This is used for doc/literal requests where we receive a datatype, and * we need to pass it to a method in out server class. * * @param string $datatype * @param string $namespace * @return string * @access public */ function getDataHandler($datatype, $namespace) { // See if we have an element by this name. if (isset($this->namespaces[$namespace])) { $namespace = $this->namespaces[$namespace]; } if (!isset($this->ns[$namespace])) { return null; } $nsp = $this->ns[$namespace]; //if (!isset($this->elements[$nsp])) // $nsp = $this->namespaces[$nsp]; if (!isset($this->elements[$nsp][$datatype])) { return null; } $checkmessages = array(); // Find what messages use this datatype. foreach ($this->messages as $messagename => $message) { foreach ($message as $part) { if ($part['type'] == $datatype) { $checkmessages[] = $messagename; break; } } } // Find the operation that uses this message. foreach($this->portTypes as $porttype) { foreach ($porttype as $opname => $opinfo) { foreach ($checkmessages as $messagename) { if ($opinfo['input']['message'] == $messagename) { return $opname; } } } } return null; } function getSoapAction($portName, $operation) { if ($this->_isfault()) { return $this->_getfault(); } if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'])) { return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']; } return false; } function getNamespace($portName, $operation) { if ($this->_isfault()) { return $this->_getfault(); } if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'])) { return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']; } return false; } function getNamespaceAttributeName($namespace) { /* If it doesn't exist at first, flip the array and check again. */ if (empty($this->ns[$namespace])) { $this->ns = array_flip($this->namespaces); } /* If it doesn't exist now, add it. */ if (empty($this->ns[$namespace])) { return $this->addNamespace($namespace); } return $this->ns[$namespace]; } function addNamespace($namespace) { if (!empty($this->ns[$namespace])) { return $this->ns[$namespace]; } $n = count($this->ns); $attr = 'ns' . $n; $this->namespaces['ns' . $n] = $namespace; $this->ns[$namespace] = $attr; return $attr; } function _validateString($string) { return preg_match('/^[\w_:#\/]+$/', $string); } function _addArg(&$args, &$argarray, $argname) { if ($args) { $args .= ', '; } $args .= '$' . $argname; if (!$this->_validateString($argname)) { return; } if ($argarray) { $argarray .= ', '; } $argarray .= "'$argname' => $" . $argname; } function _elementArg(&$args, &$argarray, &$_argtype, $_argname) { $comments = ''; $el = $this->elements[$_argtype['namespace']][$_argtype['type']]; $tns = isset($this->ns[$el['namespace']]) ? $this->ns[$el['namespace']] : $_argtype['namespace']; if (!empty($el['complex']) || (isset($el['type']) && isset($this->complexTypes[$tns][$el['type']]))) { // The element is a complex type. $comments .= " // {$_argtype['type']} is a ComplexType, refer to the WSDL for more info.\n"; $attrname = "{$_argtype['type']}_attr"; if (isset($el['type']) && isset($this->complexTypes[$tns][$el['type']]['attribute'])) { $comments .= " // {$_argtype['type']} may require attributes, refer to the WSDL for more info.\n"; } $comments .= " \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n"; $comments .= " \${$_argtype['type']} = new SOAP_Value('{$_argtype['type']}', false, \${$_argtype['type']}, \$$attrname);\n"; $this->_addArg($args, $argarray, $_argtype['type']); if (isset($el['type']) && isset($this->complexTypes[$tns][$el['type']]['attribute'])) { if ($args) { $args .= ', '; } $args .= '$' . $attrname; } } elseif (isset($el['elements'])) { foreach ($el['elements'] as $ename => $element) { $comments .= " \$$ename = new SOAP_Value('{{$this->namespaces[$element['namespace']]}}$ename', '" . (isset($element['type']) ? $element['type'] : false) . "', \$$ename);\n"; $this->_addArg($args, $argarray, $ename); } } else { $comments .= " \$$_argname = new SOAP_Value('{{$this->namespaces[$tns]}}$_argname', '{$el['type']}', \$$_argname);\n"; $this->_addArg($args, $argarray, $_argname); } return $comments; } function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname) { $comments = ''; if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) { $comments = " // $_argname is a ComplexType {$_argtype['type']},\n" . " // refer to wsdl for more info\n"; if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) { $comments .= " // $_argname may require attributes, refer to wsdl for more info\n"; } $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $_argtype['type']; $comments .= " \$$_argname = new SOAP_Value('$_argname', '$wrapname', \$$_argname);\n"; } $this->_addArg($args, $argarray, $_argname); return $comments; } /** * Generates stub code from the WSDL that can be saved to a file or eval'd * into existence. */ function generateProxyCode($port = '', $classname = '') { if ($this->_isfault()) { return $this->_getfault(); } $multiport = count($this->services[$this->service]['ports']) > 1; if (!$port) { reset($this->services[$this->service]['ports']); $port = current($this->services[$this->service]['ports']); } // XXX currently do not support HTTP ports if ($port['type'] != 'soap') { return null; } // XXX currentPort is BAD $clienturl = $port['address']['location']; if (!$classname) { if ($multiport || $port) { $classname = 'WebService_' . $this->service . '_' . $port['name']; } else { $classname = 'WebService_' . $this->service; } $classname = $this->_sanitize($classname); } if (!$this->_validateString($classname)) { return null; } if (is_array($this->proxy) && count($this->proxy)) { $class = "class $classname extends SOAP_Client\n{\n" . " function $classname(\$path = '$clienturl')\n {\n" . " \$this->SOAP_Client(\$path, 0, 0,\n" . ' array('; foreach ($this->proxy as $key => $val) { if (is_array($val)) { $class .= "'$key' => array("; foreach ($val as $key2 => $val2) { $class .= "'$key2' => '$val2', "; } $class .= ')'; } else { $class .= "'$key' => '$val', "; } } $class .= "));\n }\n"; $class = str_replace(', ))', '))', $class); } else { $class = "class $classname extends SOAP_Client\n{\n" . " function $classname(\$path = '$clienturl')\n {\n" . " \$this->SOAP_Client(\$path, 0);\n" . " }\n"; } // Get the binding, from that get the port type. $primaryBinding = $port['binding']; $primaryBinding = preg_replace("/^(.*:)/", '', $primaryBinding); $portType = $this->bindings[$primaryBinding]['type']; $portType = preg_replace("/^(.*:)/", '', $portType); $style = $this->bindings[$primaryBinding]['style']; // XXX currentPortType is BAD foreach ($this->portTypes[$portType] as $opname => $operation) { $binding = $this->bindings[$primaryBinding]['operations'][$opname]; if (isset($binding['soapAction'])) { $soapaction = $binding['soapAction']; } else { $soapaction = null; } if (isset($binding['style'])) { $opstyle = $binding['style']; } else { $opstyle = $style; } $use = $binding['input']['use']; if ($use == 'encoded') { $namespace = $binding['input']['namespace']; } else { $bindingType = $this->bindings[$primaryBinding]['type']; $ns = $this->portTypes[$bindingType][$opname]['input']['namespace']; $namespace = $this->namespaces[$ns]; } $args = ''; $argarray = ''; $comments = ''; $wrappers = ''; foreach ($operation['input'] as $argname => $argtype) { if ($argname == 'message') { foreach ($this->messages[$argtype] as $_argname => $_argtype) { $_argname = $this->_sanitize($_argname); if ($opstyle == 'document' && $use == 'literal' && $_argtype['name'] == 'parameters') { // The type or element refered to is used for // parameters. $elattrs = null; $el = $this->elements[$_argtype['namespace']][$_argtype['type']]; if ($el['complex']) { $namespace = $this->namespaces[$_argtype['namespace']]; // XXX need to wrap the parameters in a // SOAP_Value. } if (isset($el['elements'])) { foreach ($el['elements'] as $elname => $elattrs) { $elname = $this->_sanitize($elname); // Is the element a complex type? if (isset($this->complexTypes[$elattrs['namespace']][$elname])) { $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname); } else { $this->_addArg($args, $argarray, $elname); } } } if ($el['complex'] && $argarray) { $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $el['name']; $comments .= " \${$el['name']} = new SOAP_Value('$wrapname', false, \$v = array($argarray));\n"; $argarray = "'{$el['name']}' => \${$el['name']}"; } } else { if (isset($_argtype['element'])) { // Element argument. $comments .= $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']); } else { // Complex type argument. $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname); } } } } } // Validate entries. // Operation names are function names, so try to make sure it's // legal. This could potentially cause collisions, but let's try // to make everything callable and see how many problems that // causes. $opname_php = $this->_sanitize($opname); if (!$this->_validateString($opname_php)) { return null; } if ($argarray) { $argarray = "array($argarray)"; } else { $argarray = 'null'; } $class .= " function &$opname_php($args)\n {\n$comments$wrappers" . " \$result = \$this->call('$opname',\n" . " \$v = $argarray,\n" . " array('namespace' => '$namespace',\n" . " 'soapaction' => '$soapaction',\n" . " 'style' => '$opstyle',\n" . " 'use' => '$use'" . ($this->trace ? ",\n 'trace' => true" : '') . "));\n" . " return \$result;\n" . " }\n"; } $class .= "}\n"; return $class; } function generateAllProxies() { $proxycode = ''; foreach (array_keys($this->services[$this->service]['ports']) as $key) { $port =& $this->services[$this->service]['ports'][$key]; $proxycode .= $this->generateProxyCode($port); } return $proxycode; } function &getProxy($port = '', $name = '') { if ($this->_isfault()) { $fault =& $this->_getfault(); return $fault; } $multiport = count($this->services[$this->service]['ports']) > 1; if (!$port) { reset($this->services[$this->service]['ports']); $port = current($this->services[$this->service]['ports']); } if ($multiport || $port) { $classname = 'WebService_' . $this->service . '_' . $port['name']; } else { $classname = 'WebService_' . $this->service; } if ($name) { $classname = $name . '_' . $classname; } $classname = $this->_sanitize($classname); if (!class_exists($classname)) { $proxy = $this->generateProxyCode($port, $classname); require_once 'SOAP/Client.php'; eval($proxy); } $proxy = new $classname; return $proxy; } /** * Sanitizes a SOAP value, method or class name so that it can be used as * a valid PHP identifier. Invalid characters are converted into * underscores and reserved words are prefixed with an underscore. * * @param string $name The identifier to sanitize. * * @return string The sanitized identifier. */ function _sanitize($name) { $name = preg_replace($this->_invalid, '_', $name); if (in_array($name, $this->_reserved)) { $name = '_' . $name; } return $name; } function &_getComplexTypeForElement($name, $namespace) { $t = null; if (isset($this->ns[$namespace]) && isset($this->elements[$this->ns[$namespace]][$name]['type'])) { $type = $this->elements[$this->ns[$namespace]][$name]['type']; $ns = $this->elements[$this->ns[$namespace]][$name]['namespace']; if (isset($this->complexTypes[$ns][$type])) { $t = $this->complexTypes[$ns][$type]; } } return $t; } function getComplexTypeNameForElement($name, $namespace) { $t = $this->_getComplexTypeForElement($name, $namespace); if ($t) { return $t['name']; } return null; } function getComplexTypeChildType($ns, $name, $child_ns, $child_name) { // Is the type an element? $t = $this->_getComplexTypeForElement($name, $ns); if ($t) { // No, get it from complex types directly. if (isset($t['elements'][$child_name]['type'])) return $t['elements'][$child_name]['type']; } elseif (isset($this->ns[$ns]) && isset($this->elements[$this->ns[$ns]][$name]['complex']) && $this->elements[$this->ns[$ns]][$name]['complex']) { // Type is not an element but complex. return $this->elements[$this->ns[$ns]][$name]['elements'][$child_name]['type']; } return null; } /** * @param QName $name A parameter name. * @param QName $type A parameter type. * * @return array A list of [type, array element type, array element * namespace, array length]. */ function getSchemaType($type, $name) { // 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->complexTypes as $types) { if (isset($types[$type->name])) { if (isset($types[$type->name]['type'])) { list($arraytype_ns, $arraytype, $array_depth) = isset($types[$type->name]['arrayType']) ? $this->_getDeepestArrayType($types[$type->name]['namespace'], $types[$type->name]['arrayType']) : array($this->namespaces[$types[$type->name]['namespace']], null, 0); return array($types[$type->name]['type'], $arraytype, $arraytype_ns, $array_depth); } if (isset($types[$type->name]['arrayType'])) { list($arraytype_ns, $arraytype, $array_depth) = $this->_getDeepestArrayType($types[$type->name]['namespace'], $types[$type->name]['arrayType']); return array('Array', $arraytype, $arraytype_ns, $array_depth); } if (!empty($types[$type->name]['elements'][$name->name])) { $type->name = $types[$type->name]['elements']['type']; return array($type->name, null, $this->namespaces[$types[$type->name]['namespace']], null); } break; } } } 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->ns[$type->namespace]; if ($p && !empty($this->complexTypes[$p][$type->name])) { if ($arrayType = $this->complexTypes[$p][$type->name]['arrayType']) { $type->name = 'Array'; } elseif ($this->complexTypes[$p][$type->name]['order'] == 'sequence' && array_key_exists('elements', $this->complexTypes[$p][$type->name])) { reset($this->complexTypes[$p][$type->name]['elements']); // assume an array if (count($this->complexTypes[$p][$type->name]['elements']) == 1) { $arg = current($this->complexTypes[$p][$type->name]['elements']); $arrayType = $arg['type']; $type->name = 'Array'; } else { foreach ($this->complexTypes[$p][$type->name]['elements'] as $element) { if ($element['name'] == $type->name) { $arrayType = $element['type']; $type->name = $element['type']; } } } } else { $type->name = 'Struct'; } return array($type->name, $arrayType, $type->namespace, null); } } return array(null, null, null, null); } /** * Recurse through the WSDL structure looking for the innermost array type * of multi-dimensional arrays. * * Takes a namespace prefix and a type, which can be in the form 'type' or * 'type[]', and returns the full namespace URI, the type of the most * deeply nested array type found, and the number of levels of nesting. * * @access private * @return mixed array or nothing */ function _getDeepestArrayType($nsPrefix, $arrayType) { static $trail = array(); $arrayType = preg_replace('/\[\]$/', '', $arrayType); // Protect against circular references XXX We really need to remove // trail from this altogether (it's very inefficient and in the wrong // place!) and put circular reference checking in when the WSDL info // is generated in the first place if (array_search($nsPrefix . ':' . $arrayType, $trail)) { return array(null, null, -count($trail)); } if (array_key_exists($nsPrefix, $this->complexTypes) && array_key_exists($arrayType, $this->complexTypes[$nsPrefix]) && array_key_exists('arrayType', $this->complexTypes[$nsPrefix][$arrayType])) { $trail[] = $nsPrefix . ':' . $arrayType; $result = $this->_getDeepestArrayType($this->complexTypes[$nsPrefix][$arrayType]['namespace'], $this->complexTypes[$nsPrefix][$arrayType]['arrayType']); return array($result[0], $result[1], $result[2] + 1); } return array($this->namespaces[$nsPrefix], $arrayType, 0); } } class SOAP_WSDL_Cache extends SOAP_Base { /** * Use WSDL cache? * * @var boolean */ var $_cacheUse; /** * WSDL cache directory. * * @var string */ var $_cacheDir; /** * Cache maximum lifetime (in seconds) * * @var integer */ var $_cacheMaxAge; /** * Constructor. * * @param boolean $cashUse Use caching? * @param integer $cacheMaxAge Cache maximum lifetime (in seconds) */ function SOAP_WSDL_Cache($cacheUse = false, $cacheMaxAge = WSDL_CACHE_MAX_AGE, $cacheDir = null) { parent::SOAP_Base('WSDLCACHE'); $this->_cacheUse = $cacheUse; $this->_cacheDir = $cacheDir; $this->_cacheMaxAge = $cacheMaxAge; } /** * Returns the path to the cache and creates it, if it doesn't exist. * * @private * * @return string The directory to use for the cache. */ function _cacheDir() { if (!empty($this->_cacheDir)) { $dir = $this->_cacheDir; } else { $dir = getenv('WSDLCACHE'); if (empty($dir)) { $dir = './wsdlcache'; } } @mkdir($dir, 0700); return $dir; } /** * Retrieves a file from cache if it exists, otherwise retreive from net, * add to cache, and return from cache. * * @param string URL to WSDL * @param array proxy parameters * @param int expected MD5 of WSDL URL * @access public * @return string data */ function get($wsdl_fname, $proxy_params = array(), $cache = 0) { $cachename = $md5_wsdl = $file_data = ''; if ($this->_cacheUse) { // Try to retrieve WSDL from cache $cachename = $this->_cacheDir() . '/' . md5($wsdl_fname). ' .wsdl'; if (file_exists($cachename) && $file_data = file_get_contents($cachename)) { $md5_wsdl = md5($file_data); if ($cache) { if ($cache != $md5_wsdl) { return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname); } } else { $fi = stat($cachename); $cache_mtime = $fi[8]; if ($cache_mtime + $this->_cacheMaxAge < time()) { // Expired, refetch. $md5_wsdl = ''; } } } } // Not cached or not using cache. Retrieve WSDL from URL if (!$md5_wsdl) { // Is it a local file? if (strpos($wsdl_fname, 'file://') === 0) { $wsdl_fname = substr($wsdl_fname, 7); if (!file_exists($wsdl_fname)) { return $this->_raiseSoapFault('Unable to read local WSDL file', $wsdl_fname); } $file_data = file_get_contents($wsdl_fname); } elseif (!preg_match('|^https?://|', $wsdl_fname)) { return $this->_raiseSoapFault('Unknown schema of WSDL URL', $wsdl_fname); } else { $uri = explode('?', $wsdl_fname); $rq = new HTTP_Request($uri[0], $proxy_params); // the user agent HTTP_Request uses fouls things up if (isset($uri[1])) { $rq->addRawQueryString($uri[1]); } if (isset($proxy_params['proxy_host']) && isset($proxy_params['proxy_port']) && isset($proxy_params['proxy_user']) && isset($proxy_params['proxy_pass'])) { $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port'], $proxy_params['proxy_user'], $proxy_params['proxy_pass']); } elseif (isset($proxy_params['proxy_host']) && isset($proxy_params['proxy_port'])) { $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port']); } $result = $rq->sendRequest(); if (PEAR::isError($result)) { return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname," . $rq->getResponseCode(), $wsdl_fname); } $file_data = $rq->getResponseBody(); if (!$file_data) { return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, no http body", $wsdl_fname); } } $md5_wsdl = md5($file_data); if ($this->_cacheUse) { $fp = fopen($cachename, "wb"); fwrite($fp, $file_data); fclose($fp); } } if ($this->_cacheUse && $cache && $cache != $md5_wsdl) { return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname); } return $file_data; } } class SOAP_WSDL_Parser extends SOAP_Base { /** * Define internal arrays of bindings, ports, operations, * messages, etc. */ var $currentMessage; var $currentOperation; var $currentPortType; var $currentBinding; var $currentPort; /** * Parser vars. */ var $cache; var $tns = null; var $soapns = array('soap'); var $uri = ''; var $wsdl = null; var $status = ''; var $element_stack = array(); var $parentElement = ''; var $schema = ''; var $schemaStatus = ''; var $schema_stack = array(); var $currentComplexType; var $schema_element_stack = array(); var $currentElement; /** * Constructor. */ function SOAP_WSDL_Parser($uri, &$wsdl, $docs = false) { parent::SOAP_Base('WSDLPARSER'); $this->cache = new SOAP_WSDL_Cache($wsdl->cacheUse, $wsdl->cacheMaxAge, $wsdl->cacheDir); $this->uri = $uri; $this->wsdl = &$wsdl; $this->docs = $docs; $this->parse($uri); } function parse($uri) { // Check whether content has been read. $fd = $this->cache->get($uri, $this->wsdl->proxy); if (PEAR::isError($fd)) { return $this->_raiseSoapFault($fd); } // Create an XML parser. $parser = xml_parser_create(); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); xml_set_object($parser, $this); xml_set_element_handler($parser, 'startElement', 'endElement'); if ($this->docs) { xml_set_character_data_handler($parser, 'characterData'); } if (!xml_parse($parser, $fd, true)) { $detail = sprintf('XML error on line %d: %s', xml_get_current_line_number($parser), xml_error_string(xml_get_error_code($parser))); return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail"); } xml_parser_free($parser); return true; } /** * start-element handler */ function startElement($parser, $name, $attrs) { // Get element prefix. $qname = new QName($name); if ($qname->prefix) { $ns = $qname->prefix; if ($ns && ((!$this->tns && strcasecmp($qname->name, 'definitions') == 0) || $ns == $this->tns)) { $name = $qname->name; } } $this->currentTag = $qname->name; $this->parentElement = ''; $stack_size = count($this->element_stack); if ($stack_size) { $this->parentElement = $this->element_stack[$stack_size - 1]; } $this->element_stack[] = $this->currentTag; // Find status, register data. switch ($this->status) { case 'types': // sect 2.2 wsdl:types // children: xsd:schema $parent_tag = ''; $stack_size = count($this->schema_stack); if ($stack_size) { $parent_tag = $this->schema_stack[$stack_size - 1]; } switch ($qname->name) { case 'schema': // No parent should be in the stack. if (!$parent_tag || $parent_tag == 'types') { if (array_key_exists('targetNamespace', $attrs)) { $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']); } else { $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns); } $this->wsdl->complexTypes[$this->schema] = array(); $this->wsdl->elements[$this->schema] = array(); } break; case 'complexType': if ($parent_tag == 'schema') { $this->currentComplexType = $attrs['name']; if (!isset($attrs['namespace'])) { $attrs['namespace'] = $this->schema; } $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs; if (array_key_exists('base', $attrs)) { $qn = new QName($attrs['base']); $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name; $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->prefix; } else { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; } $this->schemaStatus = 'complexType'; } else { $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = true; } break; case 'element': if (isset($attrs['type'])) { $qn = new QName($attrs['type']); $attrs['type'] = $qn->name; if ($qn->prefix && array_key_exists($qn->prefix, $this->wsdl->namespaces)) { $attrs['namespace'] = $qn->prefix; } } $parentElement = ''; $stack_size = count($this->schema_element_stack); if ($stack_size > 0) { $parentElement = $this->schema_element_stack[$stack_size - 1]; } if (isset($attrs['ref'])) { $qn = new QName($attrs['ref']); $this->currentElement = $qn->name; } else { $this->currentElement = $attrs['name']; } $this->schema_element_stack[] = $this->currentElement; if (!isset($attrs['namespace'])) { $attrs['namespace'] = $this->schema; } if ($parent_tag == 'schema') { $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs; $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = false; $this->schemaStatus = 'element'; } elseif ($this->currentComplexType) { // we're inside a complexType if ((isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order']) && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence') && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = isset($attrs['type']) ? $attrs['type'] : null; } $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs; } else { $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs; } break; case 'complexContent': case 'simpleContent': break; case 'extension': case 'restriction': if ($this->schemaStatus == 'complexType') { if (!empty($attrs['base'])) { $qn = new QName($attrs['base']); $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name; // Types that extend from other types aren't // *of* those types. Reflect this by denoting // which type they extend. I'm leaving the // 'type' setting here since I'm not sure what // removing it might break at the moment. if ($qname->name == 'extension') { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['extends'] = $qn->name; } } else { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; } } break; case 'sequence': if ($this->schemaStatus == 'complexType') { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; } } break; case 'all': $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; } break; case 'choice': $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; } case 'attribute': if ($this->schemaStatus == 'complexType') { if (isset($attrs['name'])) { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs; } else { if (isset($attrs['ref'])) { $q = new QName($attrs['ref']); foreach ($attrs as $k => $v) { if ($k != 'ref' && strstr($k, $q->name)) { $vq = new QName($v); if ($q->name == 'arrayType') { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name. $vq->arrayInfo; $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->prefix; } else { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name; } } } } } } break; } $this->schema_stack[] = $qname->name; break; case 'message': // sect 2.3 wsdl:message child wsdl:part switch ($qname->name) { case 'part': $qn = null; if (isset($attrs['type'])) { $qn = new QName($attrs['type']); } elseif (isset($attrs['element'])) { $qn = new QName($attrs['element']); } if ($qn) { $attrs['type'] = $qn->name; $attrs['namespace'] = $qn->prefix; } $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs; // error in wsdl case 'documentation': break; default: break; } break; case 'portType': // sect 2.4 switch ($qname->name) { case 'operation': // attributes: name // children: wsdl:input wsdl:output wsdl:fault $this->currentOperation = $attrs['name']; $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs; break; case 'input': case 'output': case 'fault': // wsdl:input wsdl:output wsdl:fault // attributes: name message parameterOrder(optional) if ($this->currentOperation) { if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) { $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name], $attrs); } else { $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs; } if (array_key_exists('message', $attrs)) { $qn = new QName($attrs['message']); $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name; $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->prefix; } } break; case 'documentation': break; default: break; } break; case 'binding': $ns = $qname->prefix ? $this->wsdl->namespaces[$qname->prefix] : SCHEMA_WSDL; switch ($ns) { case SCHEMA_SOAP: case SCHEMA_SOAP12: // this deals with wsdl section 3 soap binding switch ($qname->name) { case 'binding': // sect 3.3 // soap:binding, attributes: transport(required), style(optional, default = document) // if style is missing, it is assumed to be 'document' if (!isset($attrs['style'])) { $attrs['style'] = 'document'; } $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs); break; case 'operation': // sect 3.4 // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style) if (!isset($attrs['style'])) { $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style']; } if (isset($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation])) { $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = array_merge($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation], $attrs); } else { $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs; } break; case 'body': // sect 3.5 // soap:body attributes: // part - optional. listed parts must appear in body, missing means all parts appear in body // use - required. encoded|literal // encodingStyle - optional. space seperated list of encodings (uri's) $this->wsdl->bindings[$this->currentBinding] ['operations'][$this->currentOperation][$this->opStatus] = $attrs; break; case 'fault': // sect 3.6 // soap:fault attributes: name use encodingStyle namespace $this->wsdl->bindings[$this->currentBinding] ['operations'][$this->currentOperation][$this->opStatus] = $attrs; break; case 'header': // sect 3.7 // soap:header attributes: message part use encodingStyle namespace $this->wsdl->bindings[$this->currentBinding] ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; break; case 'headerfault': // sect 3.7 // soap:header attributes: message part use encodingStyle namespace $header = count($this->wsdl->bindings[$this->currentBinding] ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1; $this->wsdl->bindings[$this->currentBinding] ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs; break; case 'documentation': break; default: // error! not a valid element inside binding break; } break; case SCHEMA_WSDL: // XXX verify correct namespace // for now, default is the 'wsdl' namespace // other possible namespaces include smtp, http, etc. for alternate bindings switch ($qname->name) { case 'operation': // sect 2.5 // wsdl:operation attributes: name $this->currentOperation = $attrs['name']; break; case 'output': case 'input': case 'fault': // sect 2.5 // wsdl:input attributes: name $this->opStatus = $qname->name; break; case 'documentation': break; default: break; } break; case SCHEMA_WSDL_HTTP: switch ($qname->name) { case 'binding': // sect 4.4 // http:binding attributes: verb // parent: wsdl:binding $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs); break; case 'operation': // sect 4.5 // http:operation attributes: location // parent: wsdl:operation $this->wsdl->bindings[$this->currentBinding]['operations'] [$this->currentOperation] = $attrs; break; case 'urlEncoded': // sect 4.6 // http:urlEncoded attributes: location // parent: wsdl:input wsdl:output etc. $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus] [$this->currentOperation]['uri'] = 'urlEncoded'; break; case 'urlReplacement': // sect 4.7 // http:urlReplacement attributes: location // parent: wsdl:input wsdl:output etc. $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus] [$this->currentOperation]['uri'] = 'urlReplacement'; break; case 'documentation': break; default: // error break; } case SCHEMA_MIME: // sect 5 // all mime parts are children of wsdl:input, wsdl:output, etc. // unsuported as of yet switch ($qname->name) { case 'content': // sect 5.3 mime:content // // part attribute only required if content is child of multipart related, // it contains the name of the part // type attribute contains the mime type case 'multipartRelated': // sect 5.4 mime:multipartRelated case 'part': case 'mimeXml': // sect 5.6 mime:mimeXml // // case 'documentation': break; default: // error break; } case SCHEMA_DIME: // DIME is defined in: // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm // all DIME parts are children of wsdl:input, wsdl:output, etc. // unsuported as of yet switch ($qname->name) { case 'message': // sect 4.1 dime:message // appears in binding section $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs; break; default: break; } default: break; } break; case 'service': $ns = $qname->prefix ? $this->wsdl->namespaces[$qname->prefix] : SCHEMA_WSDL; switch ($qname->name) { case 'port': // sect 2.6 wsdl:port attributes: name binding $this->currentPort = $attrs['name']; $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs; // XXX hack to deal with binding namespaces $qn = new QName($attrs['binding']); $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name; $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->prefix; break; case 'address': $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs; // what TYPE of port is it? SOAP or HTTP? $ns = $qname->prefix ? $this->wsdl->namespaces[$qname->prefix] : SCHEMA_WSDL; switch ($ns) { case SCHEMA_WSDL_HTTP: $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http'; break; case SCHEMA_SOAP: $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap'; break; default: // Shouldn't happen, we'll assume SOAP. $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap'; } break; case 'documentation': break; default: break; } } // Top level elements found under wsdl:definitions. switch ($qname->name) { case 'import': case 'include': // WSDL 2.1.1 wsdl:import, XML Schema 4.2.3 xsd:import, XML Schema // 4.2.1 xsd:include attributes $this->status = 'types'; if (isset($attrs['location']) || isset($attrs['schemaLocation'])) { $uri = isset($attrs['location']) ? $attrs['location'] : $attrs['schemaLocation']; $location = @parse_url($uri); if (!isset($location['scheme'])) { $base = @parse_url($this->uri); $uri = $this->mergeUrl($base, $uri); } if (isset($this->wsdl->imports[$uri])) { break; } $this->wsdl->imports[$uri] = $attrs; $import_parser_class = get_class($this); $import_parser = new $import_parser_class($uri, $this->wsdl, $this->docs); if ($import_parser->fault) { unset($this->wsdl->imports[$uri]); return false; } } $this->status = 'types'; break; case 'types': // sect 2.2 wsdl:types $this->status = 'types'; break; case 'schema': // We can hit this at the top level if we've been asked to // import an XSD file. if (!empty($attrs['targetNamespace'])) { $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']); } else { $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns); } $this->wsdl->complexTypes[$this->schema] = array(); $this->wsdl->elements[$this->schema] = array(); $this->schema_stack[] = $qname->name; $this->status = 'types'; break; case 'message': // sect 2.3 wsdl:message attributes: name children:wsdl:part $this->status = 'message'; if (isset($attrs['name'])) { $this->currentMessage = $attrs['name']; $this->wsdl->messages[$this->currentMessage] = array(); } break; case 'portType': // sect 2.4 wsdl:portType // attributes: name // children: wsdl:operation $this->status = 'portType'; $this->currentPortType = $attrs['name']; $this->wsdl->portTypes[$this->currentPortType] = array(); break; case 'binding': // sect 2.5 wsdl:binding attributes: name type // children: wsdl:operation soap:binding http:binding if ($qname->prefix && $qname->prefix != $this->tns) { break; } $this->status = 'binding'; $this->currentBinding = $attrs['name']; $qn = new QName($attrs['type']); $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name; $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->prefix; break; case 'service': // sect 2.7 wsdl:service attributes: name children: ports $this->currentService = $attrs['name']; $this->wsdl->services[$this->currentService]['ports'] = array(); $this->status = 'service'; break; case 'definitions': // sec 2.1 wsdl:definitions // attributes: name targetNamespace xmlns:* // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service $this->wsdl->definition = $attrs; foreach ($attrs as $key => $value) { if (strstr($key, 'xmlns:') !== false) { $qn = new QName($key); // XXX need to refactor ns handling. $this->wsdl->namespaces[$qn->name] = $value; $this->wsdl->ns[$value] = $qn->name; if ($key == 'targetNamespace' || strcasecmp($value,SOAP_SCHEMA) == 0) { $this->soapns[] = $qn->name; } else { if (in_array($value, $this->_XMLSchema)) { $this->wsdl->xsd = $value; } } } } if (isset($ns) && $ns) { $namespace = 'xmlns:' . $ns; if (!$this->wsdl->definition[$namespace]) { return $this->_raiseSoapFault("parse error, no namespace for $namespace", $this->uri); } $this->tns = $ns; } break; } } /** * end-element handler. */ function endElement($parser, $name) { $stacksize = count($this->element_stack); if ($stacksize) { if ($this->element_stack[$stacksize - 1] == 'definitions') { $this->status = ''; } array_pop($this->element_stack); } if (stristr($name, 'schema')) { array_pop($this->schema_stack); $this->schema = ''; } if ($this->schema) { array_pop($this->schema_stack); if (count($this->schema_stack) <= 1) { /* Correct the type for sequences with multiple * elements. */ if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type']) && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array' && array_key_exists('elements', $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]) && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) { $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; } } if (stristr($name, 'complexType')) { $this->currentComplexType = ''; if (count($this->schema_element_stack)) { $this->currentElement = array_pop($this->schema_element_stack); } else { $this->currentElement = ''; } } elseif (stristr($name, 'element')) { if (count($this->schema_element_stack)) { $this->currentElement = array_pop($this->schema_element_stack); } else { $this->currentElement = ''; } } } } /** * Element content handler. */ function characterData($parser, $data) { // Store the documentation in the WSDL file. if ($this->currentTag == 'documentation') { $data = trim(preg_replace('/\s+/', ' ', $data)); if (!strlen($data)) { return; } switch ($this->status) { case 'service': $ptr =& $this->wsdl->services[$this->currentService]; break; case 'portType': $ptr =& $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation]; break; case 'binding': $ptr =& $this->wsdl->bindings[$this->currentBinding]; break; case 'message': $ptr =& $this->wsdl->messages[$this->currentMessage]; break; case 'operation': break; case 'types': if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) { if ($this->currentElement) { $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement]; } else { $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]; } } break; } if (isset($ptr)) { if (!isset($ptr['documentation'])) { $ptr['documentation'] = ''; } else { $ptr['documentation'] .= ' '; } $ptr['documentation'] .= $data; } } } /** * $parsed is an array returned by parse_url(). * * @access private */ function mergeUrl($parsed, $path) { if (!is_array($parsed)) { return false; } $uri = ''; if (!empty($parsed['scheme'])) { $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'); $uri = $parsed['scheme'] . $sep; } if (isset($parsed['pass'])) { $uri .= "$parsed[user]:$parsed[pass]@"; } elseif (isset($parsed['user'])) { $uri .= "$parsed[user]@"; } if (isset($parsed['host'])) { $uri .= $parsed['host']; } if (isset($parsed['port'])) { $uri .= ":$parsed[port]"; } if ($path[0] != '/' && isset($parsed['path'])) { if ($parsed['path'][strlen($parsed['path']) - 1] != '/') { $path = dirname($parsed['path']) . '/' . $path; } else { $path = $parsed['path'] . $path; } $path = $this->_normalize($path); } $sep = $path[0] == '/' ? '' : '/'; $uri .= $sep . $path; return $uri; } function _normalize($path_str) { $pwd = ''; $strArr = preg_split('/(\/)/', $path_str, -1, PREG_SPLIT_NO_EMPTY); $pwdArr = ''; $j = 0; for ($i = 0; $i < count($strArr); $i++) { if ($strArr[$i] != ' ..') { if ($strArr[$i] != ' .') { $pwdArr[$j] = $strArr[$i]; $j++; } } else { array_pop($pwdArr); $j--; } } $pStr = implode('/', $pwdArr); $pwd = (strlen($pStr) > 0) ? ('/' . $pStr) : '/'; return $pwd; } } /** * Parses the types and methods used in web service objects into the internal * data structures used by SOAP_WSDL. * * Assumes the SOAP_WSDL class is unpopulated to start with. * * @author Chris Coe */ class SOAP_WSDL_ObjectParser extends SOAP_Base { /** * Target namespace for the WSDL document will have the following * prefix. */ var $tnsPrefix = 'tns'; /** * Reference to the SOAP_WSDL object to populate. */ var $wsdl = null; /** * Constructor. * * @param object|array $objects Reference to the object or array of * objects to parse. * @param SOAP_WSDL $wsdl Reference to the SOAP_WSDL object to * populate. * @param string $targetNamespace The target namespace of schema types * etc. * @param string $service_name Name of the WSDL . * @param string $service_desc Optional description of the WSDL * . */ function SOAP_WSDL_ObjectParser($objects, &$wsdl, $targetNamespace, $service_name, $service_desc = '') { parent::SOAP_Base('WSDLOBJECTPARSER'); $this->wsdl = &$wsdl; // Set up the SOAP_WSDL object $this->_initialise($service_name); // Parse each web service object $wsdl_ref = is_array($objects) ? $objects : array($objects); foreach ($wsdl_ref as $ref_item) { if (!is_object($ref_item)) { $this->_raiseSoapFault('Invalid web service object passed to object parser'); continue; } if (!$this->_parse($ref_item, $targetNamespace, $service_name)) { break; } } // Build bindings from abstract data. if ($this->fault == null) { $this->_generateBindingsAndServices($targetNamespace, $service_name, $service_desc); } } /** * Initialise the SOAP_WSDL tree (destructive). * * If the object has already been initialised, the only effect * will be to change the tns namespace to the new service name. * * @param $service_name Name of the WSDL * @access private */ function _initialise($service_name) { // Set up the basic namespaces that all WSDL definitions use. $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL; // WSDL language $this->wsdl->namespaces['soap'] = SCHEMA_SOAP; // WSDL SOAP bindings $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name; // Target namespace $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces); // XML Schema $this->wsdl->namespaces[SOAP_BASE::SOAPENCPrefix()] = array_search(SOAP_BASE::SOAPENCPrefix(), $this->_namespaces); // SOAP types // XXX Refactor $namespace/$ns for Shane :-) unset($this->wsdl->ns['urn:' . $service_name]); $this->wsdl->ns += array_flip($this->wsdl->namespaces); // Imports are not implemented in WSDL generation from classes. // *** *** } /** * Parser - takes a single object to add to tree (non-destructive). * * @access private * * @param object $object Reference to the object to parse. * @param string $schemaNamespace * @param string $service_name Name of the WSDL . */ function _parse($object, $schemaNamespace, $service_name) { // Create namespace prefix for the schema list($schPrefix,) = $this->_getTypeNs('{' . $schemaNamespace . '}'); // Parse all the types defined by the object in whatever // schema language we are using (currently __typedef arrays) // *** *** foreach ($object->__typedef as $typeName => $typeValue) { // Get/create namespace definition list($nsPrefix, $typeName) = $this->_getTypeNs($typeName); // Create type definition $this->wsdl->complexTypes[$schPrefix][$typeName] = array('name' => $typeName); $thisType =& $this->wsdl->complexTypes[$schPrefix][$typeName]; // According to Dmitri's documentation, __typedef comes in two // flavors: // Array = array(array("item" => "value")) // Struct = array("item1" => "value1", "item2" => "value2", ...) if (is_array($typeValue)) { if (is_array(current($typeValue)) && count($typeValue) == 1 && count(current($typeValue)) == 1) { // It's an array $thisType['type'] = 'Array'; $nsType = current(current($typeValue)); list($nsPrefix, $typeName) = $this->_getTypeNs($nsType); $thisType['namespace'] = $nsPrefix; $thisType['arrayType'] = $typeName . '[]'; } elseif (!is_array(current($typeValue))) { // It's a struct $thisType['type'] = 'Struct'; $thisType['order'] = 'all'; $thisType['namespace'] = $nsPrefix; $thisType['elements'] = array(); foreach ($typeValue as $elementName => $elementType) { list($nsPrefix, $typeName) = $this->_getTypeNs($elementType); $thisType['elements'][$elementName]['name'] = $elementName; $thisType['elements'][$elementName]['type'] = $typeName; $thisType['elements'][$elementName]['namespace'] = $nsPrefix; } } else { // It's erroneous return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object)); } } else { // It's erroneous return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object)); } } // Create an empty element array with the target namespace // prefix, to match the results of WSDL parsing. $this->wsdl->elements[$schPrefix] = array(); // Populate tree with message information // *** *** foreach ($object->__dispatch_map as $operationName => $messages) { // We need at least 'in' and 'out' parameters. if (!isset($messages['in']) || !isset($messages['out'])) { return $this->_raiseSoapFault('The dispatch map for the method "' . $operationName . '" is missing an "in" or "out" definition.', 'urn:' . get_class($object)); } foreach ($messages as $messageType => $messageParts) { unset($thisMessage); switch ($messageType) { case 'in': $this->wsdl->messages[$operationName . 'Request'] = array(); $thisMessage =& $this->wsdl->messages[$operationName . 'Request']; break; case 'out': $this->wsdl->messages[$operationName . 'Response'] = array(); $thisMessage =& $this->wsdl->messages[$operationName . 'Response']; break; case 'alias': // Do nothing break; default: // Error condition break; } if (isset($thisMessage)) { foreach ($messageParts as $partName => $partType) { list ($nsPrefix, $typeName) = $this->_getTypeNs($partType); $thisMessage[$partName] = array( 'name' => $partName, 'type' => $typeName, 'namespace' => $nsPrefix ); } } } } // Populate tree with portType information // XXX Current implementation only supports one portType that // encompasses all of the operations available. // *** *** if (!isset($this->wsdl->portTypes[$service_name . 'Port'])) { $this->wsdl->portTypes[$service_name . 'Port'] = array(); } $thisPortType =& $this->wsdl->portTypes[$service_name . 'Port']; foreach ($object->__dispatch_map as $operationName => $messages) { $thisPortType[$operationName] = array('name' => $operationName); foreach ($messages as $messageType => $messageParts) { switch ($messageType) { case 'in': $thisPortType[$operationName]['input'] = array( 'message' => $operationName . 'Request', 'namespace' => $this->tnsPrefix); break; case 'out': $thisPortType[$operationName]['output'] = array( 'message' => $operationName . 'Response', 'namespace' => $this->tnsPrefix); break; } } } return true; } /** * Takes all the abstract WSDL data and builds concrete bindings and * services (destructive). * * @access private * @todo Current implementation discards $service_desc. * * @param string $schemaNamespace Namespace for types etc. * @param string $service_name Name of the WSDL . * @param string $service_desc Optional description of the WSDL * . */ function _generateBindingsAndServices($schemaNamespace, $service_name, $service_desc = '') { // Populate tree with bindings information // XXX Current implementation only supports one binding that // matches the single portType and all of its operations. // XXX Is this the correct use of $schemaNamespace here? // *** *** $this->wsdl->bindings[$service_name . 'Binding'] = array( 'type' => $service_name . 'Port', 'namespace' => $this->tnsPrefix, 'style' => 'rpc', 'transport' => SCHEMA_SOAP_HTTP, 'operations' => array()); $thisBinding =& $this->wsdl->bindings[$service_name . 'Binding']; foreach ($this->wsdl->portTypes[$service_name . 'Port'] as $operationName => $operationData) { $thisBinding['operations'][$operationName] = array( 'soapAction' => $schemaNamespace . '#' . $operationName, 'style' => $thisBinding['style']); foreach (array('input', 'output') as $messageType) if (isset($operationData[$messageType])) { $thisBinding['operations'][$operationName][$messageType] = array( 'use' => 'encoded', 'namespace' => $schemaNamespace, 'encodingStyle' => SOAP_SCHEMA_ENCODING); } } // Populate tree with service information // XXX Current implementation supports one service which groups // all of the ports together, one port per binding // *** *** $this->wsdl->services[$service_name . 'Service'] = array('ports' => array()); $thisService =& $this->wsdl->services[$service_name . 'Service']['ports']; $https = (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) || getenv('SSL_PROTOCOL_VERSION'); foreach ($this->wsdl->bindings as $bindingName => $bindingData) { $thisService[$bindingData['type']] = array( 'name' => $bindingData['type'], 'binding' => $bindingName, 'namespace' => $this->tnsPrefix, 'address' => array('location' => ($https ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')), 'type' => 'soap'); } // Set service $this->wsdl->set_service($service_name . 'Service'); $this->wsdl->uri = $this->wsdl->namespaces[$this->tnsPrefix]; // Create WSDL definition // *** *** $this->wsdl->definition = array( 'name' => $service_name, 'targetNamespace' => $this->wsdl->namespaces[$this->tnsPrefix], 'xmlns' => SCHEMA_WSDL); foreach ($this->wsdl->namespaces as $nsPrefix => $namespace) { $this->wsdl->definition['xmlns:' . $nsPrefix] = $namespace; } } /** * This function is adapted from Dmitri V's implementation of * DISCO/WSDL generation. It separates namespace from type name in * a __typedef key and creates a new namespace entry in the WSDL * structure if the namespace has not been used before. The * namespace prefix and type name are returned. If no namespace is * specified, xsd is assumed. * * We will not need this function anymore once __typedef is * eliminated. */ function _getTypeNs($type) { preg_match_all('/\{(.*)\}/sm', $type, $m); if (!empty($m[1][0])) { if (!isset($this->wsdl->ns[$m[1][0]])) { $ns_pref = 'ns' . count($this->wsdl->namespaces); $this->wsdl->ns[$m[1][0]] = $ns_pref; $this->wsdl->namespaces[$ns_pref] = $m[1][0]; } $typens = $this->wsdl->ns[$m[1][0]]; $type = str_replace($m[0][0], '', $type); } else { $typens = 'xsd'; } return array($typens, $type); } } php-soap-0.13.0/SOAP-0.13.0/example/000077500000000000000000000000001214222670500162355ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/example/attachment.php000066400000000000000000000016111214222670500210750ustar00rootroot00000000000000call('echoMimeAttachment',array($v), array('attachments'=>'Mime', 'namespace'=>'http://soapinterop.org/', 'from'=>'user@domain.com', 'host'=>'smtp.domain.com')); 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); ?>php-soap-0.13.0/SOAP-0.13.0/example/client.php000066400000000000000000000114731214222670500202320ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Client */ require 'SOAP/Client.php'; /* This client runs against the example server in SOAP/example/server.php. It * does not use WSDL to run these requests, but that can be changed easily by * simply adding '?wsdl' to the end of the url. */ $soapclient = new SOAP_Client('http://localhost/SOAP/example/server.php'); /* Set a few options. */ $options = array(); /* This namespace is the same as declared in server.php. */ $options['namespace'] = 'urn:SOAP_Example_Server'; /* Trace the communication for debugging purposes, so we can later inspect the * data with getWire(). */ $options['trace'] = true; /* Uncomment the following lines if you want to use Basic HTTP * Authentication. */ // $options['user'] = 'username'; // $options['pass'] = 'password'; header('Content-Type: text/plain'); /* Calling echoStringSimple. */ $ret = $soapclient->call('echoStringSimple', array('inputStringSimple' => 'this is a test string'), $options); // echo $soapclient->getWire(); print_r($ret); echo "\n"; /* Calling echoString. */ $ret = $soapclient->call('echoString', array('inputString' => 'this is a test string'), $options); // echo $soapclient->getWire(); print_r($ret); echo "\n"; /* Calling divide with valid parameters. */ $ret = $soapclient->call('divide', array('dividend' => 22, 'divisor' => 7), $options); // echo $soapclient->getWire(); if (PEAR::isError($ret)) { echo 'Error: ' . $ret->getMessage(); } else { echo 'Quotient is ' . $ret; } echo "\n"; /* Calling divide with invalid parameters. */ $ret = $soapclient->call('divide', array('dividend' => 22, 'divisor' => 0), $options); // echo $soapclient->getWire(); if (PEAR::isError($ret)) { echo 'Error: ' . $ret->getMessage(); } else { echo 'Quotient is ' . $ret; } echo "\n"; /* The SOAPStruct class is defined in example_types.php. */ require_once 'example_types.php'; $struct = new SOAPStruct('test string', 123, 123.123); /* Send an object, get an object back. Tell the client to translate to classes * we provide if possible. */ $soapclient->_auto_translation = true; /* You can explicitly set the translation for a specific * class. auto_translation works for all cases, but opens ANY class in the * script to be used as a data type, and may not be desireable. Both can be * used on client or server. */ $soapclient->setTypeTranslation('{http://soapinterop.org/xsd}SOAPStruct', 'SOAPStruct'); /* Calling echoStruct. */ $ret = $soapclient->call('echoStruct', array('inputStruct' => $struct->__to_soap()), $options); // echo $soapclient->getWire(); print_r($ret); /* Calling echoStructAsSimpleTypes. * PHP doesn't support multiple return values in function calls, so we must do * a little work to make it happen here, for example returning an array * instead. This requires knowledge on the developers part to figure out how * they want to deal with it. */ $ret = $soapclient->call('echoStructAsSimpleTypes', array('inputStruct' => $struct->__to_soap()), $options); // echo $soapclient->getWire(); if (PEAR::isError($ret)) { echo 'Error: ' . $ret->getMessage(); } else { list($string, $int, $float) = array_values($ret); echo "varString: $string\nvarInt: $int\nvarFloat: $float"; } echo "\n"; /* Calling echoMimeAttachment. * We want to use MIME encoding here, the default is to use DIME encoding. */ $options['attachments'] = 'Mime'; $attachment = new SOAP_Attachment('attachment', 'text/plain', null, 'This is a MIME attachment'); $ret = $soapclient->call('echoMimeAttachment', array($attachment), $options); // echo $soapclient->getWire(); print_r($ret); php-soap-0.13.0/SOAP-0.13.0/example/com_client.php000066400000000000000000000036131214222670500210650ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAPStruct */ require_once './example_types.php'; /* just a simple example of using MS SOAP on win32 as a client to the php server. */ //load COM SOAP client object $soapclient = new COM("MSSOAP.SoapClient30"); //connect to web service $soapclient->mssoapinit("http://localhost/SOAP/example/server.php?wsdl"); //obtain result from web service method $ret = $soapclient->echoString("This is a test!"); print("$ret\n"); $ret = $soapclient->echoStringSimple("This is another test!"); print("$ret\n"); # the following causes an exception in the COM extension #$ret = $soapclient->divide(22,7); #print $soapclient->faultcode; #print $soapclient->faultstring; #print("22/7=$ret\n"); #print_r($ret); #$ret = $soapclient->divide(22,0); #print("22/0=$ret\n"); #$struct = new SOAPStruct('test string',123,123.123); #$ret = $soapclient->echoStruct($struct); #print_r($ret); #$ret = $soapclient->echoStructAsSimpleTypes($struct); #print_r($ret); ?>php-soap-0.13.0/SOAP-0.13.0/example/disco_server.php000066400000000000000000000172311214222670500214410ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ error_reporting(E_ALL); /** SOAP_Server */ require_once 'SOAP/Server.php'; /** * MP3 database class. * * @package SOAP */ class MP3DB_Class { var $__dispatch_map = array(); var $__typedef = array(); function MP3DB_Class() { /* The only way to describe all methods in WSDL (messages, * PortType-operations and bindings) is to use __dispatch_map to * describe every method (even methods using simple data types in 'in' * and 'out' parameters...) */ $this->__dispatch_map['SayHallo'] = array('in' => array('input' => 'string'), 'out' => array('return' => 'string')); $this->__dispatch_map['SayThisNTimes'] = array('in' => array('SayThis'=>'string','NTimes' => 'int'), 'out' => array('return' => '{urn:MP3DB}ArrayOfStrings')); $this->__dispatch_map['GetMP3Tracks'] = array('in' => array('query' => 'string'), 'out' => array('return' => '{urn:MP3DB}GetMP3TracksResult')); $this->__dispatch_map['AddMP3Track'] = array('in' => array('MP3Track' => '{urn:MP3DB}MP3Track'), 'out' => array('return' => '{urn:MP3DB}AddMP3TrackResult')); /* Use __typedef to describe userdefined Types in WSDL. Structs and * one-dimensional arrays are supported. * * Struct example: * $this->__typedef['TypeName'] = array('VarName' => 'xsdType', ... ); * or * $this->__typedef['TypeName'] = array('VarName' => '{namespace}SomeOtherType'); * * Array example: * $this->__typedef['TypeName'] = array(array('item' => 'xsdType')); * or * $this->__typedef['TypeName'] = array(array('item' => '{namespace}SomeOtherType')); */ /* Struct 'MP3Track'. */ $this->__typedef['MP3Track'] = array('Title' => 'string', 'Artist' => 'string', 'Album' => 'string', 'Year' => 'int', 'Genre' => 'int', 'Comment' => 'string', 'Composer' => 'string', 'Orig_Artist' => 'string', 'URL' => 'string', 'Encoded_by' => 'string'); /* MP3TracksArray - array of 'MP3Track' structs. */ $this->__typedef['MP3TracksArray'] = array(array('item' => '{urn:MP3DB}MP3Track')); /* Struct 'MethodDebug'. */ $this->__typedef['MethodDebug'] = array('rc' => 'boolean', 'ErrNo' => 'int', 'Error' => 'string'); /* Return Struct of method GetMP3Tracks. */ $this->__typedef['GetMP3TracksResult'] = array('MethodDebug' => '{urn:MP3DB}MethodDebug', 'MP3Tracks' => '{urn:MP3DB}MP3TracksArray'); /* Return Struct of method AddMP3Track. */ $this->__typedef['AddMP3TrackResult'] = array('MethodDebug' => '{urn:MP3DB}MethodDebug'); /* Array of strings. */ $this->__typedef['ArrayOfStrings'] = array(array('item'=>'string')); } function SayHallo($name) { return 'Hello, ' . $name; } function SayThisNTimes($SayThis, $NTimes) { for ($i = 0; $i < $NTimes; $i++) { $return[$i] = $SayThis . ' ' . $i; } return new SOAP_Value('return', '{urn:MP3DB}ArrayOfStrings', $return); } function GetMP3Tracks($query = '') { for ($i = 0; $i < 5; $i++) { $this->MP3Tracks[$i] = new SOAP_Value( 'item', '{urn:MP3DB}MP3Track', array('Title' => new SOAP_Value('Title', 'string', 'some track $i'), 'Artist' => new SOAP_Value('Artist', 'string', 'some artist $i'), 'Album' => new SOAP_Value('Album', 'string', 'some album $i'), 'Year' => new SOAP_Value('Year', 'int', 1999), 'Genre' => new SOAP_Value('Genre', 'int', 100), 'Comment' => new SOAP_Value('Comment', 'string', 'blabla $i'), 'Composer' => new SOAP_Value('Composer', 'string', ''), 'Orig_Artist' => new SOAP_Value('Orig_Artist', 'string', ''), 'URL' => new SOAP_Value('URL', 'string', ''), 'Encoded_by' => new SOAP_Value('Encoded_by', 'string', ''))); } $MethodDebug['rc'] = new SOAP_Value('rc', 'boolean', true); $MethodDebug['ErrNo'] = new SOAP_Value('ErrNo', 'int', 0); $MethodDebug['Error'] = new SOAP_Value('Error', 'string', ''); return new SOAP_Value( 'return', '{urn:MP3DB}GetMP3TracksResult', array('MethodDebug' => new SOAP_Value('MethodDebug', '{urn:MP3DB}MethodDebug',$MethodDebug), 'MP3Tracks' => new SOAP_Value('MP3Tracks', '{urn:MP3DB}MP3TracksArray',$this->MP3Tracks))); } function AddMP3Track($MP3Track) { /* Well, let's imagine here some code for adding given mp3track to db * or whatever... */ $MethodDebug['rc'] = new SOAP_Value('rc', 'boolean', true); $MethodDebug['ErrNo'] = new SOAP_Value('ErrNo', 'int', 0); $MethodDebug['Error'] = new SOAP_Value('Error', 'string', ''); return new SOAP_Value( 'return', '{urn:MP3DB}AddMP3TrackResult', array('MethodDebug' => new SOAP_Value('MethodDebug', '{urn:MP3DB}MethodDebug', $MethodDebug))); } function __dispatch($methodname) { if (isset($this->__dispatch_map[$methodname])) { return $this->__dispatch_map[$methodname]; } return null; } } $server = new SOAP_Server(); $server->_auto_translation = true; $MP3DB_Class = new MP3DB_Class(); $server->addObjectMap($MP3DB_Class, 'urn:MP3DB'); if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { $server->service($HTTP_RAW_POST_DATA); } else { require_once 'SOAP/Disco.php'; $disco = new SOAP_DISCO_Server($server, 'MP3DB'); header('Content-type: text/xml'); if (isset($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'wsdl') !== false) { echo $disco->getWSDL(); } else { echo $disco->getDISCO(); } } php-soap-0.13.0/SOAP-0.13.0/example/email_client.php000066400000000000000000000025101214222670500213710ustar00rootroot00000000000000 * | /usr/bin/php /path/to/email_server.php * * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 2.02 of the PHP license, * that is bundled with this package in the file LICENSE, and is available at * through the world-wide-web at http://www.php.net/license/2_02.txt. If you * did not receive a copy of the PHP license and are unable to obtain it * through the world-wide-web, please send a note to license@php.net so we can * mail you a copy immediately. * * @category Web Services * @package SOAP * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Server_Email */ require_once 'SOAP/Server/Email.php'; $server = new SOAP_Server_Email; /* Read stdin. */ $fin = fopen('php://stdin', 'rb'); if (!$fin) { exit(1); } $email = ''; while (!feof($fin) && $data = fread($fin, 8096)) { $email .= $data; } fclose($fin); $response = $server->client($email); print_r($response); php-soap-0.13.0/SOAP-0.13.0/example/email_gateway.php000066400000000000000000000027021214222670500215570ustar00rootroot00000000000000 * | /usr/bin/php /path/to/email_server.php * * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 2.02 of the PHP license, * that is bundled with this package in the file LICENSE, and is available at * through the world-wide-web at http://www.php.net/license/2_02.txt. If you * did not receive a copy of the PHP license and are unable to obtain it * through the world-wide-web, please send a note to license@php.net so we can * mail you a copy immediately. * * @category Web Services * @package SOAP * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* SOAP_Server_Email_Gateway */ require_once 'SOAP/Server/Email_Gateway.php'; /* Read stdin. */ $fin = fopen('php://stdin', 'rb'); if (!$fin) { exit(1); } $email = ''; while (!feof($fin) && $data = fread($fin, 8096)) { $email .= $data; } fclose($fin); /* Do it! */ $server = new SOAP_Server_Email_Gateway(); $server->service($data, 'http://localhost/soap/example/server.php'); php-soap-0.13.0/SOAP-0.13.0/example/email_pop_gateway.php000066400000000000000000000041001214222670500224270ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* SOAP_Server_Email_Gateway */ require_once 'SOAP/Server/Email_Gateway.php'; /* Include a class to access POP3. */ require_once 'Net/POP3.php'; /* Create the SOAP Server object. */ $server = new SOAP_Server_Email_Gateway('http://localhost/soap_interop/server_round2.php'); /* Tell the server to translate to classes we provide if possible. */ $server->_auto_translation = true; require_once './example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); /* Connect to a POP3 server and read the messages. */ $pop3 = new Net_POP3(); if ($pop3->connect('localhost', 110)) { if ($pop3->login('username', 'password')) { $listing = $pop3->getListing(); /* Now loop through each message, and call the SOAP server with that * message. */ foreach ($listing as $msg) { $email = $pop3->getMsg($msg['msg_id']); /* This is where we actually handle the SOAP response. The * SOAP::Server::Email class we are using will send the SOAP * response to the sender via email. */ if ($email) { $server->service($email); } // $pop3->deleteMsg($msg['msg_id']); } } $pop3->disconnect(); } php-soap-0.13.0/SOAP-0.13.0/example/email_pop_server.php000066400000000000000000000037601214222670500223070ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* SOAP_Server_Email */ require_once 'SOAP/Server/Email.php'; /* Include a class to access POP3. */ require_once 'Net/POP3.php'; /* Create the SOAP Server object. */ $server = new SOAP_Server_Email; /* Tell the server to translate to classes we provide if possible. */ $server->_auto_translation = true; require_once './example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); /* Connect to a POP3 server and read the messages. */ $pop3 = new Net_POP3(); if ($pop3->connect('localhost', 110)) { if ($pop3->login('username', 'password')) { $listing = $pop3->getListing(); /* Now loop through each message, and call the SOAP server with that * message. */ foreach ($listing as $msg) { $email = $pop3->getMsg($msg['msg_id']); /* This is where we actually handle the SOAP response. The * SOAP_Server_Email class we are using will send the SOAP * response to the sender via email. */ if ($email) { $server->client($email); $pop3->deleteMsg($msg['msg_id']); } } } $pop3->disconnect(); } php-soap-0.13.0/SOAP-0.13.0/example/email_server.php000066400000000000000000000030551214222670500214260ustar00rootroot00000000000000 * | /usr/bin/php /path/to/email_server.php * * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 2.02 of the PHP license, * that is bundled with this package in the file LICENSE, and is available at * through the world-wide-web at http://www.php.net/license/2_02.txt. If you * did not receive a copy of the PHP license and are unable to obtain it * through the world-wide-web, please send a note to license@php.net so we can * mail you a copy immediately. * * @category Web Services * @package SOAP * @author Shane Caraveo Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* SOAP_Server_Email */ require_once 'SOAP/Server/Email.php'; $server = new SOAP_Server_Email; /* Tell the server to translate to classes we provide if possible. */ $server->_auto_translation = true; require_once './example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); /* Read stdin. */ $fin = fopen('php://stdin', 'rb'); if (!$fin) { exit(1); } $email = ''; while (!feof($fin) && $data = fread($fin, 8096)) { $email .= $data; } fclose($fin); /* Do it! */ $server->service($email); php-soap-0.13.0/SOAP-0.13.0/example/example_server.php000066400000000000000000000137041214222670500217740ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /** SOAP_Value */ require_once 'SOAP/Value.php'; require_once 'SOAP/Fault.php'; /** SOAPStruct */ require_once dirname(__FILE__) . '/example_types.php'; /* Create a class for your SOAP functions. */ class SOAP_Example_Server { /* The dispatch map does not need to be used, but aids the server class in * knowing what parameters are used with the functions. This is the ONLY * way to have multiple OUT parameters. If you use a dispatch map, you * MUST add ALL functions you wish to allow be called. If you do not use * a dispatch map, then any public function can be called from SOAP. We * consider this to be any function in the class unless it starts with * underscore. If you do not define in/out parameters, the function can * be called with parameters, but no validation on parameters will * occur. */ var $__dispatch_map = array(); function SOAP_Example_Server() { /* When generating WSDL for a server, you have to define any special * complex types that you use (ie classes). Using a namespace id * before the type will create an XML schema with the targetNamespace * for the type multiple types with the same namespace will appear in * the same schema section. Types with different namespaces will be * in seperate schema sections. The following SOAPStruct typedef * cooresponds to the SOAPStruct class above. */ $this->__typedef['{http://soapinterop.org/xsd}SOAPStruct'] = array('varString' => 'string', 'varInt' => 'int', 'varFloat' => 'float'); /* An aliased function with multiple out parameters. */ $this->__dispatch_map['echoStructAsSimpleTypes'] = array('in' => array('inputStruct' => '{http://soapinterop.org/xsd}SOAPStruct'), 'out' => array('outputString' => 'string', 'outputInteger' => 'int', 'outputFloat' => 'float'), 'alias' => 'myEchoStructAsSimpleTypes'); $this->__dispatch_map['echoStringSimple'] = array('in' => array('inputStringSimple' => 'string'), 'out' => array('outputStringSimple' => 'string')); $this->__dispatch_map['echoString'] = array('in' => array('inputString' => 'string'), 'out' => array('outputString' => 'string')); $this->__dispatch_map['divide'] = array('in' => array('dividend' => 'int', 'divisor' => 'int'), 'out' => array('outputFloat' => 'float')); $this->__dispatch_map['echoStruct'] = array('in' => array('inputStruct' => '{http://soapinterop.org/xsd}SOAPStruct'), 'out' => array('outputStruct' => '{http://soapinterop.org/xsd}SOAPStruct')); $this->__dispatch_map['echoMimeAttachment'] = array('in' => array('stuff' => 'string'), 'out' => array('outputMime' => 'string')); } /* This private function is called on by SOAP_Server to determine any * special dispatch information that might be necessary. This, for * example, can be used to set up a dispatch map for functions that return * multiple OUT parameters. */ function __dispatch($methodname) { if (isset($this->__dispatch_map[$methodname])) { return $this->__dispatch_map[$methodname]; } return null; } /* A simple echoString function. */ function echoStringSimple($inputString) { return $inputString; } /* An explicit echoString function. */ function echoString($inputString) { return new SOAP_Value('outputString', 'string', $inputString); } function divide($dividend, $divisor) { /* The SOAP server would normally catch errors like this and return a * fault, but this is how you do it yourself. */ if ($divisor == 0) { return new SOAP_Fault('You cannot divide by zero', 'Client'); } else { return $dividend / $divisor; } } function echoStruct($inputStruct) { return $inputStruct->__to_soap('outputStruct'); } /** * Takes a SOAPStruct as input, and returns each of its elements as OUT * parameters. * * This function is also aliased so you have to call it as * echoStructAsSimpleTypes. * * SOAPStruct is defined as: * * struct SOAPStruct: * string varString * integer varInt * float varFloat * */ function myEchoStructAsSimpleTypes($struct) { /* Convert a SOAPStruct to an array. */ return array( new SOAP_Value('outputString', 'string', $struct->varString), new SOAP_Value('outputInteger', 'int', $struct->varInt), new SOAP_Value('outputFloat', 'float', $struct->varFloat) ); } function echoMimeAttachment($stuff) { return new SOAP_Attachment('return', 'application/octet-stream', null, $stuff); } } php-soap-0.13.0/SOAP-0.13.0/example/example_types.php000066400000000000000000000034521214222670500216310ustar00rootroot00000000000000varString = $s; $this->varInt = $i; $this->varFloat = $f; } function &__to_soap($name = 'inputStruct', $header = false, $mustUnderstand = 0, $actor = 'http://schemas.xmlsoap.org/soap/actor/next') { $inner = array( new SOAP_Value('varString', 'string', $this->varString), new SOAP_Value('varInt', 'int', $this->varInt), new SOAP_Value('varFloat', 'float', $this->varFloat)); if ($header) { $value = new SOAP_Header($name, '{http://soapinterop.org/xsd}SOAPStruct', $inner, $mustUnderstand, $actor); } else { $value = new SOAP_Value($name, '{http://soapinterop.org/xsd}SOAPStruct', $inner); } return $value; } } php-soap-0.13.0/SOAP-0.13.0/example/server.php000066400000000000000000000040531214222670500202560ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* If you want to implement Basic HTTP Authentication, uncomment the following * lines of code. */ // if (!isset($_SERVER['PHP_AUTH_USER']) || // !isset($_SERVER['PHP_AUTH_PW']) || // $_SERVER['PHP_AUTH_USER'] !== 'username' || // $_SERVER['PHP_AUTH_PW'] !== 'password') { // header('WWW-Authenticate: Basic realm="My Realm"'); // header('HTTP/1.0 401 Unauthorized'); // echo 'Not authorized!'; // exit; // } /* First, include the SOAP_Server class. */ require_once 'SOAP/Server.php'; $server = new SOAP_Server; /* Tell server to translate to classes we provide if possible. */ $server->_auto_translation = true; require_once dirname(__FILE__) . '/example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass, 'urn:SOAP_Example_Server'); if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { $server->service($HTTP_RAW_POST_DATA); } else { require_once 'SOAP/Disco.php'; $disco = new SOAP_DISCO_Server($server, 'ServerExample'); header('Content-type: text/xml'); if (isset($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'wsdl') !== false) { echo $disco->getWSDL(); } else { echo $disco->getDISCO(); } } php-soap-0.13.0/SOAP-0.13.0/example/server2.php000066400000000000000000000042701214222670500203410ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* First, include the SOAP_Server class. */ require_once 'SOAP/Server.php'; $server = new SOAP_Server; /* Tell server to translate to classes we provide if possible. */ $server->_auto_translation = true; /* This is a simple example of implementing a custom call handler. If you do * this, the SOAP server will ignore objects or functions added to it, and * will call your handler for **ALL** SOAP calls the server receives, whether * the call is defined in your WSDL or not. The handler receives two * arguments, the method name being called, and the arguments sent for that * call. */ function myCallHandler($methodname, $args) { global $soapclass; return call_user_func_array(array($soapclass, $methodname), $args); } $server->setCallHandler('myCallHandler', false); require_once dirname(__FILE__) . '/example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass, 'urn:SOAP_Example_Server'); if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { $server->service($HTTP_RAW_POST_DATA); } else { require_once 'SOAP/Disco.php'; $disco = new SOAP_DISCO_Server($server, 'ServerExample'); header('Content-type: text/xml'); if (isset($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'wsdl') !== false) { echo $disco->getWSDL(); } else { echo $disco->getDISCO(); } } php-soap-0.13.0/SOAP-0.13.0/example/smtp.php000066400000000000000000000027231214222670500177350ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* Include SOAP_Client class. */ require_once 'SOAP/Client.php'; $soapclient = new SOAP_Client('mailto:user@domain.com'); $options = array('namespace' => 'http://soapinterop.org/', 'from' => 'user@domain.com', 'host' => 'localhost'); $return = $soapclient->call('echoString', array('inputString' => 'this is a test'), $options); $return = $soapclient->call('echoStringArray', array('inputStringArray' => array('good', 'bad', 'ugly')), $options); /* Don't expect much of a result! */ print_r($return); echo $soapclient->wire; php-soap-0.13.0/SOAP-0.13.0/example/stockquote.php000066400000000000000000000035271214222670500211560ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* Include SOAP_Client class. */ require_once 'SOAP/Client.php'; echo '
wsdl:'; $wsdl = new SOAP_WSDL('http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl'); $soapclient = $wsdl->getProxy(); $ret = $soapclient->call('getQuote', array('symbol' => 'ibm')); print_r($ret); if (extension_loaded('overload')) { echo '
overloaded:'; $ret = $soapclient->getQuote('ibm'); print_r($ret); } echo '
non wsdl:'; $soapclient = new SOAP_Client('http://services.xmethods.net:80/soap'); $namespace = 'urn:xmethods-delayed-quotes'; /* Some SOAP servers require a Soapaction HTTP header. PEAR::SOAP does not * use them in any way, other to send them if you supply them. soapaction is * deprecated in later SOAP versions. */ $soapaction = 'urn:xmethods-delayed-quotes#getQuote'; $ret = $soapclient->call('getQuote', array('symbol' => 'ibm'), $namespace, $soapaction); print_r($ret); ?> php-soap-0.13.0/SOAP-0.13.0/example/tcp_client.php000066400000000000000000000025341214222670500210760ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Client.php'; /* Client. */ $soapclient = new SOAP_Client('tcp://127.0.0.1:82'); /* Namespace. */ $options = array('namespace' => 'urn:SOAP_Example_Server', 'trace' => true); /* One. */ $params = array('string' => 'this is string 1'); $ret1 = $soapclient->call('echoString', $params, $options); echo "WIRE: \n" . $soapclient->getWire(); print_r($ret1); /* Two. */ $params = array('string' => 'this is string 2'); $ret2 = $soapclient->call('echoString', $params, $options); echo "WIRE: \n" . $soapclient->getWire(); print_r($ret2); php-soap-0.13.0/SOAP-0.13.0/example/tcp_daemon.pl000066400000000000000000000031571214222670500207110ustar00rootroot00000000000000#!/usr/bin/perl -w use strict; =head1 Simple SOAP TCP Server Simple SOAP TCP Server with test class (just to check things are working) Before you run this test server you will need some perl classes, namely: SOAP::Lite Hook::LexWrap (if you want to see some debugging) Flee off to the CPAN if you need them :) To run type 'perl ' and if you dont get any errors, it's time to go write some code to connect. =cut use SOAP::Transport::TCP qw(trace); use Data::Dumper; ############# ## if you want to see incoming/outgoing raw xml ## uncomment the following. #use Hook::LexWrap; #wrap *IO::SessionData::read, post => \&show_read; #wrap *IO::SessionData::write, post => \&show_write; ## ############# my $daemon = SOAP::Transport::TCP::Server->new( LocalAddr => '127.0.0.1', LocalPort => '82', Listen => 5, Reuse => 1 ); # dispatch $daemon->dispatch_to('SOAP_Example_Server'); $daemon->handle; ############# ## callback functions for Hook::LexWrap; ## # show incoming xml sub show_read { print $/,'## read ##',$/; print Dumper($_[0]); } # show outgoing xml sub show_write { print $/,'## write ##',$/; print Dumper($_[0]); } ################################################################################ ################################################################################ # SOAP_Example_Server # Simple test class, method test returns double what you send to it, thats all! ################################################################################ package SOAP_Example_Server; sub echoString { return $_[1] x 2; } 1; php-soap-0.13.0/SOAP-0.13.0/example/tcp_server.php000066400000000000000000000023431214222670500211240ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ /* First, include the SOAP_Server_TCP class. */ set_time_limit(0); require_once 'SOAP/Server/TCP.php'; $server = new SOAP_Server_TCP('127.0.0.1', 82); /* Tell the server to translate to classes we provide if possible. */ $server->_auto_translation = true; require_once dirname(__FILE__) . '/example_server.php'; $soapclass = new SOAP_Example_Server(); $server->addObjectMap($soapclass, 'urn:SOAP_Example_Server'); $server->run(); php-soap-0.13.0/SOAP-0.13.0/example/wsdl_client.php000066400000000000000000000055521214222670500212640ustar00rootroot00000000000000 Port to PEAR and more * @author Jan Schneider Maintenance * @copyright 2003-2007 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */ require_once 'SOAP/Client.php'; /* This client runs against the example server in SOAP/example/server.php. It * does not use WSDL to run these requests, but that can be changed easily by * simply adding '?wsdl' to the end of the url. */ $wsdl = new SOAP_WSDL('http://localhost/SOAP/example/server.php?wsdl'); $soapclient = $wsdl->getProxy(); $ret = $soapclient->echoStringSimple('this is a test string'); // echo $soapclient->getWire(); print_r($ret); $ret = $soapclient->echoString('this is a test string'); print_r($ret); $ret = $soapclient->divide(22, 7); // echo $soapclient->getWire(); if (is_a($ret, 'PEAR_Error')) { echo 'Error: ' . $ret->getMessage() . "\n"; } else { echo 'Quotient is ' . $ret . "\n"; } $ret = $soapclient->divide(22, 0); if (is_a($ret, 'PEAR_Error')) { echo 'Error: ' . $ret->getMessage() . "\n"; } else { echo 'Quotient is ' . $ret . "\n"; } /* SOAPStruct is defined in the following file. */ require_once './example_types.php'; $struct = new SOAPStruct('test string', 123, 123.123); /* Tell the client to translate to classes we provide if possible. * You can explicitly set the translation for a specific class. * auto_translation works for all cases, but opens ANY class in the script to * be used as a data type, and may not be desireable. Both can be used on * client or server. */ $soapclient->_auto_translation = true; $soapclient->setTypeTranslation('{http://soapinterop.org/xsd}SOAPStruct', 'SOAPStruct'); $ret = $soapclient->echoStruct($struct->__to_soap()); // echo $soapclient->getWire(); print_r($ret); /* PHP doesn't support multiple OUT parameters in function calls, so we must * do a little work to make it happen here. This requires knowledge on the * developers part to figure out how they want to deal with it. */ $ret = $soapclient->echoStructAsSimpleTypes($struct->__to_soap()); if (is_a($ret, 'PEAR_Error')) { echo 'Error: ' . $ret->getMessage() . "\n"; } else { list($string, $int, $float) = array_values($ret); } echo "varString: $string\nvarInt: $int\nvarFloat: $float\n"; php-soap-0.13.0/SOAP-0.13.0/tests/000077500000000000000000000000001214222670500157445ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/tests/AllTests.php000066400000000000000000000013611214222670500202110ustar00rootroot00000000000000addTestSuite('SOAP_BugsTest'); return $suite; } } if (PHPUnit_MAIN_METHOD == 'SOAP_AllTests::main') { SOAP_AllTests::main(); } ?>php-soap-0.13.0/SOAP-0.13.0/tests/SOAP_BugsTest.php000066400000000000000000000214621214222670500210440ustar00rootroot00000000000000serialize($base); /**/ //test filled array $msg =<< test 12 EOT; $parser = new SOAP_Parser($msg); $soapval = $parser->getResponse(); $this->assertEquals('arraytest', $soapval->name); $this->assertEquals('Array', $soapval->type); $this->assertEquals(2, count($soapval->value)); $this->assertEquals('item', $soapval->value[0]->name); $this->assertEquals('string', $soapval->value[0]->type); $this->assertEquals('test', $soapval->value[0]->value); $this->assertEquals('item', $soapval->value[1]->name); $this->assertEquals('int', $soapval->value[1]->type); $this->assertEquals(12, $soapval->value[1]->value); //test empty array $msg =<< EOT; $parser = new SOAP_Parser($msg); $soapval = $parser->getResponse(); $this->assertEquals('arraytest', $soapval->name); $this->assertEquals(array(), $soapval->value); }//public function testBug10131() /** * Bug 1312: When sending a nested array to a PEAR::SOAP WebService, * some elements are objects, not arrays. * * @see http://pear.php.net/bugs/bug.php?id=1312 */ public function testBug1312() { $msg = <<15068915765481325457 EOX; $parser = new SOAP_Parser($msg); $soapval = $parser->getResponse(); $this->assertInternalType('array', $soapval->value); $this->assertInternalType('array', $soapval->value[0]->value); $this->assertEquals('anArray', $soapval->value[0]->name); //anArray -> item #3 is an object according to bug report $this->assertInternalType('array', $soapval->value[0]->value[2]->value); } /** * Bug #2627 Array in return object was not parsed correctly * * @see http://pear.php.net/bugs/bug.php?id=2627 */ public function testBug2627() { $val = new SOAP_Value('StructTest', 'Struct', array( new SOAP_Value('zero', 'string', 'val01'), new SOAP_Value('one', 'string', 'val11'), new SOAP_Value('one', 'string', 'val12'), new SOAP_Value('two', 'string', 'val21'), new SOAP_Value('two', 'string', 'val22'), )); $client = new SOAP_Base(); $dec = $client->_decode($val); $this->assertInternalType('object', $dec); $this->assertInternalType('string', $dec->zero); $this->assertInternalType('array' , $dec->one); $this->assertInternalType('array' , $dec->two); $this->assertEquals(2, count($dec->one)); $this->assertEquals(2, count($dec->two)); $this->assertEquals('val01', $dec->zero); $this->assertEquals('val11', $dec->one[0]); $this->assertEquals('val12', $dec->one[1]); $this->assertEquals('val21', $dec->two[0]); $this->assertEquals('val22', $dec->two[1]); }//public function testBug2627() /** * Bug #10206: Timezone in Type/dateTime.php not converted correctly * * @see http://pear.php.net/bugs/bug.php?id=10206 */ public function testBug10206() { $old = '2002-10-10T12:00:00+02:00'; $dt = new SOAP_Type_dateTime($old); $new = $dt->toString(); //can only check for local timezone if (date('O') == '+0200') { $this->assertEquals($old, $new); } $dt = new SOAP_Type_dateTime(time()); $new = $dt->toString(); $dt2 = new SOAP_Type_dateTime($new); $new2=$dt2->toString(); $this->assertEquals($new, $new2); $this->assertEquals(13, strpos($new , ':')); $this->assertEquals(13, strpos($new2, ':')); }//public function testBug10206() public static function echoSoapVal($val, $indent = '') { echo $indent . $val->name . '(' . $val->type . '): '; if (is_array($val->value)) { echo gettype($val->value) . '(' . count($val->value) . '):' ; } else { echo gettype($val->value) . ':' ; } if (!is_array($val->value)) { echo $val->value . "\n"; } else { echo "\n"; foreach ($val->value as $sub) { self::echoSoapVal($sub, $indent . ' '); } } }//public static function echoSoapVal($val, $indent = '') } // Call SOAP_BugsTest::main() if this source file is executed directly. if (PHPUnit_MAIN_METHOD == "SOAP_BugsTest::main") { SOAP_BugsTest::main(); } ?> php-soap-0.13.0/SOAP-0.13.0/tests/bug11013.phpt000066400000000000000000000010051214222670500200000ustar00rootroot00000000000000--TEST-- Bug #11013: Endless loop with empty service provider --FILE-- addObjectMap($service,'urn:soapservice'); ob_start(); $soap->service($GLOBALS['HTTP_RAW_POST_DATA']); ob_end_clean(); class Service { } echo 'OK'; ?> --EXPECT-- OK php-soap-0.13.0/SOAP-0.13.0/tests/bug12615.phpt000066400000000000000000000043731214222670500200240ustar00rootroot00000000000000--TEST-- Bug #12099: Client of .Net SOAP server is missing first two rows of data? Bug #12615: Decoded arrays missing some values Bug #12774: I am Missing Response Information. --FILE-- string == 'a1'), '1'); for ($i = 2; $i < 6; $i++) { $stringarray[] = 'a' . $i; $xml = getXml($stringarray); //echo $xml . "\n\n"; $decoded = parseXml($xml); //print_r($decoded); printassert (($decoded == $stringarray), $i); } // Helper functions /** * If flag is true, echo OK - otherwise echo Error * * @param bool $flag * @param string $message * @return void */ function printassert($flag, $message) { if ($flag) { echo "OK $message.\n"; } else { echo "Error $message.\n"; } } /** * Parse the XML string using SOAP_Parser. * * @param string $xml The xml string to be parsed * @return mixed Parsed result for the xml string. */ function parseXml($xml) { $response = new SOAP_Parser($xml, 'UTF-8', $v = null); // This still looks normal. $return = $response->getResponse(); // print_r($return); // This loses the first two items for $i > 3 and // has an unexpected key 'string' for $i == 3. $decoded = $response->_decode($return); //print_r($decoded); return $decoded->return; } /** * Generate a simple SOAP response XML packing the $stringarray * * @param array $stringarray * @return string SOAP xml response */ function getXml($stringarray) { $xml = ' '; foreach($stringarray as $string) { $xml .= "\n $string"; } $xml .= ''; return $xml; } ?> --EXPECT-- OK 0. OK 1. OK 2. OK 3. OK 4. OK 5. php-soap-0.13.0/SOAP-0.13.0/tests/bug12880.phpt000066400000000000000000000016721214222670500200270ustar00rootroot00000000000000--TEST-- Bug #12800: No return value if using overloading --SKIPIF-- --FILE-- _auto_translation = true; $server->addObjectMap(new SOAP_Example_Server(), 'urn:SOAP_Example_Server'); /* Create example client. */ $client = new SOAP_Client('test://foo/'); $client->setOpt('server', $server); $client->setOpt('namespace', 'urn:SOAP_Example_Server'); ob_start(); var_export($client->call('echoString', array('hello world'))); echo "\n"; var_export($client->echoString('hello world')); ob_end_flush(); ?> --EXPECT-- 'hello world' 'hello world' php-soap-0.13.0/SOAP-0.13.0/tests/bug14756.phpt000066400000000000000000000056421214222670500200340ustar00rootroot00000000000000--TEST-- Bug #14756/#14854: Parse multipart/related messages --FILE-- --xxx-WASP-CPP-MIME-Boundary-xxx-yyyyyyyyy-zzzzzzzz-xxx-END-xxx Content-ID: <0xad86d30-0xae618b8-0xae037c0-0xaffa268-0xae62400> Content-Type: application/binary --xxx-WASP-CPP-MIME-Boundary-xxx-yyyyyyyyy-zzzzzzzz-xxx-END-xxx-- FILE; $sth = new SOAP_Transport_HTTP('http://example.com/'); $sth->incoming_payload = $response; $result = $sth->_parseResponse(); if ($result) { echo "OK\n\n"; } var_dump($sth->headers); echo "\n" . $sth->response . "\n"; var_dump($sth->attachments); ?> --EXPECT-- OK array(6) { ["date"]=> string(29) "Thu, 09 Oct 2008 15:16:48 GMT" ["server"]=> string(6) "Server" ["embeddedsoapserver"]=> string(96) "WASP-C++ Vespa/4.6, build 2162 (Linux i686 2.6.18-8.el5a2xen #1 SMP Tue Apr 3 16:48:05 PDT 2007)" ["mime-version"]=> string(3) "1.0" ["connection"]=> string(5) "close" ["content-type"]=> string(25) "text/xml; charset="UTF-8"" } array(1) { ["cid:0xad86d30-0xae618b8-0xae037c0-0xaffa268-0xae62400"]=> string(176) " " } php-soap-0.13.0/SOAP-0.13.0/tests/bug16968.phpt000066400000000000000000000004161214222670500200350ustar00rootroot00000000000000--TEST-- Bad array assignment when using WSDL client (Bug #16968). --FILE-- getOperationData('WeatherAttachment', 'getDayForecastImage'); ?> --EXPECT-- php-soap-0.13.0/SOAP-0.13.0/tests/bug16968.wsdl000066400000000000000000000110751214222670500200360ustar00rootroot00000000000000 php-soap-0.13.0/SOAP-0.13.0/tests/bug1927.phpt000066400000000000000000000035331214222670500177450ustar00rootroot00000000000000--TEST-- Bug #1927: Missing namespace in SOAP_Fault response --SKIPIF-- =')) echo 'skip PHP 4 only'; ?> --FILE-- message(); ?> --EXPECTF-- SOAP-ENV:Client unknown error %s/SOAP/Fault.php 64 pear_error pear_error :: unknown error Client %s/test/bug1927.php %d soap_fault soap_fault -> php-soap-0.13.0/SOAP-0.13.0/tests/bug4523.phpt000066400000000000000000000005421214222670500177350ustar00rootroot00000000000000--TEST-- Bug #4523: Parse dates without timezone --FILE-- toUnixtime($orig); $d = $dt->toString($ts); $zone = date('O', $ts); $zone = substr($zone, 0, 3) . ':' . substr($zone, 3); var_dump($d == $orig . $zone); ?> --EXPECT-- bool(true) php-soap-0.13.0/SOAP-0.13.0/tests/dateTime.phpt000066400000000000000000000005701214222670500203770ustar00rootroot00000000000000--TEST-- SOAP_Type_dateTime test --FILE-- toUTC($orig); $ts1 = $dt->toUnixtime($orig); $ts2 = $dt->toUnixtime($utc); $b1 = $dt->toUTC(988216301); echo "$utc\n$ts1\n$ts2\n$b1"; ?> --EXPECT-- 2001-04-25T16:31:41Z 988216301 988216301 2001-04-25T16:31:41Z php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/000077500000000000000000000000001214222670500202445ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/array.phpt000066400000000000000000000051361214222670500222640ustar00rootroot00000000000000--TEST-- Deserialize nested arrays --FILE-- 1 5 0 6 8 9 1 5 7 654 8 1 32 54 57 '; $val = parseMessage($msg); var_dump($val); ?> --EXPECT-- array(4) { [0]=> string(0) "" [1]=> array(4) { [0]=> float(1) [1]=> float(5) [2]=> float(0) [3]=> float(6) } [2]=> array(3) { [0]=> array(3) { [0]=> float(8) [1]=> float(9) [2]=> float(1) } [1]=> float(0) [2]=> array(6) { [0]=> float(5) [1]=> float(7) [2]=> float(654) [3]=> float(8) [4]=> float(1) [5]=> float(32) } } [3]=> array(2) { [0]=> float(54) [1]=> float(57) } } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/multiref_1.phpt000066400000000000000000000015031214222670500232070ustar00rootroot00000000000000--TEST-- Deserialize multi-reference value with backward reference --FILE-- Hello '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s2) { ["greeting"]=> string(5) "Hello" ["salutation"]=> string(5) "Hello" } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/multiref_2.phpt000066400000000000000000000015021214222670500232070ustar00rootroot00000000000000--TEST-- Deserialize multi-reference value with forward reference --FILE-- Hello '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s2) { ["salutation"]=> string(5) "Hello" ["greeting"]=> string(5) "Hello" } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/multiref_3.phpt000066400000000000000000000022001214222670500232040ustar00rootroot00000000000000--TEST-- Deserialize multi-reference value with outside reference --FILE-- arg 34 325.325 '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s1) { ["Result"]=> %sobject(stdClass)%s3) { ["varString"]=> string(4) " arg" ["varInt"]=> int(34) ["varFloat"]=> float(325.325) } } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/multiref_4.phpt000066400000000000000000000030601214222670500232120ustar00rootroot00000000000000--TEST-- Deserialize multi-reference value with nested references --FILE-- arg 34 325.325012207031 arg 34 325.325012207031 '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s1) { ["return"]=> %sobject(stdClass)%s4) { ["varString"]=> string(4) " arg" ["varInt"]=> int(34) ["varFloat"]=> float(325.32501220703) ["varStruct"]=> %sobject(stdClass)%s3) { ["varString"]=> string(4) " arg" ["varInt"]=> int(34) ["varFloat"]=> float(325.32501220703) } } } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/null.phpt000066400000000000000000000011071214222670500221120ustar00rootroot00000000000000--TEST-- Deserialize null --FILE-- '; var_export(parseMessage($msg)); ?> --EXPECT-- NULLphp-soap-0.13.0/SOAP-0.13.0/tests/deserialize/string.phpt000066400000000000000000000014001214222670500224420ustar00rootroot00000000000000--TEST-- Deserialize string --FILE-- hello world '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s1) { ["return"]=> string(11) "hello world" }php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/struct_1.phpt000066400000000000000000000017241214222670500227110ustar00rootroot00000000000000--TEST-- Deserialize typed struct (with negeativeInteger) --FILE-- 45 5.9 -450 Blue '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s4) { ["age"]=> %sint(45) ["height"]=> %sfloat(5.9) ["displacement"]=> %sint(-450) ["color"]=> %sstring(4) "Blue" } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/struct_2.phpt000066400000000000000000000016731214222670500227150ustar00rootroot00000000000000--TEST-- Deserialize typed struct (with int) --FILE-- 45 5.9 -450 Blue '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s4) { ["age"]=> %sint(45) ["height"]=> %sfloat(5.9) ["displacement"]=> %sint(-450) ["color"]=> %sstring(4) "Blue" } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/struct_3.phpt000066400000000000000000000015601214222670500227110ustar00rootroot00000000000000--TEST-- Deserialize untyped struct --FILE-- 45 5.9 -450 Blue '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s4) { ["age"]=> string(2) "45" ["height"]=> string(3) "5.9" ["displacement"]=> string(4) "-450" ["color"]=> string(4) "Blue" } php-soap-0.13.0/SOAP-0.13.0/tests/deserialize/struct_4.phpt000066400000000000000000000022221214222670500227060ustar00rootroot00000000000000--TEST-- Deserialize custom struct --FILE-- test string 123 123.123 '; $val = parseMessage($msg); var_dump($val); ?> --EXPECTF-- object(stdClass)%s1) { ["inputStruct"]=> %sobject(stdClass)%s3) { ["varString"]=> string(11) "test string" ["varInt"]=> int(123) ["varFloat"]=> float(123.123) } } php-soap-0.13.0/SOAP-0.13.0/tests/example.wsdl000066400000000000000000000132321214222670500202730ustar00rootroot00000000000000 php-soap-0.13.0/SOAP-0.13.0/tests/example_server.phpt000066400000000000000000000040601214222670500216620ustar00rootroot00000000000000--TEST-- Example server test (PHP 4) --SKIPIF-- =')) echo 'skip PHP 4 only'; ?> --FILE-- _auto_translation = true; $server->addObjectMap(new SOAP_Example_Server(), 'urn:SOAP_Example_Server'); /* Create example client. */ $client = new SOAP_Client('test://foo/'); $client->setOpt('server', $server); $client->_auto_translation = true; $client->setTypeTranslation('{http://soapinterop.org/xsd}SOAPStruct', 'SOAPStruct'); $options = array('namespace' => 'urn:SOAP_Example_Server', 'trace' => true); /* Create test list. */ $struct = new SOAPStruct('test string', 123, 123.123); $calls = array( array('echoStringSimple', array('inputStringSimple' => 'this is a test string')), array('echoString', array('inputString' => 'this is a test string')), array('divide', array('dividend' => 22, 'divisor' => 7)), array('divide', array('dividend' => 22, 'divisor' => 0)), array('echoStruct', array('inputStruct' => $struct->__to_soap())), array('echoStructAsSimpleTypes', array('inputStruct' => $struct->__to_soap())), ); /* Run tests. */ ob_start(); foreach ($calls as $call) { $result = $client->call($call[0], $call[1], $options); if (is_a($result, 'PEAR_Error')) { echo $result->getMessage(); } else { var_export($result); } echo "\n"; } ob_end_flush(); ?> --EXPECT-- 'this is a test string' 'this is a test string' 3.1428571428571 You cannot divide by zero class soapstruct { var $varString = 'test string'; var $varInt = 123; var $varFloat = 123.123; } array ( 'outputString' => 'test string', 'outputInteger' => 123, 'outputFloat' => 123.123, ) php-soap-0.13.0/SOAP-0.13.0/tests/example_server_php5.phpt000066400000000000000000000040711214222670500226200ustar00rootroot00000000000000--TEST-- Example server test (PHP 5) --SKIPIF-- --FILE-- _auto_translation = true; $server->addObjectMap(new SOAP_Example_Server(), 'urn:SOAP_Example_Server'); /* Create example client. */ $client = new SOAP_Client('test://foo/'); $client->setOpt('server', $server); $client->_auto_translation = true; $client->setTypeTranslation('{http://soapinterop.org/xsd}SOAPStruct', 'SOAPStruct'); $options = array('namespace' => 'urn:SOAP_Example_Server', 'trace' => true); /* Create test list. */ $struct = new SOAPStruct('test string', 123, 123.123); $calls = array( array('echoStringSimple', array('inputStringSimple' => 'this is a test string')), array('echoString', array('inputString' => 'this is a test string')), array('divide', array('dividend' => 22, 'divisor' => 7)), array('divide', array('dividend' => 22, 'divisor' => 0)), array('echoStruct', array('inputStruct' => $struct->__to_soap())), array('echoStructAsSimpleTypes', array('inputStruct' => $struct->__to_soap())), ); /* Run tests. */ ob_start(); foreach ($calls as $call) { $result = $client->call($call[0], $call[1], $options); if (is_a($result, 'PEAR_Error')) { echo $result->getMessage(); } else { var_export($result); } echo "\n"; } ob_end_flush(); ?> --EXPECT-- 'this is a test string' 'this is a test string' 3.1428571428571 You cannot divide by zero SOAPStruct::__set_state(array( 'varString' => 'test string', 'varInt' => 123, 'varFloat' => 123.123, )) array ( 'outputString' => 'test string', 'outputInteger' => 123, 'outputFloat' => 123.123, ) php-soap-0.13.0/SOAP-0.13.0/tests/parser.phpt000066400000000000000000000326171214222670500201460ustar00rootroot00000000000000--TEST-- SOAP_Parser tests. --FILE-- good bad EOF; $stringArray = << good bad EOS; $stringArrayOne = << good EOO; $parser = new SOAP_Parser($foo); var_dump($parser->getResponse()); $parser = new SOAP_Parser($stringArray); var_dump($parser->getResponse()); $parser = new SOAP_Parser($stringArrayOne); var_dump($parser->getResponse()); ?> --EXPECTREGEX-- object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(1\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(2\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> string\(4\) "good" \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(4\) "item" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(4\) "item" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "string" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \} \["type"\]\=\> string\(6\) "string" \["type_namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \[1\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> string\(3\) "bad" \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(4\) "item" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(4\) "item" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "string" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \} \["type"\]\=\> string\(6\) "string" \["type_namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "return" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(6\) "return" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(5\) "Array" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(41\) "http:\/\/schemas.xmlsoap.org\/soap\/encoding\/" \} \["type"\]\=\> string\(5\) "Array" \["type_namespace"\]\=\> string\(41\) "http:\/\/schemas.xmlsoap.org\/soap\/encoding\/" \["arrayType"\]\=\> string\(6\) "string" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "Struct" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(0\) "" \} \["type"\]\=\> string\(6\) "Struct" \["type_namespace"\]\=\> string\(0\) "" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(1\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(2\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> string\(4\) "good" \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(4\) "item" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(4\) "item" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "string" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \} \["type"\]\=\> string\(6\) "string" \["type_namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \[1\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> string\(3\) "bad" \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(4\) "item" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(4\) "item" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "string" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \} \["type"\]\=\> string\(6\) "string" \["type_namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(17\) "outputStringArray" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(17\) "outputStringArray" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "Struct" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(0\) "" \} \["type"\]\=\> string\(6\) "Struct" \["type_namespace"\]\=\> string\(0\) "" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "Struct" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(0\) "" \} \["type"\]\=\> string\(6\) "Struct" \["type_namespace"\]\=\> string\(0\) "" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(1\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> array\(1\) \{ \[0\]\=\> object\((soap_value|SOAP_Value)\).+?10\) \{ \["value"\]\=\> string\(4\) "good" \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(4\) "item" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(4\) "item" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "string" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \} \["type"\]\=\> string\(6\) "string" \["type_namespace"\]\=\> string\(32\) "http:\/\/www.w3.org\/2001\/XMLSchema" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(17\) "outputStringArray" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(17\) "outputStringArray" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "Struct" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(0\) "" \} \["type"\]\=\> string\(6\) "Struct" \["type_namespace"\]\=\> string\(0\) "" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} \} \["nqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \} \["name"\]\=\> string\(23\) "echoStringArrayResponse" \["namespace"\]\=\> string\(23\) "http:\/\/soapinterop.org\/" \["tqn"\]\=\> object\((qname|QName)\).+?3\) \{ \["name"\]\=\> string\(6\) "Struct" \["prefix"\]\=\> string\(0\) "" \["namespace"\]\=\> string\(0\) "" \} \["type"\]\=\> string\(6\) "Struct" \["type_namespace"\]\=\> string\(0\) "" \["arrayType"\]\=\> string\(0\) "" \["attributes"\]\=\> array\(0\) \{ \} \["options"\]\=\> array\(0\) \{ \} \} php-soap-0.13.0/SOAP-0.13.0/tests/qnames_1.phpt000066400000000000000000000004101214222670500203400ustar00rootroot00000000000000--TEST-- QNames: Standard QName --FILE-- name, $qname->prefix); ?> --EXPECT-- string(11) "elementName" string(2) "ns" php-soap-0.13.0/SOAP-0.13.0/tests/qnames_2.phpt000066400000000000000000000004101214222670500203410ustar00rootroot00000000000000--TEST-- QNames: URN QName --FILE-- name, $qname->prefix); ?> --EXPECT-- string(16) "urn:some:api:bar" string(0) "" php-soap-0.13.0/SOAP-0.13.0/tests/serialize/000077500000000000000000000000001214222670500177335ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/tests/serialize/string_1.phpt000066400000000000000000000014321214222670500223560ustar00rootroot00000000000000--TEST-- Serialize typed string --FILE-- _generate('echoString', $p); ?> --EXPECT-- hello world php-soap-0.13.0/SOAP-0.13.0/tests/serialize/string_2.phpt000066400000000000000000000014261214222670500223620ustar00rootroot00000000000000--TEST-- Serialize untyped string --FILE-- _generate('echoString', $p); ?> --EXPECT-- hello world php-soap-0.13.0/SOAP-0.13.0/tests/serialize/string_doc.phpt000066400000000000000000000014571214222670500227720ustar00rootroot00000000000000--TEST-- Serialize typed string (document) --FILE-- setStyle('document'); $p = array(new SOAP_Value('inputString', 'string', 'hello world')); echo $soap_client->_generate('echoString', $p); ?> --EXPECT-- hello world php-soap-0.13.0/SOAP-0.13.0/tests/serialize/string_doc_literal_1.phpt000066400000000000000000000013761214222670500247260ustar00rootroot00000000000000--TEST-- Serialize typed string (document/literal) --FILE-- setStyle('document'); $soap_client->setUse('literal'); $p = array(new SOAP_Value('inputString', 'string', 'hello world')); echo $soap_client->_generate('echoString', $p); ?> --EXPECT-- hello world php-soap-0.13.0/SOAP-0.13.0/tests/serialize/string_literal_1.phpt000066400000000000000000000013531214222670500240740ustar00rootroot00000000000000--TEST-- Serialize typed string (literal) --FILE-- setUse('literal'); $p = array(new SOAP_Value('inputString', 'string', 'hello world')); echo $soap_client->_generate('echoString', $p); ?> --EXPECT-- hello world php-soap-0.13.0/SOAP-0.13.0/tests/serialize/struct_1.phpt000066400000000000000000000022251214222670500223750ustar00rootroot00000000000000--TEST-- Serialize typed struct --FILE-- _generate('echoStruct', $p); ?> --EXPECT-- 45 5.9 -450 Blue php-soap-0.13.0/SOAP-0.13.0/tests/serialize/struct_2.phpt000066400000000000000000000020741214222670500224000ustar00rootroot00000000000000--TEST-- Serialize untyped struct --FILE-- 45, 'height' => 5.9, 'displacement' => -450, 'color' => 'Blue'))); echo $soap_client->_generate('echoStruct', $p); ?> --EXPECT-- 45 5.9 -450 Blue php-soap-0.13.0/SOAP-0.13.0/tests/serialize/struct_3.phpt000066400000000000000000000022661214222670500224040ustar00rootroot00000000000000--TEST-- Serialize custom struct --FILE-- _generate('echoStruct', array('inputStruct' => $struct), 'urn:SOAP_Example_Server'); ?> --EXPECT-- test string 123 123.123 php-soap-0.13.0/SOAP-0.13.0/tests/serialize/struct_doc_literal_1.phpt000066400000000000000000000020621214222670500247350ustar00rootroot00000000000000--TEST-- Serialize typed struct (document/literal) --FILE-- setStyle('document'); $soap_client->setUse('literal'); $p = array( new SOAP_Value( 'inputStruct', 'Struct', array(new SOAP_Value('age', 'int', 45), new SOAP_Value('height', 'float', 5.9), new SOAP_Value('displacement', 'negativeInteger', -450), new SOAP_Value('color', 'string', 'Blue')))); echo $soap_client->_generate('echoStruct', $p); ?> --EXPECT-- 45 5.9 -450 Blue php-soap-0.13.0/SOAP-0.13.0/tests/serialize/struct_literal_1.phpt000066400000000000000000000020371214222670500241120ustar00rootroot00000000000000--TEST-- Serialize typed struct (literal) --FILE-- setUse('literal'); $p = array( new SOAP_Value( 'inputStruct', 'Struct', array(new SOAP_Value('age', 'int', 45), new SOAP_Value('height', 'float', 5.9), new SOAP_Value('displacement', 'negativeInteger', -450), new SOAP_Value('color', 'string', 'Blue')))); echo $soap_client->_generate('echoStruct', $p); ?> --EXPECT-- 45 5.9 -450 Blue php-soap-0.13.0/SOAP-0.13.0/tests/smtp.php000066400000000000000000000030211214222670500174340ustar00rootroot00000000000000 | // +----------------------------------------------------------------------+ // // $Id: smtp.php 322284 2012-01-14 13:15:06Z clockwerx $ // // include soap client class include("SOAP/Client.php"); $soapclient = new SOAP_Client("mailto:shane@caraveo.com"); $options = array('namespace' => 'http://soapinterop.org/', 'from' => 'shane@caraveo.com'); $return = $soapclient->call("echoString", array("inputString" => "this is a test"), $options); print_r($return); unset($soapclient); php-soap-0.13.0/SOAP-0.13.0/tests/test.utility.php000066400000000000000000000055401214222670500211420ustar00rootroot00000000000000compare($e1, $e2) == 0; } return $ok || $e1 == $e2 || strcasecmp($e1, $e2) == 0; } function array_compare(&$ar1, &$ar2) { if (gettype($ar1) != 'array' || gettype($ar2) != 'array') return false; // first a shallow diff if (count($ar1) != count($ar2)) return false; $diff = array_diff($ar1, $ar2); if (count($diff) == 0) return true; // diff failed, do a full check of the array foreach ($ar1 as $k => $v) { //print "comparing $v == $ar2[$k]\n"; if (gettype($v) == 'array') { if (!array_compare($v, $ar2[$k])) return false; } elseif (is_object($v)) { if (!object_compare($v, $ar2[$k])) return false; } else { if (!string_compare($v, $ar2[$k])) return false; } } return true; } function object_compare(&$o1, &$o2) { if (!is_object($o1) || !is_object($o2) || gettype($o1) != gettype($o2)) { return false; } $o1 = (array)$o1; $o2 = (array)$o2; return array_compare($o1, $o2); } function parseMessage($msg) { // strip line endings // $msg = preg_replace('/\r|\n/', ' ', $msg); $parser = new SOAP_Parser($msg); if ($parser->fault) { return $parser->fault->getFault(); } $response = $parser->getResponse(); $v = $parser->_decode($response); if (gettype($v) == 'array' && count($v) === 1) { return array_shift($v); } return $v; } php-soap-0.13.0/SOAP-0.13.0/tests/wsdl.phpt000066400000000000000000000012161214222670500176120ustar00rootroot00000000000000--TEST-- WSDL test --FILE-- service); echo "\n"; var_export(array_keys($wsdl->messages)); ?> --EXPECT-- 'ServerExampleService' array ( 0 => 'echoStructAsSimpleTypesRequest', 1 => 'echoStructAsSimpleTypesResponse', 2 => 'echoStringSimpleRequest', 3 => 'echoStringSimpleResponse', 4 => 'echoStringRequest', 5 => 'echoStringResponse', 6 => 'divideRequest', 7 => 'divideResponse', 8 => 'echoStructRequest', 9 => 'echoStructResponse', 10 => 'echoMimeAttachmentRequest', 11 => 'echoMimeAttachmentResponse', )php-soap-0.13.0/SOAP-0.13.0/tests/xmethods.php000066400000000000000000000040101214222670500203030ustar00rootroot00000000000000 Port to PEAR and more | // | Authors: Dietrich Ayala Original Author | // +----------------------------------------------------------------------+ // // $Id: xmethods.php 322284 2012-01-14 13:15:06Z clockwerx $ // // include soap client class include("SOAP/Client.php"); print "getting wsdl list from xmethods...\n"; $soapclient = new SOAP_Client("http://www.xmethods.net/wsdl/query.wsdl","wsdl"); $params = array(); $summary = $soapclient->call("getAllServiceSummaries", $params); # !@#^%$ php needs real timeouts on windows $skip = array('Unisys Weather Web Service'); print "getting wsdls in list...\n"; foreach ($summary as $info) { var_dump($info);break; if (in_array($info['name'],$skip)) continue; print "retrieving {$info['name']}..."; $wsdl = new SOAP_WSDL($info['wsdlURL']); if ($wsdl->fault) { print $wsdl->fault->getMessage()."\n"; } else { print "wsdl parsed OK\n"; } } print "\n\n"; ?> php-soap-0.13.0/SOAP-0.13.0/tools/000077500000000000000000000000001214222670500157425ustar00rootroot00000000000000php-soap-0.13.0/SOAP-0.13.0/tools/genproxy.php000066400000000000000000000006231214222670500203270ustar00rootroot00000000000000 foo.php * */ function do_wsdl($uri) { $wsdl = new SOAP_WSDL($uri); print $wsdl->generateAllProxies(); } echo ""; ?> php-soap-0.13.0/package.xml000066400000000000000000000326031214222670500154440ustar00rootroot00000000000000 SOAP pear.php.net SOAP Client/Server for PHP Implementation of SOAP protocol and services Jan Schneider yunosh jan@horde.org yes Chuck Hagenbuch chagenbu chuck@horde.org no Shane Caraveo shane shane@php.net no Al Baker abaker abaker@php.net no Arnaud Limbourg arnaud arnaud@php.net no 2012-01-26 0.13.0 0.13.0 beta beta PHP License * Rename QName::ns property to QName::prefix. * Fix parsing multipart/related responses (Bugs #14756, #14854). * Fix parsing certain WSDLs with attachments (Bill Blough, Bug #16968). * Use PCRE instead of ereg_* functions (Olle Jonsson, Bug #17726).] QA release Bug #11729 WSDL Local File loading Bug #14344 Use Net_Server in SOAP_Server_TCP Bug #14756 multipart/related response is not parsed Bug #14782 logic problem in SOAP_Base bulids multidimensional arrays instead of flat Bug #14854 multipart/related responses no longer handled correctly Bug #16968 Bad array assignment when using WSDL client Bug #17659 Assigning the return value of new by reference is deprecated Bug #17726 Patch: Using PCRE functions to avoid deprecated functions Bug #18458 Returning SOAP_Attachment in MIME Bug #18492 Wrong response when returning multiple results 5.0.0 1.5.4 PEAR pear.php.net HTTP_Request pear.php.net Mail pear.php.net Mail_Mime pear.php.net Net_DIME pear.php.net 0.13.0 0.13.0 beta beta 2012-01-26 PHP License * Rename QName::ns property to QName::prefix. * Fix parsing multipart/related responses (Bugs #14756, #14854). * Fix parsing certain WSDLs with attachments (Bill Blough, Bug #16968). * Use PCRE instead of ereg_* functions (Olle Jonsson, Bug #17726).] QA release Bug #11729 WSDL Local File loading Bug #14344 Use Net_Server in SOAP_Server_TCP Bug #14756 multipart/related response is not parsed Bug #14782 logic problem in SOAP_Base bulids multidimensional arrays instead of flat Bug #14854 multipart/related responses no longer handled correctly Bug #16968 Bad array assignment when using WSDL client Bug #17659 Assigning the return value of new by reference is deprecated Bug #17726 Patch: Using PCRE functions to avoid deprecated functions Bug #18458 Returning SOAP_Attachment in MIME Bug #18492 Wrong response when returning multiple results