Viewing file: Base.php (41.62 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /** * This file loads all required libraries, defines constants used across the * SOAP package, and defines the base classes that most other classes of this * package extend. * * 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 Dietrich Ayala <dietrich@ganx4.com> Original Author * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more * @author Chuck Hagenbuch <chuck@horde.org> Maintenance * @author Jan Schneider <jan@horde.org> 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_OBJECT_STRUCT makes PEAR::SOAP use objects for SOAP structures rather * than arrays. This has been done to provide a closer match to php-soap. If * the old behaviour is needed, set to false. The old behaviour is * deprecated. * * @global bool $GLOBALS['SOAP_OBJECT_STRUCT'] */ $GLOBALS['SOAP_OBJECT_STRUCT'] = true;
/** * SOAP_RAW_CONVERT makes PEAR::SOAP attempt to determine what SOAP type a PHP * string COULD be. This may result in slightly better interoperability when * you are not using WSDL, and are being lazy and not using SOAP_Value to * define types for your values. * * @global bool $GLOBALS['SOAP_RAW_CONVERT'] */ $GLOBALS['SOAP_RAW_CONVERT'] = false;
require_once 'PEAR.php'; require_once 'SOAP/Type/dateTime.php'; require_once 'SOAP/Type/hexBinary.php';
// optional features $GLOBALS['SOAP_options'] = array();
@include_once 'Mail/mimePart.php'; @include_once 'Mail/mimeDecode.php'; if (class_exists('Mail_mimePart')) { $GLOBALS['SOAP_options']['Mime'] = 1; define('MAIL_MIMEPART_CRLF', "\r\n"); }
@include_once 'Net/DIME.php'; if (class_exists('Net_DIME_Message')) { $GLOBALS['SOAP_options']['DIME'] = 1; }
/** * Enable debugging information? * * @global bool $GLOBALS['SOAP_DEBUG'] * @name $SOAP_DEBUG */ $GLOBALS['SOAP_DEBUG'] = false;
if (!function_exists('version_compare') || version_compare(phpversion(), '4.1', '<')) { die("requires PHP 4.1 or higher\n"); } if (version_compare(phpversion(), '4.1', '>=') && version_compare(phpversion(), '4.2', '<')) { define('FLOAT', 'double'); } else { define('FLOAT', 'float'); }
if (!defined('INF')) { define('INF', 1.8e307); } if (!defined('NAN')) { define('NAN', 0.0); }
define('SOAP_LIBRARY_VERSION', '0.10.1'); define('SOAP_LIBRARY_NAME', 'PEAR-SOAP 0.10.1-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');
class SOAP_Base_Object extends PEAR { /** * Store debugging information in $_debug_data? * * @see $debug_data, SOAP_Base * @var boolean $_debug_flag */ var $_debug_flag = false;
/** * String containing debugging information if $_debug_flag is true. * * @access public * @see $debug_flag, SOAP_Base * @var string $_debug_data */ var $_debug_data = '';
/** * 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. * * @see $debug_data, _debug() * * @param string $faultcode Error code. */ function SOAP_Base_Object($faultcode = 'Client') { $this->_myfaultcode = $faultcode; $this->_debug_flag = $GLOBALS['SOAP_DEBUG']; parent::PEAR('SOAP_Fault'); }
/** * Raises a SOAP error. * * Please refer to the SOAP definition for an impression of what a certain * parameter stands for. * * Use $debug_flag to store errors to the member variable $debug_data * * @see $debug_flag, $debug_data, SOAP_Fault * * @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'; } $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; }
/** * Adds a string to the debug data. * * @param string $string Debugging message. */ function _debug($string) { if ($this->_debug_flag) { $this->_debug_data .= get_class($this) . ': ' . str_replace('>', ">\r\n", $string) . "\n"; } }
}
/** * Common base class of all SOAP classes. * * @access public * @package SOAP * @author Shane Caraveo <shane@php.net> 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. * * @array */ var $_namespaces;
/** * The default namespace. * * @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. * * @see $debug_data, _debug() * * @param string $faultcode Error code. */ function SOAP_Base($faultcode = 'Client') { parent::SOAP_Base_Object($faultcode); $this->_resetNamespaces(); }
/** * 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-ENV', 'http://www.w3.org/2001/XMLSchema' => 'xsd', 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', 'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC'); }
/** * 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; }
function _isSoapValue(&$value) { return is_a($value, 'SOAP_Value'); }
function _serializeValue(&$value, $name = '', $type = false, $elNamespace = null, $typeNamespace = null, $options = array(), $attributes = array(), $artype = '') { $namespaces = array(); $arrayType = $array_depth = $xmlout_value = null; $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = ''; $xmlout_type = $xmlns = $ptype = $array_type_ns = '';
if (!$name || is_numeric($name)) { $name = 'item'; }
if ($this->_wsdl) { list($ptype, $arrayType, $array_type_ns, $array_depth) = $this->_wsdl->getSchemaType($type, $name, $typeNamespace); }
if (!$arrayType) { $arrayType = $artype; } if (!$ptype) { $ptype = $this->_getType($value); } if (!$type) { $type = $ptype; }
if (strcasecmp($ptype, 'Struct') == 0 || strcasecmp($type, 'Struct') == 0) { // Struct $vars = null; if (is_object($value)) { $vars = get_object_vars($value); } else { $vars = &$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]), $k, false, $this->_section5 ? null : $elNamespace); } } else { $xmlout_value .= $this->_serializeValue($vars[$k], $k, false, $this->_section5 ? null : $elNamespace); } } } } elseif (strcasecmp($ptype, 'Array') == 0 || strcasecmp($type, 'Array') == 0) { // Array. $typeNamespace = SOAP_SCHEMA_ENCODING; $orig_type = $type; $type = 'Array'; $numtypes = 0; // 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 ($this->_isSoapValue($array_val)) { $array_type = $array_val->type; $array_types[$array_type] = 1; $array_type_ns = $array_val->type_namespace; $xmlout_value .= $array_val->serialize($this); } else { $array_type = $this->_getType($array_val); $array_types[$array_type] = 1; $xmlout_value .= $this->_serializeValue($array_val, 'item', $array_type, $this->_section5 ? null : $elNamespace); } }
$xmlout_offset = ' SOAP-ENC:offset="[0]"'; 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]; } if ($array_type_prefix) { $arrayType = $array_type_prefix . ':' . $arrayType; } }
$xmlout_arrayType = ' SOAP-ENC:arrayType="' . $arrayType; if ($array_depth != null) { for ($i = 0; $i < $array_depth; $i++) { $xmlout_arrayType .= '[]'; } } $xmlout_arrayType .= "[$ar_size]\""; } elseif ($this->_isSoapValue($value)) { $xmlout_value = $value->serialize($this); } elseif ($type == 'string') { $xmlout_value = htmlspecialchars($value); } elseif ($type == 'rawstring') { $xmlout_value =& $value; } elseif ($type == 'boolean') { $xmlout_value = $value ? 'true' : 'false'; } else { $xmlout_value =& $value; }
// Add namespaces. if ($elNamespace) { $elPrefix = $this->_getNamespacePrefix($elNamespace); if ($elPrefix) { $xmlout_name = "$elPrefix:$name"; } else { $xmlout_name = $name; } } else { $xmlout_name = $name; }
if ($typeNamespace) { $typePrefix = $this->_getNamespacePrefix($typeNamespace); if ($typePrefix) { $xmlout_type = "$typePrefix:$type"; } else { $xmlout_type = $type; } } elseif ($type && isset($this->_typemap[$this->_XMLSchemaVersion][$type])) { $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; if ($typePrefix) { $xmlout_type = "$typePrefix:$type"; } else { $xmlout_type = $type; } }
// Handle additional attributes. $xml_attr = ''; if (count($attributes)) { foreach ($attributes as $k => $v) { $kqn =& new QName($k); $vqn =& new QName($v); $xml_attr .= ' ' . $kqn->fqn() . '="' . $vqn->fqn() . '"'; } }
// Store the 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" . "$xmlout_offset$xml_attr>$xmlout_value</$xmlout_name>"; } } 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 . "</$xmlout_name>"; } }
return $xml; }
/** * Converts a PHP type to a SOAP type. * * @access private * * @param string $value The value to inspect. * * @return string The value's SOAP type. */ function _getType(&$value) { global $SOAP_OBJECT_STRUCT, $SOAP_RAW_CONVERT;
$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'; } else { $ar_size = count($value); reset($value); $key1 = key($value); if ($ar_size > 0 && is_a($key1, 'SOAP_Value')) { // FIXME: for non-wsdl structs that are all the same type $key2 = key($value); if ($ar_size > 1 && $this->_isSoapValue($key1) && $this->_isSoapValue($key2) && $key1->name != $key2->name) { // This is a struct, not an array. $type = 'Struct'; } else { $type = 'Array'; } } else { $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': if ($SOAP_RAW_CONVERT) { if (is_numeric($value)) { if (strstr($value, '.')) { $type = 'float'; } else { $type = 'int'; } } else { if (SOAP_Type_hexBinary::is_hexbin($value)) { $type = 'hexBinary'; } else { if ($this->_isBase64($value)) { $type = 'base64Binary'; } else { $dt =& new SOAP_Type_dateTime($value); if ($dt->toUnixtime() != -1) { $type = 'dateTime'; } } } } } break;
default: break; }
return $type; }
function _multiArrayType(&$value, &$type, &$size, &$xml) { $sz = count($value); if (is_array($value)) { // Seems we have a multi dimensional array, figure it out if we // do. $c = count($value); for ($i = 0; $i < $c; $i++) { $this->_multiArrayType($value[$i], $type, $size, $xml); }
if ($size) { $size = $sz. ',' . $size; } else { $size = $sz; }
return 1; } else { if (is_object($value)) { $type = $value->type; $xml .= $value->serialize($this); } else { $type = $this->_getType($value); $xml .= $this->_serializeValue($value, 'item', $type); } } $size = null;
return 1; }
/** * Returns whether a string is base64 encoded data. * * @param string $value The string to check. * * @return boolean True if the specified value seems to be base64 encoded. */ function _isBase64(&$value) { $l = strlen($value); if ($l) { return $value[$l - 1] == '=' && preg_match('/[A-Za-z=\/\+]+/', $value); } return false; }
/** * 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) { // I really dislike having to loop through this in PHP code, really // large arrays will be slow. We need a C function to do this. $it = 0; foreach ($a as $k => $v) { // Checking the type is faster than regexp. if (is_int($k) || $this->_isSoapValue($v)) { return true; } // If someone has a large hash they should really be defining the // type. if ($it++ > 10) { $this->_raiseSoapFault('Large associative array passed where a SOAP_Value was expected'); return false; } } 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); }
function &_decode(&$soapval) { global $SOAP_OBJECT_STRUCT;
if (!$this->_isSoapValue($soapval)) { return $soapval; } elseif (is_array($soapval->value)) { if ($SOAP_OBJECT_STRUCT && $soapval->type != 'Array') { $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(); }
$counter = 1; $isstruct = !$SOAP_OBJECT_STRUCT || !is_array($return); foreach ($soapval->value as $item) { if (is_object($return)) { if ($this->_wsdl) { // Get this child's WSDL information. // /$soapval->ns/$soapval->type/$item->ns/$item->name $child_type = $this->_wsdl->getComplexTypeChildType( $soapval->namespace, $soapval->name, $item->namespace, $item->name); if ($child_type) { $item->type = $child_type; } } if (!$isstruct || $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 (is_array($return)) { $return[] =& $this->_decode($item); } else { $return->{$item->name} =& $this->_decode($item); } } elseif (isset($return->{$item->name})) { $isstruct = false; if (count(get_object_vars($return)) == 1) { $d =& $this->_decode($item); $return = array($return->{$item->name}, $d); } else { $d =& $this->_decode($item); $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 && $this->_isSoapValue($item)) { 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; } if (!$isstruct) { $return[] = $this->_decode($item); } elseif (isset($return[$item->name])) { $isstruct = false; $d =& $this->_decode($item); $return = array($return[$item->name], $d); } else { $return[$item->name] = $this->_decode($item); } } }
return $return; }
if ($soapval->type == 'boolean') { if ($soapval->value != '0' && strcasecmp($soapval->value, 'false') != 0) { $soapval->value = true; } else { $soapval->value = false; } } 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]); }
if ($this->_isBase64Type($soapval->type)) { $value = base64_decode($soapval->value); return $value; } else { return $soapval->value; } }
/** * Creates the SOAP envelope with the SOAP envelop data. * * @param mixed $method * @param array $headers * @param string $encoding * @param array $options * * @return string */ function makeEnvelope(&$method, &$headers, $encoding = SOAP_DEFAULT_ENCODING, $options = array()) { $smsg = $header_xml = $ns_string = '';
if ($headers) { $c = count($headers); for ($i = 0; $i < $c; $i++) { $header_xml .= $headers[$i]->serialize($this); } $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n"; }
if (!isset($options['input']) || $options['input'] == 'parse') { if (is_array($method)) { $c = count($method); for ($i = 0; $i < $c; $i++) { $smsg .= $method[$i]->serialize($this); } } else { $smsg = $method->serialize($this); } } else { $smsg = $method; } $body = "<SOAP-ENV:Body>\r\n" . $smsg . "\r\n</SOAP-ENV:Body>\r\n";
foreach ($this->_namespaces as $k => $v) { $ns_string .= " xmlns:$v=\"$k\"\r\n"; } if ($this->_namespace) { $ns_string .= " xmlns=\"{$this->_namespace}\"\r\n"; }
/* If 'use' == 'literal', we 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 = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n". "<SOAP-ENV:Envelope $ns_string". ($this->_section5 ? ' SOAP-ENV:encodingStyle="' . SOAP_SCHEMA_ENCODING . '"' : ''). ">\r\n". "$header_xml$body</SOAP-ENV:Envelope>\r\n";
return $xml; }
function _makeMimeMessage(&$xml, $encoding = SOAP_DEFAULT_ENCODING) { global $SOAP_options;
if (!isset($SOAP_options['Mime'])) { return $this->_raiseSoapFault('Mime is not installed'); }
// Encode any attachments. // See http://www.w3.org/TR/SOAP-attachments // Now we have to mime encode the message. $params = array('content_type' => 'multipart/related; type=text/xml'); $msg =& new Mail_mimePart('', $params);
// Add the xml part. $params['content_type'] = 'text/xml'; $params['charset'] = $encoding; $params['encoding'] = 'base64'; $msg->addSubPart($xml, $params);
// Add the attachements for ($i = 0, $c = count($this->_attachments); $i < $c; ++$i) { $attachment =& $this->_attachments[$i]; $msg->addSubPart($attachment['body'], $attachment); }
return $msg->encode(); }
// TODO: this needs to be used from the Transport system. function _makeDIMEMessage($xml) { global $SOAP_options;
if (!isset($SOAP_options['DIME'])) { return $this->_raiseSoapFault('DIME is not installed'); }
// Encode any attachments. // See http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt // Now we have to DIME encode the message $dime =& new 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++) { $attachment =& $this->_attachments[$i]; $msg .= $dime->encodeData($attachment['body'], $attachment['content_type'], $attachment['cid'], NET_DIME_TYPE_MEDIA); } $msg .= $dime->endMessage();
return $msg; }
function _decodeMimeMessage(&$data, &$headers, &$attachments) { global $SOAP_options;
if (!isset($SOAP_options['Mime'])) { $this->_raiseSoapFault('Mime Unsupported, install PEAR::Mail::Mime', '', '', 'Server'); return; }
$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;
return; } elseif (isset($structure->parts)) { $data = $structure->parts[0]->body; $headers = array_merge($structure->headers, $structure->parts[0]->headers); if (count($structure->parts) > 1) { $mime_parts = array_splice($structure->parts,1); // Prepare the parts for the SOAP parser.
$c = count($mime_parts); for ($i = 0; $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) { global $SOAP_options;
if (!isset($SOAP_options['DIME'])) { $this->_raiseSoapFault('DIME Unsupported, install PEAR::Net::DIME', '', '', 'Server'); return; }
// 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']; } }
/** * @deprecated Use setTypeTranslation(). */ function __set_type_translation($type, $class = null) { $this->setTypeTranslation($type, $class); }
/** * 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. * * @access public * @package SOAP * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates */ class QName { var $name = ''; var $ns = ''; 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); $s = array_reverse($s); $this->name = $s[0]; $this->ns = $s[1]; $this->namespace = $namespace; } else { $this->name = $name; $this->namespace = $namespace; }
// A little more magic than should be in a qname. $p = strpos($this->name, '['); if ($p) { // 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->ns) { return $this->ns . ':' . $this->name; } return $this->name; }
}
|