Commit b9b50e851b324f67e81d6cfc6c2cd3a4e2212b92
1 parent
47038201
KTS-1858
"Adding PEAR::SOAP libraries to KnowledgeTree" Installed. Reviewed By: Kevin Fourie git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@6456 c91229c3-7414-0410-bfa2-8a42b809f60b
Showing
39 changed files
with
10793 additions
and
0 deletions
thirdparty/pear/SOAP/Base.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file loads all required libraries, defines constants used across the | ||
| 4 | + * SOAP package, and defines the base classes that most other classes of this | ||
| 5 | + * package extend. | ||
| 6 | + * | ||
| 7 | + * PHP versions 4 and 5 | ||
| 8 | + * | ||
| 9 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 10 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 11 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 12 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 13 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 14 | + * mail you a copy immediately. | ||
| 15 | + * | ||
| 16 | + * @category Web Services | ||
| 17 | + * @package SOAP | ||
| 18 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 19 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 20 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 21 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 22 | + * @copyright 2003-2005 The PHP Group | ||
| 23 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 24 | + * @link http://pear.php.net/package/SOAP | ||
| 25 | + */ | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * SOAP_OBJECT_STRUCT makes PEAR::SOAP use objects for SOAP structures rather | ||
| 29 | + * than arrays. This has been done to provide a closer match to php-soap. If | ||
| 30 | + * the old behaviour is needed, set to false. The old behaviour is | ||
| 31 | + * deprecated. | ||
| 32 | + * | ||
| 33 | + * @global bool $GLOBALS['SOAP_OBJECT_STRUCT'] | ||
| 34 | + */ | ||
| 35 | +$GLOBALS['SOAP_OBJECT_STRUCT'] = true; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * SOAP_RAW_CONVERT makes PEAR::SOAP attempt to determine what SOAP type a PHP | ||
| 39 | + * string COULD be. This may result in slightly better interoperability when | ||
| 40 | + * you are not using WSDL, and are being lazy and not using SOAP_Value to | ||
| 41 | + * define types for your values. | ||
| 42 | + * | ||
| 43 | + * @global bool $GLOBALS['SOAP_RAW_CONVERT'] | ||
| 44 | + */ | ||
| 45 | +$GLOBALS['SOAP_RAW_CONVERT'] = false; | ||
| 46 | + | ||
| 47 | +require_once 'PEAR.php'; | ||
| 48 | +require_once 'SOAP/Type/dateTime.php'; | ||
| 49 | +require_once 'SOAP/Type/hexBinary.php'; | ||
| 50 | + | ||
| 51 | +// optional features | ||
| 52 | +$GLOBALS['SOAP_options'] = array(); | ||
| 53 | + | ||
| 54 | +@include_once 'Mail/mimePart.php'; | ||
| 55 | +@include_once 'Mail/mimeDecode.php'; | ||
| 56 | +if (class_exists('Mail_mimePart')) { | ||
| 57 | + $GLOBALS['SOAP_options']['Mime'] = 1; | ||
| 58 | + define('MAIL_MIMEPART_CRLF', "\r\n"); | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +@include_once 'Net/DIME.php'; | ||
| 62 | +if (class_exists('Net_DIME_Message')) { | ||
| 63 | + $GLOBALS['SOAP_options']['DIME'] = 1; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +/** | ||
| 67 | + * Enable debugging information? | ||
| 68 | + * | ||
| 69 | + * @global bool $GLOBALS['SOAP_DEBUG'] | ||
| 70 | + * @name $SOAP_DEBUG | ||
| 71 | + */ | ||
| 72 | +$GLOBALS['SOAP_DEBUG'] = false; | ||
| 73 | + | ||
| 74 | +if (!function_exists('version_compare') || | ||
| 75 | + version_compare(phpversion(), '4.1', '<')) { | ||
| 76 | + die("requires PHP 4.1 or higher\n"); | ||
| 77 | +} | ||
| 78 | +if (version_compare(phpversion(), '4.1', '>=') && | ||
| 79 | + version_compare(phpversion(), '4.2', '<')) { | ||
| 80 | + define('FLOAT', 'double'); | ||
| 81 | +} else { | ||
| 82 | + define('FLOAT', 'float'); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +if (!defined('INF')) { | ||
| 86 | + define('INF', 1.8e307); | ||
| 87 | +} | ||
| 88 | +if (!defined('NAN')) { | ||
| 89 | + define('NAN', 0.0); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +define('SOAP_LIBRARY_VERSION', '0.8.0RC4'); | ||
| 93 | +define('SOAP_LIBRARY_NAME', 'PEAR-SOAP 0.8.0RC4-devel'); | ||
| 94 | + | ||
| 95 | +// Set schema version. | ||
| 96 | +define('SOAP_XML_SCHEMA_VERSION', 'http://www.w3.org/2001/XMLSchema'); | ||
| 97 | +define('SOAP_XML_SCHEMA_INSTANCE', 'http://www.w3.org/2001/XMLSchema-instance'); | ||
| 98 | +define('SOAP_XML_SCHEMA_1999', 'http://www.w3.org/1999/XMLSchema'); | ||
| 99 | +define('SOAP_SCHEMA', 'http://schemas.xmlsoap.org/wsdl/soap/'); | ||
| 100 | +define('SOAP_SCHEMA_ENCODING', 'http://schemas.xmlsoap.org/soap/encoding/'); | ||
| 101 | +define('SOAP_ENVELOP', 'http://schemas.xmlsoap.org/soap/envelope/'); | ||
| 102 | + | ||
| 103 | +define('SCHEMA_DISCO', 'http://schemas.xmlsoap.org/disco/'); | ||
| 104 | +define('SCHEMA_DISCO_SCL', 'http://schemas.xmlsoap.org/disco/scl/'); | ||
| 105 | + | ||
| 106 | +define('SCHEMA_SOAP', 'http://schemas.xmlsoap.org/wsdl/soap/'); | ||
| 107 | +define('SCHEMA_SOAP_HTTP', 'http://schemas.xmlsoap.org/soap/http'); | ||
| 108 | +define('SCHEMA_WSDL_HTTP', 'http://schemas.xmlsoap.org/wsdl/http/'); | ||
| 109 | +define('SCHEMA_MIME', 'http://schemas.xmlsoap.org/wsdl/mime/'); | ||
| 110 | +define('SCHEMA_WSDL', 'http://schemas.xmlsoap.org/wsdl/'); | ||
| 111 | +define('SCHEMA_DIME', 'http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/'); | ||
| 112 | +define('SCHEMA_CONTENT', 'http://schemas.xmlsoap.org/ws/2002/04/content-type/'); | ||
| 113 | +define('SCHEMA_REF', 'http://schemas.xmlsoap.org/ws/2002/04/reference/'); | ||
| 114 | + | ||
| 115 | +define('SOAP_DEFAULT_ENCODING', 'UTF-8'); | ||
| 116 | + | ||
| 117 | +class SOAP_Base_Object extends PEAR | ||
| 118 | +{ | ||
| 119 | + /** | ||
| 120 | + * Store debugging information in $_debug_data? | ||
| 121 | + * | ||
| 122 | + * @see $debug_data, SOAP_Base | ||
| 123 | + * @var boolean $_debug_flag | ||
| 124 | + */ | ||
| 125 | + var $_debug_flag = false; | ||
| 126 | + | ||
| 127 | + /** | ||
| 128 | + * String containing debugging information if $_debug_flag is true. | ||
| 129 | + * | ||
| 130 | + * @access public | ||
| 131 | + * @see $debug_flag, SOAP_Base | ||
| 132 | + * @var string $_debug_data | ||
| 133 | + */ | ||
| 134 | + var $_debug_data = ''; | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * Supported encodings, limited by XML extension. | ||
| 138 | + * | ||
| 139 | + * @var array $_encodings | ||
| 140 | + */ | ||
| 141 | + var $_encodings = array('ISO-8859-1', 'US-ASCII', 'UTF-8'); | ||
| 142 | + | ||
| 143 | + /** | ||
| 144 | + * Fault code. | ||
| 145 | + * | ||
| 146 | + * @var string $_myfaultcode | ||
| 147 | + */ | ||
| 148 | + var $_myfaultcode = ''; | ||
| 149 | + | ||
| 150 | + /** | ||
| 151 | + * Recent PEAR_Error object. | ||
| 152 | + * | ||
| 153 | + * @var PEAR_Error $fault | ||
| 154 | + */ | ||
| 155 | + var $fault = null; | ||
| 156 | + | ||
| 157 | + /** | ||
| 158 | + * Constructor. | ||
| 159 | + * | ||
| 160 | + * @see $debug_data, _debug() | ||
| 161 | + * | ||
| 162 | + * @param string $faultcode Error code. | ||
| 163 | + */ | ||
| 164 | + function SOAP_Base_Object($faultcode = 'Client') | ||
| 165 | + { | ||
| 166 | + $this->_myfaultcode = $faultcode; | ||
| 167 | + $this->_debug_flag = $GLOBALS['SOAP_DEBUG']; | ||
| 168 | + parent::PEAR('SOAP_Fault'); | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + /** | ||
| 172 | + * Raises a SOAP error. | ||
| 173 | + * | ||
| 174 | + * Please refer to the SOAP definition for an impression of what a certain | ||
| 175 | + * parameter stands for. | ||
| 176 | + * | ||
| 177 | + * Use $debug_flag to store errors to the member variable $debug_data | ||
| 178 | + * | ||
| 179 | + * @see $debug_flag, $debug_data, SOAP_Fault | ||
| 180 | + * | ||
| 181 | + * @param string|object $str Error message or object. | ||
| 182 | + * @param string $detail Detailed error message. | ||
| 183 | + * @param string $actorURI | ||
| 184 | + * @param mixed $code | ||
| 185 | + * @param mixed $mode | ||
| 186 | + * @param mixed $options | ||
| 187 | + * @param boolean $skipmsg | ||
| 188 | + */ | ||
| 189 | + function &_raiseSoapFault($str, $detail = '', $actorURI = '', $code = null, | ||
| 190 | + $mode = null, $options = null, $skipmsg = false) | ||
| 191 | + { | ||
| 192 | + // Pass through previous faults. | ||
| 193 | + $is_instance = isset($this); | ||
| 194 | + if (is_object($str)) { | ||
| 195 | + $fault =& $str; | ||
| 196 | + } else { | ||
| 197 | + if (!$code) { | ||
| 198 | + $code = $is_instance ? $this->_myfaultcode : 'Client'; | ||
| 199 | + } | ||
| 200 | + $fault =& new SOAP_Fault($str, | ||
| 201 | + $code, | ||
| 202 | + $actorURI, | ||
| 203 | + $detail, | ||
| 204 | + $mode, | ||
| 205 | + $options); | ||
| 206 | + } | ||
| 207 | + if ($is_instance) { | ||
| 208 | + $this->fault =& $fault; | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + return $fault; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + function __isfault() | ||
| 215 | + { | ||
| 216 | + return $this->fault != null; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + function &__getfault() | ||
| 220 | + { | ||
| 221 | + return $this->fault; | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + /** | ||
| 225 | + * Adds a string to the debug data. | ||
| 226 | + * | ||
| 227 | + * @param string $string Debugging message. | ||
| 228 | + */ | ||
| 229 | + function _debug($string) | ||
| 230 | + { | ||
| 231 | + if ($this->_debug_flag) { | ||
| 232 | + $this->_debug_data .= get_class($this) . ': ' . | ||
| 233 | + str_replace('>', ">\r\n", $string) . "\n"; | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +/** | ||
| 240 | + * Common base class of all SOAP classes. | ||
| 241 | + * | ||
| 242 | + * @access public | ||
| 243 | + * @package SOAP | ||
| 244 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 245 | + */ | ||
| 246 | +class SOAP_Base extends SOAP_Base_Object | ||
| 247 | +{ | ||
| 248 | + var $_XMLSchema = array('http://www.w3.org/2001/XMLSchema', | ||
| 249 | + 'http://www.w3.org/1999/XMLSchema'); | ||
| 250 | + var $_XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; | ||
| 251 | + | ||
| 252 | + // load types into typemap array | ||
| 253 | + var $_typemap = array( | ||
| 254 | + 'http://www.w3.org/2001/XMLSchema' => array( | ||
| 255 | + 'string' => 'string', | ||
| 256 | + 'boolean' => 'boolean', | ||
| 257 | + 'float' => FLOAT, | ||
| 258 | + 'double' => FLOAT, | ||
| 259 | + 'decimal' => FLOAT, | ||
| 260 | + 'duration' => 'integer', | ||
| 261 | + 'dateTime' => 'string', | ||
| 262 | + 'time' => 'string', | ||
| 263 | + 'date' => 'string', | ||
| 264 | + 'gYearMonth' => 'integer', | ||
| 265 | + 'gYear' => 'integer', | ||
| 266 | + 'gMonthDay' => 'integer', | ||
| 267 | + 'gDay' => 'integer', | ||
| 268 | + 'gMonth' => 'integer', | ||
| 269 | + 'hexBinary' => 'string', | ||
| 270 | + 'base64Binary' => 'string', | ||
| 271 | + // derived datatypes | ||
| 272 | + 'normalizedString' => 'string', | ||
| 273 | + 'token' => 'string', | ||
| 274 | + 'language' => 'string', | ||
| 275 | + 'NMTOKEN' => 'string', | ||
| 276 | + 'NMTOKENS' => 'string', | ||
| 277 | + 'Name' => 'string', | ||
| 278 | + 'NCName' => 'string', | ||
| 279 | + 'ID' => 'string', | ||
| 280 | + 'IDREF' => 'string', | ||
| 281 | + 'IDREFS' => 'string', | ||
| 282 | + 'ENTITY' => 'string', | ||
| 283 | + 'ENTITIES' => 'string', | ||
| 284 | + 'integer' => 'integer', | ||
| 285 | + 'nonPositiveInteger' => 'integer', | ||
| 286 | + 'negativeInteger' => 'integer', | ||
| 287 | + 'long' => 'integer', | ||
| 288 | + 'int' => 'integer', | ||
| 289 | + 'short' => 'integer', | ||
| 290 | + 'byte' => 'string', | ||
| 291 | + 'nonNegativeInteger' => 'integer', | ||
| 292 | + 'unsignedLong' => 'integer', | ||
| 293 | + 'unsignedInt' => 'integer', | ||
| 294 | + 'unsignedShort' => 'integer', | ||
| 295 | + 'unsignedByte' => 'integer', | ||
| 296 | + 'positiveInteger' => 'integer', | ||
| 297 | + 'anyType' => 'string', | ||
| 298 | + 'anyURI' => 'string', | ||
| 299 | + 'QName' => 'string' | ||
| 300 | + ), | ||
| 301 | + 'http://www.w3.org/1999/XMLSchema' => array( | ||
| 302 | + 'i4' => 'integer', | ||
| 303 | + 'int' => 'integer', | ||
| 304 | + 'boolean' => 'boolean', | ||
| 305 | + 'string' => 'string', | ||
| 306 | + 'double' => FLOAT, | ||
| 307 | + 'float' => FLOAT, | ||
| 308 | + 'dateTime' => 'string', | ||
| 309 | + 'timeInstant' => 'string', | ||
| 310 | + 'base64Binary' => 'string', | ||
| 311 | + 'base64' => 'string', | ||
| 312 | + 'ur-type' => 'string' | ||
| 313 | + ), | ||
| 314 | + 'http://schemas.xmlsoap.org/soap/encoding/' => array( | ||
| 315 | + 'base64' => 'string', | ||
| 316 | + 'array' => 'array', | ||
| 317 | + 'Array' => 'array', | ||
| 318 | + 'Struct' => 'array') | ||
| 319 | + ); | ||
| 320 | + | ||
| 321 | + /** | ||
| 322 | + * Default class name to use for decoded response objects. | ||
| 323 | + * | ||
| 324 | + * @var string $_defaultObjectClassname | ||
| 325 | + */ | ||
| 326 | + var $_defaultObjectClassname = 'stdClass'; | ||
| 327 | + | ||
| 328 | + // Load namespace URIs into an array of URI => prefix. | ||
| 329 | + var $_namespaces; | ||
| 330 | + var $_namespace; | ||
| 331 | + | ||
| 332 | + var $_xmlEntities = array('&' => '&', | ||
| 333 | + '<' => '<', | ||
| 334 | + '>' => '>', | ||
| 335 | + "'" => ''', | ||
| 336 | + '"' => '"'); | ||
| 337 | + | ||
| 338 | + var $_doconversion = false; | ||
| 339 | + | ||
| 340 | + var $__attachments = array(); | ||
| 341 | + | ||
| 342 | + var $_wsdl = null; | ||
| 343 | + | ||
| 344 | + /** | ||
| 345 | + * True if we use section 5 encoding, or false if this is literal. | ||
| 346 | + * | ||
| 347 | + * @var boolean $_section5 | ||
| 348 | + */ | ||
| 349 | + var $_section5 = true; | ||
| 350 | + | ||
| 351 | + // Handle type to class mapping. | ||
| 352 | + var $_auto_translation = false; | ||
| 353 | + var $_type_translation = array(); | ||
| 354 | + | ||
| 355 | + /** | ||
| 356 | + * Constructor. | ||
| 357 | + * | ||
| 358 | + * @see $debug_data, _debug() | ||
| 359 | + * | ||
| 360 | + * @param string $faultcode Error code. | ||
| 361 | + */ | ||
| 362 | + function SOAP_Base($faultcode = 'Client') | ||
| 363 | + { | ||
| 364 | + parent::SOAP_Base_Object($faultcode); | ||
| 365 | + $this->_resetNamespaces(); | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + function _resetNamespaces() | ||
| 369 | + { | ||
| 370 | + $this->_namespaces = array( | ||
| 371 | + 'http://schemas.xmlsoap.org/soap/envelope/' => 'SOAP-ENV', | ||
| 372 | + 'http://www.w3.org/2001/XMLSchema' => 'xsd', | ||
| 373 | + 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', | ||
| 374 | + 'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC'); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + /** | ||
| 378 | + * Sets the schema version used in the SOAP message. | ||
| 379 | + * | ||
| 380 | + * @access private | ||
| 381 | + * @see $_XMLSchema | ||
| 382 | + * | ||
| 383 | + * @param string $schemaVersion The schema version. | ||
| 384 | + */ | ||
| 385 | + function _setSchemaVersion($schemaVersion) | ||
| 386 | + { | ||
| 387 | + if (!in_array($schemaVersion, $this->_XMLSchema)) { | ||
| 388 | + return $this->_raiseSoapFault("unsuported XMLSchema $schemaVersion"); | ||
| 389 | + } | ||
| 390 | + $this->_XMLSchemaVersion = $schemaVersion; | ||
| 391 | + $tmpNS = array_flip($this->_namespaces); | ||
| 392 | + $tmpNS['xsd'] = $this->_XMLSchemaVersion; | ||
| 393 | + $tmpNS['xsi'] = $this->_XMLSchemaVersion . '-instance'; | ||
| 394 | + $this->_namespaces = array_flip($tmpNS); | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + function _getNamespacePrefix($ns) | ||
| 398 | + { | ||
| 399 | + if ($this->_namespace && $ns == $this->_namespace) { | ||
| 400 | + return ''; | ||
| 401 | + } | ||
| 402 | + if (isset($this->_namespaces[$ns])) { | ||
| 403 | + return $this->_namespaces[$ns]; | ||
| 404 | + } | ||
| 405 | + $prefix = 'ns' . count($this->_namespaces); | ||
| 406 | + $this->_namespaces[$ns] = $prefix; | ||
| 407 | + return $prefix; | ||
| 408 | + } | ||
| 409 | + | ||
| 410 | + function _getNamespaceForPrefix($prefix) | ||
| 411 | + { | ||
| 412 | + $flipped = array_flip($this->_namespaces); | ||
| 413 | + if (isset($flipped[$prefix])) { | ||
| 414 | + return $flipped[$prefix]; | ||
| 415 | + } | ||
| 416 | + return null; | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + function _isSoapValue(&$value) | ||
| 420 | + { | ||
| 421 | + return is_a($value, 'SOAP_Value'); | ||
| 422 | + } | ||
| 423 | + | ||
| 424 | + function _serializeValue(&$value, $name = '', $type = false, | ||
| 425 | + $elNamespace = null, $typeNamespace = null, | ||
| 426 | + $options = array(), $attributes = array(), | ||
| 427 | + $artype = '') | ||
| 428 | + { | ||
| 429 | + $namespaces = array(); | ||
| 430 | + $arrayType = $array_depth = $xmlout_value = null; | ||
| 431 | + $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = ''; | ||
| 432 | + $xmlout_type = $xmlns = $ptype = $array_type_ns = ''; | ||
| 433 | + | ||
| 434 | + if (!$name || is_numeric($name)) { | ||
| 435 | + $name = 'item'; | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + if ($this->_wsdl) { | ||
| 439 | + list($ptype, $arrayType, $array_type_ns, $array_depth) | ||
| 440 | + = $this->_wsdl->getSchemaType($type, $name, $typeNamespace); | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | + if (!$arrayType) { | ||
| 444 | + $arrayType = $artype; | ||
| 445 | + } | ||
| 446 | + if (!$ptype) { | ||
| 447 | + $ptype = $this->_getType($value); | ||
| 448 | + } | ||
| 449 | + if (!$type) { | ||
| 450 | + $type = $ptype; | ||
| 451 | + } | ||
| 452 | + | ||
| 453 | + if (strcasecmp($ptype, 'Struct') == 0 || | ||
| 454 | + strcasecmp($type, 'Struct') == 0) { | ||
| 455 | + // Struct | ||
| 456 | + $vars = null; | ||
| 457 | + if (is_object($value)) { | ||
| 458 | + $vars = get_object_vars($value); | ||
| 459 | + } else { | ||
| 460 | + $vars = &$value; | ||
| 461 | + } | ||
| 462 | + if (is_array($vars)) { | ||
| 463 | + foreach (array_keys($vars) as $k) { | ||
| 464 | + // Hide private vars. | ||
| 465 | + if ($k[0] == '_') continue; | ||
| 466 | + if (is_object($vars[$k])) { | ||
| 467 | + if (is_a($vars[$k], 'SOAP_Value')) { | ||
| 468 | + $xmlout_value .= $vars[$k]->serialize($this); | ||
| 469 | + } else { | ||
| 470 | + // XXX get the members and serialize them instead | ||
| 471 | + // converting to an array is more overhead than we | ||
| 472 | + // should really do. | ||
| 473 | + $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), $k, false, $this->_section5 ? null : $elNamespace); | ||
| 474 | + } | ||
| 475 | + } else { | ||
| 476 | + $xmlout_value .= $this->_serializeValue($vars[$k], $k, false, $this->_section5 ? null : $elNamespace); | ||
| 477 | + } | ||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + } elseif (strcasecmp($ptype, 'Array') == 0 || | ||
| 481 | + strcasecmp($type, 'Array') == 0) { | ||
| 482 | + // Array. | ||
| 483 | + $typeNamespace = SOAP_SCHEMA_ENCODING; | ||
| 484 | + $orig_type = $type; | ||
| 485 | + $type = 'Array'; | ||
| 486 | + $numtypes = 0; | ||
| 487 | + // XXX this will be slow on larger arrays. Basically, it flattens | ||
| 488 | + // arrays to allow us to serialize multi-dimensional arrays. We | ||
| 489 | + // only do this if arrayType is set, which will typically only | ||
| 490 | + // happen if we are using WSDL | ||
| 491 | + if (isset($options['flatten']) || | ||
| 492 | + ($arrayType && | ||
| 493 | + (strchr($arrayType, ',') || strstr($arrayType, '][')))) { | ||
| 494 | + $numtypes = $this->_multiArrayType($value, $arrayType, | ||
| 495 | + $ar_size, $xmlout_value); | ||
| 496 | + } | ||
| 497 | + | ||
| 498 | + $array_type = $array_type_prefix = ''; | ||
| 499 | + if ($numtypes != 1) { | ||
| 500 | + $arrayTypeQName =& new QName($arrayType); | ||
| 501 | + $arrayType = $arrayTypeQName->name; | ||
| 502 | + $array_types = array(); | ||
| 503 | + $array_val = null; | ||
| 504 | + | ||
| 505 | + // Serialize each array element. | ||
| 506 | + $ar_size = count($value); | ||
| 507 | + foreach ($value as $array_val) { | ||
| 508 | + if ($this->_isSoapValue($array_val)) { | ||
| 509 | + $array_type = $array_val->type; | ||
| 510 | + $array_types[$array_type] = 1; | ||
| 511 | + $array_type_ns = $array_val->type_namespace; | ||
| 512 | + $xmlout_value .= $array_val->serialize($this); | ||
| 513 | + } else { | ||
| 514 | + $array_type = $this->_getType($array_val); | ||
| 515 | + $array_types[$array_type] = 1; | ||
| 516 | + $xmlout_value .= $this->_serializeValue($array_val, 'item', $array_type, $this->_section5 ? null : $elNamespace); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + | ||
| 520 | + $xmlout_offset = ' SOAP-ENC:offset="[0]"'; | ||
| 521 | + if (!$arrayType) { | ||
| 522 | + /* | ||
| 523 | + $numtypes = count($array_types); | ||
| 524 | + if ($numtypes == 1) { | ||
| 525 | + $arrayType = $array_type; | ||
| 526 | + } | ||
| 527 | + */ | ||
| 528 | + // Using anyType is more interoperable. | ||
| 529 | + if ($array_type == 'Struct') { | ||
| 530 | + $array_type = ''; | ||
| 531 | + } elseif ($array_type == 'Array') { | ||
| 532 | + $arrayType = 'anyType'; | ||
| 533 | + $array_type_prefix = 'xsd'; | ||
| 534 | + } else { | ||
| 535 | + if (!$arrayType) { | ||
| 536 | + $arrayType = $array_type; | ||
| 537 | + } | ||
| 538 | + } | ||
| 539 | + } | ||
| 540 | + } | ||
| 541 | + if (!$arrayType || $numtypes > 1) { | ||
| 542 | + // Should reference what schema we're using. | ||
| 543 | + $arrayType = 'xsd:anyType'; | ||
| 544 | + } else { | ||
| 545 | + if ($array_type_ns) { | ||
| 546 | + $array_type_prefix = $this->_getNamespacePrefix($array_type_ns); | ||
| 547 | + } elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) { | ||
| 548 | + $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; | ||
| 549 | + } | ||
| 550 | + if ($array_type_prefix) { | ||
| 551 | + $arrayType = $array_type_prefix . ':' . $arrayType; | ||
| 552 | + } | ||
| 553 | + } | ||
| 554 | + | ||
| 555 | + $xmlout_arrayType = ' SOAP-ENC:arrayType="' . $arrayType; | ||
| 556 | + if ($array_depth != null) { | ||
| 557 | + for ($i = 0; $i < $array_depth; $i++) { | ||
| 558 | + $xmlout_arrayType .= '[]'; | ||
| 559 | + } | ||
| 560 | + } | ||
| 561 | + $xmlout_arrayType .= "[$ar_size]\""; | ||
| 562 | + } elseif ($this->_isSoapValue($value)) { | ||
| 563 | + $xmlout_value = $value->serialize($this); | ||
| 564 | + } elseif ($type == 'string') { | ||
| 565 | + $xmlout_value = htmlspecialchars($value); | ||
| 566 | + } elseif ($type == 'rawstring') { | ||
| 567 | + $xmlout_value =& $value; | ||
| 568 | + } elseif ($type == 'boolean') { | ||
| 569 | + $xmlout_value = $value ? 'true' : 'false'; | ||
| 570 | + } else { | ||
| 571 | + $xmlout_value =& $value; | ||
| 572 | + } | ||
| 573 | + | ||
| 574 | + // Add namespaces. | ||
| 575 | + if ($elNamespace) { | ||
| 576 | + $elPrefix = $this->_getNamespacePrefix($elNamespace); | ||
| 577 | + if ($elPrefix) { | ||
| 578 | + $xmlout_name = "$elPrefix:$name"; | ||
| 579 | + } else { | ||
| 580 | + $xmlout_name = $name; | ||
| 581 | + } | ||
| 582 | + } else { | ||
| 583 | + $xmlout_name = $name; | ||
| 584 | + } | ||
| 585 | + | ||
| 586 | + if ($typeNamespace) { | ||
| 587 | + $typePrefix = $this->_getNamespacePrefix($typeNamespace); | ||
| 588 | + if ($typePrefix) { | ||
| 589 | + $xmlout_type = "$typePrefix:$type"; | ||
| 590 | + } else { | ||
| 591 | + $xmlout_type = $type; | ||
| 592 | + } | ||
| 593 | + } elseif ($type && | ||
| 594 | + isset($this->_typemap[$this->_XMLSchemaVersion][$type])) { | ||
| 595 | + $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; | ||
| 596 | + if ($typePrefix) { | ||
| 597 | + $xmlout_type = "$typePrefix:$type"; | ||
| 598 | + } else { | ||
| 599 | + $xmlout_type = $type; | ||
| 600 | + } | ||
| 601 | + } | ||
| 602 | + | ||
| 603 | + // Handle additional attributes. | ||
| 604 | + $xml_attr = ''; | ||
| 605 | + if (count($attributes)) { | ||
| 606 | + foreach ($attributes as $k => $v) { | ||
| 607 | + $kqn =& new QName($k); | ||
| 608 | + $vqn =& new QName($v); | ||
| 609 | + $xml_attr .= ' ' . $kqn->fqn() . '="' . $vqn->fqn() . '"'; | ||
| 610 | + } | ||
| 611 | + } | ||
| 612 | + | ||
| 613 | + // Store the attachment for mime encoding. | ||
| 614 | + if (isset($options['attachment']) && | ||
| 615 | + !PEAR::isError($options['attachment'])) { | ||
| 616 | + $this->__attachments[] = $options['attachment']; | ||
| 617 | + } | ||
| 618 | + | ||
| 619 | + if ($this->_section5) { | ||
| 620 | + if ($xmlout_type) { | ||
| 621 | + $xmlout_type = " xsi:type=\"$xmlout_type\""; | ||
| 622 | + } | ||
| 623 | + if (is_null($xmlout_value)) { | ||
| 624 | + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . | ||
| 625 | + "$xml_attr xsi:nil=\"true\"/>"; | ||
| 626 | + } else { | ||
| 627 | + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . | ||
| 628 | + "$xmlout_offset$xml_attr>$xmlout_value</$xmlout_name>"; | ||
| 629 | + } | ||
| 630 | + } else { | ||
| 631 | + if (is_null($xmlout_value)) { | ||
| 632 | + $xml = "\r\n<$xmlout_name$xmlns$xml_attr/>"; | ||
| 633 | + } else { | ||
| 634 | + $xml = "\r\n<$xmlout_name$xmlns$xml_attr>" . | ||
| 635 | + $xmlout_value . "</$xmlout_name>"; | ||
| 636 | + } | ||
| 637 | + } | ||
| 638 | + | ||
| 639 | + return $xml; | ||
| 640 | + } | ||
| 641 | + | ||
| 642 | + /** | ||
| 643 | + * Converts a PHP type to a SOAP type. | ||
| 644 | + * | ||
| 645 | + * @access private | ||
| 646 | + * | ||
| 647 | + * @param string $value The value to inspect. | ||
| 648 | + * | ||
| 649 | + * @return string The value's SOAP type. | ||
| 650 | + */ | ||
| 651 | + function _getType(&$value) | ||
| 652 | + { | ||
| 653 | + global $SOAP_OBJECT_STRUCT, $SOAP_RAW_CONVERT; | ||
| 654 | + | ||
| 655 | + $type = gettype($value); | ||
| 656 | + switch ($type) { | ||
| 657 | + case 'object': | ||
| 658 | + if (is_a($value, 'soap_value')) { | ||
| 659 | + $type = $value->type; | ||
| 660 | + } else { | ||
| 661 | + $type = 'Struct'; | ||
| 662 | + } | ||
| 663 | + break; | ||
| 664 | + | ||
| 665 | + case 'array': | ||
| 666 | + // Hashes are always handled as structs. | ||
| 667 | + if ($this->_isHash($value)) { | ||
| 668 | + $type = 'Struct'; | ||
| 669 | + } else { | ||
| 670 | + $ar_size = count($value); | ||
| 671 | + reset($value); | ||
| 672 | + $key1 = key($value); | ||
| 673 | + if ($ar_size > 0 && is_a($key1, 'SOAP_Value')) { | ||
| 674 | + // FIXME: for non-wsdl structs that are all the same type | ||
| 675 | + $key2 = key($value); | ||
| 676 | + if ($ar_size > 1 && | ||
| 677 | + $this->_isSoapValue($key1) && | ||
| 678 | + $this->_isSoapValue($key2) && | ||
| 679 | + $key1->name != $key2->name) { | ||
| 680 | + // This is a struct, not an array. | ||
| 681 | + $type = 'Struct'; | ||
| 682 | + } else { | ||
| 683 | + $type = 'Array'; | ||
| 684 | + } | ||
| 685 | + } else { | ||
| 686 | + $type = 'Array'; | ||
| 687 | + } | ||
| 688 | + } | ||
| 689 | + break; | ||
| 690 | + | ||
| 691 | + case 'integer': | ||
| 692 | + case 'long': | ||
| 693 | + $type = 'int'; | ||
| 694 | + break; | ||
| 695 | + | ||
| 696 | + case 'boolean': | ||
| 697 | + break; | ||
| 698 | + | ||
| 699 | + case 'double': | ||
| 700 | + // double is deprecated in PHP 4.2 and later. | ||
| 701 | + $type = 'float'; | ||
| 702 | + break; | ||
| 703 | + | ||
| 704 | + case 'null': | ||
| 705 | + $type = ''; | ||
| 706 | + break; | ||
| 707 | + | ||
| 708 | + case 'string': | ||
| 709 | + if ($SOAP_RAW_CONVERT) { | ||
| 710 | + if (is_numeric($value)) { | ||
| 711 | + if (strstr($value, '.')) { | ||
| 712 | + $type = 'float'; | ||
| 713 | + } else { | ||
| 714 | + $type = 'int'; | ||
| 715 | + } | ||
| 716 | + } else { | ||
| 717 | + if (SOAP_Type_hexBinary::is_hexbin($value)) { | ||
| 718 | + $type = 'hexBinary'; | ||
| 719 | + } else { | ||
| 720 | + if ($this->_isBase64($value)) { | ||
| 721 | + $type = 'base64Binary'; | ||
| 722 | + } else { | ||
| 723 | + $dt =& new SOAP_Type_dateTime($value); | ||
| 724 | + if ($dt->toUnixtime() != -1) { | ||
| 725 | + $type = 'dateTime'; | ||
| 726 | + } | ||
| 727 | + } | ||
| 728 | + } | ||
| 729 | + } | ||
| 730 | + } | ||
| 731 | + break; | ||
| 732 | + | ||
| 733 | + default: | ||
| 734 | + break; | ||
| 735 | + } | ||
| 736 | + | ||
| 737 | + return $type; | ||
| 738 | + } | ||
| 739 | + | ||
| 740 | + function _multiArrayType(&$value, &$type, &$size, &$xml) | ||
| 741 | + { | ||
| 742 | + $sz = count($value); | ||
| 743 | + if (is_array($value)) { | ||
| 744 | + // Seems we have a multi dimensional array, figure it out if we | ||
| 745 | + // do. | ||
| 746 | + $c = count($value); | ||
| 747 | + for ($i = 0; $i < $c; $i++) { | ||
| 748 | + $this->_multiArrayType($value[$i], $type, $size, $xml); | ||
| 749 | + } | ||
| 750 | + | ||
| 751 | + if ($size) { | ||
| 752 | + $size = $sz. ',' . $size; | ||
| 753 | + } else { | ||
| 754 | + $size = $sz; | ||
| 755 | + } | ||
| 756 | + | ||
| 757 | + return 1; | ||
| 758 | + } else { | ||
| 759 | + if (is_object($value)) { | ||
| 760 | + $type = $value->type; | ||
| 761 | + $xml .= $value->serialize($this); | ||
| 762 | + } else { | ||
| 763 | + $type = $this->_getType($value); | ||
| 764 | + $xml .= $this->_serializeValue($value, 'item', $type); | ||
| 765 | + } | ||
| 766 | + } | ||
| 767 | + $size = null; | ||
| 768 | + | ||
| 769 | + return 1; | ||
| 770 | + } | ||
| 771 | + | ||
| 772 | + /** | ||
| 773 | + * Returns whether a string is base64 encoded data. | ||
| 774 | + * | ||
| 775 | + * @param string $value The string to check. | ||
| 776 | + * | ||
| 777 | + * @return boolean True if the specified value seems to be base64 encoded. | ||
| 778 | + */ | ||
| 779 | + function _isBase64(&$value) | ||
| 780 | + { | ||
| 781 | + $l = strlen($value); | ||
| 782 | + if ($l) { | ||
| 783 | + return $value[$l - 1] == '=' && | ||
| 784 | + preg_match('/[A-Za-z=\/\+]+/', $value); | ||
| 785 | + } | ||
| 786 | + return false; | ||
| 787 | + } | ||
| 788 | + | ||
| 789 | + /** | ||
| 790 | + * Returns whether a type is a base64 type. | ||
| 791 | + * | ||
| 792 | + * @param string $type A type name. | ||
| 793 | + * | ||
| 794 | + * @return boolean True if the type name is a base64 type. | ||
| 795 | + */ | ||
| 796 | + function _isBase64Type($type) | ||
| 797 | + { | ||
| 798 | + return $type == 'base64' || $type == 'base64Binary'; | ||
| 799 | + } | ||
| 800 | + | ||
| 801 | + /** | ||
| 802 | + * Returns whether an array is a hash. | ||
| 803 | + * | ||
| 804 | + * @param array $a An array to check. | ||
| 805 | + * | ||
| 806 | + * @return boolean True if the specified array is a hash. | ||
| 807 | + */ | ||
| 808 | + function _isHash(&$a) | ||
| 809 | + { | ||
| 810 | + // I really dislike having to loop through this in PHP code, really | ||
| 811 | + // large arrays will be slow. We need a C function to do this. | ||
| 812 | + $names = array(); | ||
| 813 | + $it = 0; | ||
| 814 | + foreach ($a as $k => $v) { | ||
| 815 | + // Checking the type is faster than regexp. | ||
| 816 | + $t = gettype($k); | ||
| 817 | + if ($t != 'integer') { | ||
| 818 | + return true; | ||
| 819 | + } elseif ($this->_isSoapValue($v)) { | ||
| 820 | + $names[$v->name] = 1; | ||
| 821 | + } | ||
| 822 | + // If someone has a large hash they should really be defining the | ||
| 823 | + // type. | ||
| 824 | + if ($it++ > 10) { | ||
| 825 | + return false; | ||
| 826 | + } | ||
| 827 | + } | ||
| 828 | + return count($names)>1; | ||
| 829 | + } | ||
| 830 | + | ||
| 831 | + function _un_htmlentities($string) | ||
| 832 | + { | ||
| 833 | + $trans_tbl = get_html_translation_table(HTML_ENTITIES); | ||
| 834 | + $trans_tbl = array_flip($trans_tbl); | ||
| 835 | + return strtr($string, $trans_tbl); | ||
| 836 | + } | ||
| 837 | + | ||
| 838 | + function &_decode(&$soapval) | ||
| 839 | + { | ||
| 840 | + global $SOAP_OBJECT_STRUCT; | ||
| 841 | + | ||
| 842 | + if (!$this->_isSoapValue($soapval)) { | ||
| 843 | + return $soapval; | ||
| 844 | + } elseif (is_array($soapval->value)) { | ||
| 845 | + if ($SOAP_OBJECT_STRUCT && $soapval->type != 'Array') { | ||
| 846 | + $classname = $this->_defaultObjectClassname; | ||
| 847 | + if (isset($this->_type_translation[$soapval->tqn->fqn()])) { | ||
| 848 | + // This will force an error in PHP if the class does not | ||
| 849 | + // exist. | ||
| 850 | + $classname = $this->_type_translation[$soapval->tqn->fqn()]; | ||
| 851 | + } elseif (isset($this->_type_translation[$soapval->type])) { | ||
| 852 | + // This will force an error in PHP if the class does not | ||
| 853 | + // exist. | ||
| 854 | + $classname = $this->_type_translation[$soapval->type]; | ||
| 855 | + } elseif ($this->_auto_translation) { | ||
| 856 | + if (class_exists($soapval->type)) { | ||
| 857 | + $classname = $soapval->type; | ||
| 858 | + } elseif ($this->_wsdl) { | ||
| 859 | + $t = $this->_wsdl->getComplexTypeNameForElement($soapval->name, $soapval->namespace); | ||
| 860 | + if ($t && class_exists($t)) { | ||
| 861 | + $classname = $t; | ||
| 862 | + } | ||
| 863 | + } | ||
| 864 | + } | ||
| 865 | + $return =& new $classname; | ||
| 866 | + } else { | ||
| 867 | + $return = array(); | ||
| 868 | + } | ||
| 869 | + | ||
| 870 | + $counter = 1; | ||
| 871 | + $isstruct = !$SOAP_OBJECT_STRUCT || !is_array($return); | ||
| 872 | + foreach ($soapval->value as $item) { | ||
| 873 | + if (is_object($return)) { | ||
| 874 | + if ($this->_wsdl) { | ||
| 875 | + // Get this child's WSDL information. | ||
| 876 | + // /$soapval->ns/$soapval->type/$item->ns/$item->name | ||
| 877 | + $child_type = $this->_wsdl->getComplexTypeChildType( | ||
| 878 | + $soapval->namespace, | ||
| 879 | + $soapval->name, | ||
| 880 | + $item->namespace, | ||
| 881 | + $item->name); | ||
| 882 | + if ($child_type) { | ||
| 883 | + $item->type = $child_type; | ||
| 884 | + } | ||
| 885 | + } | ||
| 886 | + if (!$isstruct || $item->type == 'Array') { | ||
| 887 | + if (isset($return->{$item->name}) && | ||
| 888 | + is_object($return->{$item->name})) { | ||
| 889 | + $return->{$item->name} =& $this->_decode($item); | ||
| 890 | + } elseif (isset($return->{$item->name}) && | ||
| 891 | + is_array($return->{$item->name})) { | ||
| 892 | + $return->{$item->name}[] = $this->_decode($item); | ||
| 893 | + } elseif (is_array($return)) { | ||
| 894 | + $return[] =& $this->_decode($item); | ||
| 895 | + } else { | ||
| 896 | + $return->{$item->name} =& $this->_decode($item); | ||
| 897 | + } | ||
| 898 | + } elseif (isset($return->{$item->name})) { | ||
| 899 | + $isstruct = false; | ||
| 900 | + if (count(get_object_vars($return)) == 1) { | ||
| 901 | + $d =& $this->_decode($item); | ||
| 902 | + $return = array($return->{$item->name}, $d); | ||
| 903 | + } else { | ||
| 904 | + $d =& $this->_decode($item); | ||
| 905 | + $return->{$item->name} = array($return->{$item->name}, $d); | ||
| 906 | + } | ||
| 907 | + } else { | ||
| 908 | + $return->{$item->name} =& $this->_decode($item); | ||
| 909 | + } | ||
| 910 | + // Set the attributes as members in the class. | ||
| 911 | + if (method_exists($return, '__set_attribute')) { | ||
| 912 | + foreach ($soapval->attributes as $key => $value) { | ||
| 913 | + call_user_func_array(array(&$return, | ||
| 914 | + '__set_attribute'), | ||
| 915 | + array($key, $value)); | ||
| 916 | + } | ||
| 917 | + } | ||
| 918 | + } else { | ||
| 919 | + if ($soapval->arrayType && $this->_isSoapValue($item)) { | ||
| 920 | + if ($this->_isBase64Type($item->type) && | ||
| 921 | + !$this->_isBase64Type($soapval->arrayType)) { | ||
| 922 | + // Decode the value if we're losing the base64 | ||
| 923 | + // type information. | ||
| 924 | + $item->value = base64_decode($item->value); | ||
| 925 | + } | ||
| 926 | + $item->type = $soapval->arrayType; | ||
| 927 | + } | ||
| 928 | + if (!$isstruct) { | ||
| 929 | + $return[] = $this->_decode($item); | ||
| 930 | + } elseif (isset($return[$item->name])) { | ||
| 931 | + $isstruct = false; | ||
| 932 | + $d =& $this->_decode($item); | ||
| 933 | + $return = array($return[$item->name], $d); | ||
| 934 | + } else { | ||
| 935 | + $return[$item->name] = $this->_decode($item); | ||
| 936 | + } | ||
| 937 | + } | ||
| 938 | + } | ||
| 939 | + | ||
| 940 | + return $return; | ||
| 941 | + } | ||
| 942 | + | ||
| 943 | + if ($soapval->type == 'boolean') { | ||
| 944 | + if ($soapval->value != '0' && | ||
| 945 | + strcasecmp($soapval->value, 'false') != 0) { | ||
| 946 | + $soapval->value = true; | ||
| 947 | + } else { | ||
| 948 | + $soapval->value = false; | ||
| 949 | + } | ||
| 950 | + } elseif ($soapval->type && | ||
| 951 | + isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type])) { | ||
| 952 | + // If we can, set variable type. | ||
| 953 | + settype($soapval->value, | ||
| 954 | + $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); | ||
| 955 | + } | ||
| 956 | + | ||
| 957 | + if ($this->_isBase64Type($soapval->type)) { | ||
| 958 | + return base64_decode($soapval->value); | ||
| 959 | + } else { | ||
| 960 | + return $soapval->value; | ||
| 961 | + } | ||
| 962 | + } | ||
| 963 | + | ||
| 964 | + /** | ||
| 965 | + * Creates the SOAP envelope with the SOAP envelop data. | ||
| 966 | + * | ||
| 967 | + * @access private | ||
| 968 | + * | ||
| 969 | + * @param | ||
| 970 | + * @param array $headers | ||
| 971 | + * @param string $encoding | ||
| 972 | + * @param array $options | ||
| 973 | + * | ||
| 974 | + * @return string | ||
| 975 | + */ | ||
| 976 | + function _makeEnvelope(&$method, &$headers, | ||
| 977 | + $encoding = SOAP_DEFAULT_ENCODING, | ||
| 978 | + $options = array()) | ||
| 979 | + { | ||
| 980 | + $smsg = $header_xml = $ns_string = ''; | ||
| 981 | + | ||
| 982 | + if ($headers) { | ||
| 983 | + $c = count($headers); | ||
| 984 | + for ($i = 0; $i < $c; $i++) { | ||
| 985 | + $header_xml .= $headers[$i]->serialize($this); | ||
| 986 | + } | ||
| 987 | + $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n"; | ||
| 988 | + } | ||
| 989 | + | ||
| 990 | + if (!isset($options['input']) || $options['input'] == 'parse') { | ||
| 991 | + if (is_array($method)) { | ||
| 992 | + $c = count($method); | ||
| 993 | + for ($i = 0; $i < $c; $i++) { | ||
| 994 | + $smsg .= $method[$i]->serialize($this); | ||
| 995 | + } | ||
| 996 | + } else { | ||
| 997 | + $smsg = $method->serialize($this); | ||
| 998 | + } | ||
| 999 | + } else { | ||
| 1000 | + $smsg = $method; | ||
| 1001 | + } | ||
| 1002 | + $body = "<SOAP-ENV:Body>\r\n" . $smsg . "\r\n</SOAP-ENV:Body>\r\n"; | ||
| 1003 | + | ||
| 1004 | + foreach ($this->_namespaces as $k => $v) { | ||
| 1005 | + $ns_string .= " xmlns:$v=\"$k\"\r\n"; | ||
| 1006 | + } | ||
| 1007 | + if ($this->_namespace) { | ||
| 1008 | + $ns_string .= " xmlns=\"{$this->_namespace}\"\r\n"; | ||
| 1009 | + } | ||
| 1010 | + | ||
| 1011 | + /* If 'use' == 'literal', we do not put in the encodingStyle. This is | ||
| 1012 | + * denoted by $this->_section5 being false. 'use' can be defined at a | ||
| 1013 | + * more granular level than we are dealing with here, so this does not | ||
| 1014 | + * work for all services. */ | ||
| 1015 | + $xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n". | ||
| 1016 | + "<SOAP-ENV:Envelope $ns_string". | ||
| 1017 | + ($this->_section5 ? ' SOAP-ENV:encodingStyle="' . SOAP_SCHEMA_ENCODING . '"' : ''). | ||
| 1018 | + ">\r\n". | ||
| 1019 | + "$header_xml$body</SOAP-ENV:Envelope>\r\n"; | ||
| 1020 | + | ||
| 1021 | + return $xml; | ||
| 1022 | + } | ||
| 1023 | + | ||
| 1024 | + function _makeMimeMessage(&$xml, $encoding = SOAP_DEFAULT_ENCODING) | ||
| 1025 | + { | ||
| 1026 | + global $SOAP_options; | ||
| 1027 | + | ||
| 1028 | + if (!isset($SOAP_options['Mime'])) { | ||
| 1029 | + return $this->_raiseSoapFault('Mime is not installed'); | ||
| 1030 | + } | ||
| 1031 | + | ||
| 1032 | + // Encode any attachments. | ||
| 1033 | + // See http://www.w3.org/TR/SOAP-attachments | ||
| 1034 | + // Now we have to mime encode the message. | ||
| 1035 | + $params = array('content_type' => 'multipart/related; type=text/xml'); | ||
| 1036 | + $msg =& new Mail_mimePart('', $params); | ||
| 1037 | + | ||
| 1038 | + // Add the xml part. | ||
| 1039 | + $params['content_type'] = 'text/xml'; | ||
| 1040 | + $params['charset'] = $encoding; | ||
| 1041 | + $params['encoding'] = 'base64'; | ||
| 1042 | + $msg->addSubPart($xml, $params); | ||
| 1043 | + | ||
| 1044 | + // Add the attachements | ||
| 1045 | + $c = count($this->__attachments); | ||
| 1046 | + for ($i = 0; $i < $c; $i++) { | ||
| 1047 | + $attachment =& $this->__attachments[$i]; | ||
| 1048 | + $msg->addSubPart($attachment['body'], $attachment); | ||
| 1049 | + } | ||
| 1050 | + | ||
| 1051 | + return $msg->encode(); | ||
| 1052 | + } | ||
| 1053 | + | ||
| 1054 | + // TODO: this needs to be used from the Transport system. | ||
| 1055 | + function _makeDIMEMessage($xml) | ||
| 1056 | + { | ||
| 1057 | + global $SOAP_options; | ||
| 1058 | + | ||
| 1059 | + if (!isset($SOAP_options['DIME'])) { | ||
| 1060 | + return $this->_raiseSoapFault('DIME is not installed'); | ||
| 1061 | + } | ||
| 1062 | + | ||
| 1063 | + // Encode any attachments. | ||
| 1064 | + // See http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt | ||
| 1065 | + // Now we have to DIME encode the message | ||
| 1066 | + $dime =& new Net_DIME_Message(); | ||
| 1067 | + $msg = $dime->encodeData($xml, SOAP_ENVELOP, null, NET_DIME_TYPE_URI); | ||
| 1068 | + | ||
| 1069 | + // Add the attachments. | ||
| 1070 | + $c = count($this->__attachments); | ||
| 1071 | + for ($i = 0; $i < $c; $i++) { | ||
| 1072 | + $attachment =& $this->__attachments[$i]; | ||
| 1073 | + $msg .= $dime->encodeData($attachment['body'], | ||
| 1074 | + $attachment['content_type'], | ||
| 1075 | + $attachment['cid'], | ||
| 1076 | + NET_DIME_TYPE_MEDIA); | ||
| 1077 | + } | ||
| 1078 | + $msg .= $dime->endMessage(); | ||
| 1079 | + | ||
| 1080 | + return $msg; | ||
| 1081 | + } | ||
| 1082 | + | ||
| 1083 | + function _decodeMimeMessage(&$data, &$headers, &$attachments) | ||
| 1084 | + { | ||
| 1085 | + global $SOAP_options; | ||
| 1086 | + | ||
| 1087 | + if (!isset($SOAP_options['Mime'])) { | ||
| 1088 | + $this->_raiseSoapFault('Mime Unsupported, install PEAR::Mail::Mime', '', '', 'Server'); | ||
| 1089 | + return; | ||
| 1090 | + } | ||
| 1091 | + | ||
| 1092 | + $params['include_bodies'] = true; | ||
| 1093 | + $params['decode_bodies'] = true; | ||
| 1094 | + $params['decode_headers'] = true; | ||
| 1095 | + | ||
| 1096 | + // Lame thing to have to do for decoding. | ||
| 1097 | + $decoder =& new Mail_mimeDecode($data); | ||
| 1098 | + $structure = $decoder->decode($params); | ||
| 1099 | + | ||
| 1100 | + if (isset($structure->body)) { | ||
| 1101 | + $data = $structure->body; | ||
| 1102 | + $headers = $structure->headers; | ||
| 1103 | + | ||
| 1104 | + return; | ||
| 1105 | + } elseif (isset($structure->parts)) { | ||
| 1106 | + $data = $structure->parts[0]->body; | ||
| 1107 | + $headers = array_merge($structure->headers, | ||
| 1108 | + $structure->parts[0]->headers); | ||
| 1109 | + if (count($structure->parts) > 1) { | ||
| 1110 | + $mime_parts = array_splice($structure->parts,1); | ||
| 1111 | + // Prepare the parts for the SOAP parser. | ||
| 1112 | + | ||
| 1113 | + $c = count($mime_parts); | ||
| 1114 | + for ($i = 0; $i < $c; $i++) { | ||
| 1115 | + $p =& $mime_parts[$i]; | ||
| 1116 | + if (isset($p->headers['content-location'])) { | ||
| 1117 | + // TODO: modify location per SwA note section 3 | ||
| 1118 | + // http://www.w3.org/TR/SOAP-attachments | ||
| 1119 | + $attachments[$p->headers['content-location']] = $p->body; | ||
| 1120 | + } else { | ||
| 1121 | + $cid = 'cid:' . substr($p->headers['content-id'], 1, -1); | ||
| 1122 | + $attachments[$cid] = $p->body; | ||
| 1123 | + } | ||
| 1124 | + } | ||
| 1125 | + } | ||
| 1126 | + | ||
| 1127 | + return; | ||
| 1128 | + } | ||
| 1129 | + | ||
| 1130 | + $this->_raiseSoapFault('Mime parsing error', '', '', 'Server'); | ||
| 1131 | + } | ||
| 1132 | + | ||
| 1133 | + function _decodeDIMEMessage(&$data, &$headers, &$attachments) | ||
| 1134 | + { | ||
| 1135 | + global $SOAP_options; | ||
| 1136 | + | ||
| 1137 | + if (!isset($SOAP_options['DIME'])) { | ||
| 1138 | + $this->_raiseSoapFault('DIME Unsupported, install PEAR::Net::DIME', '', '', 'Server'); | ||
| 1139 | + return; | ||
| 1140 | + } | ||
| 1141 | + | ||
| 1142 | + // This SHOULD be moved to the transport layer, e.g. PHP itself should | ||
| 1143 | + // handle parsing DIME ;) | ||
| 1144 | + $dime =& new Net_DIME_Message(); | ||
| 1145 | + $err = $dime->decodeData($data); | ||
| 1146 | + if (PEAR::isError($err)) { | ||
| 1147 | + $this->_raiseSoapFault('Failed to decode the DIME message!', '', '', 'Server'); | ||
| 1148 | + return; | ||
| 1149 | + } | ||
| 1150 | + if (strcasecmp($dime->parts[0]['type'], SOAP_ENVELOP) != 0) { | ||
| 1151 | + $this->_raiseSoapFault('DIME record 1 is not a SOAP envelop!', '', '', 'Server'); | ||
| 1152 | + return; | ||
| 1153 | + } | ||
| 1154 | + | ||
| 1155 | + $data = $dime->parts[0]['data']; | ||
| 1156 | + // Fake it for now. | ||
| 1157 | + $headers['content-type'] = 'text/xml'; | ||
| 1158 | + $c = count($dime->parts); | ||
| 1159 | + for ($i = 0; $i < $c; $i++) { | ||
| 1160 | + $part =& $dime->parts[$i]; | ||
| 1161 | + // We need to handle URI's better. | ||
| 1162 | + $id = strncmp($part['id'], 'cid:', 4) | ||
| 1163 | + ? 'cid:' . $part['id'] | ||
| 1164 | + : $part['id']; | ||
| 1165 | + $attachments[$id] = $part['data']; | ||
| 1166 | + } | ||
| 1167 | + } | ||
| 1168 | + | ||
| 1169 | + function __set_type_translation($type, $class = null) | ||
| 1170 | + { | ||
| 1171 | + $tq =& new QName($type); | ||
| 1172 | + if (!$class) { | ||
| 1173 | + $class = $tq->name; | ||
| 1174 | + } | ||
| 1175 | + $this->_type_translation[$type]=$class; | ||
| 1176 | + } | ||
| 1177 | + | ||
| 1178 | +} | ||
| 1179 | + | ||
| 1180 | +/** | ||
| 1181 | + * Class used to handle QNAME values in XML. | ||
| 1182 | + * | ||
| 1183 | + * @access public | ||
| 1184 | + * @package SOAP | ||
| 1185 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 1186 | + */ | ||
| 1187 | +class QName | ||
| 1188 | +{ | ||
| 1189 | + var $name = ''; | ||
| 1190 | + var $ns = ''; | ||
| 1191 | + var $namespace=''; | ||
| 1192 | + | ||
| 1193 | + function QName($name, $namespace = '') | ||
| 1194 | + { | ||
| 1195 | + if ($name && $name[0] == '{') { | ||
| 1196 | + preg_match('/\{(.*?)\}(.*)/', $name, $m); | ||
| 1197 | + $this->name = $m[2]; | ||
| 1198 | + $this->namespace = $m[1]; | ||
| 1199 | + } elseif (substr_count($name, ':') == 1) { | ||
| 1200 | + $s = explode(':', $name); | ||
| 1201 | + $s = array_reverse($s); | ||
| 1202 | + $this->name = $s[0]; | ||
| 1203 | + $this->ns = $s[1]; | ||
| 1204 | + $this->namespace = $namespace; | ||
| 1205 | + } else { | ||
| 1206 | + $this->name = $name; | ||
| 1207 | + $this->namespace = $namespace; | ||
| 1208 | + } | ||
| 1209 | + | ||
| 1210 | + // A little more magic than should be in a qname. | ||
| 1211 | + $p = strpos($this->name, '['); | ||
| 1212 | + if ($p) { | ||
| 1213 | + // TODO: Need to re-examine this logic later. | ||
| 1214 | + // Chop off []. | ||
| 1215 | + $this->arraySize = explode(',', substr($this->name, $p + 1, -$p - 2)); | ||
| 1216 | + $this->arrayInfo = substr($this->name, $p); | ||
| 1217 | + $this->name = substr($this->name, 0, $p); | ||
| 1218 | + } | ||
| 1219 | + } | ||
| 1220 | + | ||
| 1221 | + function fqn() | ||
| 1222 | + { | ||
| 1223 | + if ($this->namespace) { | ||
| 1224 | + return '{' . $this->namespace . '}' . $this->name; | ||
| 1225 | + } elseif ($this->ns) { | ||
| 1226 | + return $this->ns . ':' . $this->name; | ||
| 1227 | + } | ||
| 1228 | + return $this->name; | ||
| 1229 | + } | ||
| 1230 | + | ||
| 1231 | +} |
thirdparty/pear/SOAP/Client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the SOAP client. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 19 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Value.php'; | ||
| 26 | +require_once 'SOAP/Base.php'; | ||
| 27 | +require_once 'SOAP/Transport.php'; | ||
| 28 | +require_once 'SOAP/WSDL.php'; | ||
| 29 | +require_once 'SOAP/Fault.php'; | ||
| 30 | +require_once 'SOAP/Parser.php'; | ||
| 31 | + | ||
| 32 | +// Arnaud: the following code was taken from DataObject and adapted to suit | ||
| 33 | + | ||
| 34 | +// this will be horrifically slow!!!! | ||
| 35 | +// NOTE: Overload SEGFAULTS ON PHP4 + Zend Optimizer | ||
| 36 | +// these two are BC/FC handlers for call in PHP4/5 | ||
| 37 | + | ||
| 38 | +if (!class_exists('SOAP_Client_Overload')) { | ||
| 39 | + if (substr(phpversion(), 0, 1) == 5) { | ||
| 40 | + class SOAP_Client_Overload extends SOAP_Base { | ||
| 41 | + function __call($method, $args) | ||
| 42 | + { | ||
| 43 | + $return = null; | ||
| 44 | + $this->_call($method, $args, $return); | ||
| 45 | + return $return; | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + } else { | ||
| 49 | + if (!function_exists('clone')) { | ||
| 50 | + eval('function clone($t) { return $t; }'); | ||
| 51 | + } | ||
| 52 | + eval(' | ||
| 53 | + class SOAP_Client_Overload extends SOAP_Base { | ||
| 54 | + function __call($method, $args, &$return) | ||
| 55 | + { | ||
| 56 | + return $this->_call($method, $args, $return); | ||
| 57 | + } | ||
| 58 | + }'); | ||
| 59 | + } | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +/** | ||
| 63 | + * SOAP Client Class | ||
| 64 | + * | ||
| 65 | + * This class is the main interface for making soap requests. | ||
| 66 | + * | ||
| 67 | + * basic usage:<code> | ||
| 68 | + * $soapclient = new SOAP_Client( string path [ , boolean wsdl] ); | ||
| 69 | + * echo $soapclient->call( string methodname [ , array parameters] ); | ||
| 70 | + * </code> | ||
| 71 | + * | ||
| 72 | + * Originally based on SOAPx4 by Dietrich Ayala | ||
| 73 | + * http://dietrich.ganx4.com/soapx4 | ||
| 74 | + * | ||
| 75 | + * @access public | ||
| 76 | + * @package SOAP | ||
| 77 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 78 | + * @author Stig Bakken <ssb@fast.no> Conversion to PEAR | ||
| 79 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 80 | + */ | ||
| 81 | +class SOAP_Client extends SOAP_Client_Overload | ||
| 82 | +{ | ||
| 83 | + /** | ||
| 84 | + * Communication endpoint. | ||
| 85 | + * | ||
| 86 | + * Currently the following transport formats are supported: | ||
| 87 | + * - HTTP | ||
| 88 | + * - SMTP | ||
| 89 | + * | ||
| 90 | + * Example endpoints: | ||
| 91 | + * http://www.example.com/soap/server.php | ||
| 92 | + * https://www.example.com/soap/server.php | ||
| 93 | + * mailto:soap@example.com | ||
| 94 | + * | ||
| 95 | + * @see SOAP_Client() | ||
| 96 | + * @var $_endpoint string | ||
| 97 | + */ | ||
| 98 | + var $_endpoint = ''; | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * The SOAP PORT name that is used by the client. | ||
| 102 | + * | ||
| 103 | + * @var $_portName string | ||
| 104 | + */ | ||
| 105 | + var $_portName = ''; | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * Endpoint type e.g. 'wdsl'. | ||
| 109 | + * | ||
| 110 | + * @var $__endpointType string | ||
| 111 | + */ | ||
| 112 | + var $__endpointType = ''; | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * The received xml. | ||
| 116 | + * | ||
| 117 | + * @var $xml string | ||
| 118 | + */ | ||
| 119 | + var $xml; | ||
| 120 | + | ||
| 121 | + /** | ||
| 122 | + * The outgoing and incoming data stream for debugging. | ||
| 123 | + * | ||
| 124 | + * @var $wire string | ||
| 125 | + */ | ||
| 126 | + var $wire; | ||
| 127 | + var $__last_request = null; | ||
| 128 | + var $__last_response = null; | ||
| 129 | + | ||
| 130 | + /** | ||
| 131 | + * Options. | ||
| 132 | + * | ||
| 133 | + * @var $__options array | ||
| 134 | + */ | ||
| 135 | + var $__options = array('trace'=>0); | ||
| 136 | + | ||
| 137 | + /** | ||
| 138 | + * The character encoding used for XML parser, etc. | ||
| 139 | + * | ||
| 140 | + * @var $_encoding string | ||
| 141 | + */ | ||
| 142 | + var $_encoding = SOAP_DEFAULT_ENCODING; | ||
| 143 | + | ||
| 144 | + /** | ||
| 145 | + * The array of SOAP_Headers that we are sending. | ||
| 146 | + * | ||
| 147 | + * @var $headersOut array | ||
| 148 | + */ | ||
| 149 | + var $headersOut = null; | ||
| 150 | + | ||
| 151 | + /** | ||
| 152 | + * The headers we recieved back in the response. | ||
| 153 | + * | ||
| 154 | + * @var $headersIn array | ||
| 155 | + */ | ||
| 156 | + var $headersIn = null; | ||
| 157 | + | ||
| 158 | + /** | ||
| 159 | + * Options for the HTTP_Request class (see HTTP/Request.php). | ||
| 160 | + * | ||
| 161 | + * @var $__proxy_params array | ||
| 162 | + */ | ||
| 163 | + var $__proxy_params = array(); | ||
| 164 | + | ||
| 165 | + var $_soap_transport = null; | ||
| 166 | + | ||
| 167 | + /** | ||
| 168 | + * Constructor. | ||
| 169 | + * | ||
| 170 | + * @access public | ||
| 171 | + * | ||
| 172 | + * @param string $endpoint An URL. | ||
| 173 | + * @param boolean $wsdl Whether the endpoint is a WSDL file. | ||
| 174 | + * @param string $portName | ||
| 175 | + * @param array $proxy_params Options for the HTTP_Request class (see | ||
| 176 | + * HTTP/Request.php) | ||
| 177 | + */ | ||
| 178 | + function SOAP_Client($endpoint, $wsdl = false, $portName = false, | ||
| 179 | + $proxy_params = array()) | ||
| 180 | + { | ||
| 181 | + parent::SOAP_Base('Client'); | ||
| 182 | + | ||
| 183 | + $this->_endpoint = $endpoint; | ||
| 184 | + $this->_portName = $portName; | ||
| 185 | + $this->__proxy_params = $proxy_params; | ||
| 186 | + | ||
| 187 | + // This hack should perhaps be removed as it might cause unexpected | ||
| 188 | + // behaviour. | ||
| 189 | + $wsdl = $wsdl | ||
| 190 | + ? $wsdl | ||
| 191 | + : strtolower(substr($endpoint, -4)) == 'wsdl'; | ||
| 192 | + | ||
| 193 | + // make values | ||
| 194 | + if ($wsdl) { | ||
| 195 | + $this->__endpointType = 'wsdl'; | ||
| 196 | + // instantiate wsdl class | ||
| 197 | + $this->_wsdl =& new SOAP_WSDL($this->_endpoint, | ||
| 198 | + $this->__proxy_params); | ||
| 199 | + if ($this->_wsdl->fault) { | ||
| 200 | + $this->_raiseSoapFault($this->_wsdl->fault); | ||
| 201 | + } | ||
| 202 | + } | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + function _reset() | ||
| 206 | + { | ||
| 207 | + $this->xml = null; | ||
| 208 | + $this->wire = null; | ||
| 209 | + $this->__last_request = null; | ||
| 210 | + $this->__last_response = null; | ||
| 211 | + $this->headersIn = null; | ||
| 212 | + $this->headersOut = null; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * Sets the character encoding. | ||
| 217 | + * | ||
| 218 | + * Limited to 'UTF-8', 'US_ASCII' and 'ISO-8859-1'. | ||
| 219 | + * | ||
| 220 | + * @access public | ||
| 221 | + * | ||
| 222 | + * @param string encoding | ||
| 223 | + * | ||
| 224 | + * @return mixed SOAP_Fault on error. | ||
| 225 | + */ | ||
| 226 | + function setEncoding($encoding) | ||
| 227 | + { | ||
| 228 | + if (in_array($encoding, $this->_encodings)) { | ||
| 229 | + $this->_encoding = $encoding; | ||
| 230 | + return; | ||
| 231 | + } | ||
| 232 | + return $this->_raiseSoapFault('Invalid Encoding'); | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + /** | ||
| 236 | + * Adds a header to the envelope. | ||
| 237 | + * | ||
| 238 | + * @access public | ||
| 239 | + * | ||
| 240 | + * @param SOAP_Header $soap_value A SOAP_Header or an array with the | ||
| 241 | + * elements 'name', 'namespace', | ||
| 242 | + * 'mustunderstand', and 'actor' to send | ||
| 243 | + * as a header. | ||
| 244 | + */ | ||
| 245 | + function addHeader(&$soap_value) | ||
| 246 | + { | ||
| 247 | + // Add a new header to the message. | ||
| 248 | + if (is_a($soap_value, 'SOAP_Header')) { | ||
| 249 | + $this->headersOut[] =& $soap_value; | ||
| 250 | + } elseif (is_array($soap_value)) { | ||
| 251 | + // name, value, namespace, mustunderstand, actor | ||
| 252 | + $this->headersOut[] =& new SOAP_Header($soap_value[0], | ||
| 253 | + null, | ||
| 254 | + $soap_value[1], | ||
| 255 | + $soap_value[2], | ||
| 256 | + $soap_value[3]);; | ||
| 257 | + } else { | ||
| 258 | + $this->_raiseSoapFault('Invalid parameter provided to addHeader(). Must be an array or a SOAP_Header.'); | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + /** | ||
| 263 | + * Calls a method on the SOAP endpoint. | ||
| 264 | + * | ||
| 265 | + * The namespace parameter is overloaded to accept an array of options | ||
| 266 | + * that can contain data necessary for various transports if it is used as | ||
| 267 | + * an array, it MAY contain a namespace value and a soapaction value. If | ||
| 268 | + * it is overloaded, the soapaction parameter is ignored and MUST be | ||
| 269 | + * placed in the options array. This is done to provide backwards | ||
| 270 | + * compatibility with current clients, but may be removed in the future. | ||
| 271 | + * The currently supported values are:<pre> | ||
| 272 | + * namespace | ||
| 273 | + * soapaction | ||
| 274 | + * timeout (HTTP socket timeout) | ||
| 275 | + * transfer-encoding (SMTP, Content-Transfer-Encoding: header) | ||
| 276 | + * from (SMTP, From: header) | ||
| 277 | + * subject (SMTP, Subject: header) | ||
| 278 | + * headers (SMTP, hash of extra SMTP headers) | ||
| 279 | + * </pre> | ||
| 280 | + * | ||
| 281 | + * @access public | ||
| 282 | + * | ||
| 283 | + * @param string $method The method to call. | ||
| 284 | + * @param array $params The method parameters. | ||
| 285 | + * @param string|array $namespace Namespace or hash with options. | ||
| 286 | + * @param string $soapAction | ||
| 287 | + * | ||
| 288 | + * @return mixed The method result or a SOAP_Fault on error. | ||
| 289 | + */ | ||
| 290 | + function &call($method, &$params, $namespace = false, $soapAction = false) | ||
| 291 | + { | ||
| 292 | + $this->headersIn = null; | ||
| 293 | + $this->__last_request = null; | ||
| 294 | + $this->__last_response = null; | ||
| 295 | + $this->wire = null; | ||
| 296 | + $this->xml = null; | ||
| 297 | + | ||
| 298 | + $soap_data =& $this->__generate($method, $params, $namespace, $soapAction); | ||
| 299 | + if (PEAR::isError($soap_data)) { | ||
| 300 | + $fault =& $this->_raiseSoapFault($soap_data); | ||
| 301 | + return $fault; | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + // __generate() may have changed the endpoint if the WSDL has more | ||
| 305 | + // than one service, so we need to see if we need to generate a new | ||
| 306 | + // transport to hook to a different URI. Since the transport protocol | ||
| 307 | + // can also change, we need to get an entirely new object. This could | ||
| 308 | + // probably be optimized. | ||
| 309 | + if (!$this->_soap_transport || | ||
| 310 | + $this->_endpoint != $this->_soap_transport->url) { | ||
| 311 | + $this->_soap_transport =& SOAP_Transport::getTransport($this->_endpoint); | ||
| 312 | + if (PEAR::isError($this->_soap_transport)) { | ||
| 313 | + $fault =& $this->_soap_transport; | ||
| 314 | + $this->_soap_transport = null; | ||
| 315 | + $fault =& $this->_raiseSoapFault($fault); | ||
| 316 | + return $fault; | ||
| 317 | + } | ||
| 318 | + } | ||
| 319 | + $this->_soap_transport->encoding = $this->_encoding; | ||
| 320 | + | ||
| 321 | + // Send the message. | ||
| 322 | + $transport_options = array_merge_recursive($this->__proxy_params, | ||
| 323 | + $this->__options); | ||
| 324 | + $this->xml = $this->_soap_transport->send($soap_data, $transport_options); | ||
| 325 | + | ||
| 326 | + // Save the wire information for debugging. | ||
| 327 | + if ($this->__options['trace'] > 0) { | ||
| 328 | + $this->__last_request =& $this->_soap_transport->outgoing_payload; | ||
| 329 | + $this->__last_response =& $this->_soap_transport->incoming_payload; | ||
| 330 | + $this->wire = $this->__get_wire(); | ||
| 331 | + } | ||
| 332 | + if ($this->_soap_transport->fault) { | ||
| 333 | + $fault =& $this->_raiseSoapFault($this->xml); | ||
| 334 | + return $fault; | ||
| 335 | + } | ||
| 336 | + | ||
| 337 | + $this->__attachments =& $this->_soap_transport->attachments; | ||
| 338 | + $this->__result_encoding = $this->_soap_transport->result_encoding; | ||
| 339 | + | ||
| 340 | + if (isset($this->__options['result']) && | ||
| 341 | + $this->__options['result'] != 'parse') { | ||
| 342 | + return $this->xml; | ||
| 343 | + } | ||
| 344 | + | ||
| 345 | + $result = &$this->__parse($this->xml, $this->__result_encoding, $this->__attachments); | ||
| 346 | + | ||
| 347 | + return $result; | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + /** | ||
| 351 | + * Sets an option to use with the transport layers. | ||
| 352 | + * | ||
| 353 | + * For example: | ||
| 354 | + * <code> | ||
| 355 | + * $soapclient->setOpt('curl', CURLOPT_VERBOSE, 1) | ||
| 356 | + * </code> | ||
| 357 | + * to pass a specific option to curl if using an SSL connection. | ||
| 358 | + * | ||
| 359 | + * @access public | ||
| 360 | + * | ||
| 361 | + * @param string $category Category to which the option applies or option | ||
| 362 | + * name. | ||
| 363 | + * @param string $option An option name if $category is a category name, | ||
| 364 | + * an option value if $category is an option name. | ||
| 365 | + * @param string $value An option value if $category is a category | ||
| 366 | + * name. | ||
| 367 | + */ | ||
| 368 | + function setOpt($category, $option, $value = null) | ||
| 369 | + { | ||
| 370 | + if (!is_null($value)) { | ||
| 371 | + if (!isset($this->__options[$category])) { | ||
| 372 | + $this->__options[$category] = array(); | ||
| 373 | + } | ||
| 374 | + $this->__options[$category][$option] = $value; | ||
| 375 | + } else { | ||
| 376 | + $this->__options[$category] = $option; | ||
| 377 | + } | ||
| 378 | + } | ||
| 379 | + | ||
| 380 | + /** | ||
| 381 | + * Call method supporting the overload extension. | ||
| 382 | + * | ||
| 383 | + * If the overload extension is loaded, you can call the client class with | ||
| 384 | + * a soap method name: | ||
| 385 | + * <code> | ||
| 386 | + * $soap = new SOAP_Client(....); | ||
| 387 | + * $value = $soap->getStockQuote('MSFT'); | ||
| 388 | + * </code> | ||
| 389 | + * | ||
| 390 | + * @access public | ||
| 391 | + * | ||
| 392 | + * @param string $method The method to call. | ||
| 393 | + * @param array $params The method parameters. | ||
| 394 | + * @param string $return_value Will get the method's return value | ||
| 395 | + * assigned. | ||
| 396 | + * | ||
| 397 | + * @return boolean Always true. | ||
| 398 | + */ | ||
| 399 | + function _call($method, $params, &$return_value) | ||
| 400 | + { | ||
| 401 | + // Overloading lowercases the method name, we need to look into the | ||
| 402 | + // wsdl and try to find the correct method name to get the correct | ||
| 403 | + // case for the call. | ||
| 404 | + if ($this->_wsdl) { | ||
| 405 | + $this->_wsdl->matchMethod($method); | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + $return_value =& $this->call($method, $params); | ||
| 409 | + | ||
| 410 | + return true; | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + function &__getlastrequest() | ||
| 414 | + { | ||
| 415 | + $request =& $this->__last_request; | ||
| 416 | + return $request; | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + function &__getlastresponse() | ||
| 420 | + { | ||
| 421 | + $response =& $this->__last_response; | ||
| 422 | + return $response; | ||
| 423 | + } | ||
| 424 | + | ||
| 425 | + function __use($use) | ||
| 426 | + { | ||
| 427 | + $this->__options['use'] = $use; | ||
| 428 | + } | ||
| 429 | + | ||
| 430 | + function __style($style) | ||
| 431 | + { | ||
| 432 | + $this->__options['style'] = $style; | ||
| 433 | + } | ||
| 434 | + | ||
| 435 | + function __trace($level) | ||
| 436 | + { | ||
| 437 | + $this->__options['trace'] = $level; | ||
| 438 | + } | ||
| 439 | + | ||
| 440 | + function &__generate($method, &$params, $namespace = false, | ||
| 441 | + $soapAction = false) | ||
| 442 | + { | ||
| 443 | + $this->fault = null; | ||
| 444 | + $this->__options['input']='parse'; | ||
| 445 | + $this->__options['result']='parse'; | ||
| 446 | + $this->__options['parameters'] = false; | ||
| 447 | + | ||
| 448 | + if ($params && gettype($params) != 'array') { | ||
| 449 | + $params = array($params); | ||
| 450 | + } | ||
| 451 | + | ||
| 452 | + if (gettype($namespace) == 'array') { | ||
| 453 | + foreach ($namespace as $optname => $opt) { | ||
| 454 | + $this->__options[strtolower($optname)] = $opt; | ||
| 455 | + } | ||
| 456 | + if (isset($this->__options['namespace'])) { | ||
| 457 | + $namespace = $this->__options['namespace']; | ||
| 458 | + } else { | ||
| 459 | + $namespace = false; | ||
| 460 | + } | ||
| 461 | + } else { | ||
| 462 | + // We'll place $soapAction into our array for usage in the | ||
| 463 | + // transport. | ||
| 464 | + $this->__options['soapaction'] = $soapAction; | ||
| 465 | + $this->__options['namespace'] = $namespace; | ||
| 466 | + } | ||
| 467 | + | ||
| 468 | + if ($this->__endpointType == 'wsdl') { | ||
| 469 | + $this->_setSchemaVersion($this->_wsdl->xsd); | ||
| 470 | + | ||
| 471 | + // Get port name. | ||
| 472 | + if (!$this->_portName) { | ||
| 473 | + $this->_portName = $this->_wsdl->getPortName($method); | ||
| 474 | + } | ||
| 475 | + if (PEAR::isError($this->_portName)) { | ||
| 476 | + $fault =& $this->_raiseSoapFault($this->_portName); | ||
| 477 | + return $fault; | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + // Get endpoint. | ||
| 481 | + $this->_endpoint = $this->_wsdl->getEndpoint($this->_portName); | ||
| 482 | + if (PEAR::isError($this->_endpoint)) { | ||
| 483 | + $fault =& $this->_raiseSoapFault($this->_endpoint); | ||
| 484 | + return $fault; | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + // Get operation data. | ||
| 488 | + $opData = $this->_wsdl->getOperationData($this->_portName, $method); | ||
| 489 | + | ||
| 490 | + if (PEAR::isError($opData)) { | ||
| 491 | + $fault =& $this->_raiseSoapFault($opData); | ||
| 492 | + return $fault; | ||
| 493 | + } | ||
| 494 | + $namespace = $opData['namespace']; | ||
| 495 | + $this->__options['style'] = $opData['style']; | ||
| 496 | + $this->__options['use'] = $opData['input']['use']; | ||
| 497 | + $this->__options['soapaction'] = $opData['soapAction']; | ||
| 498 | + | ||
| 499 | + // Set input parameters. | ||
| 500 | + if ($this->__options['input'] == 'parse') { | ||
| 501 | + $this->__options['parameters'] = $opData['parameters']; | ||
| 502 | + $nparams = array(); | ||
| 503 | + if (isset($opData['input']['parts']) && | ||
| 504 | + count($opData['input']['parts'])) { | ||
| 505 | + $i = 0; | ||
| 506 | + foreach ($opData['input']['parts'] as $name => $part) { | ||
| 507 | + $xmlns = ''; | ||
| 508 | + $attrs = array(); | ||
| 509 | + // Is the name a complex type? | ||
| 510 | + if (isset($part['element'])) { | ||
| 511 | + $xmlns = $this->_wsdl->namespaces[$part['namespace']]; | ||
| 512 | + $part = $this->_wsdl->elements[$part['namespace']][$part['type']]; | ||
| 513 | + $name = $part['name']; | ||
| 514 | + } | ||
| 515 | + if (isset($params[$name]) || | ||
| 516 | + $this->_wsdl->getDataHandler($name, $part['namespace'])) { | ||
| 517 | + $nparams[$name] =& $params[$name]; | ||
| 518 | + } else { | ||
| 519 | + // We now force an associative array for | ||
| 520 | + // parameters if using WSDL. | ||
| 521 | + $fault =& $this->_raiseSoapFault("The named parameter $name is not in the call parameters."); | ||
| 522 | + return $fault; | ||
| 523 | + } | ||
| 524 | + if (gettype($nparams[$name]) != 'object' || | ||
| 525 | + !is_a($nparams[$name], 'SOAP_Value')) { | ||
| 526 | + // Type is likely a qname, split it apart, and get | ||
| 527 | + // the type namespace from WSDL. | ||
| 528 | + $qname =& new QName($part['type']); | ||
| 529 | + if ($qname->ns) { | ||
| 530 | + $type_namespace = $this->_wsdl->namespaces[$qname->ns]; | ||
| 531 | + } elseif (isset($part['namespace'])) { | ||
| 532 | + $type_namespace = $this->_wsdl->namespaces[$part['namespace']]; | ||
| 533 | + } else { | ||
| 534 | + $type_namespace = null; | ||
| 535 | + } | ||
| 536 | + $qname->namespace = $type_namespace; | ||
| 537 | + $type = $qname->name; | ||
| 538 | + $pqname = $name; | ||
| 539 | + if ($xmlns) { | ||
| 540 | + $pqname = '{' . $xmlns . '}' . $name; | ||
| 541 | + } | ||
| 542 | + $nparams[$name] =& new SOAP_Value($pqname, | ||
| 543 | + $qname->fqn(), | ||
| 544 | + $nparams[$name], | ||
| 545 | + $attrs); | ||
| 546 | + } else { | ||
| 547 | + // WSDL fixups to the SOAP value. | ||
| 548 | + } | ||
| 549 | + } | ||
| 550 | + } | ||
| 551 | + $params =& $nparams; | ||
| 552 | + unset($nparams); | ||
| 553 | + } | ||
| 554 | + } else { | ||
| 555 | + $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + // Serialize the message. | ||
| 559 | + $this->_section5 = (!isset($this->__options['use']) || | ||
| 560 | + $this->__options['use'] != 'literal'); | ||
| 561 | + | ||
| 562 | + if (!isset($this->__options['style']) || | ||
| 563 | + $this->__options['style'] == 'rpc') { | ||
| 564 | + $this->__options['style'] = 'rpc'; | ||
| 565 | + $this->docparams = true; | ||
| 566 | + $mqname =& new QName($method, $namespace); | ||
| 567 | + $methodValue =& new SOAP_Value($mqname->fqn(), 'Struct', $params); | ||
| 568 | + $soap_msg = $this->_makeEnvelope($methodValue, | ||
| 569 | + $this->headersOut, | ||
| 570 | + $this->_encoding, | ||
| 571 | + $this->__options); | ||
| 572 | + } else { | ||
| 573 | + if (!$params) { | ||
| 574 | + $mqname =& new QName($method, $namespace); | ||
| 575 | + $mynull = null; | ||
| 576 | + $params =& new SOAP_Value($mqname->fqn(), 'Struct', $mynull); | ||
| 577 | + } elseif ($this->__options['input'] == 'parse') { | ||
| 578 | + if (is_array($params)) { | ||
| 579 | + $nparams = array(); | ||
| 580 | + $keys = array_keys($params); | ||
| 581 | + foreach ($keys as $k) { | ||
| 582 | + if (gettype($params[$k]) != 'object') { | ||
| 583 | + $nparams[] =& new SOAP_Value($k, | ||
| 584 | + false, | ||
| 585 | + $params[$k]); | ||
| 586 | + } else { | ||
| 587 | + $nparams[] =& $params[$k]; | ||
| 588 | + } | ||
| 589 | + } | ||
| 590 | + $params =& $nparams; | ||
| 591 | + } | ||
| 592 | + if ($this->__options['parameters']) { | ||
| 593 | + $mqname =& new QName($method, $namespace); | ||
| 594 | + $params =& new SOAP_Value($mqname->fqn(), | ||
| 595 | + 'Struct', | ||
| 596 | + $params); | ||
| 597 | + } | ||
| 598 | + } | ||
| 599 | + $soap_msg = $this->_makeEnvelope($params, | ||
| 600 | + $this->headersOut, | ||
| 601 | + $this->_encoding, | ||
| 602 | + $this->__options); | ||
| 603 | + } | ||
| 604 | + unset($this->headersOut); | ||
| 605 | + | ||
| 606 | + if (PEAR::isError($soap_msg)) { | ||
| 607 | + $fault =& $this->_raiseSoapFault($soap_msg); | ||
| 608 | + return $fault; | ||
| 609 | + } | ||
| 610 | + | ||
| 611 | + // Handle MIME or DIME encoding. | ||
| 612 | + // TODO: DIME encoding should move to the transport, do it here for | ||
| 613 | + // now and for ease of getting it done. | ||
| 614 | + if (count($this->__attachments)) { | ||
| 615 | + if ((isset($this->__options['attachments']) && | ||
| 616 | + $this->__options['attachments'] == 'Mime') || | ||
| 617 | + isset($this->__options['Mime'])) { | ||
| 618 | + $soap_msg =& $this->_makeMimeMessage($soap_msg, | ||
| 619 | + $this->_encoding); | ||
| 620 | + } else { | ||
| 621 | + // default is dime | ||
| 622 | + $soap_msg =& $this->_makeDIMEMessage($soap_msg, | ||
| 623 | + $this->_encoding); | ||
| 624 | + $this->__options['headers']['Content-Type'] = 'application/dime'; | ||
| 625 | + } | ||
| 626 | + if (PEAR::isError($soap_msg)) { | ||
| 627 | + $fault =& $this->_raiseSoapFault($soap_msg); | ||
| 628 | + return $fault; | ||
| 629 | + } | ||
| 630 | + } | ||
| 631 | + | ||
| 632 | + // Instantiate client. | ||
| 633 | + if (is_array($soap_msg)) { | ||
| 634 | + $soap_data =& $soap_msg['body']; | ||
| 635 | + if (count($soap_msg['headers'])) { | ||
| 636 | + if (isset($this->__options['headers'])) { | ||
| 637 | + $this->__options['headers'] = array_merge($this->__options['headers'], $soap_msg['headers']); | ||
| 638 | + } else { | ||
| 639 | + $this->__options['headers'] = $soap_msg['headers']; | ||
| 640 | + } | ||
| 641 | + } | ||
| 642 | + } else { | ||
| 643 | + $soap_data =& $soap_msg; | ||
| 644 | + } | ||
| 645 | + | ||
| 646 | + return $soap_data; | ||
| 647 | + } | ||
| 648 | + | ||
| 649 | + function &__parse(&$response, $encoding, &$attachments) | ||
| 650 | + { | ||
| 651 | + // Parse the response. | ||
| 652 | + $response =& new SOAP_Parser($response, $encoding, $attachments); | ||
| 653 | + if ($response->fault) { | ||
| 654 | + $fault =& $this->_raiseSoapFault($response->fault); | ||
| 655 | + return $fault; | ||
| 656 | + } | ||
| 657 | + | ||
| 658 | + // Return array of parameters. | ||
| 659 | + $return =& $response->getResponse(); | ||
| 660 | + $headers =& $response->getHeaders(); | ||
| 661 | + if ($headers) { | ||
| 662 | + $this->headersIn =& $this->__decodeResponse($headers, false); | ||
| 663 | + } | ||
| 664 | + | ||
| 665 | + $decoded = &$this->__decodeResponse($return); | ||
| 666 | + return $decoded; | ||
| 667 | + } | ||
| 668 | + | ||
| 669 | + function &__decodeResponse(&$response, $shift = true) | ||
| 670 | + { | ||
| 671 | + if (!$response) { | ||
| 672 | + $decoded = null; | ||
| 673 | + return $decoded; | ||
| 674 | + } | ||
| 675 | + | ||
| 676 | + // Check for valid response. | ||
| 677 | + if (PEAR::isError($response)) { | ||
| 678 | + $fault =& $this->_raiseSoapFault($response); | ||
| 679 | + return $fault; | ||
| 680 | + } elseif (!is_a($response, 'soap_value')) { | ||
| 681 | + $fault =& $this->_raiseSoapFault("Didn't get SOAP_Value object back from client"); | ||
| 682 | + return $fault; | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + // Decode to native php datatype. | ||
| 686 | + $returnArray =& $this->_decode($response); | ||
| 687 | + | ||
| 688 | + // Fault? | ||
| 689 | + if (PEAR::isError($returnArray)) { | ||
| 690 | + $fault =& $this->_raiseSoapFault($returnArray); | ||
| 691 | + return $fault; | ||
| 692 | + } | ||
| 693 | + | ||
| 694 | + if (is_object($returnArray) && | ||
| 695 | + strcasecmp(get_class($returnArray), 'stdClass') == 0) { | ||
| 696 | + $returnArray = get_object_vars($returnArray); | ||
| 697 | + } | ||
| 698 | + if (is_array($returnArray)) { | ||
| 699 | + if (isset($returnArray['faultcode']) || | ||
| 700 | + isset($returnArray['SOAP-ENV:faultcode'])) { | ||
| 701 | + $faultcode = $faultstring = $faultdetail = $faultactor = ''; | ||
| 702 | + foreach ($returnArray as $k => $v) { | ||
| 703 | + if (stristr($k, 'faultcode')) $faultcode = $v; | ||
| 704 | + if (stristr($k, 'faultstring')) $faultstring = $v; | ||
| 705 | + if (stristr($k, 'detail')) $faultdetail = $v; | ||
| 706 | + if (stristr($k, 'faultactor')) $faultactor = $v; | ||
| 707 | + } | ||
| 708 | + $fault =& $this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); | ||
| 709 | + return $fault; | ||
| 710 | + } | ||
| 711 | + // Return array of return values. | ||
| 712 | + if ($shift && count($returnArray) == 1) { | ||
| 713 | + $decoded = array_shift($returnArray); | ||
| 714 | + return $decoded; | ||
| 715 | + } | ||
| 716 | + return $returnArray; | ||
| 717 | + } | ||
| 718 | + return $returnArray; | ||
| 719 | + } | ||
| 720 | + | ||
| 721 | + function __get_wire() | ||
| 722 | + { | ||
| 723 | + if ($this->__options['trace'] > 0 && | ||
| 724 | + ($this->__last_request || $this->__last_response)) { | ||
| 725 | + return "OUTGOING:\n\n" . | ||
| 726 | + $this->__last_request . | ||
| 727 | + "\n\nINCOMING\n\n" . | ||
| 728 | + preg_replace("/></",">\r\n<", $this->__last_response); | ||
| 729 | + } | ||
| 730 | + | ||
| 731 | + return null; | ||
| 732 | + } | ||
| 733 | + | ||
| 734 | +} |
thirdparty/pear/SOAP/Copy of Base.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file loads all required libraries, defines constants used across the | ||
| 4 | + * SOAP package, and defines the base classes that most other classes of this | ||
| 5 | + * package extend. | ||
| 6 | + * | ||
| 7 | + * PHP versions 4 and 5 | ||
| 8 | + * | ||
| 9 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 10 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 11 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 12 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 13 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 14 | + * mail you a copy immediately. | ||
| 15 | + * | ||
| 16 | + * @category Web Services | ||
| 17 | + * @package SOAP | ||
| 18 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 19 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 20 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 21 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 22 | + * @copyright 2003-2005 The PHP Group | ||
| 23 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 24 | + * @link http://pear.php.net/package/SOAP | ||
| 25 | + */ | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * SOAP_OBJECT_STRUCT makes PEAR::SOAP use objects for SOAP structures rather | ||
| 29 | + * than arrays. This has been done to provide a closer match to php-soap. If | ||
| 30 | + * the old behaviour is needed, set to false. The old behaviour is | ||
| 31 | + * deprecated. | ||
| 32 | + * | ||
| 33 | + * @global bool $GLOBALS['SOAP_OBJECT_STRUCT'] | ||
| 34 | + */ | ||
| 35 | +$GLOBALS['SOAP_OBJECT_STRUCT'] = true; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * SOAP_RAW_CONVERT makes PEAR::SOAP attempt to determine what SOAP type a PHP | ||
| 39 | + * string COULD be. This may result in slightly better interoperability when | ||
| 40 | + * you are not using WSDL, and are being lazy and not using SOAP_Value to | ||
| 41 | + * define types for your values. | ||
| 42 | + * | ||
| 43 | + * @global bool $GLOBALS['SOAP_RAW_CONVERT'] | ||
| 44 | + */ | ||
| 45 | +$GLOBALS['SOAP_RAW_CONVERT'] = false; | ||
| 46 | + | ||
| 47 | +require_once 'PEAR.php'; | ||
| 48 | +require_once 'SOAP/Type/dateTime.php'; | ||
| 49 | +require_once 'SOAP/Type/hexBinary.php'; | ||
| 50 | + | ||
| 51 | +// optional features | ||
| 52 | +$GLOBALS['SOAP_options'] = array(); | ||
| 53 | + | ||
| 54 | +@include_once 'Mail/mimePart.php'; | ||
| 55 | +@include_once 'Mail/mimeDecode.php'; | ||
| 56 | +if (class_exists('Mail_mimePart')) { | ||
| 57 | + $GLOBALS['SOAP_options']['Mime'] = 1; | ||
| 58 | + define('MAIL_MIMEPART_CRLF', "\r\n"); | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +@include_once 'Net/DIME.php'; | ||
| 62 | +if (class_exists('Net_DIME_Message')) { | ||
| 63 | + $GLOBALS['SOAP_options']['DIME'] = 1; | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +/** | ||
| 67 | + * Enable debugging information? | ||
| 68 | + * | ||
| 69 | + * @global bool $GLOBALS['SOAP_DEBUG'] | ||
| 70 | + * @name $SOAP_DEBUG | ||
| 71 | + */ | ||
| 72 | +$GLOBALS['SOAP_DEBUG'] = false; | ||
| 73 | + | ||
| 74 | +if (!function_exists('version_compare') || | ||
| 75 | + version_compare(phpversion(), '4.1', '<')) { | ||
| 76 | + die("requires PHP 4.1 or higher\n"); | ||
| 77 | +} | ||
| 78 | +if (version_compare(phpversion(), '4.1', '>=') && | ||
| 79 | + version_compare(phpversion(), '4.2', '<')) { | ||
| 80 | + define('FLOAT', 'double'); | ||
| 81 | +} else { | ||
| 82 | + define('FLOAT', 'float'); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +if (!defined('INF')) { | ||
| 86 | + define('INF', 1.8e307); | ||
| 87 | +} | ||
| 88 | +if (!defined('NAN')) { | ||
| 89 | + define('NAN', 0.0); | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +define('SOAP_LIBRARY_VERSION', '0.8.0RC4'); | ||
| 93 | +define('SOAP_LIBRARY_NAME', 'PEAR-SOAP 0.8.0RC4-devel'); | ||
| 94 | + | ||
| 95 | +// Set schema version. | ||
| 96 | +define('SOAP_XML_SCHEMA_VERSION', 'http://www.w3.org/2001/XMLSchema'); | ||
| 97 | +define('SOAP_XML_SCHEMA_INSTANCE', 'http://www.w3.org/2001/XMLSchema-instance'); | ||
| 98 | +define('SOAP_XML_SCHEMA_1999', 'http://www.w3.org/1999/XMLSchema'); | ||
| 99 | +define('SOAP_SCHEMA', 'http://schemas.xmlsoap.org/wsdl/soap/'); | ||
| 100 | +define('SOAP_SCHEMA_ENCODING', 'http://schemas.xmlsoap.org/soap/encoding/'); | ||
| 101 | +define('SOAP_ENVELOP', 'http://schemas.xmlsoap.org/soap/envelope/'); | ||
| 102 | + | ||
| 103 | +define('SCHEMA_DISCO', 'http://schemas.xmlsoap.org/disco/'); | ||
| 104 | +define('SCHEMA_DISCO_SCL', 'http://schemas.xmlsoap.org/disco/scl/'); | ||
| 105 | + | ||
| 106 | +define('SCHEMA_SOAP', 'http://schemas.xmlsoap.org/wsdl/soap/'); | ||
| 107 | +define('SCHEMA_SOAP_HTTP', 'http://schemas.xmlsoap.org/soap/http'); | ||
| 108 | +define('SCHEMA_WSDL_HTTP', 'http://schemas.xmlsoap.org/wsdl/http/'); | ||
| 109 | +define('SCHEMA_MIME', 'http://schemas.xmlsoap.org/wsdl/mime/'); | ||
| 110 | +define('SCHEMA_WSDL', 'http://schemas.xmlsoap.org/wsdl/'); | ||
| 111 | +define('SCHEMA_DIME', 'http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/'); | ||
| 112 | +define('SCHEMA_CONTENT', 'http://schemas.xmlsoap.org/ws/2002/04/content-type/'); | ||
| 113 | +define('SCHEMA_REF', 'http://schemas.xmlsoap.org/ws/2002/04/reference/'); | ||
| 114 | + | ||
| 115 | +define('SOAP_DEFAULT_ENCODING', 'UTF-8'); | ||
| 116 | + | ||
| 117 | +class SOAP_Base_Object extends PEAR | ||
| 118 | +{ | ||
| 119 | + /** | ||
| 120 | + * Store debugging information in $_debug_data? | ||
| 121 | + * | ||
| 122 | + * @see $debug_data, SOAP_Base | ||
| 123 | + * @var boolean $_debug_flag | ||
| 124 | + */ | ||
| 125 | + var $_debug_flag = false; | ||
| 126 | + | ||
| 127 | + /** | ||
| 128 | + * String containing debugging information if $_debug_flag is true. | ||
| 129 | + * | ||
| 130 | + * @access public | ||
| 131 | + * @see $debug_flag, SOAP_Base | ||
| 132 | + * @var string $_debug_data | ||
| 133 | + */ | ||
| 134 | + var $_debug_data = ''; | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * Supported encodings, limited by XML extension. | ||
| 138 | + * | ||
| 139 | + * @var array $_encodings | ||
| 140 | + */ | ||
| 141 | + var $_encodings = array('ISO-8859-1', 'US-ASCII', 'UTF-8'); | ||
| 142 | + | ||
| 143 | + /** | ||
| 144 | + * Fault code. | ||
| 145 | + * | ||
| 146 | + * @var string $_myfaultcode | ||
| 147 | + */ | ||
| 148 | + var $_myfaultcode = ''; | ||
| 149 | + | ||
| 150 | + /** | ||
| 151 | + * Recent PEAR_Error object. | ||
| 152 | + * | ||
| 153 | + * @var PEAR_Error $fault | ||
| 154 | + */ | ||
| 155 | + var $fault = null; | ||
| 156 | + | ||
| 157 | + /** | ||
| 158 | + * Constructor. | ||
| 159 | + * | ||
| 160 | + * @see $debug_data, _debug() | ||
| 161 | + * | ||
| 162 | + * @param string $faultcode Error code. | ||
| 163 | + */ | ||
| 164 | + function SOAP_Base_Object($faultcode = 'Client') | ||
| 165 | + { | ||
| 166 | + $this->_myfaultcode = $faultcode; | ||
| 167 | + $this->_debug_flag = $GLOBALS['SOAP_DEBUG']; | ||
| 168 | + parent::PEAR('SOAP_Fault'); | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + /** | ||
| 172 | + * Raises a SOAP error. | ||
| 173 | + * | ||
| 174 | + * Please refer to the SOAP definition for an impression of what a certain | ||
| 175 | + * parameter stands for. | ||
| 176 | + * | ||
| 177 | + * Use $debug_flag to store errors to the member variable $debug_data | ||
| 178 | + * | ||
| 179 | + * @see $debug_flag, $debug_data, SOAP_Fault | ||
| 180 | + * | ||
| 181 | + * @param string|object $str Error message or object. | ||
| 182 | + * @param string $detail Detailed error message. | ||
| 183 | + * @param string $actorURI | ||
| 184 | + * @param mixed $code | ||
| 185 | + * @param mixed $mode | ||
| 186 | + * @param mixed $options | ||
| 187 | + * @param boolean $skipmsg | ||
| 188 | + */ | ||
| 189 | + function &_raiseSoapFault($str, $detail = '', $actorURI = '', $code = null, | ||
| 190 | + $mode = null, $options = null, $skipmsg = false) | ||
| 191 | + { | ||
| 192 | + // Pass through previous faults. | ||
| 193 | + $is_instance = isset($this); | ||
| 194 | + if (is_object($str)) { | ||
| 195 | + $fault =& $str; | ||
| 196 | + } else { | ||
| 197 | + if (!$code) { | ||
| 198 | + $code = $is_instance ? $this->_myfaultcode : 'Client'; | ||
| 199 | + } | ||
| 200 | + $fault =& new SOAP_Fault($str, | ||
| 201 | + $code, | ||
| 202 | + $actorURI, | ||
| 203 | + $detail, | ||
| 204 | + $mode, | ||
| 205 | + $options); | ||
| 206 | + } | ||
| 207 | + if ($is_instance) { | ||
| 208 | + $this->fault =& $fault; | ||
| 209 | + } | ||
| 210 | + | ||
| 211 | + return $fault; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + function __isfault() | ||
| 215 | + { | ||
| 216 | + return $this->fault != null; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + function &__getfault() | ||
| 220 | + { | ||
| 221 | + return $this->fault; | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + /** | ||
| 225 | + * Adds a string to the debug data. | ||
| 226 | + * | ||
| 227 | + * @param string $string Debugging message. | ||
| 228 | + */ | ||
| 229 | + function _debug($string) | ||
| 230 | + { | ||
| 231 | + if ($this->_debug_flag) { | ||
| 232 | + $this->_debug_data .= get_class($this) . ': ' . | ||
| 233 | + str_replace('>', ">\r\n", $string) . "\n"; | ||
| 234 | + } | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +/** | ||
| 240 | + * Common base class of all SOAP classes. | ||
| 241 | + * | ||
| 242 | + * @access public | ||
| 243 | + * @package SOAP | ||
| 244 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 245 | + */ | ||
| 246 | +class SOAP_Base extends SOAP_Base_Object | ||
| 247 | +{ | ||
| 248 | + var $_XMLSchema = array('http://www.w3.org/2001/XMLSchema', | ||
| 249 | + 'http://www.w3.org/1999/XMLSchema'); | ||
| 250 | + var $_XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema'; | ||
| 251 | + | ||
| 252 | + // load types into typemap array | ||
| 253 | + var $_typemap = array( | ||
| 254 | + 'http://www.w3.org/2001/XMLSchema' => array( | ||
| 255 | + 'string' => 'string', | ||
| 256 | + 'boolean' => 'boolean', | ||
| 257 | + 'float' => FLOAT, | ||
| 258 | + 'double' => FLOAT, | ||
| 259 | + 'decimal' => FLOAT, | ||
| 260 | + 'duration' => 'integer', | ||
| 261 | + 'dateTime' => 'string', | ||
| 262 | + 'time' => 'string', | ||
| 263 | + 'date' => 'string', | ||
| 264 | + 'gYearMonth' => 'integer', | ||
| 265 | + 'gYear' => 'integer', | ||
| 266 | + 'gMonthDay' => 'integer', | ||
| 267 | + 'gDay' => 'integer', | ||
| 268 | + 'gMonth' => 'integer', | ||
| 269 | + 'hexBinary' => 'string', | ||
| 270 | + 'base64Binary' => 'string', | ||
| 271 | + // derived datatypes | ||
| 272 | + 'normalizedString' => 'string', | ||
| 273 | + 'token' => 'string', | ||
| 274 | + 'language' => 'string', | ||
| 275 | + 'NMTOKEN' => 'string', | ||
| 276 | + 'NMTOKENS' => 'string', | ||
| 277 | + 'Name' => 'string', | ||
| 278 | + 'NCName' => 'string', | ||
| 279 | + 'ID' => 'string', | ||
| 280 | + 'IDREF' => 'string', | ||
| 281 | + 'IDREFS' => 'string', | ||
| 282 | + 'ENTITY' => 'string', | ||
| 283 | + 'ENTITIES' => 'string', | ||
| 284 | + 'integer' => 'integer', | ||
| 285 | + 'nonPositiveInteger' => 'integer', | ||
| 286 | + 'negativeInteger' => 'integer', | ||
| 287 | + 'long' => 'integer', | ||
| 288 | + 'int' => 'integer', | ||
| 289 | + 'short' => 'integer', | ||
| 290 | + 'byte' => 'string', | ||
| 291 | + 'nonNegativeInteger' => 'integer', | ||
| 292 | + 'unsignedLong' => 'integer', | ||
| 293 | + 'unsignedInt' => 'integer', | ||
| 294 | + 'unsignedShort' => 'integer', | ||
| 295 | + 'unsignedByte' => 'integer', | ||
| 296 | + 'positiveInteger' => 'integer', | ||
| 297 | + 'anyType' => 'string', | ||
| 298 | + 'anyURI' => 'string', | ||
| 299 | + 'QName' => 'string' | ||
| 300 | + ), | ||
| 301 | + 'http://www.w3.org/1999/XMLSchema' => array( | ||
| 302 | + 'i4' => 'integer', | ||
| 303 | + 'int' => 'integer', | ||
| 304 | + 'boolean' => 'boolean', | ||
| 305 | + 'string' => 'string', | ||
| 306 | + 'double' => FLOAT, | ||
| 307 | + 'float' => FLOAT, | ||
| 308 | + 'dateTime' => 'string', | ||
| 309 | + 'timeInstant' => 'string', | ||
| 310 | + 'base64Binary' => 'string', | ||
| 311 | + 'base64' => 'string', | ||
| 312 | + 'ur-type' => 'string' | ||
| 313 | + ), | ||
| 314 | + 'http://schemas.xmlsoap.org/soap/encoding/' => array( | ||
| 315 | + 'base64' => 'string', | ||
| 316 | + 'array' => 'array', | ||
| 317 | + 'Array' => 'array', | ||
| 318 | + 'Struct' => 'array') | ||
| 319 | + ); | ||
| 320 | + | ||
| 321 | + /** | ||
| 322 | + * Default class name to use for decoded response objects. | ||
| 323 | + * | ||
| 324 | + * @var string $_defaultObjectClassname | ||
| 325 | + */ | ||
| 326 | + var $_defaultObjectClassname = 'stdClass'; | ||
| 327 | + | ||
| 328 | + // Load namespace URIs into an array of URI => prefix. | ||
| 329 | + var $_namespaces; | ||
| 330 | + var $_namespace; | ||
| 331 | + | ||
| 332 | + var $_xmlEntities = array('&' => '&', | ||
| 333 | + '<' => '<', | ||
| 334 | + '>' => '>', | ||
| 335 | + "'" => ''', | ||
| 336 | + '"' => '"'); | ||
| 337 | + | ||
| 338 | + var $_doconversion = false; | ||
| 339 | + | ||
| 340 | + var $__attachments = array(); | ||
| 341 | + | ||
| 342 | + var $_wsdl = null; | ||
| 343 | + | ||
| 344 | + /** | ||
| 345 | + * True if we use section 5 encoding, or false if this is literal. | ||
| 346 | + * | ||
| 347 | + * @var boolean $_section5 | ||
| 348 | + */ | ||
| 349 | + var $_section5 = true; | ||
| 350 | + | ||
| 351 | + // Handle type to class mapping. | ||
| 352 | + var $_auto_translation = false; | ||
| 353 | + var $_type_translation = array(); | ||
| 354 | + | ||
| 355 | + /** | ||
| 356 | + * Constructor. | ||
| 357 | + * | ||
| 358 | + * @see $debug_data, _debug() | ||
| 359 | + * | ||
| 360 | + * @param string $faultcode Error code. | ||
| 361 | + */ | ||
| 362 | + function SOAP_Base($faultcode = 'Client') | ||
| 363 | + { | ||
| 364 | + parent::SOAP_Base_Object($faultcode); | ||
| 365 | + $this->_resetNamespaces(); | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + function _resetNamespaces() | ||
| 369 | + { | ||
| 370 | + $this->_namespaces = array( | ||
| 371 | + 'http://schemas.xmlsoap.org/soap/envelope/' => 'SOAP-ENV', | ||
| 372 | + 'http://www.w3.org/2001/XMLSchema' => 'xsd', | ||
| 373 | + 'http://www.w3.org/2001/XMLSchema-instance' => 'xsi', | ||
| 374 | + 'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC'); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + /** | ||
| 378 | + * Sets the schema version used in the SOAP message. | ||
| 379 | + * | ||
| 380 | + * @access private | ||
| 381 | + * @see $_XMLSchema | ||
| 382 | + * | ||
| 383 | + * @param string $schemaVersion The schema version. | ||
| 384 | + */ | ||
| 385 | + function _setSchemaVersion($schemaVersion) | ||
| 386 | + { | ||
| 387 | + if (!in_array($schemaVersion, $this->_XMLSchema)) { | ||
| 388 | + return $this->_raiseSoapFault("unsuported XMLSchema $schemaVersion"); | ||
| 389 | + } | ||
| 390 | + $this->_XMLSchemaVersion = $schemaVersion; | ||
| 391 | + $tmpNS = array_flip($this->_namespaces); | ||
| 392 | + $tmpNS['xsd'] = $this->_XMLSchemaVersion; | ||
| 393 | + $tmpNS['xsi'] = $this->_XMLSchemaVersion . '-instance'; | ||
| 394 | + $this->_namespaces = array_flip($tmpNS); | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + function _getNamespacePrefix($ns) | ||
| 398 | + { | ||
| 399 | + if ($this->_namespace && $ns == $this->_namespace) { | ||
| 400 | + return ''; | ||
| 401 | + } | ||
| 402 | + if (isset($this->_namespaces[$ns])) { | ||
| 403 | + return $this->_namespaces[$ns]; | ||
| 404 | + } | ||
| 405 | + $prefix = 'ns' . count($this->_namespaces); | ||
| 406 | + $this->_namespaces[$ns] = $prefix; | ||
| 407 | + return $prefix; | ||
| 408 | + } | ||
| 409 | + | ||
| 410 | + function _getNamespaceForPrefix($prefix) | ||
| 411 | + { | ||
| 412 | + $flipped = array_flip($this->_namespaces); | ||
| 413 | + if (isset($flipped[$prefix])) { | ||
| 414 | + return $flipped[$prefix]; | ||
| 415 | + } | ||
| 416 | + return null; | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + function _isSoapValue(&$value) | ||
| 420 | + { | ||
| 421 | + return is_a($value, 'SOAP_Value'); | ||
| 422 | + } | ||
| 423 | + | ||
| 424 | + function _serializeValue(&$value, $name = '', $type = false, | ||
| 425 | + $elNamespace = null, $typeNamespace = null, | ||
| 426 | + $options = array(), $attributes = array(), | ||
| 427 | + $artype = '') | ||
| 428 | + { | ||
| 429 | + $namespaces = array(); | ||
| 430 | + $arrayType = $array_depth = $xmlout_value = null; | ||
| 431 | + $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = ''; | ||
| 432 | + $xmlout_type = $xmlns = $ptype = $array_type_ns = ''; | ||
| 433 | + | ||
| 434 | + if (!$name || is_numeric($name)) { | ||
| 435 | + $name = 'item'; | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + if ($this->_wsdl) { | ||
| 439 | + list($ptype, $arrayType, $array_type_ns, $array_depth) | ||
| 440 | + = $this->_wsdl->getSchemaType($type, $name, $typeNamespace); | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | + if (!$arrayType) { | ||
| 444 | + $arrayType = $artype; | ||
| 445 | + } | ||
| 446 | + if (!$ptype) { | ||
| 447 | + $ptype = $this->_getType($value); | ||
| 448 | + } | ||
| 449 | + if (!$type) { | ||
| 450 | + $type = $ptype; | ||
| 451 | + } | ||
| 452 | + | ||
| 453 | + if (strcasecmp($ptype, 'Struct') == 0 || | ||
| 454 | + strcasecmp($type, 'Struct') == 0) { | ||
| 455 | + // Struct | ||
| 456 | + $vars = null; | ||
| 457 | + if (is_object($value)) { | ||
| 458 | + $vars = get_object_vars($value); | ||
| 459 | + } else { | ||
| 460 | + $vars = &$value; | ||
| 461 | + } | ||
| 462 | + if (is_array($vars)) { | ||
| 463 | + foreach (array_keys($vars) as $k) { | ||
| 464 | + // Hide private vars. | ||
| 465 | + if ($k[0] == '_') continue; | ||
| 466 | + if (is_object($vars[$k])) { | ||
| 467 | + if (is_a($vars[$k], 'SOAP_Value')) { | ||
| 468 | + $xmlout_value .= $vars[$k]->serialize($this); | ||
| 469 | + } else { | ||
| 470 | + // XXX get the members and serialize them instead | ||
| 471 | + // converting to an array is more overhead than we | ||
| 472 | + // should really do. | ||
| 473 | + $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), $k, false, $this->_section5 ? null : $elNamespace); | ||
| 474 | + } | ||
| 475 | + } else { | ||
| 476 | + $xmlout_value .= $this->_serializeValue($vars[$k], $k, false, $this->_section5 ? null : $elNamespace); | ||
| 477 | + } | ||
| 478 | + } | ||
| 479 | + } | ||
| 480 | + } elseif (strcasecmp($ptype, 'Array') == 0 || | ||
| 481 | + strcasecmp($type, 'Array') == 0) { | ||
| 482 | + // Array. | ||
| 483 | + $typeNamespace = SOAP_SCHEMA_ENCODING; | ||
| 484 | + $orig_type = $type; | ||
| 485 | + $type = 'Array'; | ||
| 486 | + $numtypes = 0; | ||
| 487 | + // XXX this will be slow on larger arrays. Basically, it flattens | ||
| 488 | + // arrays to allow us to serialize multi-dimensional arrays. We | ||
| 489 | + // only do this if arrayType is set, which will typically only | ||
| 490 | + // happen if we are using WSDL | ||
| 491 | + if (isset($options['flatten']) || | ||
| 492 | + ($arrayType && | ||
| 493 | + (strchr($arrayType, ',') || strstr($arrayType, '][')))) { | ||
| 494 | + $numtypes = $this->_multiArrayType($value, $arrayType, | ||
| 495 | + $ar_size, $xmlout_value); | ||
| 496 | + } | ||
| 497 | + | ||
| 498 | + $array_type = $array_type_prefix = ''; | ||
| 499 | + if ($numtypes != 1) { | ||
| 500 | + $arrayTypeQName =& new QName($arrayType); | ||
| 501 | + $arrayType = $arrayTypeQName->name; | ||
| 502 | + $array_types = array(); | ||
| 503 | + $array_val = null; | ||
| 504 | + | ||
| 505 | + // Serialize each array element. | ||
| 506 | + $ar_size = count($value); | ||
| 507 | + foreach ($value as $array_val) { | ||
| 508 | + if ($this->_isSoapValue($array_val)) { | ||
| 509 | + $array_type = $array_val->type; | ||
| 510 | + $array_types[$array_type] = 1; | ||
| 511 | + $array_type_ns = $array_val->type_namespace; | ||
| 512 | + $xmlout_value .= $array_val->serialize($this); | ||
| 513 | + } else { | ||
| 514 | + $array_type = $this->_getType($array_val); | ||
| 515 | + $array_types[$array_type] = 1; | ||
| 516 | + $xmlout_value .= $this->_serializeValue($array_val, 'item', $array_type, $this->_section5 ? null : $elNamespace); | ||
| 517 | + } | ||
| 518 | + } | ||
| 519 | + | ||
| 520 | + $xmlout_offset = ' SOAP-ENC:offset="[0]"'; | ||
| 521 | + if (!$arrayType) { | ||
| 522 | + $numtypes = count($array_types); | ||
| 523 | + if ($numtypes == 1) { | ||
| 524 | + $arrayType = $array_type; | ||
| 525 | + } | ||
| 526 | + // Using anyType is more interoperable. | ||
| 527 | + if ($array_type == 'Struct') { | ||
| 528 | + $array_type = ''; | ||
| 529 | + } elseif ($array_type == 'Array') { | ||
| 530 | + $arrayType = 'anyType'; | ||
| 531 | + $array_type_prefix = 'xsd'; | ||
| 532 | + } else { | ||
| 533 | + if (!$arrayType) { | ||
| 534 | + $arrayType = $array_type; | ||
| 535 | + } | ||
| 536 | + } | ||
| 537 | + } | ||
| 538 | + } | ||
| 539 | + if (!$arrayType || $numtypes > 1) { | ||
| 540 | + // Should reference what schema we're using. | ||
| 541 | + $arrayType = 'xsd:anyType'; | ||
| 542 | + } else { | ||
| 543 | + if ($array_type_ns) { | ||
| 544 | + $array_type_prefix = $this->_getNamespacePrefix($array_type_ns); | ||
| 545 | + } elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) { | ||
| 546 | + $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion]; | ||
| 547 | + } | ||
| 548 | + if ($array_type_prefix) { | ||
| 549 | + $arrayType = $array_type_prefix . ':' . $arrayType; | ||
| 550 | + } | ||
| 551 | + } | ||
| 552 | + | ||
| 553 | + $xmlout_arrayType = ' SOAP-ENC:arrayType="' . $arrayType; | ||
| 554 | + if ($array_depth != null) { | ||
| 555 | + for ($i = 0; $i < $array_depth; $i++) { | ||
| 556 | + $xmlout_arrayType .= '[]'; | ||
| 557 | + } | ||
| 558 | + } | ||
| 559 | + $xmlout_arrayType .= "[$ar_size]\""; | ||
| 560 | + } elseif ($this->_isSoapValue($value)) { | ||
| 561 | + $xmlout_value = $value->serialize($this); | ||
| 562 | + } elseif ($type == 'string') { | ||
| 563 | + $xmlout_value = htmlspecialchars($value); | ||
| 564 | + } elseif ($type == 'rawstring') { | ||
| 565 | + $xmlout_value =& $value; | ||
| 566 | + } elseif ($type == 'boolean') { | ||
| 567 | + $xmlout_value = $value ? 'true' : 'false'; | ||
| 568 | + } else { | ||
| 569 | + $xmlout_value =& $value; | ||
| 570 | + } | ||
| 571 | + | ||
| 572 | + // Add namespaces. | ||
| 573 | + if ($elNamespace) { | ||
| 574 | + $elPrefix = $this->_getNamespacePrefix($elNamespace); | ||
| 575 | + if ($elPrefix) { | ||
| 576 | + $xmlout_name = "$elPrefix:$name"; | ||
| 577 | + } else { | ||
| 578 | + $xmlout_name = $name; | ||
| 579 | + } | ||
| 580 | + } else { | ||
| 581 | + $xmlout_name = $name; | ||
| 582 | + } | ||
| 583 | + | ||
| 584 | + if ($typeNamespace) { | ||
| 585 | + $typePrefix = $this->_getNamespacePrefix($typeNamespace); | ||
| 586 | + if ($typePrefix) { | ||
| 587 | + $xmlout_type = "$typePrefix:$type"; | ||
| 588 | + } else { | ||
| 589 | + $xmlout_type = $type; | ||
| 590 | + } | ||
| 591 | + } elseif ($type && | ||
| 592 | + isset($this->_typemap[$this->_XMLSchemaVersion][$type])) { | ||
| 593 | + $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion]; | ||
| 594 | + if ($typePrefix) { | ||
| 595 | + $xmlout_type = "$typePrefix:$type"; | ||
| 596 | + } else { | ||
| 597 | + $xmlout_type = $type; | ||
| 598 | + } | ||
| 599 | + } | ||
| 600 | + | ||
| 601 | + // Handle additional attributes. | ||
| 602 | + $xml_attr = ''; | ||
| 603 | + if (count($attributes)) { | ||
| 604 | + foreach ($attributes as $k => $v) { | ||
| 605 | + $kqn =& new QName($k); | ||
| 606 | + $vqn =& new QName($v); | ||
| 607 | + $xml_attr .= ' ' . $kqn->fqn() . '="' . $vqn->fqn() . '"'; | ||
| 608 | + } | ||
| 609 | + } | ||
| 610 | + | ||
| 611 | + // Store the attachment for mime encoding. | ||
| 612 | + if (isset($options['attachment']) && | ||
| 613 | + !PEAR::isError($options['attachment'])) { | ||
| 614 | + $this->__attachments[] = $options['attachment']; | ||
| 615 | + } | ||
| 616 | + | ||
| 617 | + if ($this->_section5) { | ||
| 618 | + if ($xmlout_type) { | ||
| 619 | + $xmlout_type = " xsi:type=\"$xmlout_type\""; | ||
| 620 | + } | ||
| 621 | + if (is_null($xmlout_value)) { | ||
| 622 | + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . | ||
| 623 | + "$xml_attr xsi:nil=\"true\"/>"; | ||
| 624 | + } else { | ||
| 625 | + $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" . | ||
| 626 | + "$xmlout_offset$xml_attr>$xmlout_value</$xmlout_name>"; | ||
| 627 | + } | ||
| 628 | + } else { | ||
| 629 | + if (is_null($xmlout_value)) { | ||
| 630 | + $xml = "\r\n<$xmlout_name$xmlns$xml_attr/>"; | ||
| 631 | + } else { | ||
| 632 | + $xml = "\r\n<$xmlout_name$xmlns$xml_attr>" . | ||
| 633 | + $xmlout_value . "</$xmlout_name>"; | ||
| 634 | + } | ||
| 635 | + } | ||
| 636 | + | ||
| 637 | + return $xml; | ||
| 638 | + } | ||
| 639 | + | ||
| 640 | + /** | ||
| 641 | + * Converts a PHP type to a SOAP type. | ||
| 642 | + * | ||
| 643 | + * @access private | ||
| 644 | + * | ||
| 645 | + * @param string $value The value to inspect. | ||
| 646 | + * | ||
| 647 | + * @return string The value's SOAP type. | ||
| 648 | + */ | ||
| 649 | + function _getType(&$value) | ||
| 650 | + { | ||
| 651 | + global $SOAP_OBJECT_STRUCT, $SOAP_RAW_CONVERT; | ||
| 652 | + | ||
| 653 | + $type = gettype($value); | ||
| 654 | + switch ($type) { | ||
| 655 | + case 'object': | ||
| 656 | + if (is_a($value, 'soap_value')) { | ||
| 657 | + $type = $value->type; | ||
| 658 | + } else { | ||
| 659 | + $type = 'Struct'; | ||
| 660 | + } | ||
| 661 | + break; | ||
| 662 | + | ||
| 663 | + case 'array': | ||
| 664 | + // Hashes are always handled as structs. | ||
| 665 | + if ($this->_isHash($value)) { | ||
| 666 | + $type = 'Struct'; | ||
| 667 | + } else { | ||
| 668 | + $ar_size = count($value); | ||
| 669 | + reset($value); | ||
| 670 | + $key1 = key($value); | ||
| 671 | + if ($ar_size > 0 && is_a($key1, 'SOAP_Value')) { | ||
| 672 | + // FIXME: for non-wsdl structs that are all the same type | ||
| 673 | + $key2 = key($value); | ||
| 674 | + if ($ar_size > 1 && | ||
| 675 | + $this->_isSoapValue($key1) && | ||
| 676 | + $this->_isSoapValue($key2) && | ||
| 677 | + $key1->name != $key2->name) { | ||
| 678 | + // This is a struct, not an array. | ||
| 679 | + $type = 'Struct'; | ||
| 680 | + } else { | ||
| 681 | + $type = 'Array'; | ||
| 682 | + } | ||
| 683 | + } else { | ||
| 684 | + $type = 'Array'; | ||
| 685 | + } | ||
| 686 | + } | ||
| 687 | + break; | ||
| 688 | + | ||
| 689 | + case 'integer': | ||
| 690 | + case 'long': | ||
| 691 | + $type = 'int'; | ||
| 692 | + break; | ||
| 693 | + | ||
| 694 | + case 'boolean': | ||
| 695 | + break; | ||
| 696 | + | ||
| 697 | + case 'double': | ||
| 698 | + // double is deprecated in PHP 4.2 and later. | ||
| 699 | + $type = 'float'; | ||
| 700 | + break; | ||
| 701 | + | ||
| 702 | + case 'null': | ||
| 703 | + $type = ''; | ||
| 704 | + break; | ||
| 705 | + | ||
| 706 | + case 'string': | ||
| 707 | + if ($SOAP_RAW_CONVERT) { | ||
| 708 | + if (is_numeric($value)) { | ||
| 709 | + if (strstr($value, '.')) { | ||
| 710 | + $type = 'float'; | ||
| 711 | + } else { | ||
| 712 | + $type = 'int'; | ||
| 713 | + } | ||
| 714 | + } else { | ||
| 715 | + if (SOAP_Type_hexBinary::is_hexbin($value)) { | ||
| 716 | + $type = 'hexBinary'; | ||
| 717 | + } else { | ||
| 718 | + if ($this->_isBase64($value)) { | ||
| 719 | + $type = 'base64Binary'; | ||
| 720 | + } else { | ||
| 721 | + $dt =& new SOAP_Type_dateTime($value); | ||
| 722 | + if ($dt->toUnixtime() != -1) { | ||
| 723 | + $type = 'dateTime'; | ||
| 724 | + } | ||
| 725 | + } | ||
| 726 | + } | ||
| 727 | + } | ||
| 728 | + } | ||
| 729 | + break; | ||
| 730 | + | ||
| 731 | + default: | ||
| 732 | + break; | ||
| 733 | + } | ||
| 734 | + | ||
| 735 | + return $type; | ||
| 736 | + } | ||
| 737 | + | ||
| 738 | + function _multiArrayType(&$value, &$type, &$size, &$xml) | ||
| 739 | + { | ||
| 740 | + $sz = count($value); | ||
| 741 | + if (is_array($value)) { | ||
| 742 | + // Seems we have a multi dimensional array, figure it out if we | ||
| 743 | + // do. | ||
| 744 | + $c = count($value); | ||
| 745 | + for ($i = 0; $i < $c; $i++) { | ||
| 746 | + $this->_multiArrayType($value[$i], $type, $size, $xml); | ||
| 747 | + } | ||
| 748 | + | ||
| 749 | + if ($size) { | ||
| 750 | + $size = $sz. ',' . $size; | ||
| 751 | + } else { | ||
| 752 | + $size = $sz; | ||
| 753 | + } | ||
| 754 | + | ||
| 755 | + return 1; | ||
| 756 | + } else { | ||
| 757 | + if (is_object($value)) { | ||
| 758 | + $type = $value->type; | ||
| 759 | + $xml .= $value->serialize($this); | ||
| 760 | + } else { | ||
| 761 | + $type = $this->_getType($value); | ||
| 762 | + $xml .= $this->_serializeValue($value, 'item', $type); | ||
| 763 | + } | ||
| 764 | + } | ||
| 765 | + $size = null; | ||
| 766 | + | ||
| 767 | + return 1; | ||
| 768 | + } | ||
| 769 | + | ||
| 770 | + /** | ||
| 771 | + * Returns whether a string is base64 encoded data. | ||
| 772 | + * | ||
| 773 | + * @param string $value The string to check. | ||
| 774 | + * | ||
| 775 | + * @return boolean True if the specified value seems to be base64 encoded. | ||
| 776 | + */ | ||
| 777 | + function _isBase64(&$value) | ||
| 778 | + { | ||
| 779 | + $l = strlen($value); | ||
| 780 | + if ($l) { | ||
| 781 | + return $value[$l - 1] == '=' && | ||
| 782 | + preg_match('/[A-Za-z=\/\+]+/', $value); | ||
| 783 | + } | ||
| 784 | + return false; | ||
| 785 | + } | ||
| 786 | + | ||
| 787 | + /** | ||
| 788 | + * Returns whether a type is a base64 type. | ||
| 789 | + * | ||
| 790 | + * @param string $type A type name. | ||
| 791 | + * | ||
| 792 | + * @return boolean True if the type name is a base64 type. | ||
| 793 | + */ | ||
| 794 | + function _isBase64Type($type) | ||
| 795 | + { | ||
| 796 | + return $type == 'base64' || $type == 'base64Binary'; | ||
| 797 | + } | ||
| 798 | + | ||
| 799 | + /** | ||
| 800 | + * Returns whether an array is a hash. | ||
| 801 | + * | ||
| 802 | + * @param array $a An array to check. | ||
| 803 | + * | ||
| 804 | + * @return boolean True if the specified array is a hash. | ||
| 805 | + */ | ||
| 806 | + function _isHash(&$a) | ||
| 807 | + { | ||
| 808 | + // I really dislike having to loop through this in PHP code, really | ||
| 809 | + // large arrays will be slow. We need a C function to do this. | ||
| 810 | + $names = array(); | ||
| 811 | + $it = 0; | ||
| 812 | + foreach ($a as $k => $v) { | ||
| 813 | + // Checking the type is faster than regexp. | ||
| 814 | + $t = gettype($k); | ||
| 815 | + if ($t != 'integer') { | ||
| 816 | + return true; | ||
| 817 | + } elseif ($this->_isSoapValue($v)) { | ||
| 818 | + $names[$v->name] = 1; | ||
| 819 | + } | ||
| 820 | + // If someone has a large hash they should really be defining the | ||
| 821 | + // type. | ||
| 822 | + if ($it++ > 10) { | ||
| 823 | + return false; | ||
| 824 | + } | ||
| 825 | + } | ||
| 826 | + return count($names)>1; | ||
| 827 | + } | ||
| 828 | + | ||
| 829 | + function _un_htmlentities($string) | ||
| 830 | + { | ||
| 831 | + $trans_tbl = get_html_translation_table(HTML_ENTITIES); | ||
| 832 | + $trans_tbl = array_flip($trans_tbl); | ||
| 833 | + return strtr($string, $trans_tbl); | ||
| 834 | + } | ||
| 835 | + | ||
| 836 | + function &_decode(&$soapval) | ||
| 837 | + { | ||
| 838 | + global $SOAP_OBJECT_STRUCT; | ||
| 839 | + | ||
| 840 | + if (!$this->_isSoapValue($soapval)) { | ||
| 841 | + return $soapval; | ||
| 842 | + } elseif (is_array($soapval->value)) { | ||
| 843 | + if ($SOAP_OBJECT_STRUCT && $soapval->type != 'Array') { | ||
| 844 | + $classname = $this->_defaultObjectClassname; | ||
| 845 | + if (isset($this->_type_translation[$soapval->tqn->fqn()])) { | ||
| 846 | + // This will force an error in PHP if the class does not | ||
| 847 | + // exist. | ||
| 848 | + $classname = $this->_type_translation[$soapval->tqn->fqn()]; | ||
| 849 | + } elseif (isset($this->_type_translation[$soapval->type])) { | ||
| 850 | + // This will force an error in PHP if the class does not | ||
| 851 | + // exist. | ||
| 852 | + $classname = $this->_type_translation[$soapval->type]; | ||
| 853 | + } elseif ($this->_auto_translation) { | ||
| 854 | + if (class_exists($soapval->type)) { | ||
| 855 | + $classname = $soapval->type; | ||
| 856 | + } elseif ($this->_wsdl) { | ||
| 857 | + $t = $this->_wsdl->getComplexTypeNameForElement($soapval->name, $soapval->namespace); | ||
| 858 | + if ($t && class_exists($t)) { | ||
| 859 | + $classname = $t; | ||
| 860 | + } | ||
| 861 | + } | ||
| 862 | + } | ||
| 863 | + $return =& new $classname; | ||
| 864 | + } else { | ||
| 865 | + $return = array(); | ||
| 866 | + } | ||
| 867 | + | ||
| 868 | + $counter = 1; | ||
| 869 | + $isstruct = !$SOAP_OBJECT_STRUCT || !is_array($return); | ||
| 870 | + foreach ($soapval->value as $item) { | ||
| 871 | + if (is_object($return)) { | ||
| 872 | + if ($this->_wsdl) { | ||
| 873 | + // Get this child's WSDL information. | ||
| 874 | + // /$soapval->ns/$soapval->type/$item->ns/$item->name | ||
| 875 | + $child_type = $this->_wsdl->getComplexTypeChildType( | ||
| 876 | + $soapval->namespace, | ||
| 877 | + $soapval->name, | ||
| 878 | + $item->namespace, | ||
| 879 | + $item->name); | ||
| 880 | + if ($child_type) { | ||
| 881 | + $item->type = $child_type; | ||
| 882 | + } | ||
| 883 | + } | ||
| 884 | + if (!$isstruct || $item->type == 'Array') { | ||
| 885 | + if (isset($return->{$item->name}) && | ||
| 886 | + is_object($return->{$item->name})) { | ||
| 887 | + $return->{$item->name} =& $this->_decode($item); | ||
| 888 | + } elseif (isset($return->{$item->name}) && | ||
| 889 | + is_array($return->{$item->name})) { | ||
| 890 | + $return->{$item->name}[] = $this->_decode($item); | ||
| 891 | + } elseif (is_array($return)) { | ||
| 892 | + $return[] =& $this->_decode($item); | ||
| 893 | + } else { | ||
| 894 | + $return->{$item->name} =& $this->_decode($item); | ||
| 895 | + } | ||
| 896 | + } elseif (isset($return->{$item->name})) { | ||
| 897 | + $isstruct = false; | ||
| 898 | + if (count(get_object_vars($return)) == 1) { | ||
| 899 | + $d =& $this->_decode($item); | ||
| 900 | + $return = array($return->{$item->name}, $d); | ||
| 901 | + } else { | ||
| 902 | + $d =& $this->_decode($item); | ||
| 903 | + $return->{$item->name} = array($return->{$item->name}, $d); | ||
| 904 | + } | ||
| 905 | + } else { | ||
| 906 | + $return->{$item->name} =& $this->_decode($item); | ||
| 907 | + } | ||
| 908 | + // Set the attributes as members in the class. | ||
| 909 | + if (method_exists($return, '__set_attribute')) { | ||
| 910 | + foreach ($soapval->attributes as $key => $value) { | ||
| 911 | + call_user_func_array(array(&$return, | ||
| 912 | + '__set_attribute'), | ||
| 913 | + array($key, $value)); | ||
| 914 | + } | ||
| 915 | + } | ||
| 916 | + } else { | ||
| 917 | + if ($soapval->arrayType && $this->_isSoapValue($item)) { | ||
| 918 | + if ($this->_isBase64Type($item->type) && | ||
| 919 | + !$this->_isBase64Type($soapval->arrayType)) { | ||
| 920 | + // Decode the value if we're losing the base64 | ||
| 921 | + // type information. | ||
| 922 | + $item->value = base64_decode($item->value); | ||
| 923 | + } | ||
| 924 | + $item->type = $soapval->arrayType; | ||
| 925 | + } | ||
| 926 | + if (!$isstruct) { | ||
| 927 | + $return[] = $this->_decode($item); | ||
| 928 | + } elseif (isset($return[$item->name])) { | ||
| 929 | + $isstruct = false; | ||
| 930 | + $d =& $this->_decode($item); | ||
| 931 | + $return = array($return[$item->name], $d); | ||
| 932 | + } else { | ||
| 933 | + $return[$item->name] = $this->_decode($item); | ||
| 934 | + } | ||
| 935 | + } | ||
| 936 | + } | ||
| 937 | + | ||
| 938 | + return $return; | ||
| 939 | + } | ||
| 940 | + | ||
| 941 | + if ($soapval->type == 'boolean') { | ||
| 942 | + if ($soapval->value != '0' && | ||
| 943 | + strcasecmp($soapval->value, 'false') != 0) { | ||
| 944 | + $soapval->value = true; | ||
| 945 | + } else { | ||
| 946 | + $soapval->value = false; | ||
| 947 | + } | ||
| 948 | + } elseif ($soapval->type && | ||
| 949 | + isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type])) { | ||
| 950 | + // If we can, set variable type. | ||
| 951 | + settype($soapval->value, | ||
| 952 | + $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]); | ||
| 953 | + } | ||
| 954 | + | ||
| 955 | + if ($this->_isBase64Type($soapval->type)) { | ||
| 956 | + return base64_decode($soapval->value); | ||
| 957 | + } else { | ||
| 958 | + return $soapval->value; | ||
| 959 | + } | ||
| 960 | + } | ||
| 961 | + | ||
| 962 | + /** | ||
| 963 | + * Creates the SOAP envelope with the SOAP envelop data. | ||
| 964 | + * | ||
| 965 | + * @access private | ||
| 966 | + * | ||
| 967 | + * @param | ||
| 968 | + * @param array $headers | ||
| 969 | + * @param string $encoding | ||
| 970 | + * @param array $options | ||
| 971 | + * | ||
| 972 | + * @return string | ||
| 973 | + */ | ||
| 974 | + function _makeEnvelope(&$method, &$headers, | ||
| 975 | + $encoding = SOAP_DEFAULT_ENCODING, | ||
| 976 | + $options = array()) | ||
| 977 | + { | ||
| 978 | + $smsg = $header_xml = $ns_string = ''; | ||
| 979 | + | ||
| 980 | + if ($headers) { | ||
| 981 | + $c = count($headers); | ||
| 982 | + for ($i = 0; $i < $c; $i++) { | ||
| 983 | + $header_xml .= $headers[$i]->serialize($this); | ||
| 984 | + } | ||
| 985 | + $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n"; | ||
| 986 | + } | ||
| 987 | + | ||
| 988 | + if (!isset($options['input']) || $options['input'] == 'parse') { | ||
| 989 | + if (is_array($method)) { | ||
| 990 | + $c = count($method); | ||
| 991 | + for ($i = 0; $i < $c; $i++) { | ||
| 992 | + $smsg .= $method[$i]->serialize($this); | ||
| 993 | + } | ||
| 994 | + } else { | ||
| 995 | + $smsg = $method->serialize($this); | ||
| 996 | + } | ||
| 997 | + } else { | ||
| 998 | + $smsg = $method; | ||
| 999 | + } | ||
| 1000 | + $body = "<SOAP-ENV:Body>\r\n" . $smsg . "\r\n</SOAP-ENV:Body>\r\n"; | ||
| 1001 | + | ||
| 1002 | + foreach ($this->_namespaces as $k => $v) { | ||
| 1003 | + $ns_string .= " xmlns:$v=\"$k\"\r\n"; | ||
| 1004 | + } | ||
| 1005 | + if ($this->_namespace) { | ||
| 1006 | + $ns_string .= " xmlns=\"{$this->_namespace}\"\r\n"; | ||
| 1007 | + } | ||
| 1008 | + | ||
| 1009 | + /* If 'use' == 'literal', we do not put in the encodingStyle. This is | ||
| 1010 | + * denoted by $this->_section5 being false. 'use' can be defined at a | ||
| 1011 | + * more granular level than we are dealing with here, so this does not | ||
| 1012 | + * work for all services. */ | ||
| 1013 | + $xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n". | ||
| 1014 | + "<SOAP-ENV:Envelope $ns_string". | ||
| 1015 | + ($this->_section5 ? ' SOAP-ENV:encodingStyle="' . SOAP_SCHEMA_ENCODING . '"' : ''). | ||
| 1016 | + ">\r\n". | ||
| 1017 | + "$header_xml$body</SOAP-ENV:Envelope>\r\n"; | ||
| 1018 | + | ||
| 1019 | + return $xml; | ||
| 1020 | + } | ||
| 1021 | + | ||
| 1022 | + function _makeMimeMessage(&$xml, $encoding = SOAP_DEFAULT_ENCODING) | ||
| 1023 | + { | ||
| 1024 | + global $SOAP_options; | ||
| 1025 | + | ||
| 1026 | + if (!isset($SOAP_options['Mime'])) { | ||
| 1027 | + return $this->_raiseSoapFault('Mime is not installed'); | ||
| 1028 | + } | ||
| 1029 | + | ||
| 1030 | + // Encode any attachments. | ||
| 1031 | + // See http://www.w3.org/TR/SOAP-attachments | ||
| 1032 | + // Now we have to mime encode the message. | ||
| 1033 | + $params = array('content_type' => 'multipart/related; type=text/xml'); | ||
| 1034 | + $msg =& new Mail_mimePart('', $params); | ||
| 1035 | + | ||
| 1036 | + // Add the xml part. | ||
| 1037 | + $params['content_type'] = 'text/xml'; | ||
| 1038 | + $params['charset'] = $encoding; | ||
| 1039 | + $params['encoding'] = 'base64'; | ||
| 1040 | + $msg->addSubPart($xml, $params); | ||
| 1041 | + | ||
| 1042 | + // Add the attachements | ||
| 1043 | + $c = count($this->__attachments); | ||
| 1044 | + for ($i = 0; $i < $c; $i++) { | ||
| 1045 | + $attachment =& $this->__attachments[$i]; | ||
| 1046 | + $msg->addSubPart($attachment['body'], $attachment); | ||
| 1047 | + } | ||
| 1048 | + | ||
| 1049 | + return $msg->encode(); | ||
| 1050 | + } | ||
| 1051 | + | ||
| 1052 | + // TODO: this needs to be used from the Transport system. | ||
| 1053 | + function _makeDIMEMessage($xml) | ||
| 1054 | + { | ||
| 1055 | + global $SOAP_options; | ||
| 1056 | + | ||
| 1057 | + if (!isset($SOAP_options['DIME'])) { | ||
| 1058 | + return $this->_raiseSoapFault('DIME is not installed'); | ||
| 1059 | + } | ||
| 1060 | + | ||
| 1061 | + // Encode any attachments. | ||
| 1062 | + // See http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt | ||
| 1063 | + // Now we have to DIME encode the message | ||
| 1064 | + $dime =& new Net_DIME_Message(); | ||
| 1065 | + $msg = $dime->encodeData($xml, SOAP_ENVELOP, null, NET_DIME_TYPE_URI); | ||
| 1066 | + | ||
| 1067 | + // Add the attachments. | ||
| 1068 | + $c = count($this->__attachments); | ||
| 1069 | + for ($i = 0; $i < $c; $i++) { | ||
| 1070 | + $attachment =& $this->__attachments[$i]; | ||
| 1071 | + $msg .= $dime->encodeData($attachment['body'], | ||
| 1072 | + $attachment['content_type'], | ||
| 1073 | + $attachment['cid'], | ||
| 1074 | + NET_DIME_TYPE_MEDIA); | ||
| 1075 | + } | ||
| 1076 | + $msg .= $dime->endMessage(); | ||
| 1077 | + | ||
| 1078 | + return $msg; | ||
| 1079 | + } | ||
| 1080 | + | ||
| 1081 | + function _decodeMimeMessage(&$data, &$headers, &$attachments) | ||
| 1082 | + { | ||
| 1083 | + global $SOAP_options; | ||
| 1084 | + | ||
| 1085 | + if (!isset($SOAP_options['Mime'])) { | ||
| 1086 | + $this->_raiseSoapFault('Mime Unsupported, install PEAR::Mail::Mime', '', '', 'Server'); | ||
| 1087 | + return; | ||
| 1088 | + } | ||
| 1089 | + | ||
| 1090 | + $params['include_bodies'] = true; | ||
| 1091 | + $params['decode_bodies'] = true; | ||
| 1092 | + $params['decode_headers'] = true; | ||
| 1093 | + | ||
| 1094 | + // Lame thing to have to do for decoding. | ||
| 1095 | + $decoder =& new Mail_mimeDecode($data); | ||
| 1096 | + $structure = $decoder->decode($params); | ||
| 1097 | + | ||
| 1098 | + if (isset($structure->body)) { | ||
| 1099 | + $data = $structure->body; | ||
| 1100 | + $headers = $structure->headers; | ||
| 1101 | + | ||
| 1102 | + return; | ||
| 1103 | + } elseif (isset($structure->parts)) { | ||
| 1104 | + $data = $structure->parts[0]->body; | ||
| 1105 | + $headers = array_merge($structure->headers, | ||
| 1106 | + $structure->parts[0]->headers); | ||
| 1107 | + if (count($structure->parts) > 1) { | ||
| 1108 | + $mime_parts = array_splice($structure->parts,1); | ||
| 1109 | + // Prepare the parts for the SOAP parser. | ||
| 1110 | + | ||
| 1111 | + $c = count($mime_parts); | ||
| 1112 | + for ($i = 0; $i < $c; $i++) { | ||
| 1113 | + $p =& $mime_parts[$i]; | ||
| 1114 | + if (isset($p->headers['content-location'])) { | ||
| 1115 | + // TODO: modify location per SwA note section 3 | ||
| 1116 | + // http://www.w3.org/TR/SOAP-attachments | ||
| 1117 | + $attachments[$p->headers['content-location']] = $p->body; | ||
| 1118 | + } else { | ||
| 1119 | + $cid = 'cid:' . substr($p->headers['content-id'], 1, -1); | ||
| 1120 | + $attachments[$cid] = $p->body; | ||
| 1121 | + } | ||
| 1122 | + } | ||
| 1123 | + } | ||
| 1124 | + | ||
| 1125 | + return; | ||
| 1126 | + } | ||
| 1127 | + | ||
| 1128 | + $this->_raiseSoapFault('Mime parsing error', '', '', 'Server'); | ||
| 1129 | + } | ||
| 1130 | + | ||
| 1131 | + function _decodeDIMEMessage(&$data, &$headers, &$attachments) | ||
| 1132 | + { | ||
| 1133 | + global $SOAP_options; | ||
| 1134 | + | ||
| 1135 | + if (!isset($SOAP_options['DIME'])) { | ||
| 1136 | + $this->_raiseSoapFault('DIME Unsupported, install PEAR::Net::DIME', '', '', 'Server'); | ||
| 1137 | + return; | ||
| 1138 | + } | ||
| 1139 | + | ||
| 1140 | + // This SHOULD be moved to the transport layer, e.g. PHP itself should | ||
| 1141 | + // handle parsing DIME ;) | ||
| 1142 | + $dime =& new Net_DIME_Message(); | ||
| 1143 | + $err = $dime->decodeData($data); | ||
| 1144 | + if (PEAR::isError($err)) { | ||
| 1145 | + $this->_raiseSoapFault('Failed to decode the DIME message!', '', '', 'Server'); | ||
| 1146 | + return; | ||
| 1147 | + } | ||
| 1148 | + if (strcasecmp($dime->parts[0]['type'], SOAP_ENVELOP) != 0) { | ||
| 1149 | + $this->_raiseSoapFault('DIME record 1 is not a SOAP envelop!', '', '', 'Server'); | ||
| 1150 | + return; | ||
| 1151 | + } | ||
| 1152 | + | ||
| 1153 | + $data = $dime->parts[0]['data']; | ||
| 1154 | + // Fake it for now. | ||
| 1155 | + $headers['content-type'] = 'text/xml'; | ||
| 1156 | + $c = count($dime->parts); | ||
| 1157 | + for ($i = 0; $i < $c; $i++) { | ||
| 1158 | + $part =& $dime->parts[$i]; | ||
| 1159 | + // We need to handle URI's better. | ||
| 1160 | + $id = strncmp($part['id'], 'cid:', 4) | ||
| 1161 | + ? 'cid:' . $part['id'] | ||
| 1162 | + : $part['id']; | ||
| 1163 | + $attachments[$id] = $part['data']; | ||
| 1164 | + } | ||
| 1165 | + } | ||
| 1166 | + | ||
| 1167 | + function __set_type_translation($type, $class = null) | ||
| 1168 | + { | ||
| 1169 | + $tq =& new QName($type); | ||
| 1170 | + if (!$class) { | ||
| 1171 | + $class = $tq->name; | ||
| 1172 | + } | ||
| 1173 | + $this->_type_translation[$type]=$class; | ||
| 1174 | + } | ||
| 1175 | + | ||
| 1176 | +} | ||
| 1177 | + | ||
| 1178 | +/** | ||
| 1179 | + * Class used to handle QNAME values in XML. | ||
| 1180 | + * | ||
| 1181 | + * @access public | ||
| 1182 | + * @package SOAP | ||
| 1183 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 1184 | + */ | ||
| 1185 | +class QName | ||
| 1186 | +{ | ||
| 1187 | + var $name = ''; | ||
| 1188 | + var $ns = ''; | ||
| 1189 | + var $namespace=''; | ||
| 1190 | + | ||
| 1191 | + function QName($name, $namespace = '') | ||
| 1192 | + { | ||
| 1193 | + if ($name && $name[0] == '{') { | ||
| 1194 | + preg_match('/\{(.*?)\}(.*)/', $name, $m); | ||
| 1195 | + $this->name = $m[2]; | ||
| 1196 | + $this->namespace = $m[1]; | ||
| 1197 | + } elseif (substr_count($name, ':') == 1) { | ||
| 1198 | + $s = explode(':', $name); | ||
| 1199 | + $s = array_reverse($s); | ||
| 1200 | + $this->name = $s[0]; | ||
| 1201 | + $this->ns = $s[1]; | ||
| 1202 | + $this->namespace = $namespace; | ||
| 1203 | + } else { | ||
| 1204 | + $this->name = $name; | ||
| 1205 | + $this->namespace = $namespace; | ||
| 1206 | + } | ||
| 1207 | + | ||
| 1208 | + // A little more magic than should be in a qname. | ||
| 1209 | + $p = strpos($this->name, '['); | ||
| 1210 | + if ($p) { | ||
| 1211 | + // TODO: Need to re-examine this logic later. | ||
| 1212 | + // Chop off []. | ||
| 1213 | + $this->arraySize = explode(',', substr($this->name, $p + 1, -$p - 2)); | ||
| 1214 | + $this->arrayInfo = substr($this->name, $p); | ||
| 1215 | + $this->name = substr($this->name, 0, $p); | ||
| 1216 | + } | ||
| 1217 | + } | ||
| 1218 | + | ||
| 1219 | + function fqn() | ||
| 1220 | + { | ||
| 1221 | + if ($this->namespace) { | ||
| 1222 | + return '{' . $this->namespace . '}' . $this->name; | ||
| 1223 | + } elseif ($this->ns) { | ||
| 1224 | + return $this->ns . ':' . $this->name; | ||
| 1225 | + } | ||
| 1226 | + return $this->name; | ||
| 1227 | + } | ||
| 1228 | + | ||
| 1229 | +} |
thirdparty/pear/SOAP/Disco.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the DISCO server, providing DISO and WSDL | ||
| 4 | + * services. | ||
| 5 | + * | ||
| 6 | + * PHP versions 4 and 5 | ||
| 7 | + * | ||
| 8 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 9 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 10 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 11 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 12 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 13 | + * mail you a copy immediately. | ||
| 14 | + * | ||
| 15 | + * @category Web Services | ||
| 16 | + * @package SOAP | ||
| 17 | + * @author Dmitri Vinogradov <dimitri@vinogradov.de> | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> | ||
| 19 | + * @author Jan Schneider <jan@horde.org> | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Base.php'; | ||
| 26 | + | ||
| 27 | +class SOAP_DISCO_Server extends SOAP_Base_Object { | ||
| 28 | + | ||
| 29 | + var $namespaces = array(SCHEMA_WSDL => 'wsdl', SCHEMA_SOAP => 'soap'); | ||
| 30 | + var $import_ns = array(); | ||
| 31 | + var $wsdl = ''; | ||
| 32 | + var $disco = ''; | ||
| 33 | + var $_wsdl = array(); | ||
| 34 | + var $_disco = array(); | ||
| 35 | + var $_service_name = ''; | ||
| 36 | + var $_service_ns = ''; | ||
| 37 | + var $_service_desc = ''; | ||
| 38 | + var $_portname = ''; | ||
| 39 | + var $_bindingname = ''; | ||
| 40 | + var $soap_server = NULL; | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + function SOAP_DISCO_Server($soap_server, $service_name, $service_desc = '', | ||
| 44 | + $import_ns = null) | ||
| 45 | + { | ||
| 46 | + parent::SOAP_Base_Object('Server'); | ||
| 47 | + | ||
| 48 | + if ( !is_object($soap_server) | ||
| 49 | + || !get_class($soap_server) == 'soap_server') return; | ||
| 50 | + | ||
| 51 | + $this->_service_name = $service_name; | ||
| 52 | + $this->_service_ns = "urn:$service_name"; | ||
| 53 | + $this->_service_desc = $service_desc; | ||
| 54 | + $this->import_ns = isset($import_ns) ? $import_ns : $this->import_ns; | ||
| 55 | + $this->soap_server = $soap_server; | ||
| 56 | + $this->host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost'; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + function getDISCO() | ||
| 60 | + { | ||
| 61 | + $this->_generate_DISCO(); | ||
| 62 | + return $this->disco; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + function getWSDL() | ||
| 66 | + { | ||
| 67 | + $this->_generate_WSDL(); | ||
| 68 | + return $this->wsdl; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + function _generate_DISCO() | ||
| 72 | + { | ||
| 73 | + // DISCO | ||
| 74 | + $this->_disco['disco:discovery']['attr']['xmlns:disco'] = SCHEMA_DISCO; | ||
| 75 | + $this->_disco['disco:discovery']['attr']['xmlns:scl'] = SCHEMA_DISCO_SCL; | ||
| 76 | + $this->_disco['disco:discovery']['scl:contractRef']['attr']['ref'] = | ||
| 77 | + (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') | ||
| 78 | + ? 'https://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl' | ||
| 79 | + : 'http://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl'; | ||
| 80 | + | ||
| 81 | + // generate disco xml | ||
| 82 | + $this->_generate_DISCO_XML($this->_disco); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + function _generate_WSDL() | ||
| 86 | + { | ||
| 87 | + // WSDL | ||
| 88 | + if (is_array($this->soap_server->_namespaces)) { | ||
| 89 | + // need to get: typens, xsd & SOAP-ENC | ||
| 90 | + $flipped = array_flip($this->soap_server->_namespaces); | ||
| 91 | + $this->namespaces[$this->_service_ns] = 'tns'; | ||
| 92 | + $this->namespaces[$flipped['xsd']] = 'xsd'; | ||
| 93 | + $this->namespaces[$flipped['SOAP-ENC']] = 'SOAP-ENC'; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + // DEFINITIONS | ||
| 97 | + $this->_wsdl['definitions']['attr']['name'] = $this->_service_name; | ||
| 98 | + $this->_wsdl['definitions']['attr']['targetNamespace'] = $this->_service_ns; | ||
| 99 | + foreach ($this->namespaces as $ns => $prefix) { | ||
| 100 | + $this->_wsdl['definitions']['attr']['xmlns:' . $prefix] = $ns; | ||
| 101 | + } | ||
| 102 | + $this->_wsdl['definitions']['attr']['xmlns'] = SCHEMA_WSDL; | ||
| 103 | + | ||
| 104 | + // Import namespaces. Seems to not work yet: wsdl.exe fom .NET can't | ||
| 105 | + // handle imported complete wsdl-definitions. | ||
| 106 | + if (count($this->import_ns)) { | ||
| 107 | + $i = 0; | ||
| 108 | + foreach ($this->import_ns as $_ns => $_location) { | ||
| 109 | + $this->_wsdl['definitions']['import'][$i]['attr']['location'] = $_location; | ||
| 110 | + $this->_wsdl['definitions']['import'][$i]['attr']['namespace'] = $_ns; | ||
| 111 | + $i++; | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + $this->_wsdl['definitions']['types']['attr']['xmlns']='http://schemas.xmlsoap.org/wsdl/'; | ||
| 115 | + $this->_wsdl['definitions']['types']['schema']=array(); | ||
| 116 | + | ||
| 117 | + // Placeholder for messages | ||
| 118 | + $this->_wsdl['definitions']['message'] = array(); | ||
| 119 | + | ||
| 120 | + // PORTTYPE-NAME | ||
| 121 | + $this->_portname = $this->_service_name . 'Port'; | ||
| 122 | + $this->_wsdl['definitions']['portType']['attr']['name'] = $this->_portname; | ||
| 123 | + | ||
| 124 | + // BINDING-NAME | ||
| 125 | + $this->_bindingname = $this->_service_name . 'Binding'; | ||
| 126 | + $this->_wsdl['definitions']['binding']['attr']['name'] = $this->_bindingname; | ||
| 127 | + $this->_wsdl['definitions']['binding']['attr']['type'] = 'tns:' . $this->_portname; | ||
| 128 | + $this->_wsdl['definitions']['binding']['soap:binding']['attr']['style'] = 'rpc'; | ||
| 129 | + $this->_wsdl['definitions']['binding']['soap:binding']['attr']['transport'] = SCHEMA_SOAP_HTTP; | ||
| 130 | + | ||
| 131 | + // SERVICE | ||
| 132 | + $this->_wsdl['definitions']['service']['attr']['name'] = $this->_service_name . 'Service'; | ||
| 133 | + $this->_wsdl['definitions']['service']['documentation']['attr'] = ''; | ||
| 134 | + $this->_wsdl['definitions']['service']['documentation'] = htmlentities($this->_service_desc); | ||
| 135 | + $this->_wsdl['definitions']['service']['port']['attr']['name'] = $this->_portname; | ||
| 136 | + $this->_wsdl['definitions']['service']['port']['attr']['binding'] = 'tns:' . $this->_bindingname; | ||
| 137 | + $this->_wsdl['definitions']['service']['port']['soap:address']['attr']['location'] = | ||
| 138 | + (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on') | ||
| 139 | + ? 'https://' . $this->host . $_SERVER['PHP_SELF'] | ||
| 140 | + : 'http://' . $this->host . $_SERVER['PHP_SELF']; | ||
| 141 | + | ||
| 142 | + // | ||
| 143 | + $dispatch_keys = array_keys($this->soap_server->dispatch_objects); | ||
| 144 | + $dc = count($dispatch_keys); | ||
| 145 | + for ($di = 0; $di < $dc; $di++) { | ||
| 146 | + $namespace = $dispatch_keys[$di]; | ||
| 147 | + $namespace_objects =& $this->soap_server->dispatch_objects[$namespace]; | ||
| 148 | + $oc = count($namespace_objects); | ||
| 149 | + for ($oi = 0; $oi < $oc; $oi++) { | ||
| 150 | + $object = $namespace_objects[$oi]; | ||
| 151 | + // types definitions | ||
| 152 | + $this->addSchemaFromMap($object->__typedef); | ||
| 153 | + // MESSAGES | ||
| 154 | + $this->addMethodsFromMap($object->__dispatch_map, $namespace, get_class($object)); | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + if (isset($server->dispatch_map)) { | ||
| 158 | + $this->addMethodsFromMap($server->dispatch_map, $namespace); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + // generate wsdl | ||
| 162 | + $this->_generate_WSDL_XML(); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + function &_getSchema($namespace) | ||
| 166 | + { | ||
| 167 | + // SCHEMA | ||
| 168 | + $c = count($this->_wsdl['definitions']['types']['schema']); | ||
| 169 | + for($i = 0; $i < $c; $i++) { | ||
| 170 | + if ($this->_wsdl['definitions']['types']['schema'][$i]['attr']['targetNamespace'] == $namespace) { | ||
| 171 | + return $this->_wsdl['definitions']['types']['schema'][$i]; | ||
| 172 | + } | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + // don't have this namespace | ||
| 176 | + $schema = array(); | ||
| 177 | + $schema['attr'] = array(); | ||
| 178 | + $schema['complexType'] = array(); | ||
| 179 | + $schema['attr']['xmlns'] = array_search('xsd',$this->namespaces); | ||
| 180 | + $schema['attr']['targetNamespace'] = $namespace; | ||
| 181 | + $this->_wsdl['definitions']['types']['schema'][] =& $schema; | ||
| 182 | + | ||
| 183 | + return $schema; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + function addSchemaFromMap(&$map) | ||
| 187 | + { | ||
| 188 | + if (!$map) { | ||
| 189 | + return; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + foreach ($map as $_type_name => $_type_def) { | ||
| 193 | + list($typens,$type) = $this->_getTypeNs($_type_name); | ||
| 194 | + if ($typens == 'xsd') { | ||
| 195 | + // cannot add to xsd, lets use method_namespace | ||
| 196 | + $typens = 'tns'; | ||
| 197 | + } | ||
| 198 | + $schema =& $this->_getSchema(array_search($typens, $this->namespaces)); | ||
| 199 | + if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) { | ||
| 200 | + $ctype =& $schema['complexType'][]; | ||
| 201 | + $ctype['attr']['name'] = $type; | ||
| 202 | + foreach ($_type_def as $_varname => $_vartype) { | ||
| 203 | + if (!is_int($_varname)) { | ||
| 204 | + list($_vartypens,$_vartype) = $this->_getTypeNs($_vartype); | ||
| 205 | + $ctype['all']['attr'] = ''; | ||
| 206 | + $el =& $ctype['all']['element'][]; | ||
| 207 | + $el['attr']['name'] = $_varname; | ||
| 208 | + $el['attr']['type'] = $_vartypens . ':' . $_vartype; | ||
| 209 | + } else { | ||
| 210 | + $ctype['complexContent']['attr'] = ''; | ||
| 211 | + $ctype['complexContent']['restriction']['attr']['base'] = 'SOAP-ENC:Array'; | ||
| 212 | + foreach ($_vartype as $array_var => $array_type) { | ||
| 213 | + list($_vartypens, $_vartype) = $this->_getTypeNs($array_type); | ||
| 214 | + $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = 'SOAP-ENC:arrayType'; | ||
| 215 | + $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]'; | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + } | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + function addMethodsFromMap(&$map, $namespace, $classname = null) | ||
| 224 | + { | ||
| 225 | + if (!$map) { | ||
| 226 | + return; | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + foreach ($map as $method_name => $method_types) { | ||
| 230 | + if (array_key_exists('namespace', $method_types)) { | ||
| 231 | + $method_namespace = $method_types['namespace']; | ||
| 232 | + } else { | ||
| 233 | + $method_namespace = $namespace; | ||
| 234 | + } | ||
| 235 | + // INPUT | ||
| 236 | + if (isset($method_types['in']) && is_array($method_types['in'])) { | ||
| 237 | + $input_message =& $this->_wsdl['definitions']['message'][]; | ||
| 238 | + $input_message['attr']['name'] = $method_name . 'Request'; | ||
| 239 | + foreach ($method_types['in'] as $name => $type) { | ||
| 240 | + list($typens, $type) = $this->_getTypeNs($type); | ||
| 241 | + $part =& $input_message['part'][]; | ||
| 242 | + $part['attr']['name'] = $name; | ||
| 243 | + $part['attr']['type'] = $typens . ':' . $type; | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + // OUTPUT | ||
| 248 | + if (isset($method_types['out']) && is_array($method_types['out'])) { | ||
| 249 | + $output_message =& $this->_wsdl['definitions']['message'][]; | ||
| 250 | + $output_message['attr']['name'] = $method_name . 'Response'; | ||
| 251 | + foreach ($method_types['out'] as $name => $type) { | ||
| 252 | + list($typens, $type) = $this->_getTypeNs($type); | ||
| 253 | + $part =& $output_message['part'][]; | ||
| 254 | + $part['attr']['name'] = $name; | ||
| 255 | + $part['attr']['type'] = $typens . ':' . $type; | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + // PORTTYPES | ||
| 260 | + $operation =& $this->_wsdl['definitions']['portType']['operation'][]; | ||
| 261 | + $operation['attr']['name'] = $method_name; | ||
| 262 | + | ||
| 263 | + // INPUT | ||
| 264 | + $operation['input']['attr']['message'] = 'tns:' | ||
| 265 | + . $input_message['attr']['name']; | ||
| 266 | + | ||
| 267 | + // OUTPUT | ||
| 268 | + $operation['output']['attr']['message'] = 'tns:' | ||
| 269 | + . $output_message['attr']['name']; | ||
| 270 | + | ||
| 271 | + // BINDING | ||
| 272 | + $binding =& $this->_wsdl['definitions']['binding']['operation'][]; | ||
| 273 | + $binding['attr']['name'] = $method_name; | ||
| 274 | + $action = $method_namespace . '#' . ($classname ? $classname . '#' : '') . $method_name; | ||
| 275 | + $binding['soap:operation']['attr']['soapAction'] = $action; | ||
| 276 | + | ||
| 277 | + // INPUT | ||
| 278 | + $binding['input']['attr'] = ''; | ||
| 279 | + $binding['input']['soap:body']['attr']['use'] = 'encoded'; | ||
| 280 | + $binding['input']['soap:body']['attr']['namespace'] = $method_namespace; | ||
| 281 | + $binding['input']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING; | ||
| 282 | + | ||
| 283 | + // OUTPUT | ||
| 284 | + $binding['output']['attr'] = ''; | ||
| 285 | + $binding['output']['soap:body']['attr']['use'] = 'encoded'; | ||
| 286 | + $binding['output']['soap:body']['attr']['namespace'] = $method_namespace; | ||
| 287 | + $binding['output']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING; | ||
| 288 | + } | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + function _generate_DISCO_XML($disco_array) | ||
| 292 | + { | ||
| 293 | + $disco = '<?xml version="1.0"?>'; | ||
| 294 | + foreach ($disco_array as $key => $val) { | ||
| 295 | + $disco .= $this->_arrayToNode($key,$val); | ||
| 296 | + } | ||
| 297 | + $this->disco = $disco; | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + function _generate_WSDL_XML() | ||
| 301 | + { | ||
| 302 | + $wsdl = '<?xml version="1.0"?>'; | ||
| 303 | + foreach ($this->_wsdl as $key => $val) { | ||
| 304 | + $wsdl .= $this->_arrayToNode($key, $val); | ||
| 305 | + } | ||
| 306 | + $this->wsdl = $wsdl; | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + function _arrayToNode($node_name = '', $array) | ||
| 310 | + { | ||
| 311 | + $return = ''; | ||
| 312 | + if (is_array($array)) { | ||
| 313 | + // we have a node if there's key 'attr' | ||
| 314 | + if (array_key_exists('attr',$array)) { | ||
| 315 | + $return .= "<$node_name"; | ||
| 316 | + if (is_array($array['attr'])) { | ||
| 317 | + foreach ($array['attr'] as $attr_name => $attr_value) { | ||
| 318 | + $return .= " $attr_name=\"$attr_value\""; | ||
| 319 | + } | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + // unset 'attr' and proceed other childs... | ||
| 323 | + unset($array['attr']); | ||
| 324 | + | ||
| 325 | + if (count($array) > 0) { | ||
| 326 | + $i = 0; | ||
| 327 | + foreach ($array as $child_node_name => $child_node_value) { | ||
| 328 | + $return .= $i == 0 ? ">\n" : ''; | ||
| 329 | + $return .= $this->_arrayToNode($child_node_name,$child_node_value); | ||
| 330 | + $i++; | ||
| 331 | + } | ||
| 332 | + $return .= "</$node_name>\n"; | ||
| 333 | + } else { | ||
| 334 | + $return .= " />\n"; | ||
| 335 | + } | ||
| 336 | + } else { | ||
| 337 | + // we have no 'attr' key in array - so it's list of nodes with | ||
| 338 | + // the same name ... | ||
| 339 | + foreach ($array as $child_node_name => $child_node_value) { | ||
| 340 | + $return .= $this->_arrayToNode($node_name,$child_node_value); | ||
| 341 | + } | ||
| 342 | + } | ||
| 343 | + } else { | ||
| 344 | + // $array is not an array | ||
| 345 | + if ($array !='') { | ||
| 346 | + // and its not empty | ||
| 347 | + $return .= "<$node_name>$array</$node_name>\n"; | ||
| 348 | + } else { | ||
| 349 | + // and its empty... | ||
| 350 | + $return .= "<$node_name />\n"; | ||
| 351 | + } | ||
| 352 | + } | ||
| 353 | + return $return; | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + function _getTypeNs($type) | ||
| 357 | + { | ||
| 358 | + preg_match_all("'\{(.*)\}'sm", $type, $m); | ||
| 359 | + if (isset($m[1][0]) && $m[1][0] != '') { | ||
| 360 | + if (!array_key_exists($m[1][0],$this->namespaces)) { | ||
| 361 | + $ns_pref = 'ns' . count($this->namespaces); | ||
| 362 | + $this->namespaces[$m[1][0]] = $ns_pref; | ||
| 363 | + $this->_wsdl['definitions']['attr']['xmlns:' . $ns_pref] = $m[1][0]; | ||
| 364 | + } | ||
| 365 | + $typens = $this->namespaces[$m[1][0]]; | ||
| 366 | + $type = ereg_replace($m[0][0],'',$type); | ||
| 367 | + } else { | ||
| 368 | + $typens = 'xsd'; | ||
| 369 | + } | ||
| 370 | + return array($typens,$type); | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + function _ifComplexTypeExists($typesArray, $type_name) | ||
| 374 | + { | ||
| 375 | + if (is_array($typesArray)) { | ||
| 376 | + foreach ($typesArray as $index => $type_data) { | ||
| 377 | + if ($typesArray[$index]['attr']['name'] == $type_name) { | ||
| 378 | + return true; | ||
| 379 | + } | ||
| 380 | + } | ||
| 381 | + } | ||
| 382 | + return false; | ||
| 383 | + } | ||
| 384 | +} |
thirdparty/pear/SOAP/Fault.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the SOAP_Fault class, used for all error objects in this | ||
| 4 | + * package. | ||
| 5 | + * | ||
| 6 | + * PHP versions 4 and 5 | ||
| 7 | + * | ||
| 8 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 9 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 10 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 11 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 12 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 13 | + * mail you a copy immediately. | ||
| 14 | + * | ||
| 15 | + * @category Web Services | ||
| 16 | + * @package SOAP | ||
| 17 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 18 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 19 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 20 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 21 | + * @copyright 2003-2005 The PHP Group | ||
| 22 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 23 | + * @link http://pear.php.net/package/SOAP | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | +require_once('PEAR.php'); | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | + * SOAP_Fault | ||
| 30 | + * PEAR::Error wrapper used to match SOAP Faults to PEAR Errors | ||
| 31 | + * | ||
| 32 | + * @package SOAP | ||
| 33 | + * @access public | ||
| 34 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 35 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 36 | + */ | ||
| 37 | +class SOAP_Fault extends PEAR_Error | ||
| 38 | +{ | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * Constructor | ||
| 42 | + * | ||
| 43 | + * @param string message string for fault | ||
| 44 | + * @param mixed the faultcode | ||
| 45 | + * @param mixed see PEAR::ERROR | ||
| 46 | + * @param mixed see PEAR::ERROR | ||
| 47 | + * @param array the userinfo array is used to pass in the | ||
| 48 | + * SOAP actor and detail for the fault | ||
| 49 | + */ | ||
| 50 | + function SOAP_Fault($faultstring = 'unknown error', $faultcode = 'Client', $faultactor=NULL, $detail=NULL, $mode = null, $options = null) | ||
| 51 | + { | ||
| 52 | + parent::PEAR_Error($faultstring, $faultcode, $mode, $options, $detail); | ||
| 53 | + if ($faultactor) $this->error_message_prefix = $faultactor; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * message | ||
| 58 | + * | ||
| 59 | + * returns a SOAP_Message class that can be sent as a server response | ||
| 60 | + * | ||
| 61 | + * @return SOAP_Message | ||
| 62 | + * @access public | ||
| 63 | + */ | ||
| 64 | + function message() | ||
| 65 | + { | ||
| 66 | + $msg =& new SOAP_Base(); | ||
| 67 | + $params = array(); | ||
| 68 | + $params[] =& new SOAP_Value('faultcode', 'QName', 'SOAP-ENV:'.$this->code); | ||
| 69 | + $params[] =& new SOAP_Value('faultstring', 'string', $this->message); | ||
| 70 | + $params[] =& new SOAP_Value('faultactor', 'anyURI', $this->error_message_prefix); | ||
| 71 | + if (isset($this->backtrace)) { | ||
| 72 | + $params[] =& new SOAP_Value('detail', 'string', $this->backtrace); | ||
| 73 | + } else { | ||
| 74 | + $params[] =& new SOAP_Value('detail', 'string', $this->userinfo); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + $methodValue =& new SOAP_Value('{'.SOAP_ENVELOP.'}Fault', 'Struct', $params); | ||
| 78 | + $headers = NULL; | ||
| 79 | + return $msg->_makeEnvelope($methodValue, $headers); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * getFault | ||
| 84 | + * | ||
| 85 | + * returns a simple native php array containing the fault data | ||
| 86 | + * | ||
| 87 | + * @return array | ||
| 88 | + * @access public | ||
| 89 | + */ | ||
| 90 | + function getFault() | ||
| 91 | + { | ||
| 92 | + global $SOAP_OBJECT_STRUCT; | ||
| 93 | + if ($SOAP_OBJECT_STRUCT) { | ||
| 94 | + $fault =& new stdClass(); | ||
| 95 | + $fault->faultcode = $this->code; | ||
| 96 | + $fault->faultstring = $this->message; | ||
| 97 | + $fault->faultactor = $this->error_message_prefix; | ||
| 98 | + $fault->detail = $this->userinfo; | ||
| 99 | + return $fault; | ||
| 100 | + } | ||
| 101 | + return array( | ||
| 102 | + 'faultcode' => $this->code, | ||
| 103 | + 'faultstring' => $this->message, | ||
| 104 | + 'faultactor' => $this->error_message_prefix, | ||
| 105 | + 'detail' => $this->userinfo | ||
| 106 | + ); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * getActor | ||
| 111 | + * | ||
| 112 | + * returns the SOAP actor for the fault | ||
| 113 | + * | ||
| 114 | + * @return string | ||
| 115 | + * @access public | ||
| 116 | + */ | ||
| 117 | + function getActor() | ||
| 118 | + { | ||
| 119 | + return $this->error_message_prefix; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + /** | ||
| 123 | + * getDetail | ||
| 124 | + * | ||
| 125 | + * returns the fault detail | ||
| 126 | + * | ||
| 127 | + * @return string | ||
| 128 | + * @access public | ||
| 129 | + */ | ||
| 130 | + function getDetail() | ||
| 131 | + { | ||
| 132 | + return $this->userinfo; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | +} | ||
| 136 | +?> | ||
| 0 | \ No newline at end of file | 137 | \ No newline at end of file |
thirdparty/pear/SOAP/Parser.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the SOAP message parser. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 19 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Base.php'; | ||
| 26 | +require_once 'SOAP/Value.php'; | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | + * SOAP Parser | ||
| 30 | + * | ||
| 31 | + * This class is used by SOAP::Message and SOAP::Server to parse soap | ||
| 32 | + * packets. Originally based on SOAPx4 by Dietrich Ayala | ||
| 33 | + * http://dietrich.ganx4.com/soapx4 | ||
| 34 | + * | ||
| 35 | + * @access public | ||
| 36 | + * @package SOAP | ||
| 37 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 38 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 39 | + */ | ||
| 40 | +class SOAP_Parser extends SOAP_Base | ||
| 41 | +{ | ||
| 42 | + var $status = ''; | ||
| 43 | + var $position = 0; | ||
| 44 | + var $pos_stat = 0; | ||
| 45 | + var $depth = 0; | ||
| 46 | + var $default_namespace = ''; | ||
| 47 | + var $message = array(); | ||
| 48 | + var $depth_array = array(); | ||
| 49 | + var $previous_element = ''; | ||
| 50 | + var $soapresponse = null; | ||
| 51 | + var $soapheaders = null; | ||
| 52 | + var $parent = 0; | ||
| 53 | + var $root_struct_name = array(); | ||
| 54 | + var $header_struct_name = array(); | ||
| 55 | + var $curent_root_struct_name = ''; | ||
| 56 | + var $entities = array ( '&' => '&', '<' => '<', '>' => '>', "'" => ''', '"' => '"' ); | ||
| 57 | + var $root_struct = array(); | ||
| 58 | + var $header_struct = array(); | ||
| 59 | + var $curent_root_struct = 0; | ||
| 60 | + var $references = array(); | ||
| 61 | + var $need_references = array(); | ||
| 62 | + var $XMLSchemaVersion; | ||
| 63 | + var $bodyDepth; // used to handle non-root elements before root body element | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * SOAP_Parser constructor | ||
| 67 | + * | ||
| 68 | + * @param string xml content | ||
| 69 | + * @param string xml character encoding, defaults to 'UTF-8' | ||
| 70 | + */ | ||
| 71 | + function SOAP_Parser(&$xml, $encoding = SOAP_DEFAULT_ENCODING, $attachments = null) | ||
| 72 | + { | ||
| 73 | + parent::SOAP_Base('Parser'); | ||
| 74 | + $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION); | ||
| 75 | + | ||
| 76 | + $this->attachments = $attachments; | ||
| 77 | + | ||
| 78 | + // Check the xml tag for encoding. | ||
| 79 | + if (preg_match('/<\?xml[^>]+encoding\s*?=\s*?(\'([^\']*)\'|"([^"]*)")[^>]*?[\?]>/', $xml, $m)) { | ||
| 80 | + $encoding = strtoupper($m[2] ? $m[2] : $m[3]); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + // Determines where in the message we are | ||
| 84 | + // (envelope,header,body,method). Check whether content has | ||
| 85 | + // been read. | ||
| 86 | + if (!empty($xml)) { | ||
| 87 | + // Prepare the xml parser. | ||
| 88 | + $parser = xml_parser_create($encoding); | ||
| 89 | + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); | ||
| 90 | + xml_set_object($parser, $this); | ||
| 91 | + xml_set_element_handler($parser, 'startElement', 'endElement'); | ||
| 92 | + xml_set_character_data_handler($parser, 'characterData'); | ||
| 93 | + | ||
| 94 | + // Some lame soap implementations add null bytes at the | ||
| 95 | + // end of the soap stream, and expat choaks on that. | ||
| 96 | + if ($xml[strlen($xml) - 1] == 0) { | ||
| 97 | + $xml = trim($xml); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + // Parse the XML file. | ||
| 101 | + if (!xml_parse($parser, $xml, true)) { | ||
| 102 | + $err = sprintf('XML error on line %d col %d byte %d %s', | ||
| 103 | + xml_get_current_line_number($parser), | ||
| 104 | + xml_get_current_column_number($parser), | ||
| 105 | + xml_get_current_byte_index($parser), | ||
| 106 | + xml_error_string(xml_get_error_code($parser))); | ||
| 107 | + $this->_raiseSoapFault($err,htmlspecialchars($xml)); | ||
| 108 | + } | ||
| 109 | + xml_parser_free($parser); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * domulti | ||
| 116 | + * recurse to build a multi-dim array, used by buildResponse | ||
| 117 | + * | ||
| 118 | + * @access private | ||
| 119 | + */ | ||
| 120 | + function domulti($d, &$ar, &$r, &$v, $ad=0) | ||
| 121 | + { | ||
| 122 | + if ($d) { | ||
| 123 | + $this->domulti($d-1, $ar, $r[$ar[$ad]], $v, $ad+1); | ||
| 124 | + } else { | ||
| 125 | + $r = $v; | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + /** | ||
| 130 | + * buildResponse | ||
| 131 | + * loop through msg, building response structures | ||
| 132 | + * | ||
| 133 | + * @param int position | ||
| 134 | + * @return SOAP_Value | ||
| 135 | + * @access private | ||
| 136 | + */ | ||
| 137 | + function &buildResponse($pos) | ||
| 138 | + { | ||
| 139 | + $response = null; | ||
| 140 | + | ||
| 141 | + if (isset($this->message[$pos]['children'])) { | ||
| 142 | + $children = explode('|', $this->message[$pos]['children']); | ||
| 143 | + | ||
| 144 | + foreach ($children as $c => $child_pos) { | ||
| 145 | + if ($this->message[$child_pos]['type'] != null) { | ||
| 146 | + $response[] =& $this->buildResponse($child_pos); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + if (array_key_exists('arraySize', $this->message[$pos])) { | ||
| 150 | + $ardepth = count($this->message[$pos]['arraySize']); | ||
| 151 | + if ($ardepth > 1) { | ||
| 152 | + $ar = array_pad(array(), $ardepth, 0); | ||
| 153 | + if (array_key_exists('arrayOffset', $this->message[$pos])) { | ||
| 154 | + for ($i = 0; $i < $ardepth; $i++) { | ||
| 155 | + $ar[$i] += $this->message[$pos]['arrayOffset'][$i]; | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + $elc = count($response); | ||
| 159 | + for ($i = 0; $i < $elc; $i++) { | ||
| 160 | + // recurse to build a multi-dimensional array | ||
| 161 | + $this->domulti($ardepth, $ar, $newresp, $response[$i]); | ||
| 162 | + | ||
| 163 | + // increment our array pointers | ||
| 164 | + $ad = $ardepth - 1; | ||
| 165 | + $ar[$ad]++; | ||
| 166 | + while ($ad > 0 && $ar[$ad] >= $this->message[$pos]['arraySize'][$ad]) { | ||
| 167 | + $ar[$ad] = 0; | ||
| 168 | + $ad--; | ||
| 169 | + $ar[$ad]++; | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + $response = $newresp; | ||
| 173 | + } elseif (isset($this->message[$pos]['arrayOffset']) && | ||
| 174 | + $this->message[$pos]['arrayOffset'][0] > 0) { | ||
| 175 | + // check for padding | ||
| 176 | + $pad = $this->message[$pos]['arrayOffset'][0] + count($response) * -1; | ||
| 177 | + $response = array_pad($response, $pad, null); | ||
| 178 | + } | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + // Build attributes. | ||
| 183 | + $attrs = array(); | ||
| 184 | + foreach ($this->message[$pos]['attrs'] as $atn => $atv) { | ||
| 185 | + if (!strstr($atn, 'xmlns') && | ||
| 186 | + !strpos($atn, ':')) { | ||
| 187 | + $attrs[$atn] = $atv; | ||
| 188 | + } | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + // Add current node's value. | ||
| 192 | + if ($response) { | ||
| 193 | + $nqn =& new Qname($this->message[$pos]['name'], $this->message[$pos]['namespace']); | ||
| 194 | + $tqn =& new Qname($this->message[$pos]['type'], $this->message[$pos]['type_namespace']); | ||
| 195 | + $response =& new SOAP_Value($nqn->fqn(), $tqn->fqn(), $response, $attrs); | ||
| 196 | + if (isset($this->message[$pos]['arrayType'])) { | ||
| 197 | + $response->arrayType = $this->message[$pos]['arrayType']; | ||
| 198 | + } | ||
| 199 | + } else { | ||
| 200 | + $nqn =& new Qname($this->message[$pos]['name'], $this->message[$pos]['namespace']); | ||
| 201 | + $tqn =& new Qname($this->message[$pos]['type'], $this->message[$pos]['type_namespace']); | ||
| 202 | + $response =& new SOAP_Value($nqn->fqn(), $tqn->fqn(), $this->message[$pos]['cdata'], $attrs); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + // handle header attribute that we need | ||
| 206 | + if (array_key_exists('actor', $this->message[$pos])) { | ||
| 207 | + $response->actor = $this->message[$pos]['actor']; | ||
| 208 | + } | ||
| 209 | + if (array_key_exists('mustUnderstand', $this->message[$pos])) { | ||
| 210 | + $response->mustunderstand = $this->message[$pos]['mustUnderstand']; | ||
| 211 | + } | ||
| 212 | + return $response; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * startElement | ||
| 217 | + * start-element handler used with xml parser | ||
| 218 | + * | ||
| 219 | + * @access private | ||
| 220 | + */ | ||
| 221 | + function startElement($parser, $name, $attrs) | ||
| 222 | + { | ||
| 223 | + // position in a total number of elements, starting from 0 | ||
| 224 | + // update class level pos | ||
| 225 | + $pos = $this->position++; | ||
| 226 | + | ||
| 227 | + // and set mine | ||
| 228 | + $this->message[$pos] = array(); | ||
| 229 | + $this->message[$pos]['type'] = ''; | ||
| 230 | + $this->message[$pos]['type_namespace'] = ''; | ||
| 231 | + $this->message[$pos]['cdata'] = ''; | ||
| 232 | + $this->message[$pos]['pos'] = $pos; | ||
| 233 | + $this->message[$pos]['id'] = ''; | ||
| 234 | + | ||
| 235 | + // parent/child/depth determinations | ||
| 236 | + | ||
| 237 | + // depth = how many levels removed from root? | ||
| 238 | + // set mine as current global depth and increment global depth value | ||
| 239 | + $this->message[$pos]['depth'] = $this->depth++; | ||
| 240 | + | ||
| 241 | + // else add self as child to whoever the current parent is | ||
| 242 | + if ($pos != 0) { | ||
| 243 | + if (isset($this->message[$this->parent]['children'])) | ||
| 244 | + $this->message[$this->parent]['children'] .= "|$pos"; | ||
| 245 | + else | ||
| 246 | + $this->message[$this->parent]['children'] = $pos; | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + // set my parent | ||
| 250 | + $this->message[$pos]['parent'] = $this->parent; | ||
| 251 | + | ||
| 252 | + // set self as current value for this depth | ||
| 253 | + $this->depth_array[$this->depth] = $pos; | ||
| 254 | + // set self as current parent | ||
| 255 | + $this->parent = $pos; | ||
| 256 | + $qname =& new QName($name); | ||
| 257 | + // set status | ||
| 258 | + if (strcasecmp('envelope', $qname->name) == 0) { | ||
| 259 | + $this->status = 'envelope'; | ||
| 260 | + } elseif (strcasecmp('header', $qname->name) == 0) { | ||
| 261 | + $this->status = 'header'; | ||
| 262 | + $this->header_struct_name[] = $this->curent_root_struct_name = $qname->name; | ||
| 263 | + $this->header_struct[] = $this->curent_root_struct = $pos; | ||
| 264 | + $this->message[$pos]['type'] = 'Struct'; | ||
| 265 | + } elseif (strcasecmp('body', $qname->name) == 0) { | ||
| 266 | + $this->status = 'body'; | ||
| 267 | + $this->bodyDepth = $this->depth; | ||
| 268 | + | ||
| 269 | + // Set method | ||
| 270 | + } elseif ($this->status == 'body') { | ||
| 271 | + // Is this element allowed to be a root? | ||
| 272 | + // XXX this needs to be optimized, we loop through attrs twice now. | ||
| 273 | + $can_root = $this->depth == $this->bodyDepth + 1; | ||
| 274 | + if ($can_root) { | ||
| 275 | + foreach ($attrs as $key => $value) { | ||
| 276 | + if (stristr($key, ':root') && !$value) { | ||
| 277 | + $can_root = FALSE; | ||
| 278 | + } | ||
| 279 | + } | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + if ($can_root) { | ||
| 283 | + $this->status = 'method'; | ||
| 284 | + $this->root_struct_name[] = $this->curent_root_struct_name = $qname->name; | ||
| 285 | + $this->root_struct[] = $this->curent_root_struct = $pos; | ||
| 286 | + $this->message[$pos]['type'] = 'Struct'; | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + | ||
| 290 | + // Set my status. | ||
| 291 | + $this->message[$pos]['status'] = $this->status; | ||
| 292 | + | ||
| 293 | + // Set name. | ||
| 294 | + $this->message[$pos]['name'] = htmlspecialchars($qname->name); | ||
| 295 | + | ||
| 296 | + // Set attributes. | ||
| 297 | + $this->message[$pos]['attrs'] = $attrs; | ||
| 298 | + | ||
| 299 | + // Loop through attributes, logging ns and type declarations. | ||
| 300 | + foreach ($attrs as $key => $value) { | ||
| 301 | + // If ns declarations, add to class level array of valid | ||
| 302 | + // namespaces. | ||
| 303 | + $kqn =& new QName($key); | ||
| 304 | + if ($kqn->ns == 'xmlns') { | ||
| 305 | + $prefix = $kqn->name; | ||
| 306 | + | ||
| 307 | + if (in_array($value, $this->_XMLSchema)) { | ||
| 308 | + $this->_setSchemaVersion($value); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + $this->_namespaces[$value] = $prefix; | ||
| 312 | + | ||
| 313 | + // Set method namespace. | ||
| 314 | + } elseif ($key == 'xmlns') { | ||
| 315 | + $qname->ns = $this->_getNamespacePrefix($value); | ||
| 316 | + $qname->namespace = $value; | ||
| 317 | + } elseif ($kqn->name == 'actor') { | ||
| 318 | + $this->message[$pos]['actor'] = $value; | ||
| 319 | + } elseif ($kqn->name == 'mustUnderstand') { | ||
| 320 | + $this->message[$pos]['mustUnderstand'] = $value; | ||
| 321 | + | ||
| 322 | + // If it's a type declaration, set type. | ||
| 323 | + } elseif ($kqn->name == 'type') { | ||
| 324 | + $vqn =& new QName($value); | ||
| 325 | + $this->message[$pos]['type'] = $vqn->name; | ||
| 326 | + $this->message[$pos]['type_namespace'] = $this->_getNamespaceForPrefix($vqn->ns); | ||
| 327 | + // Should do something here with the namespace of | ||
| 328 | + // specified type? | ||
| 329 | + | ||
| 330 | + } elseif ($kqn->name == 'arrayType') { | ||
| 331 | + $vqn =& new QName($value); | ||
| 332 | + $this->message[$pos]['type'] = 'Array'; | ||
| 333 | + if (isset($vqn->arraySize)) { | ||
| 334 | + $this->message[$pos]['arraySize'] = $vqn->arraySize; | ||
| 335 | + } | ||
| 336 | + $this->message[$pos]['arrayType'] = $vqn->name; | ||
| 337 | + | ||
| 338 | + } elseif ($kqn->name == 'offset') { | ||
| 339 | + $this->message[$pos]['arrayOffset'] = split(',', substr($value, 1, strlen($value) - 2)); | ||
| 340 | + | ||
| 341 | + } elseif ($kqn->name == 'id') { | ||
| 342 | + // Save id to reference array. | ||
| 343 | + $this->references[$value] = $pos; | ||
| 344 | + $this->message[$pos]['id'] = $value; | ||
| 345 | + | ||
| 346 | + } elseif ($kqn->name == 'href') { | ||
| 347 | + if ($value[0] == '#') { | ||
| 348 | + $ref = substr($value, 1); | ||
| 349 | + if (isset($this->references[$ref])) { | ||
| 350 | + // cdata, type, inval. | ||
| 351 | + $ref_pos = $this->references[$ref]; | ||
| 352 | + $this->message[$pos]['children'] = &$this->message[$ref_pos]['children']; | ||
| 353 | + $this->message[$pos]['cdata'] = &$this->message[$ref_pos]['cdata']; | ||
| 354 | + $this->message[$pos]['type'] = &$this->message[$ref_pos]['type']; | ||
| 355 | + $this->message[$pos]['arraySize'] = &$this->message[$ref_pos]['arraySize']; | ||
| 356 | + $this->message[$pos]['arrayType'] = &$this->message[$ref_pos]['arrayType']; | ||
| 357 | + } else { | ||
| 358 | + // Reverse reference, store in 'need reference'. | ||
| 359 | + if (!isset($this->need_references[$ref])) { | ||
| 360 | + $this->need_references[$ref] = array(); | ||
| 361 | + } | ||
| 362 | + $this->need_references[$ref][] = $pos; | ||
| 363 | + } | ||
| 364 | + } elseif (isset($this->attachments[$value])) { | ||
| 365 | + $this->message[$pos]['cdata'] = $this->attachments[$value]; | ||
| 366 | + } | ||
| 367 | + } | ||
| 368 | + } | ||
| 369 | + // See if namespace is defined in tag. | ||
| 370 | + if (array_key_exists('xmlns:' . $qname->ns, $attrs)) { | ||
| 371 | + $namespace = $attrs['xmlns:' . $qname->ns]; | ||
| 372 | + } elseif ($qname->ns && !$qname->namespace) { | ||
| 373 | + $namespace = $this->_getNamespaceForPrefix($qname->ns); | ||
| 374 | + } else { | ||
| 375 | + // Get namespace. | ||
| 376 | + $namespace = $qname->namespace ? $qname->namespace : $this->default_namespace; | ||
| 377 | + } | ||
| 378 | + $this->message[$pos]['namespace'] = $namespace; | ||
| 379 | + $this->default_namespace = $namespace; | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + /** | ||
| 383 | + * endElement | ||
| 384 | + * end-element handler used with xml parser | ||
| 385 | + * | ||
| 386 | + * @access private | ||
| 387 | + */ | ||
| 388 | + function endElement($parser, $name) | ||
| 389 | + { | ||
| 390 | + // Position of current element is equal to the last value left | ||
| 391 | + // in depth_array for my depth. | ||
| 392 | + $pos = $this->depth_array[$this->depth]; | ||
| 393 | + | ||
| 394 | + // Bring depth down a notch. | ||
| 395 | + $this->depth--; | ||
| 396 | + $qname =& new QName($name); | ||
| 397 | + | ||
| 398 | + // Get type if not explicitly declared in an xsi:type attribute. | ||
| 399 | + // XXX check on integrating wsdl validation here | ||
| 400 | + if ($this->message[$pos]['type'] == '') { | ||
| 401 | + if (isset($this->message[$pos]['children'])) { | ||
| 402 | + /* this is slow, need to look at some faster method | ||
| 403 | + $children = explode('|', $this->message[$pos]['children']); | ||
| 404 | + if (count($children) > 2 && | ||
| 405 | + $this->message[$children[1]]['name'] == $this->message[$children[2]]['name']) { | ||
| 406 | + $this->message[$pos]['type'] = 'Array'; | ||
| 407 | + } else { | ||
| 408 | + $this->message[$pos]['type'] = 'Struct'; | ||
| 409 | + }*/ | ||
| 410 | + $this->message[$pos]['type'] = 'Struct'; | ||
| 411 | + } else { | ||
| 412 | + $parent = $this->message[$pos]['parent']; | ||
| 413 | + if ($this->message[$parent]['type'] == 'Array' && | ||
| 414 | + array_key_exists('arrayType', $this->message[$parent])) { | ||
| 415 | + $this->message[$pos]['type'] = $this->message[$parent]['arrayType']; | ||
| 416 | + } else { | ||
| 417 | + $this->message[$pos]['type'] = 'string'; | ||
| 418 | + } | ||
| 419 | + } | ||
| 420 | + } | ||
| 421 | + | ||
| 422 | + // If tag we are currently closing is the method wrapper. | ||
| 423 | + if ($pos == $this->curent_root_struct) { | ||
| 424 | + $this->status = 'body'; | ||
| 425 | + } elseif ($qname->name == 'Body' || $qname->name == 'Header') { | ||
| 426 | + $this->status = 'envelope'; | ||
| 427 | + } | ||
| 428 | + | ||
| 429 | + // Set parent back to my parent. | ||
| 430 | + $this->parent = $this->message[$pos]['parent']; | ||
| 431 | + | ||
| 432 | + // Handle any reverse references now. | ||
| 433 | + $idref = $this->message[$pos]['id']; | ||
| 434 | + | ||
| 435 | + if ($idref != '' && array_key_exists($idref, $this->need_references)) { | ||
| 436 | + foreach ($this->need_references[$idref] as $ref_pos) { | ||
| 437 | + // XXX is this stuff there already? | ||
| 438 | + $this->message[$ref_pos]['children'] = &$this->message[$pos]['children']; | ||
| 439 | + $this->message[$ref_pos]['cdata'] = &$this->message[$pos]['cdata']; | ||
| 440 | + $this->message[$ref_pos]['type'] = &$this->message[$pos]['type']; | ||
| 441 | + $this->message[$ref_pos]['arraySize'] = &$this->message[$pos]['arraySize']; | ||
| 442 | + $this->message[$ref_pos]['arrayType'] = &$this->message[$pos]['arrayType']; | ||
| 443 | + } | ||
| 444 | + } | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + /** | ||
| 448 | + * characterData | ||
| 449 | + * element content handler used with xml parser | ||
| 450 | + * | ||
| 451 | + * @access private | ||
| 452 | + */ | ||
| 453 | + function characterData($parser, $data) | ||
| 454 | + { | ||
| 455 | + $pos = $this->depth_array[$this->depth]; | ||
| 456 | + if (isset($this->message[$pos]['cdata'])) { | ||
| 457 | + $this->message[$pos]['cdata'] .= $data; | ||
| 458 | + } else { | ||
| 459 | + $this->message[$pos]['cdata'] = $data; | ||
| 460 | + } | ||
| 461 | + } | ||
| 462 | + | ||
| 463 | + /** | ||
| 464 | + * Returns an array of responses. | ||
| 465 | + * | ||
| 466 | + * After parsing a SOAP message, use this to get the response. | ||
| 467 | + * | ||
| 468 | + * @return array | ||
| 469 | + * @access public | ||
| 470 | + */ | ||
| 471 | + function &getResponse() | ||
| 472 | + { | ||
| 473 | + if (isset($this->root_struct[0]) && | ||
| 474 | + $this->root_struct[0]) { | ||
| 475 | + $response =& $this->buildResponse($this->root_struct[0]); | ||
| 476 | + } else { | ||
| 477 | + $response =& $this->_raiseSoapFault("couldn't build response"); | ||
| 478 | + } | ||
| 479 | + return $response; | ||
| 480 | + } | ||
| 481 | + | ||
| 482 | + /** | ||
| 483 | + * Returns an array of header responses. | ||
| 484 | + * | ||
| 485 | + * After parsing a SOAP message, use this to get the response. | ||
| 486 | + * | ||
| 487 | + * @return array | ||
| 488 | + * @access public | ||
| 489 | + */ | ||
| 490 | + function &getHeaders() | ||
| 491 | + { | ||
| 492 | + if (isset($this->header_struct[0]) && | ||
| 493 | + $this->header_struct[0]) { | ||
| 494 | + $response = &$this->buildResponse($this->header_struct[0]); | ||
| 495 | + } else { | ||
| 496 | + // We don't fault if there are no headers; that can be handled by | ||
| 497 | + // the application if necessary. | ||
| 498 | + $response = null; | ||
| 499 | + } | ||
| 500 | + return $response; | ||
| 501 | + } | ||
| 502 | + | ||
| 503 | + /** | ||
| 504 | + * decodeEntities | ||
| 505 | + * | ||
| 506 | + * removes entities from text | ||
| 507 | + * | ||
| 508 | + * @param string | ||
| 509 | + * @return string | ||
| 510 | + * @access private | ||
| 511 | + */ | ||
| 512 | + function decodeEntities($text) | ||
| 513 | + { | ||
| 514 | + $trans_tbl = array_flip($this->entities); | ||
| 515 | + return strtr($text, $trans_tbl); | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | +} |
thirdparty/pear/SOAP/Server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the SOAP server. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 19 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Base.php'; | ||
| 26 | +require_once 'SOAP/Fault.php'; | ||
| 27 | +require_once 'SOAP/Parser.php'; | ||
| 28 | +require_once 'SOAP/Value.php'; | ||
| 29 | +require_once 'SOAP/WSDL.php'; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * SOAP Server Class | ||
| 33 | + * | ||
| 34 | + * Originaly based on SOAPx4 by Dietrich Ayala | ||
| 35 | + * http://dietrich.ganx4.com/soapx4 | ||
| 36 | + * | ||
| 37 | + * @access public | ||
| 38 | + * @package SOAP | ||
| 39 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 40 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 41 | + */ | ||
| 42 | +class SOAP_Server extends SOAP_Base | ||
| 43 | +{ | ||
| 44 | + /** | ||
| 45 | + * | ||
| 46 | + * @var array | ||
| 47 | + */ | ||
| 48 | + var $dispatch_map = array(); // create empty dispatch map | ||
| 49 | + var $dispatch_objects = array(); | ||
| 50 | + var $soapobject = null; | ||
| 51 | + var $call_methodname = null; | ||
| 52 | + var $callHandler = null; | ||
| 53 | + var $callValidation = true; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * A list of headers that are going to be sent back to the client. | ||
| 57 | + * | ||
| 58 | + * @var array | ||
| 59 | + */ | ||
| 60 | + var $headers = array(); | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * | ||
| 64 | + * @var string | ||
| 65 | + */ | ||
| 66 | + var $request = ''; | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * | ||
| 70 | + * @var string XML-Encoding | ||
| 71 | + */ | ||
| 72 | + var $xml_encoding = SOAP_DEFAULT_ENCODING; | ||
| 73 | + var $response_encoding = 'UTF-8'; | ||
| 74 | + | ||
| 75 | + var $result = 'successful'; // for logging interop results to db | ||
| 76 | + | ||
| 77 | + var $endpoint = ''; // the uri to ME! | ||
| 78 | + | ||
| 79 | + var $service = ''; //soapaction header | ||
| 80 | + var $method_namespace = null; | ||
| 81 | + var $__options = array('use' => 'encoded', | ||
| 82 | + 'style' => 'rpc', | ||
| 83 | + 'parameters' => 0, | ||
| 84 | + 'http_status_success' => '200 OK', | ||
| 85 | + 'http_status_fault' => '500 SOAP Fault'); | ||
| 86 | + | ||
| 87 | + function SOAP_Server($options = null) | ||
| 88 | + { | ||
| 89 | + ini_set('track_errors', 1); | ||
| 90 | + parent::SOAP_Base('Server'); | ||
| 91 | + | ||
| 92 | + if (is_array($options)) { | ||
| 93 | + if (isset($options['use'])) { | ||
| 94 | + $this->__options['use'] = $options['use']; | ||
| 95 | + } | ||
| 96 | + if (isset($options['style'])) { | ||
| 97 | + $this->__options['style'] = $options['style']; | ||
| 98 | + } | ||
| 99 | + if (isset($options['parameters'])) { | ||
| 100 | + $this->__options['parameters'] = $options['parameters']; | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + // assume we encode with section 5 | ||
| 104 | + $this->_section5 = true; | ||
| 105 | + if ($this->__options['use']=='literal') { | ||
| 106 | + $this->_section5 = false; | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + /** | ||
| 111 | + * Error handler for errors that happen in proxied methods. | ||
| 112 | + * | ||
| 113 | + * To always return a valid SOAP response even on errors that don't happen | ||
| 114 | + * in this code, the errors are catched, transformed to a SOAP fault and | ||
| 115 | + * immediately sent to the client. | ||
| 116 | + * | ||
| 117 | + * @see http://www.php.net/set_error_handler | ||
| 118 | + */ | ||
| 119 | + function _errorHandler($errno, $errmsg, $filename, $linenum, $vars) | ||
| 120 | + { | ||
| 121 | + /* The error handler should ignore '0' errors, eg. hidden by @ - see | ||
| 122 | + * the set_error_handler manual page. (thanks to Alan Knowles). */ | ||
| 123 | + if (!$errno || $errno == E_NOTICE || | ||
| 124 | + (defined('E_STRICT') && $errno == constant('E_STRICT'))) { | ||
| 125 | + return; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + $this->fault =& new SOAP_Fault($errmsg, 'Server', 'PHP', "Errno: $errno\nFilename: $filename\nLineno: $linenum\n"); | ||
| 129 | + | ||
| 130 | + $this->_sendResponse(); | ||
| 131 | + exit; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + function _getContentEncoding($content_type) | ||
| 135 | + { | ||
| 136 | + /* Get the character encoding of the incoming request treat incoming | ||
| 137 | + * data as UTF-8 if no encoding set. */ | ||
| 138 | + $this->xml_encoding = 'UTF-8'; | ||
| 139 | + if (strpos($content_type, '=')) { | ||
| 140 | + $enc = strtoupper(str_replace('"', '', substr(strstr($content_type, '='), 1))); | ||
| 141 | + if (!in_array($enc, $this->_encodings)) { | ||
| 142 | + return false; | ||
| 143 | + } | ||
| 144 | + $this->xml_encoding = $enc; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + return true; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + | ||
| 151 | + /** | ||
| 152 | + * Parses request and posts response. | ||
| 153 | + */ | ||
| 154 | + function service($data, $endpoint = '', $test = false) | ||
| 155 | + { | ||
| 156 | + $response = null; | ||
| 157 | + $attachments = array(); | ||
| 158 | + $useEncoding = 'DIME'; | ||
| 159 | + | ||
| 160 | + /* Figure out our endpoint. */ | ||
| 161 | + $this->endpoint = $endpoint; | ||
| 162 | + if (!$test && !$this->endpoint) { | ||
| 163 | + /* We'll try to build our endpoint. */ | ||
| 164 | + $this->endpoint = 'http://' . $_SERVER['SERVER_NAME']; | ||
| 165 | + if ($_SERVER['SERVER_PORT']) { | ||
| 166 | + $this->endpoint .= ':' . $_SERVER['SERVER_PORT']; | ||
| 167 | + } | ||
| 168 | + $this->endpoint .= $_SERVER['SCRIPT_NAME']; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + /* Get the character encoding of the incoming request treat incoming | ||
| 172 | + * data as UTF-8 if no encoding set. */ | ||
| 173 | + if (isset($_SERVER['CONTENT_TYPE'])) { | ||
| 174 | + if (strcasecmp($_SERVER['CONTENT_TYPE'], 'application/dime') == 0) { | ||
| 175 | + $this->_decodeDIMEMessage($data, $headers, $attachments); | ||
| 176 | + $useEncoding = 'DIME'; | ||
| 177 | + } elseif (stristr($_SERVER['CONTENT_TYPE'], 'multipart/related')) { | ||
| 178 | + /* This is a mime message, let's decode it. */ | ||
| 179 | + $data = 'Content-Type: ' . | ||
| 180 | + stripslashes($_SERVER['CONTENT_TYPE']) . | ||
| 181 | + "\r\n\r\n" . $data; | ||
| 182 | + $this->_decodeMimeMessage($data, $headers, $attachments); | ||
| 183 | + $useEncoding = 'Mime'; | ||
| 184 | + } | ||
| 185 | + if (!isset($headers['content-type'])) { | ||
| 186 | + $headers['content-type'] = stripslashes($_SERVER['CONTENT_TYPE']); | ||
| 187 | + } | ||
| 188 | + if (!$this->fault && | ||
| 189 | + !$this->_getContentEncoding($headers['content-type'])) { | ||
| 190 | + $this->xml_encoding = SOAP_DEFAULT_ENCODING; | ||
| 191 | + /* Found encoding we don't understand; return a fault. */ | ||
| 192 | + $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + /* If this is not a POST with Content-Type text/xml, try to return a | ||
| 197 | + * WSDL file. */ | ||
| 198 | + if (!$this->fault && !$test && | ||
| 199 | + ($_SERVER['REQUEST_METHOD'] != 'POST' || | ||
| 200 | + strncmp($headers['content-type'], 'text/xml', 8) != 0)) { | ||
| 201 | + /* This is not possibly a valid SOAP request, try to return a WSDL | ||
| 202 | + * file. */ | ||
| 203 | + $this->_raiseSoapFault('Invalid SOAP request, must be POST with content-type: text/xml, got: ' . (isset($headers['content-type']) ? $headers['content-type'] : 'Nothing!'), '', '', 'Server'); | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + if (!$this->fault) { | ||
| 207 | + /* $response is a SOAP_Msg object. */ | ||
| 208 | + $soap_msg = $this->parseRequest($data, $attachments); | ||
| 209 | + | ||
| 210 | + /* Handle Mime or DIME encoding. */ | ||
| 211 | + /* TODO: DIME decoding should move to the transport, do it here | ||
| 212 | + * for now and for ease of getting it done. */ | ||
| 213 | + if (count($this->__attachments)) { | ||
| 214 | + if ($useEncoding == 'Mime') { | ||
| 215 | + $soap_msg = $this->_makeMimeMessage($soap_msg); | ||
| 216 | + } else { | ||
| 217 | + // default is dime | ||
| 218 | + $soap_msg = $this->_makeDIMEMessage($soap_msg); | ||
| 219 | + $this->headers['Content-Type'] = 'application/dime'; | ||
| 220 | + } | ||
| 221 | + if (PEAR::isError($soap_msg)) { | ||
| 222 | + return $this->_raiseSoapFault($soap_msg); | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + if (is_array($soap_msg)) { | ||
| 227 | + $response = $soap_msg['body']; | ||
| 228 | + if (count($soap_msg['headers'])) { | ||
| 229 | + $this->headers = $soap_msg['headers']; | ||
| 230 | + } | ||
| 231 | + } else { | ||
| 232 | + $response = $soap_msg; | ||
| 233 | + } | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + $this->_sendResponse($response); | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + /** | ||
| 240 | + * Sends the final HTTP response to the client, including the HTTP header | ||
| 241 | + * and the HTTP body. | ||
| 242 | + * | ||
| 243 | + * If an error happened, it returns a SOAP fault instead of the response | ||
| 244 | + * body. | ||
| 245 | + * | ||
| 246 | + * @param string $response The response body. | ||
| 247 | + */ | ||
| 248 | + function _sendResponse($response = '') | ||
| 249 | + { | ||
| 250 | + /* Make distinction between the different SAPIs, running PHP as CGI or | ||
| 251 | + * as a module. */ | ||
| 252 | + if (stristr(php_sapi_name(), 'cgi') === 0) { | ||
| 253 | + $hdrs_type = 'Status:'; | ||
| 254 | + } else { | ||
| 255 | + $hdrs_type = 'HTTP/1.1'; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + if ($this->fault) { | ||
| 259 | + $hdrs = $hdrs_type . ' ' . $this->__options['http_status_fault'] . "\r\n"; | ||
| 260 | + $response = $this->fault->message(); | ||
| 261 | + } else { | ||
| 262 | + $hdrs = $hdrs_type . ' ' . $this->__options['http_status_success'] . "\r\n"; | ||
| 263 | + } | ||
| 264 | + header($hdrs); | ||
| 265 | + | ||
| 266 | + $this->headers['Server'] = SOAP_LIBRARY_NAME; | ||
| 267 | + if (!isset($this->headers['Content-Type'])) { | ||
| 268 | + $this->headers['Content-Type'] = 'text/xml; charset=' . | ||
| 269 | + $this->response_encoding; | ||
| 270 | + } | ||
| 271 | + $this->headers['Content-Length'] = strlen($response); | ||
| 272 | + | ||
| 273 | + foreach ($this->headers as $k => $v) { | ||
| 274 | + header("$k: $v"); | ||
| 275 | + $hdrs .= "$k: $v\r\n"; | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + $this->response = $hdrs . "\r\n" . $response; | ||
| 279 | + print $response; | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + function &callMethod($methodname, &$args) | ||
| 283 | + { | ||
| 284 | + if ($this->callHandler) { | ||
| 285 | + | ||
| 286 | + $ret = @call_user_func_array($this->callHandler, array($methodname, $args)); | ||
| 287 | + | ||
| 288 | + return $ret; | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + set_error_handler(array($this, '_errorHandler')); | ||
| 292 | + | ||
| 293 | + if ($args) { | ||
| 294 | + /* Call method with parameters. */ | ||
| 295 | + if (isset($this->soapobject) && is_object($this->soapobject)) { | ||
| 296 | + $ret = @call_user_func_array(array(&$this->soapobject, $methodname), $args); | ||
| 297 | + } else { | ||
| 298 | + $ret = @call_user_func_array($methodname, $args); | ||
| 299 | + } | ||
| 300 | + } else { | ||
| 301 | + /* Call method withour parameters. */ | ||
| 302 | + if (is_object($this->soapobject)) { | ||
| 303 | + $ret = @call_user_func(array(&$this->soapobject, $methodname)); | ||
| 304 | + } else { | ||
| 305 | + $ret = @call_user_func($methodname); | ||
| 306 | + } | ||
| 307 | + } | ||
| 308 | + | ||
| 309 | + restore_error_handler(); | ||
| 310 | + | ||
| 311 | + return $ret; | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + /** | ||
| 315 | + * Creates SOAP_Value objects with return values from method. | ||
| 316 | + * Uses method signature to determine type. | ||
| 317 | + * | ||
| 318 | + * @param mixed $method_response The result(s). | ||
| 319 | + * @param array|string $type The type(s) of the return value(s). | ||
| 320 | + * @param string $return_name The name of the return value. | ||
| 321 | + * @param string $namespace The namespace of the return value. | ||
| 322 | + * | ||
| 323 | + * @return array List of SOAP_Value objects. | ||
| 324 | + */ | ||
| 325 | + function buildResult(&$method_response, &$return_type, | ||
| 326 | + $return_name = 'return', $namespace = '') | ||
| 327 | + { | ||
| 328 | + if (is_a($method_response, 'SOAP_Value')) { | ||
| 329 | + $return_val = array($method_response); | ||
| 330 | + } else { | ||
| 331 | + if (is_array($return_type) && is_array($method_response)) { | ||
| 332 | + $i = 0; | ||
| 333 | + | ||
| 334 | + foreach ($return_type as $key => $type) { | ||
| 335 | + if (is_numeric($key)) { | ||
| 336 | + $key = 'item'; | ||
| 337 | + } | ||
| 338 | + if (is_a($method_response[$i], 'SOAP_Value')) { | ||
| 339 | + $return_val[] =& $method_response[$i++]; | ||
| 340 | + } else { | ||
| 341 | + $qn =& new QName($key, $namespace); | ||
| 342 | + $return_val[] =& new SOAP_Value($qn->fqn(), $type, $method_response[$i++]); | ||
| 343 | + } | ||
| 344 | + } | ||
| 345 | + } else { | ||
| 346 | + if (is_array($return_type)) { | ||
| 347 | + $keys = array_keys($return_type); | ||
| 348 | + if (!is_numeric($keys[0])) { | ||
| 349 | + $return_name = $keys[0]; | ||
| 350 | + } | ||
| 351 | + $values = array_values($return_type); | ||
| 352 | + $return_type = $values[0]; | ||
| 353 | + } | ||
| 354 | + $qn =& new QName($return_name, $namespace); | ||
| 355 | + $return_val = array(new SOAP_Value($qn->fqn(), $return_type, $method_response)); | ||
| 356 | + } | ||
| 357 | + } | ||
| 358 | + return $return_val; | ||
| 359 | + } | ||
| 360 | + | ||
| 361 | + function parseRequest($data = '', $attachments = null) | ||
| 362 | + { | ||
| 363 | + /* Parse response, get SOAP_Parser object. */ | ||
| 364 | + $parser =& new SOAP_Parser($data, $this->xml_encoding, $attachments); | ||
| 365 | + /* If fault occurred during message parsing. */ | ||
| 366 | + if ($parser->fault) { | ||
| 367 | + $this->fault = $parser->fault; | ||
| 368 | + return null; | ||
| 369 | + } | ||
| 370 | + | ||
| 371 | + /* Handle message headers. */ | ||
| 372 | + $request_headers = $parser->getHeaders(); | ||
| 373 | + $header_results = array(); | ||
| 374 | + | ||
| 375 | + if ($request_headers) { | ||
| 376 | + if (!is_a($request_headers, 'SOAP_Value')) { | ||
| 377 | + $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_headers, '', '', 'Server'); | ||
| 378 | + return null; | ||
| 379 | + } | ||
| 380 | + if ($request_headers->value) { | ||
| 381 | + /* Handle headers now. */ | ||
| 382 | + foreach ($request_headers->value as $header_val) { | ||
| 383 | + $f_exists = $this->validateMethod($header_val->name, $header_val->namespace); | ||
| 384 | + | ||
| 385 | + /* TODO: this does not take into account message routing | ||
| 386 | + * yet. */ | ||
| 387 | + $myactor = !$header_val->actor || | ||
| 388 | + $header_val->actor == 'http://schemas.xmlsoap.org/soap/actor/next' || | ||
| 389 | + $header_val->actor == $this->endpoint; | ||
| 390 | + | ||
| 391 | + if (!$f_exists && $header_val->mustunderstand && $myactor) { | ||
| 392 | + $this->_raiseSoapFault('I don\'t understand header ' . $header_val->name, '', '', 'MustUnderstand'); | ||
| 393 | + return null; | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + /* We only handle the header if it's for us. */ | ||
| 397 | + $isok = $f_exists && $myactor; | ||
| 398 | + | ||
| 399 | + if ($isok) { | ||
| 400 | + /* Call our header now! */ | ||
| 401 | + $header_method = $header_val->name; | ||
| 402 | + $header_data = array($this->_decode($header_val)); | ||
| 403 | + /* If there are parameters to pass. */ | ||
| 404 | + $hr =& $this->callMethod($header_method, $header_data); | ||
| 405 | + if (PEAR::isError($hr)) { | ||
| 406 | + $this->_raiseSoapDefault($hr); | ||
| 407 | + return null; | ||
| 408 | + } | ||
| 409 | + $results = $this->buildResult($hr, $this->return_type, $header_method, $header_val->namespace); | ||
| 410 | + $header_results[] = $results[0]; | ||
| 411 | + } | ||
| 412 | + } | ||
| 413 | + } | ||
| 414 | + } | ||
| 415 | + | ||
| 416 | + /* Handle the method call. */ | ||
| 417 | + /* Evaluate message, getting back a SOAP_Value object. */ | ||
| 418 | + $this->call_methodname = $this->methodname = $parser->root_struct_name[0]; | ||
| 419 | + | ||
| 420 | + /* Figure out the method namespace. */ | ||
| 421 | + $this->method_namespace = $parser->message[$parser->root_struct[0]]['namespace']; | ||
| 422 | + | ||
| 423 | + if ($this->_wsdl) { | ||
| 424 | + $this->_setSchemaVersion($this->_wsdl->xsd); | ||
| 425 | + $dataHandler = $this->_wsdl->getDataHandler($this->methodname, $this->method_namespace); | ||
| 426 | + if ($dataHandler) | ||
| 427 | + $this->call_methodname = $this->methodname = $dataHandler; | ||
| 428 | + | ||
| 429 | + $this->_portName = $this->_wsdl->getPortName($this->methodname); | ||
| 430 | + if (PEAR::isError($this->_portName)) { | ||
| 431 | + $this->_raiseSoapFault($this->_portName); | ||
| 432 | + return null; | ||
| 433 | + } | ||
| 434 | + $opData = $this->_wsdl->getOperationData($this->_portName, $this->methodname); | ||
| 435 | + if (PEAR::isError($opData)) { | ||
| 436 | + $this->_raiseSoapFault($opData); | ||
| 437 | + return null; | ||
| 438 | + } | ||
| 439 | + $this->__options['style'] = $opData['style']; | ||
| 440 | + $this->__options['use'] = $opData['output']['use']; | ||
| 441 | + $this->__options['parameters'] = $opData['parameters']; | ||
| 442 | + } | ||
| 443 | + | ||
| 444 | + /* Does method exist? */ | ||
| 445 | + if (!$this->methodname || | ||
| 446 | + !$this->validateMethod($this->methodname, $this->method_namespace)) { | ||
| 447 | + $this->_raiseSoapFault('method "' . $this->method_namespace . $this->methodname . '" not defined in service', '', '', 'Server'); | ||
| 448 | + return null; | ||
| 449 | + } | ||
| 450 | + | ||
| 451 | + if (!$request_val = $parser->getResponse()) { | ||
| 452 | + return null; | ||
| 453 | + } | ||
| 454 | + if (!is_a($request_val, 'SOAP_Value')) { | ||
| 455 | + $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_val, '', '', 'Server'); | ||
| 456 | + return null; | ||
| 457 | + } | ||
| 458 | + | ||
| 459 | + /* Verify that SOAP_Value objects in request match the methods | ||
| 460 | + * signature. */ | ||
| 461 | + if (!$this->verifyMethod($request_val)) { | ||
| 462 | + /* verifyMethod() creates the fault. */ | ||
| 463 | + return null; | ||
| 464 | + } | ||
| 465 | + | ||
| 466 | + /* Need to set special error detection inside the value class to | ||
| 467 | + * differentiate between no params passed, and an error decoding. */ | ||
| 468 | + $request_data = $this->__decodeRequest($request_val); | ||
| 469 | + if (PEAR::isError($request_data)) { | ||
| 470 | + $this->_raiseSoapFault($request_data); | ||
| 471 | + return null; | ||
| 472 | + } | ||
| 473 | + $method_response =& $this->callMethod($this->call_methodname, $request_data); | ||
| 474 | + if (PEAR::isError($method_response)) { | ||
| 475 | + $this->_raiseSoapFault($method_response); | ||
| 476 | + return null; | ||
| 477 | + } | ||
| 478 | + | ||
| 479 | + if ($this->__options['parameters'] || | ||
| 480 | + !$method_response || | ||
| 481 | + $this->__options['style']=='rpc') { | ||
| 482 | + /* Get the method result. */ | ||
| 483 | + if (is_null($method_response)) { | ||
| 484 | + $return_val = null; | ||
| 485 | + } else { | ||
| 486 | + $return_val = $this->buildResult($method_response, $this->return_type); | ||
| 487 | + } | ||
| 488 | + | ||
| 489 | + $qn =& new QName($this->methodname . 'Response', $this->method_namespace); | ||
| 490 | + $methodValue =& new SOAP_Value($qn->fqn(), 'Struct', $return_val); | ||
| 491 | + } else { | ||
| 492 | + $methodValue =& $method_response; | ||
| 493 | + } | ||
| 494 | + return $this->_makeEnvelope($methodValue, $header_results, $this->response_encoding); | ||
| 495 | + } | ||
| 496 | + | ||
| 497 | + function &__decodeRequest($request, $shift = false) | ||
| 498 | + { | ||
| 499 | + if (!$request) { | ||
| 500 | + $decoded = null; | ||
| 501 | + return $decoded; | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | + /* Check for valid response. */ | ||
| 505 | + if (PEAR::isError($request)) { | ||
| 506 | + $fault = &$this->_raiseSoapFault($request); | ||
| 507 | + return $fault; | ||
| 508 | + } else if (!is_a($request, 'SOAP_Value')) { | ||
| 509 | + $fault = &$this->_raiseSoapFault('Invalid data in server::__decodeRequest'); | ||
| 510 | + return $fault; | ||
| 511 | + } | ||
| 512 | + | ||
| 513 | + /* Decode to native php datatype. */ | ||
| 514 | + $requestArray = $this->_decode($request); | ||
| 515 | + /* Fault? */ | ||
| 516 | + if (PEAR::isError($requestArray)) { | ||
| 517 | + $fault = &$this->_raiseSoapFault($requestArray); | ||
| 518 | + return $fault; | ||
| 519 | + } | ||
| 520 | + if (is_object($requestArray) && | ||
| 521 | + get_class($requestArray) == 'stdClass') { | ||
| 522 | + $requestArray = get_object_vars($requestArray); | ||
| 523 | + } elseif ($this->__options['style'] == 'document') { | ||
| 524 | + $requestArray = array($requestArray); | ||
| 525 | + } | ||
| 526 | + if (is_array($requestArray)) { | ||
| 527 | + if (isset($requestArray['faultcode']) || | ||
| 528 | + isset($requestArray['SOAP-ENV:faultcode'])) { | ||
| 529 | + $faultcode = $faultstring = $faultdetail = $faultactor = ''; | ||
| 530 | + foreach ($requestArray as $k => $v) { | ||
| 531 | + if (stristr($k, 'faultcode')) { | ||
| 532 | + $faultcode = $v; | ||
| 533 | + } | ||
| 534 | + if (stristr($k, 'faultstring')) { | ||
| 535 | + $faultstring = $v; | ||
| 536 | + } | ||
| 537 | + if (stristr($k, 'detail')) { | ||
| 538 | + $faultdetail = $v; | ||
| 539 | + } | ||
| 540 | + if (stristr($k, 'faultactor')) { | ||
| 541 | + $faultactor = $v; | ||
| 542 | + } | ||
| 543 | + } | ||
| 544 | + $fault = &$this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode); | ||
| 545 | + return $fault; | ||
| 546 | + } | ||
| 547 | + /* Return array of return values. */ | ||
| 548 | + if ($shift && count($requestArray) == 1) { | ||
| 549 | + $decoded = array_shift($requestArray); | ||
| 550 | + return $decoded; | ||
| 551 | + } | ||
| 552 | + return $requestArray; | ||
| 553 | + } | ||
| 554 | + return $requestArray; | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + function verifyMethod($request) | ||
| 558 | + { | ||
| 559 | + if (!$this->callValidation) { | ||
| 560 | + return true; | ||
| 561 | + } | ||
| 562 | + | ||
| 563 | + $params = $request->value; | ||
| 564 | + | ||
| 565 | + /* Get the dispatch map if one exists. */ | ||
| 566 | + $map = null; | ||
| 567 | + if (array_key_exists($this->methodname, $this->dispatch_map)) { | ||
| 568 | + $map = $this->dispatch_map[$this->methodname]; | ||
| 569 | + } elseif (isset($this->soapobject)) { | ||
| 570 | + if (method_exists($this->soapobject, '__dispatch')) { | ||
| 571 | + $map = $this->soapobject->__dispatch($this->methodname); | ||
| 572 | + } elseif (method_exists($this->soapobject, $this->methodname)) { | ||
| 573 | + /* No map, all public functions are SOAP functions. */ | ||
| 574 | + return true; | ||
| 575 | + } | ||
| 576 | + } | ||
| 577 | + if (!$map) { | ||
| 578 | + $this->_raiseSoapFault('SOAP request specified an unhandled method "' . $this->methodname . '"', '', '', 'Client'); | ||
| 579 | + return false; | ||
| 580 | + } | ||
| 581 | + | ||
| 582 | + /* If we aliased the SOAP method name to a PHP function, change | ||
| 583 | + * call_methodname so we do the right thing. */ | ||
| 584 | + if (array_key_exists('alias', $map) && !empty($map['alias'])) { | ||
| 585 | + $this->call_methodname = $map['alias']; | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + /* If there are input parameters required. */ | ||
| 589 | + if ($sig = $map['in']) { | ||
| 590 | + $this->input_value = count($sig); | ||
| 591 | + $this->return_type = false; | ||
| 592 | + if (is_array($map['out'])) { | ||
| 593 | + $this->return_type = count($map['out']) > 1 | ||
| 594 | + ? $map['out'] | ||
| 595 | + : array_shift($map['out']); | ||
| 596 | + } | ||
| 597 | + if (is_array($params)) { | ||
| 598 | + /* Validate the number of parameters. */ | ||
| 599 | + if (count($params) == count($sig)) { | ||
| 600 | + /* Make array of param types. */ | ||
| 601 | + foreach ($params as $param) { | ||
| 602 | + $p[] = strtolower($param->type); | ||
| 603 | + } | ||
| 604 | + $sig_t = array_values($sig); | ||
| 605 | + /* Validate each param's type. */ | ||
| 606 | + for ($i = 0; $i < count($p); $i++) { | ||
| 607 | + /* If SOAP types do not match, it's still fine if the | ||
| 608 | + * mapped php types match this allows using plain PHP | ||
| 609 | + * variables to work (i.e. stuff like Decimal would | ||
| 610 | + * fail otherwise). We consider this only error if the | ||
| 611 | + * types exist in our type maps, and they differ. */ | ||
| 612 | + if (strcasecmp($sig_t[$i], $p[$i]) != 0 && | ||
| 613 | + isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]]) && | ||
| 614 | + strcasecmp($this->_typemap[SOAP_XML_SCHEMA_VERSION][$sig_t[$i]], $this->_typemap[SOAP_XML_SCHEMA_VERSION][$p[$i]]) != 0) { | ||
| 615 | + | ||
| 616 | + $param = $params[$i]; | ||
| 617 | + $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'); | ||
| 618 | + return false; | ||
| 619 | + } | ||
| 620 | + } | ||
| 621 | + return true; | ||
| 622 | + } else { | ||
| 623 | + /* Wrong number of params. */ | ||
| 624 | + $this->_raiseSoapFault('SOAP request contained incorrect number of parameters. method "' . $this->methodname . '" required ' . count($sig) . ' and request provided ' . count($params), '', '', 'Client'); | ||
| 625 | + return false; | ||
| 626 | + } | ||
| 627 | + } else { | ||
| 628 | + /* No params. */ | ||
| 629 | + $this->_raiseSoapFault('SOAP request contained incorrect number of parameters. method "' . $this->methodname . '" requires ' . count($sig) . ' parameters, and request provided none.', '', '', 'Client'); | ||
| 630 | + return false; | ||
| 631 | + } | ||
| 632 | + } | ||
| 633 | + | ||
| 634 | + /* We'll try it anyway. */ | ||
| 635 | + return true; | ||
| 636 | + } | ||
| 637 | + | ||
| 638 | + function validateMethod($methodname, $namespace = null) | ||
| 639 | + { | ||
| 640 | + unset($this->soapobject); | ||
| 641 | + | ||
| 642 | + if (!$this->callValidation) { | ||
| 643 | + return true; | ||
| 644 | + } | ||
| 645 | + | ||
| 646 | + /* No SOAP access to private functions. */ | ||
| 647 | + if ($methodname[0] == '_') { | ||
| 648 | + return false; | ||
| 649 | + } | ||
| 650 | + | ||
| 651 | + /* if it's in our function list, ok */ | ||
| 652 | + if (array_key_exists($methodname, $this->dispatch_map) && | ||
| 653 | + (!$namespace || | ||
| 654 | + !array_key_exists('namespace', $this->dispatch_map[$methodname]) || | ||
| 655 | + $namespace == $this->dispatch_map[$methodname]['namespace'])) { | ||
| 656 | + if (array_key_exists('namespace', $this->dispatch_map[$methodname])) | ||
| 657 | + $this->method_namespace = $this->dispatch_map[$methodname]['namespace']; | ||
| 658 | + return true; | ||
| 659 | + } | ||
| 660 | + | ||
| 661 | + /* if it's in an object, it's ok */ | ||
| 662 | + if (isset($this->dispatch_objects[$namespace])) { | ||
| 663 | + $c = count($this->dispatch_objects[$namespace]); | ||
| 664 | + for ($i = 0; $i < $c; $i++) { | ||
| 665 | + $obj =& $this->dispatch_objects[$namespace][$i]; | ||
| 666 | + /* If we have a dispatch map, and the function is not in the | ||
| 667 | + * dispatch map, then it is not callable! */ | ||
| 668 | + if (method_exists($obj, '__dispatch')) { | ||
| 669 | + if ($obj->__dispatch($methodname)) { | ||
| 670 | + $this->method_namespace = $namespace; | ||
| 671 | + $this->soapobject =& $obj; | ||
| 672 | + return true; | ||
| 673 | + } | ||
| 674 | + } elseif (method_exists($obj, $methodname)) { | ||
| 675 | + $this->method_namespace = $namespace; | ||
| 676 | + $this->soapobject =& $obj; | ||
| 677 | + return true; | ||
| 678 | + } | ||
| 679 | + } | ||
| 680 | + } | ||
| 681 | + | ||
| 682 | + return false; | ||
| 683 | + } | ||
| 684 | + | ||
| 685 | + function addObjectMap(&$obj, $namespace = null, $service_name = 'Default', | ||
| 686 | + $service_desc = '') | ||
| 687 | + { | ||
| 688 | + if (!$namespace) { | ||
| 689 | + if (isset($obj->namespace)) { | ||
| 690 | + // XXX a bit of backwards compatibility | ||
| 691 | + $namespace = $obj->namespace; | ||
| 692 | + } else { | ||
| 693 | + $this->_raiseSoapFault('No namespace provided for class!', '', '', 'Server'); | ||
| 694 | + return false; | ||
| 695 | + } | ||
| 696 | + } | ||
| 697 | + if (!isset($this->dispatch_objects[$namespace])) { | ||
| 698 | + $this->dispatch_objects[$namespace] = array(); | ||
| 699 | + } | ||
| 700 | + $this->dispatch_objects[$namespace][] =& $obj; | ||
| 701 | + | ||
| 702 | + // Create internal WSDL structures for object | ||
| 703 | + | ||
| 704 | + // XXX Because some internal workings of PEAR::SOAP decide whether to | ||
| 705 | + // do certain things by the presence or absence of _wsdl, we should | ||
| 706 | + // only create a _wsdl structure if we know we can fill it; if | ||
| 707 | + // __dispatch_map or __typedef for the object is missing, we should | ||
| 708 | + // avoid creating it. Later, when we are using PHP 5 introspection, we | ||
| 709 | + // will be able to make the data for all objects without any extra | ||
| 710 | + // information from the developers, and this condition should be | ||
| 711 | + // dropped. | ||
| 712 | + | ||
| 713 | + // XXX Known issue: if imported WSDL (bindWSDL) or another WSDL source | ||
| 714 | + // is used to add _wsdl structure information, then addObjectWSDL is | ||
| 715 | + // used, there is a high possibility of _wsdl data corruption; | ||
| 716 | + // therefore you should avoid using __dispatch_map/__typedef | ||
| 717 | + // definitions AND other WSDL data sources in the same service. We | ||
| 718 | + // exclude classes that don't have __typedefs to allow external WSDL | ||
| 719 | + // files to be used with classes with no internal type definitions | ||
| 720 | + // (the types are defined in the WSDL file). When addObjectWSDL is | ||
| 721 | + // refactored to not cause corruption, this restriction can be | ||
| 722 | + // relaxed. | ||
| 723 | + | ||
| 724 | + // In summary, if you add an object with both a dispatch map and type | ||
| 725 | + // definitions, then previous WSDL file operation and type definitions | ||
| 726 | + // will be overwritten. | ||
| 727 | + if (isset($obj->__dispatch_map) && isset($obj->__typedef)) { | ||
| 728 | + $this->addObjectWSDL($obj, $namespace, $service_name, $service_desc); | ||
| 729 | + } | ||
| 730 | + | ||
| 731 | + return true; | ||
| 732 | + } | ||
| 733 | + | ||
| 734 | + /** | ||
| 735 | + * Adds a method to the dispatch map. | ||
| 736 | + */ | ||
| 737 | + function addToMap($methodname, $in, $out, $namespace = null, $alias = null) | ||
| 738 | + { | ||
| 739 | + if (!function_exists($methodname)) { | ||
| 740 | + $this->_raiseSoapFault('Error mapping function', '', '', 'Server'); | ||
| 741 | + return false; | ||
| 742 | + } | ||
| 743 | + | ||
| 744 | + $this->dispatch_map[$methodname]['in'] = $in; | ||
| 745 | + $this->dispatch_map[$methodname]['out'] = $out; | ||
| 746 | + $this->dispatch_map[$methodname]['alias'] = $alias; | ||
| 747 | + if ($namespace) { | ||
| 748 | + $this->dispatch_map[$methodname]['namespace'] = $namespace; | ||
| 749 | + } | ||
| 750 | + | ||
| 751 | + return true; | ||
| 752 | + } | ||
| 753 | + | ||
| 754 | + function setCallHandler($callHandler, $validation = true) | ||
| 755 | + { | ||
| 756 | + $this->callHandler = $callHandler; | ||
| 757 | + $this->callValidation = $validation; | ||
| 758 | + } | ||
| 759 | + | ||
| 760 | + /** | ||
| 761 | + * @deprecated use bindWSDL from now on | ||
| 762 | + */ | ||
| 763 | + function bind($wsdl_url) | ||
| 764 | + { | ||
| 765 | + $this->bindWSDL($wsdl_url); | ||
| 766 | + } | ||
| 767 | + | ||
| 768 | + /** | ||
| 769 | + * @param string a url to a WSDL resource | ||
| 770 | + * @return void | ||
| 771 | + */ | ||
| 772 | + function bindWSDL($wsdl_url) | ||
| 773 | + { | ||
| 774 | + /* Instantiate WSDL class. */ | ||
| 775 | + $this->_wsdl =& new SOAP_WSDL($wsdl_url); | ||
| 776 | + if ($this->_wsdl->fault) { | ||
| 777 | + $this->_raiseSoapFault($this->_wsdl->fault); | ||
| 778 | + } | ||
| 779 | + } | ||
| 780 | + | ||
| 781 | + /** | ||
| 782 | + * @return void | ||
| 783 | + */ | ||
| 784 | + function addObjectWSDL(&$wsdl_obj, $targetNamespace, $service_name, | ||
| 785 | + $service_desc = '') | ||
| 786 | + { | ||
| 787 | + if (!isset($this->_wsdl)) { | ||
| 788 | + $this->_wsdl =& new SOAP_WSDL; | ||
| 789 | + } | ||
| 790 | + | ||
| 791 | + $this->_wsdl->parseObject($wsdl_obj, $targetNamespace, $service_name, $service_desc); | ||
| 792 | + | ||
| 793 | + if ($this->_wsdl->fault) { | ||
| 794 | + $this->_raiseSoapFault($this->_wsdl->fault); | ||
| 795 | + } | ||
| 796 | + } | ||
| 797 | +} |
thirdparty/pear/SOAP/Server/Email.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the email SOAP server. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 17 | + * @copyright 2003-2005 The PHP Group | ||
| 18 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 19 | + * @link http://pear.php.net/package/SOAP | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +require_once 'SOAP/Server.php'; | ||
| 23 | +require_once 'SOAP/Client.php'; | ||
| 24 | +require_once 'SOAP/Transport.php'; | ||
| 25 | +require_once 'Mail/mimeDecode.php'; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * SOAP Server Class that implements an email SOAP server. | ||
| 29 | + * http://www.pocketsoap.com/specs/smtpbinding/ | ||
| 30 | + * | ||
| 31 | + * This class overrides the default HTTP server, providing the ability to | ||
| 32 | + * parse an email message and execute SOAP calls. This class DOES NOT pop the | ||
| 33 | + * message; the message, complete with headers, must be passed in as a | ||
| 34 | + * parameter to the service function call. | ||
| 35 | + * | ||
| 36 | + * @access public | ||
| 37 | + * @package SOAP | ||
| 38 | + * @author Shane Caraveo <shane@php.net> | ||
| 39 | + */ | ||
| 40 | +class SOAP_Server_Email extends SOAP_Server { | ||
| 41 | + | ||
| 42 | + var $headers = array(); | ||
| 43 | + | ||
| 44 | + function SOAP_Server_Email($send_response = true) | ||
| 45 | + { | ||
| 46 | + parent::SOAP_Server(); | ||
| 47 | + $this->send_response = $send_response; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Removes HTTP headers from response. | ||
| 52 | + * | ||
| 53 | + * TODO: use PEAR email classes | ||
| 54 | + * | ||
| 55 | + * @return boolean | ||
| 56 | + * @access private | ||
| 57 | + */ | ||
| 58 | + function _parseEmail(&$data) | ||
| 59 | + { | ||
| 60 | + if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $data, $match)) { | ||
| 61 | + | ||
| 62 | + if (preg_match_all('/^(.*?):\s+(.*)$/m', $match[1], $matches)) { | ||
| 63 | + $hc = count($matches[0]); | ||
| 64 | + for ($i = 0; $i < $hc; $i++) { | ||
| 65 | + $this->headers[strtolower($matches[1][$i])] = trim($matches[2][$i]); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + if (!stristr($this->headers['content-type'], 'text/xml')) { | ||
| 70 | + $this->_raiseSoapFault('Invalid Content Type', '', '', 'Client'); | ||
| 71 | + return false; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + if (strcasecmp($this->headers['content-transfer-encoding'], 'base64')==0) { | ||
| 75 | + /* Unfold lines. */ | ||
| 76 | + $enctext = preg_replace("/[\r|\n]/", '', $match[2]); | ||
| 77 | + $data = base64_decode($enctext); | ||
| 78 | + } else { | ||
| 79 | + $data = $match[2]; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + /* If no content, return false. */ | ||
| 83 | + return strlen($this->request) > 0; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + $this->_raiseSoapFault('Invalid Email Format', '', '', 'Client'); | ||
| 87 | + | ||
| 88 | + return false; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + function client(&$data) | ||
| 92 | + { | ||
| 93 | + $attachments = array(); | ||
| 94 | + | ||
| 95 | + /* If neither matches, we'll just try it anyway. */ | ||
| 96 | + if (stristr($data, 'Content-Type: application/dime')) { | ||
| 97 | + $this->_decodeDIMEMessage($data, $this->headers, $attachments); | ||
| 98 | + $useEncoding = 'DIME'; | ||
| 99 | + } elseif (stristr($data, 'MIME-Version:')) { | ||
| 100 | + /* This is a mime message, let's decode it. */ | ||
| 101 | + $this->_decodeMimeMessage($data, $this->headers, $attachments); | ||
| 102 | + $useEncoding = 'Mime'; | ||
| 103 | + } else { | ||
| 104 | + /* The old fallback, but decodeMimeMessage handles things fine. */ | ||
| 105 | + $this->_parseEmail($data); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + /* Get the character encoding of the incoming request treat incoming | ||
| 109 | + * data as UTF-8 if no encoding set. */ | ||
| 110 | + if (!$this->soapfault && | ||
| 111 | + !$this->_getContentEncoding($this->headers['content-type'])) { | ||
| 112 | + $this->xml_encoding = SOAP_DEFAULT_ENCODING; | ||
| 113 | + /* An encoding we don't understand, return a fault. */ | ||
| 114 | + $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + if ($this->soapfault) { | ||
| 118 | + return $this->soapfault->getFault(); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + $client =& new SOAP_Client(null); | ||
| 122 | + | ||
| 123 | + return $client->__parse($data, $this->xml_encoding, $this->attachments); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + function service(&$data, $endpoint = '', $send_response = true, | ||
| 127 | + $dump = false) | ||
| 128 | + { | ||
| 129 | + $this->endpoint = $endpoint; | ||
| 130 | + $attachments = array(); | ||
| 131 | + $headers = array(); | ||
| 132 | + | ||
| 133 | + /* If neither matches, we'll just try it anyway. */ | ||
| 134 | + if (stristr($data, 'Content-Type: application/dime')) { | ||
| 135 | + $this->_decodeDIMEMessage($data, $this->headers, $attachments); | ||
| 136 | + $useEncoding = 'DIME'; | ||
| 137 | + } elseif (stristr($data, 'MIME-Version:')) { | ||
| 138 | + /* This is a mime message, let's decode it. */ | ||
| 139 | + $this->_decodeMimeMessage($data, $this->headers, $attachments); | ||
| 140 | + $useEncoding = 'Mime'; | ||
| 141 | + } else { | ||
| 142 | + /* The old fallback, but decodeMimeMessage handles things fine. */ | ||
| 143 | + $this->_parseEmail($data); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + /* Get the character encoding of the incoming request treat incoming | ||
| 147 | + * data as UTF-8 if no encoding set. */ | ||
| 148 | + if (!$response && | ||
| 149 | + !$this->_getContentEncoding($this->headers['content-type'])) { | ||
| 150 | + $this->xml_encoding = SOAP_DEFAULT_ENCODING; | ||
| 151 | + /* An encoding we don't understand, return a fault. */ | ||
| 152 | + $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); | ||
| 153 | + $response = $this->getFaultMessage(); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + if ($this->soapfault) { | ||
| 157 | + $response = $this->soapfault->message(); | ||
| 158 | + } else { | ||
| 159 | + $soap_msg = $this->parseRequest($data,$attachments); | ||
| 160 | + | ||
| 161 | + /* Handle Mime or DIME encoding. */ | ||
| 162 | + /* TODO: DIME Encoding should move to the transport, do it here | ||
| 163 | + * for now and for ease of getting it done. */ | ||
| 164 | + if (count($this->__attachments)) { | ||
| 165 | + if ($useEncoding == 'Mime') { | ||
| 166 | + $soap_msg = $this->_makeMimeMessage($soap_msg); | ||
| 167 | + } else { | ||
| 168 | + /* Default is DIME. */ | ||
| 169 | + $soap_msg = $this->_makeDIMEMessage($soap_msg); | ||
| 170 | + $header['Content-Type'] = 'application/dime'; | ||
| 171 | + } | ||
| 172 | + if (PEAR::isError($soap_msg)) { | ||
| 173 | + return $this->raiseSoapFault($soap_msg); | ||
| 174 | + } | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + if (is_array($soap_msg)) { | ||
| 178 | + $response = $soap_msg['body']; | ||
| 179 | + if (count($soap_msg['headers'])) { | ||
| 180 | + $headers = $soap_msg['headers']; | ||
| 181 | + } | ||
| 182 | + } else { | ||
| 183 | + $response = $soap_msg; | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + if ($this->send_response) { | ||
| 188 | + if ($dump) { | ||
| 189 | + print $response; | ||
| 190 | + } else { | ||
| 191 | + $from = array_key_exists('reply-to', $this->headers) ? $this->headers['reply-to'] : $this->headers['from']; | ||
| 192 | + | ||
| 193 | + $soap_transport =& SOAP_Transport::getTransport('mailto:' . $from, $this->response_encoding); | ||
| 194 | + $from = $this->endpoint ? $this->endpoint : $this->headers['to']; | ||
| 195 | + $headers['In-Reply-To'] = $this->headers['message-id']; | ||
| 196 | + $options = array('from' => $from, 'subject' => $this->headers['subject'], 'headers' => $headers); | ||
| 197 | + $soap_transport->send($response, $options); | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | + } | ||
| 201 | +} |
thirdparty/pear/SOAP/Server/Email_Gateway.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the email-HTTP SOAP gateway server. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 17 | + * @copyright 2003-2005 The PHP Group | ||
| 18 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 19 | + * @link http://pear.php.net/package/SOAP | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +require_once 'SOAP/Server/Email.php'; | ||
| 23 | +require_once 'SOAP/Transport.php'; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * SOAP Server Class that implements an email SOAP server. | ||
| 27 | + * http://www.pocketsoap.com/specs/smtpbinding/ | ||
| 28 | + * | ||
| 29 | + * This class overrides the default HTTP server, providing the ability to | ||
| 30 | + * parse an email message and execute soap calls. This class DOES NOT pop the | ||
| 31 | + * message; the message, complete with headers, must be passed in as a | ||
| 32 | + * parameter to the service function call. | ||
| 33 | + * | ||
| 34 | + * This class calls a provided HTTP SOAP server, forwarding the email request, | ||
| 35 | + * then sending the HTTP response out as an email. | ||
| 36 | + * | ||
| 37 | + * @access public | ||
| 38 | + * @package SOAP | ||
| 39 | + * @author Shane Caraveo <shane@php.net> | ||
| 40 | + */ | ||
| 41 | +class SOAP_Server_Email_Gateway extends SOAP_Server_Email { | ||
| 42 | + | ||
| 43 | + var $gateway = null; | ||
| 44 | + var $dump = false; | ||
| 45 | + | ||
| 46 | + function SOAP_Server_Email_Gateway($gateway = '', $send_response = true, | ||
| 47 | + $dump = false) | ||
| 48 | + { | ||
| 49 | + parent::SOAP_Server(); | ||
| 50 | + $this->send_response = $send_response; | ||
| 51 | + $this->gateway = $gateway; | ||
| 52 | + $this->dump = $dump; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + function service(&$data, $gateway = '', $endpoint = '', | ||
| 56 | + $send_response = true, $dump = false) | ||
| 57 | + { | ||
| 58 | + $this->endpoint = $endpoint; | ||
| 59 | + $response = ''; | ||
| 60 | + $useEncoding = 'Mime'; | ||
| 61 | + $options = array(); | ||
| 62 | + if (!$gateway) { | ||
| 63 | + $gateway = $this->gateway; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /* We have a full set of headers, need to find the first blank | ||
| 67 | + * line. */ | ||
| 68 | + $this->_parseEmail($data); | ||
| 69 | + if ($this->fault) { | ||
| 70 | + $response = $this->fault->message(); | ||
| 71 | + } | ||
| 72 | + if ($this->headers['content-type'] == 'application/dime') | ||
| 73 | + $useEncoding = 'DIME'; | ||
| 74 | + | ||
| 75 | + /* Call the HTTP Server. */ | ||
| 76 | + if (!$response) { | ||
| 77 | + $soap_transport =& SOAP_Transport::getTransport($gateway, $this->xml_encoding); | ||
| 78 | + if ($soap_transport->fault) { | ||
| 79 | + $response = $soap_transport->fault->message(); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /* Send the message. */ | ||
| 84 | + if (!$response) { | ||
| 85 | + $options['soapaction'] = $this->headers['soapaction']; | ||
| 86 | + $options['headers']['Content-Type'] = $this->headers['content-type']; | ||
| 87 | + | ||
| 88 | + $response = $soap_transport->send($data, $options); | ||
| 89 | + if (isset($this->headers['mime-version'])) | ||
| 90 | + $options['headers']['MIME-Version'] = $this->headers['mime-version']; | ||
| 91 | + | ||
| 92 | + if ($soap_transport->fault) { | ||
| 93 | + $response = $soap_transport->fault->message(); | ||
| 94 | + } else { | ||
| 95 | + foreach ($soap_transport->transport->attachments as $cid => $body) { | ||
| 96 | + $this->attachments[] = array('body' => $body, 'cid' => $cid, 'encoding' => 'base64'); | ||
| 97 | + } | ||
| 98 | + if (count($this->__attachments)) { | ||
| 99 | + if ($useEncoding == 'Mime') { | ||
| 100 | + $soap_msg = $this->_makeMimeMessage($response); | ||
| 101 | + $options['headers']['MIME-Version'] = '1.0'; | ||
| 102 | + } else { | ||
| 103 | + /* Default is DIME. */ | ||
| 104 | + $soap_msg = $this->_makeDIMEMessage($response); | ||
| 105 | + $options['headers']['Content-Type'] = 'application/dime'; | ||
| 106 | + } | ||
| 107 | + if (PEAR::isError($soap_msg)) { | ||
| 108 | + return $this->_raiseSoapFault($soap_msg); | ||
| 109 | + } | ||
| 110 | + if (is_array($soap_msg)) { | ||
| 111 | + $response = $soap_msg['body']; | ||
| 112 | + if (count($soap_msg['headers'])) { | ||
| 113 | + if (isset($options['headers'])) { | ||
| 114 | + $options['headers'] = array_merge($options['headers'], $soap_msg['headers']); | ||
| 115 | + } else { | ||
| 116 | + $options['headers'] = $soap_msg['headers']; | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + if ($this->send_response) { | ||
| 125 | + if ($this->dump || $dump) { | ||
| 126 | + print $response; | ||
| 127 | + } else { | ||
| 128 | + $from = array_key_exists('reply-to', $this->headers) ? $this->headers['reply-to'] : $this->headers['from']; | ||
| 129 | + | ||
| 130 | + $soap_transport =& SOAP_Transport::getTransport('mailto:' . $from, $this->response_encoding); | ||
| 131 | + $from = $this->endpoint ? $this->endpoint : $this->headers['to']; | ||
| 132 | + $headers = array('In-Reply-To' => $this->headers['message-id']); | ||
| 133 | + $options = array('from' => $from, 'subject'=> $this->headers['subject'], 'headers' => $headers); | ||
| 134 | + $soap_transport->send($response, $options); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | +} |
thirdparty/pear/SOAP/Server/TCP.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the TCP SOAP server. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 17 | + * @copyright 2003-2005 The PHP Group | ||
| 18 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 19 | + * @link http://pear.php.net/package/SOAP | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +require_once 'SOAP/Server.php'; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * SOAP Server Class that implements a TCP SOAP Server. | ||
| 26 | + * http://www.pocketsoap.com/specs/smtpbinding/ | ||
| 27 | + * | ||
| 28 | + * This class overrides the default HTTP server, providing the ability to | ||
| 29 | + * accept socket connections and execute SOAP calls. | ||
| 30 | + * | ||
| 31 | + * TODO: | ||
| 32 | + * use Net_Socket | ||
| 33 | + * implement some security scheme | ||
| 34 | + * implement support for attachments | ||
| 35 | + * | ||
| 36 | + * @access public | ||
| 37 | + * @package SOAP | ||
| 38 | + * @author Shane Caraveo <shane@php.net> | ||
| 39 | + */ | ||
| 40 | +class SOAP_Server_TCP extends SOAP_Server { | ||
| 41 | + | ||
| 42 | + var $headers = array(); | ||
| 43 | + var $localaddr; | ||
| 44 | + var $port; | ||
| 45 | + var $listen; | ||
| 46 | + var $reuse; | ||
| 47 | + | ||
| 48 | + function SOAP_Server_TCP($localaddr = '127.0.0.1', $port = 10000, | ||
| 49 | + $listen = 5, $reuse = true) | ||
| 50 | + { | ||
| 51 | + parent::SOAP_Server(); | ||
| 52 | + $this->localaddr = $localaddr; | ||
| 53 | + $this->port = $port; | ||
| 54 | + $this->listen = $listen; | ||
| 55 | + $this->reuse = $reuse; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + function run() | ||
| 59 | + { | ||
| 60 | + if (($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0) { | ||
| 61 | + return $this->_raiseSoapFault('socket_create() failed. Reason: ' . socket_strerror($sock)); | ||
| 62 | + } | ||
| 63 | + if ($this->reuse && | ||
| 64 | + !@socket_setopt($sock, SOL_SOCKET, SO_REUSEADDR, 1)) { | ||
| 65 | + return $this->_raiseSoapFault('socket_setopt() failed. Reason: ' . socket_strerror(socket_last_error($sock))); | ||
| 66 | + } | ||
| 67 | + if (($ret = socket_bind($sock, $this->localaddr, $this->port)) < 0) { | ||
| 68 | + return $this->_raiseSoapFault('socket_bind() failed. Reason: ' . socket_strerror($ret)); | ||
| 69 | + } | ||
| 70 | + if (($ret = socket_listen($sock, $this->listen)) < 0) { | ||
| 71 | + return $this->_raiseSoapFault('socket_listen() failed. Reason: ' . socket_strerror($ret)); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + while (true) { | ||
| 75 | + $data = null; | ||
| 76 | + if (($msgsock = socket_accept($sock)) < 0) { | ||
| 77 | + $this->_raiseSoapFault('socket_accept() failed. Reason: ' . socket_strerror($msgsock)); | ||
| 78 | + break; | ||
| 79 | + } | ||
| 80 | + while ($buf = socket_read($msgsock, 8192)) { | ||
| 81 | + if (!$buf = trim($buf)) { | ||
| 82 | + continue; | ||
| 83 | + } | ||
| 84 | + $data .= $buf; | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + if ($data) { | ||
| 88 | + $response = $this->service($data); | ||
| 89 | + /* Write to the socket. */ | ||
| 90 | + if (!socket_write($msgsock, $response, strlen($response))) { | ||
| 91 | + return $this->_raiseSoapFault('Error sending response data reason ' . socket_strerror()); | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + socket_close ($msgsock); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + socket_close ($sock); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + function service(&$data) | ||
| 102 | + { | ||
| 103 | + /* TODO: we need to handle attachments somehow. */ | ||
| 104 | + return $this->parseRequest($data, $attachments); | ||
| 105 | + } | ||
| 106 | +} |
thirdparty/pear/SOAP/Transport.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for an abstract transport layer. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> | ||
| 18 | + * @copyright 2003-2005 The PHP Group | ||
| 19 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 20 | + * @link http://pear.php.net/package/SOAP | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +require_once 'SOAP/Base.php'; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * SOAP Transport Layer | ||
| 27 | + * | ||
| 28 | + * This layer can use different protocols dependant on the endpoint url provided | ||
| 29 | + * no knowlege of the SOAP protocol is available at this level | ||
| 30 | + * no knowlege of the transport protocols is available at this level | ||
| 31 | + * | ||
| 32 | + * @access public | ||
| 33 | + * @package SOAP | ||
| 34 | + * @author Shane Caraveo <shane@php.net> | ||
| 35 | + */ | ||
| 36 | +class SOAP_Transport | ||
| 37 | +{ | ||
| 38 | + function &getTransport($url, $encoding = SOAP_DEFAULT_ENCODING) | ||
| 39 | + { | ||
| 40 | + $urlparts = @parse_url($url); | ||
| 41 | + | ||
| 42 | + if (!$urlparts['scheme']) { | ||
| 43 | + $fault = SOAP_Base_Object::_raiseSoapFault("Invalid transport URI: $url"); | ||
| 44 | + return $fault; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + if (strcasecmp($urlparts['scheme'], 'mailto') == 0) { | ||
| 48 | + $transport_type = 'SMTP'; | ||
| 49 | + } elseif (strcasecmp($urlparts['scheme'], 'https') == 0) { | ||
| 50 | + $transport_type = 'HTTP'; | ||
| 51 | + } else { | ||
| 52 | + /* handle other transport types */ | ||
| 53 | + $transport_type = strtoupper($urlparts['scheme']); | ||
| 54 | + } | ||
| 55 | + $transport_include = 'SOAP/Transport/' . $transport_type . '.php'; | ||
| 56 | + $res = @include_once($transport_include); | ||
| 57 | + if (!$res && !in_array($transport_include, get_included_files())) { | ||
| 58 | + $fault = SOAP_Base_Object::_raiseSoapFault("No Transport for {$urlparts['scheme']}"); | ||
| 59 | + return $fault; | ||
| 60 | + } | ||
| 61 | + $transport_class = "SOAP_Transport_$transport_type"; | ||
| 62 | + if (!class_exists($transport_class)) { | ||
| 63 | + $fault = SOAP_Base_Object::_raiseSoapFault("No Transport class $transport_class"); | ||
| 64 | + return $fault; | ||
| 65 | + } | ||
| 66 | + $t =& new $transport_class($url, $encoding); | ||
| 67 | + | ||
| 68 | + return $t; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | +} |
thirdparty/pear/SOAP/Transport/HTTP.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for a HTTP transport layer. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Shane Caraveo <Shane@Caraveo.com> | ||
| 17 | + * @copyright 2003-2005 The PHP Group | ||
| 18 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 19 | + * @link http://pear.php.net/package/SOAP | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * HTTP Transport class | ||
| 24 | + * | ||
| 25 | + * @package SOAP | ||
| 26 | + * @category Web_Services | ||
| 27 | + */ | ||
| 28 | + | ||
| 29 | +/** | ||
| 30 | + * Needed Classes | ||
| 31 | + */ | ||
| 32 | +require_once 'SOAP/Base.php'; | ||
| 33 | + | ||
| 34 | +/** | ||
| 35 | + * HTTP Transport for SOAP | ||
| 36 | + * | ||
| 37 | + * @access public | ||
| 38 | + * @package SOAP | ||
| 39 | + * @author Shane Caraveo <shane@php.net> | ||
| 40 | + */ | ||
| 41 | +class SOAP_Transport_HTTP extends SOAP_Base | ||
| 42 | +{ | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * Basic Auth string. | ||
| 46 | + * | ||
| 47 | + * @var array | ||
| 48 | + */ | ||
| 49 | + var $headers = array(); | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * Cookies. | ||
| 53 | + * | ||
| 54 | + * @var array | ||
| 55 | + */ | ||
| 56 | + var $cookies; | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * Connection timeout in seconds. 0 = none. | ||
| 60 | + * | ||
| 61 | + * @var integer | ||
| 62 | + */ | ||
| 63 | + var $timeout = 4; | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * Array containing urlparts - parse_url(). | ||
| 67 | + * | ||
| 68 | + * @var mixed | ||
| 69 | + */ | ||
| 70 | + var $urlparts = null; | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * Connection endpoint - URL. | ||
| 74 | + * | ||
| 75 | + * @var string | ||
| 76 | + */ | ||
| 77 | + var $url = ''; | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * Incoming payload. | ||
| 81 | + * | ||
| 82 | + * @var string | ||
| 83 | + */ | ||
| 84 | + var $incoming_payload = ''; | ||
| 85 | + | ||
| 86 | + /** | ||
| 87 | + * HTTP-Request User-Agent. | ||
| 88 | + * | ||
| 89 | + * @var string | ||
| 90 | + */ | ||
| 91 | + var $_userAgent = SOAP_LIBRARY_NAME; | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * HTTP encoding. | ||
| 95 | + * | ||
| 96 | + * @var string | ||
| 97 | + */ | ||
| 98 | + var $encoding = SOAP_DEFAULT_ENCODING; | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * HTTP-Response Content-Type encoding. | ||
| 102 | + * We assume UTF-8 if no encoding is set. | ||
| 103 | + * | ||
| 104 | + * @var string | ||
| 105 | + */ | ||
| 106 | + var $result_encoding = 'UTF-8'; | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * HTTP-Response Content-Type. | ||
| 110 | + */ | ||
| 111 | + var $result_content_type; | ||
| 112 | + | ||
| 113 | + var $result_headers = array(); | ||
| 114 | + | ||
| 115 | + var $result_cookies = array(); | ||
| 116 | + | ||
| 117 | + /** | ||
| 118 | + * SOAP_Transport_HTTP Constructor | ||
| 119 | + * | ||
| 120 | + * @access public | ||
| 121 | + * | ||
| 122 | + * @param string $url HTTP url to SOAP endpoint. | ||
| 123 | + * @param string $encoding Encoding to use. | ||
| 124 | + */ | ||
| 125 | + function SOAP_Transport_HTTP($url, $encoding = SOAP_DEFAULT_ENCODING) | ||
| 126 | + { | ||
| 127 | + parent::SOAP_Base('HTTP'); | ||
| 128 | + $this->urlparts = @parse_url($url); | ||
| 129 | + $this->url = $url; | ||
| 130 | + $this->encoding = $encoding; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * Sends and receives SOAP data. | ||
| 135 | + * | ||
| 136 | + * @param string Outgoing POST data. | ||
| 137 | + * @param array Options. | ||
| 138 | + * | ||
| 139 | + * @return string|SOAP_Fault | ||
| 140 | + * @access public | ||
| 141 | + */ | ||
| 142 | + function send($msg, $options = null) | ||
| 143 | + { | ||
| 144 | + if (!$this->_validateUrl()) { | ||
| 145 | + return $this->fault; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + if (isset($options['timeout'])) { | ||
| 149 | + $this->timeout = (int)$options['timeout']; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { | ||
| 153 | + return $this->_sendHTTP($msg, $options); | ||
| 154 | + } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { | ||
| 155 | + return $this->_sendHTTPS($msg, $options); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + return $this->_raiseSoapFault('Invalid url scheme ' . $this->url); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + /** | ||
| 162 | + * Sets data for HTTP authentication, creates authorization header. | ||
| 163 | + * | ||
| 164 | + * @param string $username Username. | ||
| 165 | + * @param string $password Response data, minus HTTP headers. | ||
| 166 | + * | ||
| 167 | + * @access public | ||
| 168 | + */ | ||
| 169 | + function setCredentials($username, $password) | ||
| 170 | + { | ||
| 171 | + $this->headers['Authorization'] = 'Basic ' . base64_encode($username . ':' . $password); | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + /** | ||
| 175 | + * Adds a cookie. | ||
| 176 | + * | ||
| 177 | + * @access public | ||
| 178 | + * @param string $name Cookie name. | ||
| 179 | + * @param mixed $value Cookie value. | ||
| 180 | + */ | ||
| 181 | + function addCookie($name, $value) | ||
| 182 | + { | ||
| 183 | + $this->cookies[$name] = $value; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + /** | ||
| 187 | + * Generates the correct headers for the cookies. | ||
| 188 | + * | ||
| 189 | + * @access private | ||
| 190 | + */ | ||
| 191 | + function _genCookieHeader() | ||
| 192 | + { | ||
| 193 | + foreach ($this->cookies as $name=>$value) { | ||
| 194 | + $cookies = (isset($cookies) ? $cookies. '; ' : '') . | ||
| 195 | + urlencode($name) . '=' . urlencode($value); | ||
| 196 | + } | ||
| 197 | + return $cookies; | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + /** | ||
| 201 | + * Validate url data passed to constructor. | ||
| 202 | + * | ||
| 203 | + * @access private | ||
| 204 | + * @return boolean | ||
| 205 | + */ | ||
| 206 | + function _validateUrl() | ||
| 207 | + { | ||
| 208 | + if (!is_array($this->urlparts) ) { | ||
| 209 | + $this->_raiseSoapFault('Unable to parse URL ' . $this->url); | ||
| 210 | + return false; | ||
| 211 | + } | ||
| 212 | + if (!isset($this->urlparts['host'])) { | ||
| 213 | + $this->_raiseSoapFault('No host in URL ' . $this->url); | ||
| 214 | + return false; | ||
| 215 | + } | ||
| 216 | + if (!isset($this->urlparts['port'])) { | ||
| 217 | + if (strcasecmp($this->urlparts['scheme'], 'HTTP') == 0) { | ||
| 218 | + $this->urlparts['port'] = 80; | ||
| 219 | + } elseif (strcasecmp($this->urlparts['scheme'], 'HTTPS') == 0) { | ||
| 220 | + $this->urlparts['port'] = 443; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + } | ||
| 224 | + if (isset($this->urlparts['user'])) { | ||
| 225 | + $this->setCredentials(urldecode($this->urlparts['user']), | ||
| 226 | + urldecode($this->urlparts['pass'])); | ||
| 227 | + } | ||
| 228 | + if (!isset($this->urlparts['path']) || !$this->urlparts['path']) { | ||
| 229 | + $this->urlparts['path'] = '/'; | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + return true; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + /** | ||
| 236 | + * Finds out what the encoding is. | ||
| 237 | + * Sets the object property accordingly. | ||
| 238 | + * | ||
| 239 | + * @access private | ||
| 240 | + * @param array $headers Headers. | ||
| 241 | + */ | ||
| 242 | + function _parseEncoding($headers) | ||
| 243 | + { | ||
| 244 | + $h = stristr($headers, 'Content-Type'); | ||
| 245 | + preg_match_all('/^Content-Type:\s*(.*)$/im', $h, $ct, PREG_SET_ORDER); | ||
| 246 | + $n = count($ct); | ||
| 247 | + $ct = $ct[$n - 1]; | ||
| 248 | + | ||
| 249 | + // Strip the string of \r. | ||
| 250 | + $this->result_content_type = str_replace("\r", '', $ct[1]); | ||
| 251 | + | ||
| 252 | + if (preg_match('/(.*?)(?:;\s?charset=)(.*)/i', | ||
| 253 | + $this->result_content_type, | ||
| 254 | + $m)) { | ||
| 255 | + $this->result_content_type = $m[1]; | ||
| 256 | + if (count($m) > 2) { | ||
| 257 | + $enc = strtoupper(str_replace('"', '', $m[2])); | ||
| 258 | + if (in_array($enc, $this->_encodings)) { | ||
| 259 | + $this->result_encoding = $enc; | ||
| 260 | + } | ||
| 261 | + } | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + // Deal with broken servers that don't set content type on faults. | ||
| 265 | + if (!$this->result_content_type) { | ||
| 266 | + $this->result_content_type = 'text/xml'; | ||
| 267 | + } | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + /** | ||
| 271 | + * Parses the headers. | ||
| 272 | + * | ||
| 273 | + * @param array $headers The headers. | ||
| 274 | + */ | ||
| 275 | + function _parseHeaders($headers) | ||
| 276 | + { | ||
| 277 | + /* Largely borrowed from HTTP_Request. */ | ||
| 278 | + $this->result_headers = array(); | ||
| 279 | + $headers = split("\r?\n", $headers); | ||
| 280 | + foreach ($headers as $value) { | ||
| 281 | + if (strpos($value,':') === false) { | ||
| 282 | + $this->result_headers[0] = $value; | ||
| 283 | + continue; | ||
| 284 | + } | ||
| 285 | + list($name, $value) = split(':', $value); | ||
| 286 | + $headername = strtolower($name); | ||
| 287 | + $headervalue = trim($value); | ||
| 288 | + $this->result_headers[$headername] = $headervalue; | ||
| 289 | + | ||
| 290 | + if ($headername == 'set-cookie') { | ||
| 291 | + // Parse a SetCookie header to fill _cookies array. | ||
| 292 | + $cookie = array('expires' => null, | ||
| 293 | + 'domain' => $this->urlparts['host'], | ||
| 294 | + 'path' => null, | ||
| 295 | + 'secure' => false); | ||
| 296 | + | ||
| 297 | + if (!strpos($headervalue, ';')) { | ||
| 298 | + // Only a name=value pair. | ||
| 299 | + list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $headervalue)); | ||
| 300 | + $cookie['name'] = urldecode($cookie['name']); | ||
| 301 | + $cookie['value'] = urldecode($cookie['value']); | ||
| 302 | + | ||
| 303 | + } else { | ||
| 304 | + // Some optional parameters are supplied. | ||
| 305 | + $elements = explode(';', $headervalue); | ||
| 306 | + list($cookie['name'], $cookie['value']) = array_map('trim', explode('=', $elements[0])); | ||
| 307 | + $cookie['name'] = urldecode($cookie['name']); | ||
| 308 | + $cookie['value'] = urldecode($cookie['value']); | ||
| 309 | + | ||
| 310 | + for ($i = 1; $i < count($elements);$i++) { | ||
| 311 | + list($elName, $elValue) = array_map('trim', explode('=', $elements[$i])); | ||
| 312 | + if ('secure' == $elName) { | ||
| 313 | + $cookie['secure'] = true; | ||
| 314 | + } elseif ('expires' == $elName) { | ||
| 315 | + $cookie['expires'] = str_replace('"', '', $elValue); | ||
| 316 | + } elseif ('path' == $elName OR 'domain' == $elName) { | ||
| 317 | + $cookie[$elName] = urldecode($elValue); | ||
| 318 | + } else { | ||
| 319 | + $cookie[$elName] = $elValue; | ||
| 320 | + } | ||
| 321 | + } | ||
| 322 | + } | ||
| 323 | + $this->result_cookies[] = $cookie; | ||
| 324 | + } | ||
| 325 | + } | ||
| 326 | + } | ||
| 327 | + | ||
| 328 | + /** | ||
| 329 | + * Removes HTTP headers from response. | ||
| 330 | + * | ||
| 331 | + * @return boolean | ||
| 332 | + * @access private | ||
| 333 | + */ | ||
| 334 | + function _parseResponse() | ||
| 335 | + { | ||
| 336 | + if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", | ||
| 337 | + $this->incoming_payload, | ||
| 338 | + $match)) { | ||
| 339 | + $this->response = $match[2]; | ||
| 340 | + // Find the response error, some servers response with 500 for | ||
| 341 | + // SOAP faults. | ||
| 342 | + $this->_parseHeaders($match[1]); | ||
| 343 | + | ||
| 344 | + list($protocol, $code, $msg) = sscanf($this->result_headers[0], | ||
| 345 | + '%s %s %s'); | ||
| 346 | + unset($this->result_headers[0]); | ||
| 347 | + | ||
| 348 | + switch($code) { | ||
| 349 | + case 100: // Continue | ||
| 350 | + $this->incoming_payload = $match[2]; | ||
| 351 | + return $this->_parseResponse(); | ||
| 352 | + case 400: | ||
| 353 | + $this->_raiseSoapFault("HTTP Response $code Bad Request"); | ||
| 354 | + return false; | ||
| 355 | + break; | ||
| 356 | + case 401: | ||
| 357 | + $this->_raiseSoapFault("HTTP Response $code Authentication Failed"); | ||
| 358 | + return false; | ||
| 359 | + break; | ||
| 360 | + case 403: | ||
| 361 | + $this->_raiseSoapFault("HTTP Response $code Forbidden"); | ||
| 362 | + return false; | ||
| 363 | + break; | ||
| 364 | + case 404: | ||
| 365 | + $this->_raiseSoapFault("HTTP Response $code Not Found"); | ||
| 366 | + return false; | ||
| 367 | + break; | ||
| 368 | + case 407: | ||
| 369 | + $this->_raiseSoapFault("HTTP Response $code Proxy Authentication Required"); | ||
| 370 | + return false; | ||
| 371 | + break; | ||
| 372 | + case 408: | ||
| 373 | + $this->_raiseSoapFault("HTTP Response $code Request Timeout"); | ||
| 374 | + return false; | ||
| 375 | + break; | ||
| 376 | + case 410: | ||
| 377 | + $this->_raiseSoapFault("HTTP Response $code Gone"); | ||
| 378 | + return false; | ||
| 379 | + break; | ||
| 380 | + default: | ||
| 381 | + if ($code >= 400 && $code < 500) { | ||
| 382 | + $this->_raiseSoapFault("HTTP Response $code Not Found, Server message: $msg"); | ||
| 383 | + return false; | ||
| 384 | + } | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + $this->_parseEncoding($match[1]); | ||
| 388 | + | ||
| 389 | + if ($this->result_content_type == 'application/dime') { | ||
| 390 | + // XXX quick hack insertion of DIME | ||
| 391 | + if (PEAR::isError($this->_decodeDIMEMessage($this->response,$this->headers,$this->attachments))) { | ||
| 392 | + // _decodeDIMEMessage already raised $this->fault | ||
| 393 | + return false; | ||
| 394 | + } | ||
| 395 | + $this->result_content_type = $this->headers['content-type']; | ||
| 396 | + } elseif (stristr($this->result_content_type,'multipart/related')) { | ||
| 397 | + $this->response = $this->incoming_payload; | ||
| 398 | + if (PEAR::isError($this->_decodeMimeMessage($this->response,$this->headers,$this->attachments))) { | ||
| 399 | + // _decodeMimeMessage already raised $this->fault | ||
| 400 | + return false; | ||
| 401 | + } | ||
| 402 | + } elseif ($this->result_content_type != 'text/xml') { | ||
| 403 | + $this->_raiseSoapFault($this->response); | ||
| 404 | + return false; | ||
| 405 | + } | ||
| 406 | + // if no content, return false | ||
| 407 | + return strlen($this->response) > 0; | ||
| 408 | + } | ||
| 409 | + $this->_raiseSoapFault('Invalid HTTP Response'); | ||
| 410 | + return false; | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + /** | ||
| 414 | + * Creates HTTP request, including headers, for outgoing request. | ||
| 415 | + * | ||
| 416 | + * @param string $msg Outgoing SOAP package. | ||
| 417 | + * @param array $options Options. | ||
| 418 | + * @return string Outgoing payload. | ||
| 419 | + * @access private | ||
| 420 | + */ | ||
| 421 | + function _getRequest($msg, $options) | ||
| 422 | + { | ||
| 423 | + $this->headers = array(); | ||
| 424 | + | ||
| 425 | + $action = isset($options['soapaction']) ? $options['soapaction'] : ''; | ||
| 426 | + $fullpath = $this->urlparts['path']; | ||
| 427 | + if (isset($this->urlparts['query'])) { | ||
| 428 | + $fullpath .= '?' . $this->urlparts['query']; | ||
| 429 | + } | ||
| 430 | + if (isset($this->urlparts['fragment'])) { | ||
| 431 | + $fullpath .= '#' . $this->urlparts['fragment']; | ||
| 432 | + } | ||
| 433 | + | ||
| 434 | + if (isset($options['proxy_host'])) { | ||
| 435 | + $fullpath = 'http://' . $this->urlparts['host'] . ':' . | ||
| 436 | + $this->urlparts['port'] . $fullpath; | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + if (isset($options['proxy_user'])) { | ||
| 440 | + $this->headers['Proxy-Authorization'] = 'Basic ' . | ||
| 441 | + base64_encode($options['proxy_user'] . ':' . | ||
| 442 | + $options['proxy_pass']); | ||
| 443 | + } | ||
| 444 | + | ||
| 445 | + if (isset($options['user'])) { | ||
| 446 | + $this->setCredentials($options['user'], $options['pass']); | ||
| 447 | + } | ||
| 448 | + | ||
| 449 | + $this->headers['User-Agent'] = $this->_userAgent; | ||
| 450 | + $this->headers['Host'] = $this->urlparts['host']; | ||
| 451 | + $this->headers['Content-Type'] = "text/xml; charset=$this->encoding"; | ||
| 452 | + $this->headers['Content-Length'] = strlen($msg); | ||
| 453 | + $this->headers['SOAPAction'] = '"' . $action . '"'; | ||
| 454 | + if (isset($options['headers'])) { | ||
| 455 | + $this->headers = array_merge($this->headers, $options['headers']); | ||
| 456 | + } | ||
| 457 | + | ||
| 458 | + $this->cookies = array(); | ||
| 459 | + if (!isset($options['nocookies']) || !$options['nocookies']) { | ||
| 460 | + // Add the cookies we got from the last request. | ||
| 461 | + if (isset($this->result_cookies)) { | ||
| 462 | + foreach ($this->result_cookies as $cookie) { | ||
| 463 | + if ($cookie['domain'] == $this->urlparts['host']) | ||
| 464 | + $this->cookies[$cookie['name']] = $cookie['value']; | ||
| 465 | + } | ||
| 466 | + } | ||
| 467 | + } | ||
| 468 | + // Add cookies the user wants to set. | ||
| 469 | + if (isset($options['cookies'])) { | ||
| 470 | + foreach ($options['cookies'] as $cookie) { | ||
| 471 | + if ($cookie['domain'] == $this->urlparts['host']) | ||
| 472 | + $this->cookies[$cookie['name']] = $cookie['value']; | ||
| 473 | + } | ||
| 474 | + } | ||
| 475 | + if (count($this->cookies)) { | ||
| 476 | + $this->headers['Cookie'] = $this->_genCookieHeader(); | ||
| 477 | + } | ||
| 478 | + $headers = ''; | ||
| 479 | + foreach ($this->headers as $k => $v) { | ||
| 480 | + $headers .= "$k: $v\r\n"; | ||
| 481 | + } | ||
| 482 | + $this->outgoing_payload = "POST $fullpath HTTP/1.0\r\n" . $headers . | ||
| 483 | + "\r\n" . $msg; | ||
| 484 | + | ||
| 485 | + return $this->outgoing_payload; | ||
| 486 | + } | ||
| 487 | + | ||
| 488 | + /** | ||
| 489 | + * Sends outgoing request, and read/parse response. | ||
| 490 | + * | ||
| 491 | + * @param string $msg Outgoing SOAP package. | ||
| 492 | + * @param string $action SOAP Action. | ||
| 493 | + * @return string Response data, minus HTTP headers. | ||
| 494 | + * @access private | ||
| 495 | + */ | ||
| 496 | + function _sendHTTP($msg, $options) | ||
| 497 | + { | ||
| 498 | + $this->incoming_payload = ''; | ||
| 499 | + $this->_getRequest($msg, $options); | ||
| 500 | + $host = $this->urlparts['host']; | ||
| 501 | + $port = $this->urlparts['port']; | ||
| 502 | + if (isset($options['proxy_host'])) { | ||
| 503 | + $host = $options['proxy_host']; | ||
| 504 | + $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; | ||
| 505 | + } | ||
| 506 | + // Send. | ||
| 507 | + if ($this->timeout > 0) { | ||
| 508 | + $fp = @fsockopen($host, $port, $this->errno, $this->errmsg, $this->timeout); | ||
| 509 | + } else { | ||
| 510 | + $fp = @fsockopen($host, $port, $this->errno, $this->errmsg); | ||
| 511 | + } | ||
| 512 | + if (!$fp) { | ||
| 513 | + return $this->_raiseSoapFault("Connect Error to $host:$port"); | ||
| 514 | + } | ||
| 515 | + if ($this->timeout > 0) { | ||
| 516 | + // some builds of PHP do not support this, silence the warning | ||
| 517 | + @socket_set_timeout($fp, $this->timeout); | ||
| 518 | + } | ||
| 519 | + if (!fputs($fp, $this->outgoing_payload, strlen($this->outgoing_payload))) { | ||
| 520 | + return $this->_raiseSoapFault("Error POSTing Data to $host"); | ||
| 521 | + } | ||
| 522 | + | ||
| 523 | + // get reponse | ||
| 524 | + // XXX time consumer | ||
| 525 | + do { | ||
| 526 | + $data = fread($fp, 4096); | ||
| 527 | + $_tmp_status = socket_get_status($fp); | ||
| 528 | + if ($_tmp_status['timed_out']) { | ||
| 529 | + return $this->_raiseSoapFault("Timed out read from $host"); | ||
| 530 | + } else { | ||
| 531 | + $this->incoming_payload .= $data; | ||
| 532 | + } | ||
| 533 | + } while (!$_tmp_status['eof']); | ||
| 534 | + | ||
| 535 | + fclose($fp); | ||
| 536 | + | ||
| 537 | + if (!$this->_parseResponse()) { | ||
| 538 | + return $this->fault; | ||
| 539 | + } | ||
| 540 | + return $this->response; | ||
| 541 | + } | ||
| 542 | + | ||
| 543 | + /** | ||
| 544 | + * Sends outgoing request, and read/parse response, via HTTPS. | ||
| 545 | + * | ||
| 546 | + * @param string $msg Outgoing SOAP package. | ||
| 547 | + * @param string $action SOAP Action. | ||
| 548 | + * @return string $response Response data, minus HTTP headers. | ||
| 549 | + * @access private | ||
| 550 | + */ | ||
| 551 | + function _sendHTTPS($msg, $options) | ||
| 552 | + { | ||
| 553 | + /* NOTE This function uses the CURL functions | ||
| 554 | + * Your php must be compiled with CURL | ||
| 555 | + */ | ||
| 556 | + if (!extension_loaded('curl')) { | ||
| 557 | + return $this->_raiseSoapFault('CURL Extension is required for HTTPS'); | ||
| 558 | + } | ||
| 559 | + | ||
| 560 | + $ch = curl_init(); | ||
| 561 | + | ||
| 562 | + if (isset($options['proxy_host'])) { | ||
| 563 | + // $options['http_proxy'] == 'hostname:port' | ||
| 564 | + $host = $options['proxy_host']; | ||
| 565 | + $port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080; | ||
| 566 | + curl_setopt($ch, CURLOPT_PROXY, $host . ":" . $port); | ||
| 567 | + } | ||
| 568 | + | ||
| 569 | + if (isset($options['proxy_user'])) { | ||
| 570 | + // $options['http_proxy_userpw'] == 'username:password' | ||
| 571 | + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $options['proxy_user'] . ':' . $options['proxy_pass']); | ||
| 572 | + } | ||
| 573 | + | ||
| 574 | + if (isset($options['user'])) { | ||
| 575 | + curl_setopt($ch, CURLOPT_USERPWD, $options['user'] . ':' . $options['pass']); | ||
| 576 | + } | ||
| 577 | + | ||
| 578 | + if (!isset($options['soapaction'])) { | ||
| 579 | + $options['soapaction'] = ''; | ||
| 580 | + } | ||
| 581 | + curl_setopt($ch, CURLOPT_HTTPHEADER , array('Content-Type: text/xml;charset=' . $this->encoding, 'SOAPAction: "'.$options['soapaction'].'"')); | ||
| 582 | + curl_setopt($ch, CURLOPT_USERAGENT , $this->_userAgent); | ||
| 583 | + | ||
| 584 | + if ($this->timeout) { | ||
| 585 | + curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); //times out after 4s | ||
| 586 | + } | ||
| 587 | + | ||
| 588 | + curl_setopt($ch, CURLOPT_POSTFIELDS, $msg); | ||
| 589 | + curl_setopt($ch, CURLOPT_URL, $this->url); | ||
| 590 | + curl_setopt($ch, CURLOPT_POST, 1); | ||
| 591 | + curl_setopt($ch, CURLOPT_FAILONERROR, 0); | ||
| 592 | + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | ||
| 593 | + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||
| 594 | + curl_setopt($ch, CURLOPT_HEADER, 1); | ||
| 595 | + if (defined('CURLOPT_HTTP_VERSION')) { | ||
| 596 | + curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); | ||
| 597 | + } | ||
| 598 | + | ||
| 599 | + if (isset($options['curl'])) { | ||
| 600 | + foreach ($options['curl'] as $key => $val) { | ||
| 601 | + curl_setopt($ch, $key, $val); | ||
| 602 | + } | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + // Save the outgoing XML. This doesn't quite match _sendHTTP as CURL | ||
| 606 | + // generates the headers, but having the XML is usually the most | ||
| 607 | + // important part for tracing/debugging. | ||
| 608 | + $this->outgoing_payload = $msg; | ||
| 609 | + | ||
| 610 | + $this->incoming_payload = curl_exec($ch); | ||
| 611 | + if (!$this->incoming_payload) { | ||
| 612 | + $m = 'curl_exec error ' . curl_errno($ch) . ' ' . curl_error($ch); | ||
| 613 | + curl_close($ch); | ||
| 614 | + return $this->_raiseSoapFault($m); | ||
| 615 | + } | ||
| 616 | + curl_close($ch); | ||
| 617 | + | ||
| 618 | + if (!$this->_parseResponse()) { | ||
| 619 | + return $this->fault; | ||
| 620 | + } | ||
| 621 | + | ||
| 622 | + return $this->response; | ||
| 623 | + } | ||
| 624 | + | ||
| 625 | +} |
thirdparty/pear/SOAP/Transport/SMTP.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for an SMTP transport layer. | ||
| 4 | + * | ||
| 5 | + * This code is still a rough and untested draft. | ||
| 6 | + * TODO: | ||
| 7 | + * switch to pear mail stuff | ||
| 8 | + * smtp authentication | ||
| 9 | + * smtp ssl support | ||
| 10 | + * ability to define smtp options (encoding, from, etc.) | ||
| 11 | + * | ||
| 12 | + * PHP versions 4 and 5 | ||
| 13 | + * | ||
| 14 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 15 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 16 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 17 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 18 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 19 | + * mail you a copy immediately. | ||
| 20 | + * | ||
| 21 | + * @category Web Services | ||
| 22 | + * @package SOAP | ||
| 23 | + * @author Shane Caraveo <Shane@Caraveo.com> | ||
| 24 | + * @copyright 2003-2005 The PHP Group | ||
| 25 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 26 | + * @link http://pear.php.net/package/SOAP | ||
| 27 | + */ | ||
| 28 | + | ||
| 29 | +require_once 'SOAP/Base.php'; | ||
| 30 | +require_once 'Mail/smtp.php'; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * SMTP Transport for SOAP | ||
| 34 | + * | ||
| 35 | + * implements SOAP-SMTP as defined at | ||
| 36 | + * http://www.pocketsoap.com/specs/smtpbinding/ | ||
| 37 | + * | ||
| 38 | + * TODO: use PEAR smtp and Mime classes | ||
| 39 | + * | ||
| 40 | + * @access public | ||
| 41 | + * @package SOAP | ||
| 42 | + * @author Shane Caraveo <shane@php.net> | ||
| 43 | + */ | ||
| 44 | +class SOAP_Transport_SMTP extends SOAP_Base | ||
| 45 | +{ | ||
| 46 | + | ||
| 47 | + var $credentials = ''; | ||
| 48 | + var $timeout = 4; // connect timeout | ||
| 49 | + var $urlparts = NULL; | ||
| 50 | + var $url = ''; | ||
| 51 | + var $incoming_payload = ''; | ||
| 52 | + var $_userAgent = SOAP_LIBRARY_NAME; | ||
| 53 | + var $encoding = SOAP_DEFAULT_ENCODING; | ||
| 54 | + var $host = '127.0.0.1'; | ||
| 55 | + var $port = 25; | ||
| 56 | + var $auth = NULL; | ||
| 57 | + /** | ||
| 58 | + * SOAP_Transport_SMTP Constructor | ||
| 59 | + * | ||
| 60 | + * @param string $URL mailto:address | ||
| 61 | + * | ||
| 62 | + * @access public | ||
| 63 | + */ | ||
| 64 | + function SOAP_Transport_SMTP($URL, $encoding='US-ASCII') | ||
| 65 | + { | ||
| 66 | + parent::SOAP_Base('SMTP'); | ||
| 67 | + $this->encoding = $encoding; | ||
| 68 | + $this->urlparts = @parse_url($URL); | ||
| 69 | + $this->url = $URL; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * Sends and receives SOAP data. | ||
| 74 | + * | ||
| 75 | + * @param string $msg Outgoing POST data. | ||
| 76 | + * @param string $action SOAP Action header data. | ||
| 77 | + * @param integer $timeout Socket timeout, defaults to 0 or off. | ||
| 78 | + * | ||
| 79 | + * @return string Response data, minus HTTP headers. | ||
| 80 | + * @access public | ||
| 81 | + */ | ||
| 82 | + function send($msg, $options = array()) | ||
| 83 | + { | ||
| 84 | + $this->incoming_payload = ''; | ||
| 85 | + $this->outgoing_payload = $msg; | ||
| 86 | + if (!$this->_validateUrl()) { | ||
| 87 | + return $this->fault; | ||
| 88 | + } | ||
| 89 | + if (!$options || !isset($options['from'])) { | ||
| 90 | + return $this->_raiseSoapFault('No From: address to send message with'); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + if (isset($options['host'])) $this->host = $options['host']; | ||
| 94 | + if (isset($options['port'])) $this->port = $options['port']; | ||
| 95 | + if (isset($options['auth'])) $this->auth = $options['auth']; | ||
| 96 | + if (isset($options['username'])) $this->username = $options['username']; | ||
| 97 | + if (isset($options['password'])) $this->password = $options['password']; | ||
| 98 | + | ||
| 99 | + $headers = array(); | ||
| 100 | + $headers['From'] = $options['from']; | ||
| 101 | + $headers['X-Mailer'] = $this->_userAgent; | ||
| 102 | + $headers['MIME-Version'] = '1.0'; | ||
| 103 | + $headers['Message-ID'] = md5(time()) . '.soap@' . $this->host; | ||
| 104 | + $headers['To'] = $this->urlparts['path']; | ||
| 105 | + if (isset($options['soapaction'])) { | ||
| 106 | + $headers['Soapaction'] = "\"{$options['soapaction']}\""; | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + if (isset($options['headers'])) | ||
| 110 | + $headers = array_merge($headers, $options['headers']); | ||
| 111 | + | ||
| 112 | + // If the content type is already set, we assume that MIME encoding is | ||
| 113 | + // already done. | ||
| 114 | + if (isset($headers['Content-Type'])) { | ||
| 115 | + $out = $msg; | ||
| 116 | + } else { | ||
| 117 | + // Do a simple inline MIME encoding. | ||
| 118 | + $headers['Content-Disposition'] = 'inline'; | ||
| 119 | + $headers['Content-Type'] = "text/xml; charset=\"$this->encoding\""; | ||
| 120 | + if (isset($options['transfer-encoding'])) { | ||
| 121 | + if (strcasecmp($options['transfer-encoding'], 'quoted-printable') == 0) { | ||
| 122 | + $headers['Content-Transfer-Encoding'] = $options['transfer-encoding']; | ||
| 123 | + $out = $msg; | ||
| 124 | + } elseif (strcasecmp($options['transfer-encoding'],'base64') == 0) { | ||
| 125 | + $headers['Content-Transfer-Encoding'] = 'base64'; | ||
| 126 | + $out = chunk_split(base64_encode($msg), 76, "\n"); | ||
| 127 | + } else { | ||
| 128 | + return $this->_raiseSoapFault("Invalid Transfer Encoding: {$options['transfer-encoding']}"); | ||
| 129 | + } | ||
| 130 | + } else { | ||
| 131 | + // Default to base64. | ||
| 132 | + $headers['Content-Transfer-Encoding'] = 'base64'; | ||
| 133 | + $out = chunk_split(base64_encode($msg)); | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + $headers['Subject'] = isset($options['subject']) ? $options['subject'] : 'SOAP Message'; | ||
| 138 | + | ||
| 139 | + foreach ($headers as $key => $value) { | ||
| 140 | + $header_text .= "$key: $value\n"; | ||
| 141 | + } | ||
| 142 | + $this->outgoing_payload = $header_text . "\r\n" . $this->outgoing_payload; | ||
| 143 | + | ||
| 144 | + $mailer_params = array( | ||
| 145 | + 'host' => $this->host, | ||
| 146 | + 'port' => $this->port, | ||
| 147 | + 'username' => $this->username, | ||
| 148 | + 'password' => $this->password, | ||
| 149 | + 'auth' => $this->auth | ||
| 150 | + ); | ||
| 151 | + $mailer =& new Mail_smtp($mailer_params); | ||
| 152 | + $result = $mailer->send($this->urlparts['path'], $headers, $out); | ||
| 153 | + if (!PEAR::isError($result)) { | ||
| 154 | + $val =& new SOAP_Value('Message-ID', 'string', $headers['Message-ID']); | ||
| 155 | + } else { | ||
| 156 | + $sval[] =& new SOAP_Value('faultcode', 'QName', 'SOAP-ENV:Client'); | ||
| 157 | + $sval[] =& new SOAP_Value('faultstring', 'string', "couldn't send SMTP message to {$this->urlparts['path']}"); | ||
| 158 | + $val =& new SOAP_Value('Fault', 'Struct', $sval); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + $mqname =& new QName($method, $namespace); | ||
| 162 | + $methodValue =& new SOAP_Value('Response', 'Struct', array($val)); | ||
| 163 | + | ||
| 164 | + $this->incoming_payload = $this->_makeEnvelope($methodValue, | ||
| 165 | + $this->headers, | ||
| 166 | + $this->encoding); | ||
| 167 | + | ||
| 168 | + return $this->incoming_payload; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + /** | ||
| 172 | + * Sets data for HTTP authentication, creates Authorization header. | ||
| 173 | + * | ||
| 174 | + * @param string $username Username. | ||
| 175 | + * @param string $password Response data, minus HTTP headers. | ||
| 176 | + * | ||
| 177 | + * @access public | ||
| 178 | + */ | ||
| 179 | + function setCredentials($username, $password) | ||
| 180 | + { | ||
| 181 | + $this->username = $username; | ||
| 182 | + $this->password = $password; | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + /** | ||
| 186 | + * Validates url data passed to constructor. | ||
| 187 | + * | ||
| 188 | + * @return boolean | ||
| 189 | + * @access private | ||
| 190 | + */ | ||
| 191 | + function _validateUrl() | ||
| 192 | + { | ||
| 193 | + if (!is_array($this->urlparts)) { | ||
| 194 | + $this->_raiseSoapFault("Unable to parse URL $url"); | ||
| 195 | + return false; | ||
| 196 | + } | ||
| 197 | + if (!isset($this->urlparts['scheme']) || | ||
| 198 | + strcasecmp($this->urlparts['scheme'], 'mailto') != 0) { | ||
| 199 | + $this->_raiseSoapFault("Unable to parse URL $url"); | ||
| 200 | + return false; | ||
| 201 | + } | ||
| 202 | + if (!isset($this->urlparts['path'])) { | ||
| 203 | + $this->_raiseSoapFault("Unable to parse URL $url"); | ||
| 204 | + return false; | ||
| 205 | + } | ||
| 206 | + return true; | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | +} |
thirdparty/pear/SOAP/Transport/TCP.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for a TCP transport layer. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Shane Hanna <iordy_at_iordy_dot_com> | ||
| 17 | + * @copyright 2003-2005 The PHP Group | ||
| 18 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 19 | + * @link http://pear.php.net/package/SOAP | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | +require_once 'SOAP/Base.php'; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * TCP transport for SOAP. | ||
| 26 | + * | ||
| 27 | + * @todo use Net_Socket; implement some security scheme; implement support | ||
| 28 | + * for attachments | ||
| 29 | + * @access public | ||
| 30 | + * @package SOAP | ||
| 31 | + * @author Shane Hanna <iordy_at_iordy_dot_com> | ||
| 32 | + */ | ||
| 33 | +class SOAP_Transport_TCP extends SOAP_Base_Object | ||
| 34 | +{ | ||
| 35 | + | ||
| 36 | + var $headers = array(); | ||
| 37 | + var $urlparts = null; | ||
| 38 | + var $url = ''; | ||
| 39 | + var $incoming_payload = ''; | ||
| 40 | + var $_userAgent = SOAP_LIBRARY_NAME; | ||
| 41 | + var $encoding = SOAP_DEFAULT_ENCODING; | ||
| 42 | + var $result_encoding = 'UTF-8'; | ||
| 43 | + var $result_content_type; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * socket | ||
| 47 | + */ | ||
| 48 | + var $socket = null; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Constructor. | ||
| 52 | + * | ||
| 53 | + * @param string $url HTTP url to SOAP endpoint. | ||
| 54 | + * | ||
| 55 | + * @access public | ||
| 56 | + */ | ||
| 57 | + function SOAP_Transport_TCP($url, $encoding = SOAP_DEFAULT_ENCODING) | ||
| 58 | + { | ||
| 59 | + parent::SOAP_Base_Object('TCP'); | ||
| 60 | + $this->urlparts = @parse_url($url); | ||
| 61 | + $this->url = $url; | ||
| 62 | + $this->encoding = $encoding; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + function _socket_ping() | ||
| 66 | + { | ||
| 67 | + // XXX how do we restart after socket_shutdown? | ||
| 68 | + //if (!$this->socket) { | ||
| 69 | + // Create socket resource. | ||
| 70 | + $this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP); | ||
| 71 | + if ($this->socket < 0) { | ||
| 72 | + return 0; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + // Connect. | ||
| 76 | + $result = socket_connect($this->socket, $this->urlparts['host'], | ||
| 77 | + $this->urlparts['port']); | ||
| 78 | + if ($result < 0) { | ||
| 79 | + return 0; | ||
| 80 | + } | ||
| 81 | + //} | ||
| 82 | + return 1; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * Sends and receives SOAP data. | ||
| 87 | + * | ||
| 88 | + * @param string $msg Outgoing POST data. | ||
| 89 | + * @param string $action SOAP Action header data. | ||
| 90 | + * | ||
| 91 | + * @return string|SOAP_Fault | ||
| 92 | + * @access public | ||
| 93 | + */ | ||
| 94 | + function send($msg, $options = NULL) | ||
| 95 | + { | ||
| 96 | + $this->incoming_payload = ''; | ||
| 97 | + $this->outgoing_payload = $msg; | ||
| 98 | + if (!$this->_validateUrl()) { | ||
| 99 | + return $this->fault; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + // Check for TCP scheme. | ||
| 103 | + if (strcasecmp($this->urlparts['scheme'], 'TCP') == 0) { | ||
| 104 | + // Check connection. | ||
| 105 | + if (!$this->_socket_ping()) { | ||
| 106 | + return $this->_raiseSoapFault('Error connecting to ' . $this->url . '; reason: ' . socket_strerror(socket_last_error($this->socket))); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + // Write to the socket. | ||
| 110 | + if (!@socket_write($this->socket, $this->outgoing_payload, | ||
| 111 | + strlen($this->outgoing_payload))) { | ||
| 112 | + return $this->_raiseSoapFault('Error sending data to ' . $this->url . '; reason: ' . socket_strerror(socket_last_error($this->socket))); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + // Shutdown writing. | ||
| 116 | + if(!socket_shutdown($this->socket, 1)) { | ||
| 117 | + return $this->_raiseSoapFault('Cannot change socket mode to read.'); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + // Read everything we can. | ||
| 121 | + while ($buf = @socket_read($this->socket, 1024, PHP_BINARY_READ)) { | ||
| 122 | + $this->incoming_payload .= $buf; | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + // Return payload or die. | ||
| 126 | + if ($this->incoming_payload) { | ||
| 127 | + return $this->incoming_payload; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + return $this->_raiseSoapFault('Error reveiving data from ' . $this->url); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + return $this->_raiseSoapFault('Invalid url scheme ' . $this->url); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + /** | ||
| 137 | + * Validates the url data passed to the constructor. | ||
| 138 | + * | ||
| 139 | + * @return boolean | ||
| 140 | + * @access private | ||
| 141 | + */ | ||
| 142 | + function _validateUrl() | ||
| 143 | + { | ||
| 144 | + if (!is_array($this->urlparts) ) { | ||
| 145 | + $this->_raiseSoapFault("Unable to parse URL $url"); | ||
| 146 | + return false; | ||
| 147 | + } | ||
| 148 | + if (!isset($this->urlparts['host'])) { | ||
| 149 | + $this->_raiseSoapFault("No host in URL $url"); | ||
| 150 | + return false; | ||
| 151 | + } | ||
| 152 | + if (!isset($this->urlparts['path']) || !$this->urlparts['path']) { | ||
| 153 | + $this->urlparts['path'] = '/'; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + return true; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | +} |
thirdparty/pear/SOAP/Type/dateTime.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for the SOAP date/time clas. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 19 | + * @copyright 2003-2005 The PHP Group | ||
| 20 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 21 | + * @link http://pear.php.net/package/SOAP | ||
| 22 | + */ | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * This class converts from and to unix timestamps and ISO 8601 date/time. | ||
| 26 | + * | ||
| 27 | + * @access public | ||
| 28 | + * @package SOAP | ||
| 29 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 30 | + * @author Shane Caraveo <shane@php.net> Port to PEAR and more | ||
| 31 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 32 | + */ | ||
| 33 | +class SOAP_Type_dateTime | ||
| 34 | +{ | ||
| 35 | + var $_iso8601 = | ||
| 36 | + '# 1: centuries & years CCYY- | ||
| 37 | + (-?[0-9]{4})- | ||
| 38 | + # 2: months MM- | ||
| 39 | + ([0-9]{2})- | ||
| 40 | + # 3: days DD | ||
| 41 | + ([0-9]{2}) | ||
| 42 | + # 4: separator T | ||
| 43 | + T | ||
| 44 | + # 5: hours hh: | ||
| 45 | + ([0-9]{2}): | ||
| 46 | + # 6: minutes mm: | ||
| 47 | + ([0-9]{2}): | ||
| 48 | + # 7: seconds ss.ss... | ||
| 49 | + ([0-9]{2})(\.[0-9]*)? | ||
| 50 | + # 8: Z to indicate UTC, -+HH:MM:SS.SS... for local zones | ||
| 51 | + (Z|[+\-][0-9]{4}|[+\-][0-9]{2}:[0-9]{2})?'; | ||
| 52 | + | ||
| 53 | + var $timestamp = -1; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * Constructor. | ||
| 57 | + * | ||
| 58 | + * @param string|integer $date The timestamp or ISO 8601 formatted | ||
| 59 | + * date and time this object is going to | ||
| 60 | + * represent. | ||
| 61 | + */ | ||
| 62 | + function SOAP_Type_dateTime($date = -1) | ||
| 63 | + { | ||
| 64 | + if ($date == -1) { | ||
| 65 | + $this->timestamp = time(); | ||
| 66 | + } elseif (is_int($date)) { | ||
| 67 | + $this->timestamp = $date; | ||
| 68 | + } else { | ||
| 69 | + $this->timestamp = $this->toUnixtime($date); | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Alias of {@link SOAP_Type_dateTime::toUTC}. | ||
| 75 | + */ | ||
| 76 | + function toSOAP($date = NULL) | ||
| 77 | + { | ||
| 78 | + return $this->toUTC($date); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * Converts this object or a timestamp to an ISO 8601 date/time string. | ||
| 83 | + * | ||
| 84 | + * @param integer $timestamp A unix timestamp | ||
| 85 | + * | ||
| 86 | + * @return string An ISO 8601 formatted date/time string. | ||
| 87 | + */ | ||
| 88 | + function toString($timestamp = 0) | ||
| 89 | + { | ||
| 90 | + if (!$timestamp) { | ||
| 91 | + $timestamp = $this->timestamp; | ||
| 92 | + } | ||
| 93 | + if ($timestamp < 0) { | ||
| 94 | + return 0; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + return date('Y-m-d\TH:i:sO', $timestamp); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * Splits a date/time into its components. | ||
| 102 | + * | ||
| 103 | + * @param string|integer $datestr A unix timestamp or ISO 8601 date/time | ||
| 104 | + * string. If empty, this object is used. | ||
| 105 | + * | ||
| 106 | + * @return boolean|array An array with the date and time components or | ||
| 107 | + * false on failure. | ||
| 108 | + */ | ||
| 109 | + function _split($datestr) | ||
| 110 | + { | ||
| 111 | + if (!$datestr) { | ||
| 112 | + $datestr = $this->toString(); | ||
| 113 | + } elseif (is_int($datestr)) { | ||
| 114 | + $datestr = $this->toString($datestr); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + if (preg_match('/' . $this->_iso8601 . '/x', $datestr, $regs)) { | ||
| 118 | + if (empty($regs[8])) { | ||
| 119 | + $timestamp = strtotime(sprintf('%04d-%02d-%02d %02d:%02d:%02d', | ||
| 120 | + $regs[1], | ||
| 121 | + $regs[2], | ||
| 122 | + $regs[3], | ||
| 123 | + $regs[4], | ||
| 124 | + $regs[5], | ||
| 125 | + $regs[6])); | ||
| 126 | + $regs[8] = date('O', $timestamp); | ||
| 127 | + } | ||
| 128 | + if ($regs[8] != 'Z') { | ||
| 129 | + $op = substr($regs[8], 0, 1); | ||
| 130 | + $h = substr($regs[8], 1, 2); | ||
| 131 | + if (strstr($regs[8], ':')) { | ||
| 132 | + $m = substr($regs[8], 4, 2); | ||
| 133 | + } else { | ||
| 134 | + $m = substr($regs[8], 3, 2); | ||
| 135 | + } | ||
| 136 | + if ($op == '+') { | ||
| 137 | + $regs[4] = $regs[4] - $h; | ||
| 138 | + if ($regs[4] < 0) { | ||
| 139 | + $regs[4] += 24; | ||
| 140 | + } | ||
| 141 | + $regs[5] = $regs[5] - $m; | ||
| 142 | + if ($regs[5] < 0) { | ||
| 143 | + $regs[5] += 60; | ||
| 144 | + } | ||
| 145 | + } else { | ||
| 146 | + $regs[4] = $regs[4] + $h; | ||
| 147 | + if ($regs[4] > 23) { | ||
| 148 | + $regs[4] -= 24; | ||
| 149 | + } | ||
| 150 | + $regs[5] = $regs[5] + $m; | ||
| 151 | + if ($regs[5] > 59) { | ||
| 152 | + $regs[5] -= 60; | ||
| 153 | + } | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + return $regs; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + return false; | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + /** | ||
| 163 | + * Returns an ISO 8601 formatted UTC date/time string. | ||
| 164 | + * | ||
| 165 | + * @param string|integer $datestr @see SOAP_Type_dateTime::_split | ||
| 166 | + * | ||
| 167 | + * @return string The ISO 8601 formatted UTC date/time string. | ||
| 168 | + */ | ||
| 169 | + function toUTC($datestr = null) | ||
| 170 | + { | ||
| 171 | + $regs = $this->_split($datestr); | ||
| 172 | + | ||
| 173 | + if ($regs) { | ||
| 174 | + return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', | ||
| 175 | + $regs[1], | ||
| 176 | + $regs[2], | ||
| 177 | + $regs[3], | ||
| 178 | + $regs[4], | ||
| 179 | + $regs[5], | ||
| 180 | + $regs[6]); | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + return ''; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + /** | ||
| 187 | + * Returns a unix timestamp. | ||
| 188 | + * | ||
| 189 | + * @param string|integer $datestr @see SOAP_Type_dateTime::_split | ||
| 190 | + * | ||
| 191 | + * @return integer The unix timestamp. | ||
| 192 | + */ | ||
| 193 | + function toUnixtime($datestr = null) | ||
| 194 | + { | ||
| 195 | + $regs = $this->_split($datestr); | ||
| 196 | + if ($regs) { | ||
| 197 | + return strtotime(sprintf('%04d-%02d-%02d %02d:%02d:%02dZ', | ||
| 198 | + $regs[1], | ||
| 199 | + $regs[2], | ||
| 200 | + $regs[3], | ||
| 201 | + $regs[4], | ||
| 202 | + $regs[5], | ||
| 203 | + $regs[6])); | ||
| 204 | + } | ||
| 205 | + return -1; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + /** | ||
| 209 | + * Compares two dates or this object with a second date. | ||
| 210 | + * | ||
| 211 | + * @param string|integer $date1 A unix timestamp or ISO 8601 date/time | ||
| 212 | + * string. | ||
| 213 | + * @param string|integer $date2 A unix timestamp or ISO 8601 date/time | ||
| 214 | + * string. If empty, this object is used. | ||
| 215 | + * | ||
| 216 | + * @return integer The difference between the first and the second date. | ||
| 217 | + */ | ||
| 218 | + function compare($date1, $date2 = null) | ||
| 219 | + { | ||
| 220 | + if (is_null($date2)) { | ||
| 221 | + $date2 = $date1; | ||
| 222 | + $date1 = $this->timestamp; | ||
| 223 | + } | ||
| 224 | + if (!is_int($date1)) { | ||
| 225 | + $date1 = $this->toUnixtime($date1); | ||
| 226 | + } | ||
| 227 | + if (!is_int($date2)) { | ||
| 228 | + $date2 = $this->toUnixtime($date2); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + if ($date1 != -1 && $date2 != -1) { | ||
| 232 | + return $date1 - $date2; | ||
| 233 | + } | ||
| 234 | + | ||
| 235 | + return -1; | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | +} |
thirdparty/pear/SOAP/Type/duration.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/* | ||
| 3 | +http://www.w3.org/TR/xmlschema-2/ | ||
| 4 | + | ||
| 5 | +[Definition:] duration represents a duration of time. The value space of | ||
| 6 | +duration is a six-dimensional space where the coordinates designate the | ||
| 7 | +Gregorian year, month, day, hour, minute, and second components | ||
| 8 | +defined in 5.5.3.2 of [ISO 8601], respectively. These components are | ||
| 9 | +ordered in their significance by their order of appearance i.e. as year, | ||
| 10 | +month, day, hour, minute, and second. | ||
| 11 | + | ||
| 12 | +3.2.6.1 Lexical representation | ||
| 13 | +The lexical representation for duration is the [ISO 8601] extended | ||
| 14 | +format PnYn MnDTnH nMnS, where nY represents the number of | ||
| 15 | +years, nM the number of months, nD the number of days, 'T' is the | ||
| 16 | +date/time separator, nH the number of hours, nM the number of | ||
| 17 | +minutes and nS the number of seconds. The number of seconds | ||
| 18 | +can include decimal digits to arbitrary precision. | ||
| 19 | + | ||
| 20 | +The values of the Year, Month, Day, Hour and Minutes components | ||
| 21 | +are not restricted but allow an arbitrary integer. Similarly, the | ||
| 22 | +value of the Seconds component allows an arbitrary decimal. | ||
| 23 | +Thus, the lexical representation of duration does not follow the | ||
| 24 | +alternative format of 5.5.3.2.1 of [ISO 8601]. | ||
| 25 | + | ||
| 26 | +An optional preceding minus sign ('-') is allowed, to indicate a | ||
| 27 | +negative duration. If the sign is omitted a positive duration is | ||
| 28 | +indicated. See also ISO 8601 Date and Time Formats (D). | ||
| 29 | + | ||
| 30 | +For example, to indicate a duration of 1 year, 2 months, 3 days, | ||
| 31 | +10 hours, and 30 minutes, one would write: P1Y2M3DT10H30M. | ||
| 32 | +One could also indicate a duration of minus 120 days as: -P120D. | ||
| 33 | + | ||
| 34 | +Reduced precision and truncated representations of this format | ||
| 35 | +are allowed provided they conform to the following: | ||
| 36 | + | ||
| 37 | +If the number of years, months, days, hours, minutes, or seconds | ||
| 38 | +in any expression equals zero, the number and its corresponding | ||
| 39 | +designator *may* be omitted. However, at least one number and | ||
| 40 | +its designator *must* be present. | ||
| 41 | +The seconds part *may* have a decimal fraction. | ||
| 42 | +The designator 'T' shall be absent if all of the time items are absent. | ||
| 43 | +The designator 'P' must always be present. | ||
| 44 | +For example, P1347Y, P1347M and P1Y2MT2H are all allowed; P0Y1347M | ||
| 45 | +and P0Y1347M0D are allowed. P-1347M is not allowed although -P1347M | ||
| 46 | +is allowed. P1Y2MT is not allowed. | ||
| 47 | + | ||
| 48 | +*/ | ||
| 49 | + | ||
| 50 | +/* this is only an aproximation of duration, more work still to do. | ||
| 51 | + see above schema url for more info on duration | ||
| 52 | + | ||
| 53 | + TODO: figure out best aproximation for year and month conversion to seconds | ||
| 54 | +*/ | ||
| 55 | + | ||
| 56 | +$ereg_duration = '(-)?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T?([0-9]+H)?([0-9]+M)?([0-9]+S)?'; | ||
| 57 | +class SOAP_Type_duration | ||
| 58 | +{ | ||
| 59 | + // format PnYnMnDTnHnMnS | ||
| 60 | + function unix_to_duration($seconds) { | ||
| 61 | + return SOAP_Type_duration::getduration($seconds); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + function mod($a, $b, &$d, &$r) { | ||
| 65 | + $d = floor( $a / $b ); | ||
| 66 | + $r = $a % $b; | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + function getduration($seconds) { | ||
| 70 | + $neg = ''; | ||
| 71 | + if ($seconds < 0) { | ||
| 72 | + $neg = '-'; | ||
| 73 | + $seconds = $seconds * -1; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + $_mi = 60; | ||
| 77 | + $_h = $_mi * 60; | ||
| 78 | + $_d = $_h * 24; | ||
| 79 | + // XXX how do we properly handle month and year values? | ||
| 80 | + $_m = $_d * 30; | ||
| 81 | + $_y = $_d * 365; | ||
| 82 | + | ||
| 83 | + SOAP_Type_duration::mod($seconds, $_y, $y, $seconds); | ||
| 84 | + SOAP_Type_duration::mod($seconds, $_m, $m, $seconds); | ||
| 85 | + SOAP_Type_duration::mod($seconds, $_d, $d, $seconds); | ||
| 86 | + SOAP_Type_duration::mod($seconds, $_h, $h, $seconds); | ||
| 87 | + SOAP_Type_duration::mod($seconds, $_mi, $mi, $s); | ||
| 88 | + | ||
| 89 | + $duration = $neg.'P'; | ||
| 90 | + if ($y) $duration .= $y.'Y'; | ||
| 91 | + if ($m) $duration .= $m.'M'; | ||
| 92 | + if ($d) $duration .= $d.'D'; | ||
| 93 | + if ($h || $mi || $s) $duration .='T'; | ||
| 94 | + if ($h) $duration .= $h.'H'; | ||
| 95 | + if ($mi) $duration .= $mi.'M'; | ||
| 96 | + if ($s) $duration .= $s.'S'; | ||
| 97 | + if ($duration == 'P' || $duration == '-P') $duration = 'PT0S'; | ||
| 98 | + return $duration; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + function mkduration($n, $Y, $Mo, $D, $H, $Mi, $S) { | ||
| 102 | + $_mi = 60; | ||
| 103 | + $_h = $_mi * 60; | ||
| 104 | + $_d = $_h * 24; | ||
| 105 | + // XXX how do we properly handle month and year values? | ||
| 106 | + $_m = $_d * 30; | ||
| 107 | + $_y = $_d * 365; | ||
| 108 | + | ||
| 109 | + $sec = $Y * $_y + $Mo * $_m + $D * $_d + $H * $_h + $Mi * $_mi + $S; | ||
| 110 | + if ($n == '-') $sec = $sec * -1; | ||
| 111 | + return $sec; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + function duration_to_unix($duration) { | ||
| 115 | + global $ereg_duration; | ||
| 116 | + if (ereg($ereg_duration,$duration,$regs)) { | ||
| 117 | + return SOAP_Type_duration::mkduration($regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6], $regs[7]); | ||
| 118 | + } | ||
| 119 | + return FALSE; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + function is_duration($duration) { | ||
| 123 | + global $ereg_duration; | ||
| 124 | + return ereg($ereg_duration,$duration,$regs); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + function _test($time) { | ||
| 128 | + if (SOAP_Type_duration::is_duration($time)) { | ||
| 129 | + $t = SOAP_Type_duration::duration_to_unix($time); | ||
| 130 | + echo "Duration: $time is ".$t." seconds\n"; | ||
| 131 | + } else { | ||
| 132 | + $t = SOAP_Type_duration::unix_to_duration($time); | ||
| 133 | + echo "Seconds: $time is ".$t." duration\n"; | ||
| 134 | + } | ||
| 135 | + return $t; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + function add($d1, $d2) { | ||
| 139 | + $s1 = SOAP_Type_duration::duration_to_unix($d1); | ||
| 140 | + $s2 = SOAP_Type_duration::duration_to_unix($d2); | ||
| 141 | + return SOAP_Type_duration::unix_to_duration($s1 + $s2); | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + function subtract($d1, $d2) { | ||
| 145 | + $s1 = SOAP_Type_duration::duration_to_unix($d1); | ||
| 146 | + $s2 = SOAP_Type_duration::duration_to_unix($d2); | ||
| 147 | + return SOAP_Type_duration::unix_to_duration($s1 - $s2); | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +/* tests */ | ||
| 153 | + | ||
| 154 | +$t = SOAP_Type_duration::_test('P1Y2M3DT10H30M'); | ||
| 155 | +SOAP_Type_duration::_test($t); | ||
| 156 | +$t = SOAP_Type_duration::_test('-P120D'); | ||
| 157 | +SOAP_Type_duration::_test($t); | ||
| 158 | + | ||
| 159 | +// duration since 1970 | ||
| 160 | +$t = SOAP_Type_duration::_test(time()); | ||
| 161 | +SOAP_Type_duration::_test($t); | ||
| 162 | + | ||
| 163 | +print "Add should be PT0S: ".SOAP_Type_duration::add('-P120D','P4M')."\n"; | ||
| 164 | +print "Subtract should be PT0S: ".SOAP_Type_duration::subtract('P120D','P4M')."\n"; | ||
| 165 | +?> | ||
| 0 | \ No newline at end of file | 166 | \ No newline at end of file |
thirdparty/pear/SOAP/Type/hexBinary.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | | ||
| 18 | +// +----------------------------------------------------------------------+ | ||
| 19 | +// | ||
| 20 | +// $Id: hexBinary.php,v 1.6 2005/03/10 23:16:39 yunosh Exp $ | ||
| 21 | +// | ||
| 22 | +class SOAP_Type_hexBinary | ||
| 23 | +{ | ||
| 24 | + function to_bin($value) | ||
| 25 | + { | ||
| 26 | + $len = strlen($value); | ||
| 27 | + return pack('H' . $len, $value); | ||
| 28 | + } | ||
| 29 | + function to_hex($value) | ||
| 30 | + { | ||
| 31 | + return bin2hex($value); | ||
| 32 | + } | ||
| 33 | + function is_hexbin($value) | ||
| 34 | + { | ||
| 35 | + # first see if there are any invalid chars | ||
| 36 | + $l = strlen($value); | ||
| 37 | + | ||
| 38 | + if ($l < 1 || strspn($value, '0123456789ABCDEFabcdef') != $l) return FALSE; | ||
| 39 | + | ||
| 40 | + $bin = SOAP_Type_hexBinary::to_bin($value); | ||
| 41 | + $hex = SOAP_Type_hexBinary::to_hex($bin); | ||
| 42 | + return strcasecmp($value, $hex) == 0; | ||
| 43 | + } | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +?> | ||
| 0 | \ No newline at end of file | 47 | \ No newline at end of file |
thirdparty/pear/SOAP/Value.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for converting values between SOAP and PHP. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 19 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Base.php'; | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * SOAP::Value | ||
| 29 | + * | ||
| 30 | + * This class converts values between PHP and SOAP. | ||
| 31 | + * | ||
| 32 | + * Originally based on SOAPx4 by Dietrich Ayala | ||
| 33 | + * http://dietrich.ganx4.com/soapx4 | ||
| 34 | + * | ||
| 35 | + * @access public | ||
| 36 | + * @package SOAP | ||
| 37 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 38 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 39 | + */ | ||
| 40 | +class SOAP_Value | ||
| 41 | +{ | ||
| 42 | + /** | ||
| 43 | + * @var string | ||
| 44 | + */ | ||
| 45 | + var $value = null; | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * @var string | ||
| 49 | + */ | ||
| 50 | + var $name = ''; | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * @var string | ||
| 54 | + */ | ||
| 55 | + var $type = ''; | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * Namespace | ||
| 59 | + * | ||
| 60 | + * @var string | ||
| 61 | + */ | ||
| 62 | + var $namespace = ''; | ||
| 63 | + var $type_namespace = ''; | ||
| 64 | + | ||
| 65 | + var $attributes = array(); | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * @var string | ||
| 69 | + */ | ||
| 70 | + var $arrayType = ''; | ||
| 71 | + | ||
| 72 | + var $options = array(); | ||
| 73 | + | ||
| 74 | + var $nqn; | ||
| 75 | + var $tqn; | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Constructor. | ||
| 79 | + * | ||
| 80 | + * @param string $name Name of the SOAP value {namespace}name. | ||
| 81 | + * @param mixed $type SOAP value {namespace}type. Determined | ||
| 82 | + * automatically if not set. | ||
| 83 | + * @param mixed $value Value to set. | ||
| 84 | + * @param array $attributes Attributes. | ||
| 85 | + */ | ||
| 86 | + function SOAP_Value($name = '', $type = false, $value = null, | ||
| 87 | + $attributes = array()) | ||
| 88 | + { | ||
| 89 | + // Detect type if not passed. | ||
| 90 | + $this->nqn =& new QName($name); | ||
| 91 | + $this->name = $this->nqn->name; | ||
| 92 | + $this->namespace = $this->nqn->namespace; | ||
| 93 | + $this->tqn =& new QName($type); | ||
| 94 | + $this->type = $this->tqn->name; | ||
| 95 | + $this->type_prefix = $this->tqn->ns; | ||
| 96 | + $this->type_namespace = $this->tqn->namespace; | ||
| 97 | + $this->value =& $value; | ||
| 98 | + $this->attributes = $attributes; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Serializes this value. | ||
| 103 | + * | ||
| 104 | + * @param SOAP_Base $serializer A SOAP_Base instance or subclass to | ||
| 105 | + * serialize with. | ||
| 106 | + * | ||
| 107 | + * @return string XML representation of $this. | ||
| 108 | + */ | ||
| 109 | + function serialize(&$serializer) | ||
| 110 | + { | ||
| 111 | + return $serializer->_serializeValue($this->value, | ||
| 112 | + $this->name, | ||
| 113 | + $this->type, | ||
| 114 | + $this->namespace, | ||
| 115 | + $this->type_namespace, | ||
| 116 | + $this->options, | ||
| 117 | + $this->attributes, | ||
| 118 | + $this->arrayType); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +/** | ||
| 124 | + * This class converts values between PHP and SOAP. It is a simple wrapper | ||
| 125 | + * around SOAP_Value, adding support for SOAP actor and mustunderstand | ||
| 126 | + * parameters. | ||
| 127 | + * | ||
| 128 | + * Originally based on SOAPx4 by Dietrich Ayala | ||
| 129 | + * http://dietrich.ganx4.com/soapx4 | ||
| 130 | + * | ||
| 131 | + * @access public | ||
| 132 | + * @package SOAP | ||
| 133 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 134 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 135 | + */ | ||
| 136 | +class SOAP_Header extends SOAP_Value | ||
| 137 | +{ | ||
| 138 | + /** | ||
| 139 | + * Constructor | ||
| 140 | + * | ||
| 141 | + * @param string $name Name of the SOAP value {namespace}name. | ||
| 142 | + * @param mixed $type SOAP value {namespace}type. Determined | ||
| 143 | + * automatically if not set. | ||
| 144 | + * @param mixed $value Value to set | ||
| 145 | + * @param integer $mustunderstand Zero or one. | ||
| 146 | + * @param mixed $attributes Attributes. | ||
| 147 | + */ | ||
| 148 | + function SOAP_Header($name = '', $type, $value, $mustunderstand = 0, | ||
| 149 | + $attributes = array()) | ||
| 150 | + { | ||
| 151 | + if (!is_array($attributes)) { | ||
| 152 | + $actor = $attributes; | ||
| 153 | + $attributes = array(); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + parent::SOAP_Value($name, $type, $value, $attributes); | ||
| 157 | + | ||
| 158 | + if (isset($actor)) { | ||
| 159 | + $this->attributes['SOAP-ENV:actor'] = $actor; | ||
| 160 | + } elseif (!isset($this->attributes['SOAP-ENV:actor'])) { | ||
| 161 | + $this->attributes['SOAP-ENV:actor'] = 'http://schemas.xmlsoap.org/soap/actor/next'; | ||
| 162 | + } | ||
| 163 | + $this->attributes['SOAP-ENV:mustUnderstand'] = (int)$mustunderstand; | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +/** | ||
| 169 | + * This class handles MIME attachements per W3C's Note on Soap Attachements at | ||
| 170 | + * http://www.w3.org/TR/SOAP-attachments | ||
| 171 | + * | ||
| 172 | + * @access public | ||
| 173 | + * @package SOAP | ||
| 174 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 175 | + */ | ||
| 176 | +class SOAP_Attachment extends SOAP_Value | ||
| 177 | +{ | ||
| 178 | + /** | ||
| 179 | + * Constructor. | ||
| 180 | + * | ||
| 181 | + * @param string $name Name of the SOAP value <value_name> | ||
| 182 | + * @param string $type The attachment's MIME type. | ||
| 183 | + * @param string $filename The attachment's file name. Ignored if $file | ||
| 184 | + * is provide. | ||
| 185 | + * @param string $file The attachment data. | ||
| 186 | + */ | ||
| 187 | + function SOAP_Attachment($name = '', $type = 'application/octet-stream', | ||
| 188 | + $filename, $file = null) | ||
| 189 | + { | ||
| 190 | + parent::SOAP_Value($name, null, null); | ||
| 191 | + | ||
| 192 | + if (!isset($GLOBALS['SOAP_options']['Mime'])) { | ||
| 193 | + $this->options['attachment'] = PEAR::raiseError('Mail_mime is not installed, unable to support SOAP Attachements'); | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + $filedata = ($file === null) ? $this->_file2str($filename) : $file; | ||
| 198 | + $filename = basename($filename); | ||
| 199 | + if (PEAR::isError($filedata)) { | ||
| 200 | + $this->options['attachment'] = $filedata; | ||
| 201 | + return; | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + $cid = md5(uniqid(time())); | ||
| 205 | + | ||
| 206 | + $this->attributes['href'] = 'cid:' . $cid; | ||
| 207 | + | ||
| 208 | + $this->options['attachment'] = array('body' => $filedata, | ||
| 209 | + 'disposition' => $filename, | ||
| 210 | + 'content_type' => $type, | ||
| 211 | + 'encoding' => 'base64', | ||
| 212 | + 'cid' => $cid); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /** | ||
| 216 | + * Returns the contents of the given file name as string. | ||
| 217 | + * | ||
| 218 | + * @access private | ||
| 219 | + * | ||
| 220 | + * @param string $file_name The file location. | ||
| 221 | + * | ||
| 222 | + * @return string The file data or a PEAR_Error. | ||
| 223 | + */ | ||
| 224 | + function _file2str($file_name) | ||
| 225 | + { | ||
| 226 | + if (!is_readable($file_name)) { | ||
| 227 | + return PEAR::raiseError('File is not readable: ' . $file_name); | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + if (function_exists('file_get_contents')) { | ||
| 231 | + return file_get_contents($file_name); | ||
| 232 | + } | ||
| 233 | + | ||
| 234 | + if (!$fd = fopen($file_name, 'rb')) { | ||
| 235 | + return PEAR::raiseError('Could not open ' . $file_name); | ||
| 236 | + } | ||
| 237 | + $cont = fread($fd, filesize($file_name)); | ||
| 238 | + fclose($fd); | ||
| 239 | + | ||
| 240 | + return $cont; | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | +} |
thirdparty/pear/SOAP/WSDL.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains the code for dealing with WSDL access and services. | ||
| 4 | + * | ||
| 5 | + * PHP versions 4 and 5 | ||
| 6 | + * | ||
| 7 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 8 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 9 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 10 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 11 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 12 | + * mail you a copy immediately. | ||
| 13 | + * | ||
| 14 | + * @category Web Services | ||
| 15 | + * @package SOAP | ||
| 16 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @author Chuck Hagenbuch <chuck@horde.org> Maintenance | ||
| 19 | + * @author Jan Schneider <jan@horde.org> Maintenance | ||
| 20 | + * @copyright 2003-2005 The PHP Group | ||
| 21 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 22 | + * @link http://pear.php.net/package/SOAP | ||
| 23 | + */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Base.php'; | ||
| 26 | +require_once 'SOAP/Fault.php'; | ||
| 27 | +require_once 'HTTP/Request.php'; | ||
| 28 | + | ||
| 29 | +define('WSDL_CACHE_MAX_AGE', 43200); | ||
| 30 | +define('WSDL_CACHE_USE', 0); // set to zero to turn off caching | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * This class parses WSDL files, and can be used by SOAP::Client to properly | ||
| 34 | + * register soap values for services. | ||
| 35 | + * | ||
| 36 | + * Originally based on SOAPx4 by Dietrich Ayala | ||
| 37 | + * http://dietrich.ganx4.com/soapx4 | ||
| 38 | + * | ||
| 39 | + * @todo | ||
| 40 | + * - add wsdl caching | ||
| 41 | + * - refactor namespace handling ($namespace/$ns) | ||
| 42 | + * - implement IDL type syntax declaration so we can generate WSDL | ||
| 43 | + * | ||
| 44 | + * @access public | ||
| 45 | + * @package SOAP | ||
| 46 | + * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates | ||
| 47 | + * @author Dietrich Ayala <dietrich@ganx4.com> Original Author | ||
| 48 | + */ | ||
| 49 | +class SOAP_WSDL extends SOAP_Base | ||
| 50 | +{ | ||
| 51 | + var $tns = null; | ||
| 52 | + var $definition = array(); | ||
| 53 | + var $namespaces = array(); | ||
| 54 | + var $ns = array(); | ||
| 55 | + var $xsd = SOAP_XML_SCHEMA_VERSION; | ||
| 56 | + var $complexTypes = array(); | ||
| 57 | + var $elements = array(); | ||
| 58 | + var $messages = array(); | ||
| 59 | + var $portTypes = array(); | ||
| 60 | + var $bindings = array(); | ||
| 61 | + var $imports = array(); | ||
| 62 | + var $services = array(); | ||
| 63 | + var $service = ''; | ||
| 64 | + var $uri = ''; | ||
| 65 | + var $docs = false; | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * Proxy parameters | ||
| 69 | + * | ||
| 70 | + * @var array | ||
| 71 | + */ | ||
| 72 | + var $proxy = null; | ||
| 73 | + | ||
| 74 | + var $trace = 0; | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * Use WSDL cache. | ||
| 78 | + * | ||
| 79 | + * @var boolean | ||
| 80 | + */ | ||
| 81 | + var $cacheUse = null; | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * Cache max lifetime (in seconds). | ||
| 85 | + * | ||
| 86 | + * @var integer | ||
| 87 | + */ | ||
| 88 | + var $cacheMaxAge = null; | ||
| 89 | + | ||
| 90 | + /** | ||
| 91 | + * Class to use for WSDL parsing. Can be overridden for special cases, | ||
| 92 | + * subclasses, etc. | ||
| 93 | + * | ||
| 94 | + * @var string | ||
| 95 | + */ | ||
| 96 | + var $wsdlParserClass = 'SOAP_WSDL_Parser'; | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * SOAP_WSDL constructor. | ||
| 100 | + * | ||
| 101 | + * @param string $wsdl_uri URL to WSDL file. | ||
| 102 | + * @param array $proxy Contains options for HTTP_Request class | ||
| 103 | + * @see HTTP_Request. | ||
| 104 | + * @param boolean $cacheUse Use WSDL caching. Defaults to false. | ||
| 105 | + * @param integer $cacheMaxAge Cache max lifetime (in seconds). | ||
| 106 | + * @param boolean $docs Parse documentation in the WSDL? Defaults | ||
| 107 | + * to false. | ||
| 108 | + * | ||
| 109 | + * @access public | ||
| 110 | + */ | ||
| 111 | + function SOAP_WSDL($wsdl_uri = false, | ||
| 112 | + $proxy = array(), | ||
| 113 | + $cacheUse = WSDL_CACHE_USE, | ||
| 114 | + $cacheMaxAge = WSDL_CACHE_MAX_AGE, | ||
| 115 | + $docs = false) | ||
| 116 | + { | ||
| 117 | + parent::SOAP_Base('WSDL'); | ||
| 118 | + $this->uri = $wsdl_uri; | ||
| 119 | + $this->proxy = $proxy; | ||
| 120 | + $this->cacheUse = $cacheUse; | ||
| 121 | + $this->cacheMaxAge = $cacheMaxAge; | ||
| 122 | + $this->docs = $docs; | ||
| 123 | + | ||
| 124 | + if ($wsdl_uri) { | ||
| 125 | + if (!PEAR::isError($this->parseURL($wsdl_uri))) { | ||
| 126 | + reset($this->services); | ||
| 127 | + $this->service = key($this->services); | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + function set_service($service) | ||
| 133 | + { | ||
| 134 | + if (array_key_exists($service, $this->services)) { | ||
| 135 | + $this->service = $service; | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + /** | ||
| 140 | + * @deprecated use parseURL instead | ||
| 141 | + */ | ||
| 142 | + function parse($wsdl_uri, $proxy = array()) | ||
| 143 | + { | ||
| 144 | + $this->parseURL($wsdl_uri, $proxy); | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + /** | ||
| 148 | + * Fills the WSDL array tree with data from a WSDL file. | ||
| 149 | + * | ||
| 150 | + * @param string $wsdl_uri URL to WSDL file. | ||
| 151 | + * @param array $proxy Contains options for HTTP_Request class | ||
| 152 | + * @see HTTP_Request. | ||
| 153 | + */ | ||
| 154 | + function parseURL($wsdl_uri, $proxy = array()) | ||
| 155 | + { | ||
| 156 | + $parser =& new $this->wsdlParserClass($wsdl_uri, $this, $this->docs); | ||
| 157 | + | ||
| 158 | + if ($parser->fault) { | ||
| 159 | + $this->_raiseSoapFault($parser->fault); | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + /** | ||
| 164 | + * Fills the WSDL array tree with data from one or more PHP class objects. | ||
| 165 | + * | ||
| 166 | + * @param mixed $wsdl_obj An object or array of objects to add to | ||
| 167 | + * the internal WSDL tree. | ||
| 168 | + * @param string $targetNamespace The target namespace of schema types | ||
| 169 | + * etc. | ||
| 170 | + * @param string $service_name Name of the WSDL service. | ||
| 171 | + * @param string $service_desc Optional description of the WSDL | ||
| 172 | + * service. | ||
| 173 | + */ | ||
| 174 | + function parseObject(&$wsdl_obj, $targetNamespace, $service_name, | ||
| 175 | + $service_desc = '') | ||
| 176 | + { | ||
| 177 | + $parser =& new SOAP_WSDL_ObjectParser($wsdl_obj, $this, | ||
| 178 | + $targetNamespace, $service_name, | ||
| 179 | + $service_desc); | ||
| 180 | + | ||
| 181 | + if ($parser->fault) { | ||
| 182 | + $this->_raiseSoapFault($parser->fault); | ||
| 183 | + } | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + function getEndpoint($portName) | ||
| 187 | + { | ||
| 188 | + if ($this->__isfault()) { | ||
| 189 | + return $this->__getfault(); | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + return (isset($this->services[$this->service]['ports'][$portName]['address']['location'])) | ||
| 193 | + ? $this->services[$this->service]['ports'][$portName]['address']['location'] | ||
| 194 | + : $this->_raiseSoapFault("No endpoint for port for $portName", $this->uri); | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + function _getPortName($operation, $service) | ||
| 198 | + { | ||
| 199 | + if (isset($this->services[$service]['ports'])) { | ||
| 200 | + $ports = $this->services[$service]['ports']; | ||
| 201 | + foreach ($ports as $port => $portAttrs) { | ||
| 202 | + $type = $ports[$port]['type']; | ||
| 203 | + if ($type == 'soap' && | ||
| 204 | + isset($this->bindings[$portAttrs['binding']]['operations'][$operation])) { | ||
| 205 | + return $port; | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + } | ||
| 209 | + return null; | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + /** | ||
| 213 | + * Finds the name of the first port that contains an operation of name | ||
| 214 | + * $operation. Always returns a SOAP portName. | ||
| 215 | + */ | ||
| 216 | + function getPortName($operation, $service = null) | ||
| 217 | + { | ||
| 218 | + if ($this->__isfault()) { | ||
| 219 | + return $this->__getfault(); | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + if (!$service) { | ||
| 223 | + $service = $this->service; | ||
| 224 | + } | ||
| 225 | + if (isset($this->services[$service]['ports'])) { | ||
| 226 | + if ($portName = $this->_getPortName($operation, $service)) { | ||
| 227 | + return $portName; | ||
| 228 | + } | ||
| 229 | + } | ||
| 230 | + // Try any service in the WSDL. | ||
| 231 | + foreach ($this->services as $serviceName => $service) { | ||
| 232 | + if (isset($this->services[$serviceName]['ports'])) { | ||
| 233 | + if ($portName = $this->_getPortName($operation, $serviceName)) { | ||
| 234 | + $this->service = $serviceName; | ||
| 235 | + return $portName; | ||
| 236 | + } | ||
| 237 | + } | ||
| 238 | + } | ||
| 239 | + return $this->_raiseSoapFault("No operation $operation in WSDL.", $this->uri); | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + function getOperationData($portName, $operation) | ||
| 243 | + { | ||
| 244 | + if ($this->__isfault()) { | ||
| 245 | + return $this->__getfault(); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + if (!isset($this->services[$this->service]['ports'][$portName]['binding']) || | ||
| 249 | + !($binding = $this->services[$this->service]['ports'][$portName]['binding'])) { | ||
| 250 | + return $this->_raiseSoapFault("No binding for port $portName in WSDL.", $this->uri); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + // Get operation data from binding. | ||
| 254 | + if (is_array($this->bindings[$binding]['operations'][$operation])) { | ||
| 255 | + $opData = $this->bindings[$binding]['operations'][$operation]; | ||
| 256 | + } | ||
| 257 | + // get operation data from porttype | ||
| 258 | + $portType = $this->bindings[$binding]['type']; | ||
| 259 | + if (!$portType) { | ||
| 260 | + return $this->_raiseSoapFault("No port type for binding $binding in WSDL.", $this->uri); | ||
| 261 | + } | ||
| 262 | + if (is_array($type = $this->portTypes[$portType][$operation])) { | ||
| 263 | + if (isset($type['parameterOrder'])) { | ||
| 264 | + $opData['parameterOrder'] = $type['parameterOrder']; | ||
| 265 | + } | ||
| 266 | + $opData['input'] = array_merge($opData['input'], $type['input']); | ||
| 267 | + $opData['output'] = array_merge($opData['output'], $type['output']); | ||
| 268 | + } | ||
| 269 | + if (!$opData) | ||
| 270 | + return $this->_raiseSoapFault("No operation $operation for port $portName in WSDL.", $this->uri); | ||
| 271 | + $opData['parameters'] = false; | ||
| 272 | + if (isset($this->bindings[$binding]['operations'][$operation]['input']['namespace'])) | ||
| 273 | + $opData['namespace'] = $this->bindings[$binding]['operations'][$operation]['input']['namespace']; | ||
| 274 | + // Message data from messages. | ||
| 275 | + $inputMsg = $opData['input']['message']; | ||
| 276 | + if (is_array($this->messages[$inputMsg])) { | ||
| 277 | + foreach ($this->messages[$inputMsg] as $pname => $pattrs) { | ||
| 278 | + if ($opData['style'] == 'document' && | ||
| 279 | + $opData['input']['use'] == 'literal' && | ||
| 280 | + $pname == 'parameters') { | ||
| 281 | + $opData['parameters'] = true; | ||
| 282 | + $opData['namespace'] = $this->namespaces[$pattrs['namespace']]; | ||
| 283 | + $el = $this->elements[$pattrs['namespace']][$pattrs['type']]; | ||
| 284 | + if (isset($el['elements'])) { | ||
| 285 | + foreach ($el['elements'] as $elname => $elattrs) { | ||
| 286 | + $opData['input']['parts'][$elname] = $elattrs; | ||
| 287 | + } | ||
| 288 | + } | ||
| 289 | + } else { | ||
| 290 | + $opData['input']['parts'][$pname] = $pattrs; | ||
| 291 | + } | ||
| 292 | + } | ||
| 293 | + } | ||
| 294 | + $outputMsg = $opData['output']['message']; | ||
| 295 | + if (is_array($this->messages[$outputMsg])) { | ||
| 296 | + foreach ($this->messages[$outputMsg] as $pname => $pattrs) { | ||
| 297 | + if ($opData['style'] == 'document' && | ||
| 298 | + $opData['output']['use'] == 'literal' && | ||
| 299 | + $pname == 'parameters') { | ||
| 300 | + | ||
| 301 | + $el = $this->elements[$pattrs['namespace']][$pattrs['type']]; | ||
| 302 | + if (isset($el['elements'])) { | ||
| 303 | + foreach ($el['elements'] as $elname => $elattrs) { | ||
| 304 | + $opData['output']['parts'][$elname] = $elattrs; | ||
| 305 | + } | ||
| 306 | + } | ||
| 307 | + } else { | ||
| 308 | + $opData['output']['parts'][$pname] = $pattrs; | ||
| 309 | + } | ||
| 310 | + } | ||
| 311 | + } | ||
| 312 | + return $opData; | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + function matchMethod(&$operation) | ||
| 316 | + { | ||
| 317 | + if ($this->__isfault()) { | ||
| 318 | + return $this->__getfault(); | ||
| 319 | + } | ||
| 320 | + | ||
| 321 | + // Overloading lowercases function names :( | ||
| 322 | + foreach ($this->services[$this->service]['ports'] as $port => $portAttrs) { | ||
| 323 | + foreach (array_keys($this->bindings[$portAttrs['binding']]['operations']) as $op) { | ||
| 324 | + if (strcasecmp($op, $operation) == 0) { | ||
| 325 | + $operation = $op; | ||
| 326 | + } | ||
| 327 | + } | ||
| 328 | + } | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + /** | ||
| 332 | + * Given a datatype, what function handles the processing? | ||
| 333 | + * | ||
| 334 | + * This is used for doc/literal requests where we receive a datatype, and | ||
| 335 | + * we need to pass it to a method in out server class. | ||
| 336 | + * | ||
| 337 | + * @param string $datatype | ||
| 338 | + * @param string $namespace | ||
| 339 | + * @return string | ||
| 340 | + * @access public | ||
| 341 | + */ | ||
| 342 | + function getDataHandler($datatype, $namespace) | ||
| 343 | + { | ||
| 344 | + // See if we have an element by this name. | ||
| 345 | + if (isset($this->namespaces[$namespace])) { | ||
| 346 | + $namespace = $this->namespaces[$namespace]; | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + if (isset($this->ns[$namespace])) { | ||
| 350 | + $nsp = $this->ns[$namespace]; | ||
| 351 | + //if (!isset($this->elements[$nsp])) | ||
| 352 | + // $nsp = $this->namespaces[$nsp]; | ||
| 353 | + if (isset($this->elements[$nsp][$datatype])) { | ||
| 354 | + $checkmessages = array(); | ||
| 355 | + // Find what messages use this datatype. | ||
| 356 | + foreach ($this->messages as $messagename => $message) { | ||
| 357 | + foreach ($message as $partname => $part) { | ||
| 358 | + if ($part['type'] == $datatype) { | ||
| 359 | + $checkmessages[] = $messagename; | ||
| 360 | + break; | ||
| 361 | + } | ||
| 362 | + } | ||
| 363 | + } | ||
| 364 | + // Find the operation that uses this message. | ||
| 365 | + $dataHandler = null; | ||
| 366 | + foreach($this->portTypes as $portname => $porttype) { | ||
| 367 | + foreach ($porttype as $opname => $opinfo) { | ||
| 368 | + foreach ($checkmessages as $messagename) { | ||
| 369 | + if ($opinfo['input']['message'] == $messagename) { | ||
| 370 | + return $opname; | ||
| 371 | + } | ||
| 372 | + } | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | + } | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + return null; | ||
| 379 | + } | ||
| 380 | + | ||
| 381 | + function getSoapAction($portName, $operation) | ||
| 382 | + { | ||
| 383 | + if ($this->__isfault()) { | ||
| 384 | + return $this->__getfault(); | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction'])) { | ||
| 388 | + return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['soapAction']; | ||
| 389 | + } | ||
| 390 | + | ||
| 391 | + return false; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + function getNamespace($portName, $operation) | ||
| 395 | + { | ||
| 396 | + if ($this->__isfault()) { | ||
| 397 | + return $this->__getfault(); | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + if (!empty($this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace'])) { | ||
| 401 | + return $this->bindings[$this->services[$this->service]['ports'][$portName]['binding']]['operations'][$operation]['input']['namespace']; | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + return false; | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + function getNamespaceAttributeName($namespace) | ||
| 408 | + { | ||
| 409 | + /* If it doesn't exist at first, flip the array and check again. */ | ||
| 410 | + if (empty($this->ns[$namespace])) { | ||
| 411 | + $this->ns = array_flip($this->namespaces); | ||
| 412 | + } | ||
| 413 | + | ||
| 414 | + /* If it doesn't exist now, add it. */ | ||
| 415 | + if (empty($this->ns[$namespace])) { | ||
| 416 | + return $this->addNamespace($namespace); | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + return $this->ns[$namespace]; | ||
| 420 | + } | ||
| 421 | + | ||
| 422 | + function addNamespace($namespace) | ||
| 423 | + { | ||
| 424 | + if (!empty($this->ns[$namespace])) { | ||
| 425 | + return $this->ns[$namespace]; | ||
| 426 | + } | ||
| 427 | + | ||
| 428 | + $n = count($this->ns); | ||
| 429 | + $attr = 'ns' . $n; | ||
| 430 | + $this->namespaces['ns' . $n] = $namespace; | ||
| 431 | + $this->ns[$namespace] = $attr; | ||
| 432 | + | ||
| 433 | + return $attr; | ||
| 434 | + } | ||
| 435 | + | ||
| 436 | + function _validateString($string) | ||
| 437 | + { | ||
| 438 | + return preg_match('/^[\w_:#\/]+$/', $string); | ||
| 439 | + } | ||
| 440 | + | ||
| 441 | + function _addArg(&$args, &$argarray, $argname) | ||
| 442 | + { | ||
| 443 | + if ($args) { | ||
| 444 | + $args .= ', '; | ||
| 445 | + } | ||
| 446 | + $args .= '$' . $argname; | ||
| 447 | + if (!$this->_validateString($argname)) { | ||
| 448 | + return; | ||
| 449 | + } | ||
| 450 | + if ($argarray) { | ||
| 451 | + $argarray .= ', '; | ||
| 452 | + } | ||
| 453 | + $argarray .= "'$argname' => $" . $argname; | ||
| 454 | + } | ||
| 455 | + | ||
| 456 | + function _elementArg(&$args, &$argarray, &$_argtype, $_argname) | ||
| 457 | + { | ||
| 458 | + $comments = ''; | ||
| 459 | + $el = $this->elements[$_argtype['namespace']][$_argtype['type']]; | ||
| 460 | + $tns = isset($this->ns[$el['namespace']]) | ||
| 461 | + ? $this->ns[$el['namespace']] | ||
| 462 | + : $_argtype['namespace']; | ||
| 463 | + | ||
| 464 | + if (!empty($el['complex']) || | ||
| 465 | + (isset($el['type']) && | ||
| 466 | + isset($this->complexTypes[$tns][$el['type']]))) { | ||
| 467 | + // The element is a complex type. | ||
| 468 | + $comments .= " // {$_argtype['type']} is a ComplexType, refer to the WSDL for more info.\n"; | ||
| 469 | + $attrname = "{$_argtype['type']}_attr"; | ||
| 470 | + if (isset($el['type']) && | ||
| 471 | + isset($this->complexTypes[$tns][$el['type']]['attribute'])) { | ||
| 472 | + $comments .= " // {$_argtype['type']} may require attributes, refer to the WSDL for more info.\n"; | ||
| 473 | + } | ||
| 474 | + $comments .= " \${$attrname}['xmlns'] = '{$this->namespaces[$_argtype['namespace']]}';\n"; | ||
| 475 | + $comments .= " \${$_argtype['type']} =& new SOAP_Value('{$_argtype['type']}', false, \${$_argtype['type']}, \$$attrname);\n"; | ||
| 476 | + $this->_addArg($args, $argarray, $_argtype['type']); | ||
| 477 | + if (isset($el['type']) && | ||
| 478 | + isset($this->complexTypes[$tns][$el['type']]['attribute'])) { | ||
| 479 | + if ($args) { | ||
| 480 | + $args .= ', '; | ||
| 481 | + } | ||
| 482 | + $args .= '$' . $attrname; | ||
| 483 | + } | ||
| 484 | + } elseif (isset($el['elements'])) { | ||
| 485 | + foreach ($el['elements'] as $ename => $element) { | ||
| 486 | + $comments .= " \$$ename =& new SOAP_Value('{{$this->namespaces[$element['namespace']]}}$ename', '" . | ||
| 487 | + (isset($element['type']) ? $element['type'] : false) . | ||
| 488 | + "', \$$ename);\n"; | ||
| 489 | + $this->_addArg($args, $argarray, $ename); | ||
| 490 | + } | ||
| 491 | + } else { | ||
| 492 | + $comments .= " \$$_argname =& new SOAP_Value('{{$this->namespaces[$tns]}}$_argname', '{$el['type']}', \$$_argname);\n"; | ||
| 493 | + $this->_addArg($args, $argarray, $_argname); | ||
| 494 | + } | ||
| 495 | + | ||
| 496 | + return $comments; | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + function _complexTypeArg(&$args, &$argarray, &$_argtype, $_argname) | ||
| 500 | + { | ||
| 501 | + $comments = ''; | ||
| 502 | + if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']])) { | ||
| 503 | + $comments = " // $_argname is a ComplexType {$_argtype['type']},\n" . | ||
| 504 | + " // refer to wsdl for more info\n"; | ||
| 505 | + if (isset($this->complexTypes[$_argtype['namespace']][$_argtype['type']]['attribute'])) { | ||
| 506 | + $comments .= " // $_argname may require attributes, refer to wsdl for more info\n"; | ||
| 507 | + } | ||
| 508 | + $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $_argtype['type']; | ||
| 509 | + $comments .= " \$$_argname =& new SOAP_Value('$_argname', '$wrapname', \$$_argname);\n"; | ||
| 510 | + } | ||
| 511 | + | ||
| 512 | + $this->_addArg($args, $argarray, $_argname); | ||
| 513 | + | ||
| 514 | + return $comments; | ||
| 515 | + } | ||
| 516 | + | ||
| 517 | + /** | ||
| 518 | + * Generates stub code from the WSDL that can be saved to a file or eval'd | ||
| 519 | + * into existence. | ||
| 520 | + */ | ||
| 521 | + function generateProxyCode($port = '', $classname = '') | ||
| 522 | + { | ||
| 523 | + if ($this->__isfault()) { | ||
| 524 | + return $this->__getfault(); | ||
| 525 | + } | ||
| 526 | + | ||
| 527 | + $multiport = count($this->services[$this->service]['ports']) > 1; | ||
| 528 | + if (!$port) { | ||
| 529 | + reset($this->services[$this->service]['ports']); | ||
| 530 | + $port = current($this->services[$this->service]['ports']); | ||
| 531 | + } | ||
| 532 | + // XXX currently do not support HTTP ports | ||
| 533 | + if ($port['type'] != 'soap') { | ||
| 534 | + return null; | ||
| 535 | + } | ||
| 536 | + | ||
| 537 | + // XXX currentPort is BAD | ||
| 538 | + $clienturl = $port['address']['location']; | ||
| 539 | + if (!$classname) { | ||
| 540 | + if ($multiport || $port) { | ||
| 541 | + $classname = 'WebService_' . $this->service . '_' . $port['name']; | ||
| 542 | + } else { | ||
| 543 | + $classname = 'WebService_' . $this->service; | ||
| 544 | + } | ||
| 545 | + $classname = preg_replace('/[ .\-\(\)]+/', '_', $classname); | ||
| 546 | + } | ||
| 547 | + | ||
| 548 | + if (!$this->_validateString($classname)) { | ||
| 549 | + return null; | ||
| 550 | + } | ||
| 551 | + | ||
| 552 | + if (is_array($this->proxy) && count($this->proxy)) { | ||
| 553 | + $class = "class $classname extends SOAP_Client\n{\n" . | ||
| 554 | + " function $classname(\$path = '$clienturl')\n {\n" . | ||
| 555 | + " \$this->SOAP_Client(\$path, 0, 0,\n" . | ||
| 556 | + ' array('; | ||
| 557 | + | ||
| 558 | + foreach ($this->proxy as $key => $val) { | ||
| 559 | + if (is_array($val)) { | ||
| 560 | + $class .= "'$key' => array("; | ||
| 561 | + foreach ($val as $key2 => $val2) { | ||
| 562 | + $class .= "'$key2' => '$val2', "; | ||
| 563 | + } | ||
| 564 | + $class .= ')'; | ||
| 565 | + } else { | ||
| 566 | + $class .= "'$key' => '$val', "; | ||
| 567 | + } | ||
| 568 | + } | ||
| 569 | + $class .= "));\n }\n"; | ||
| 570 | + $class = str_replace(', ))', '))', $class); | ||
| 571 | + } else { | ||
| 572 | + $class = "class $classname extends SOAP_Client\n{\n" . | ||
| 573 | + " function $classname(\$path = '$clienturl')\n {\n" . | ||
| 574 | + " \$this->SOAP_Client(\$path, 0);\n" . | ||
| 575 | + " }\n"; | ||
| 576 | + } | ||
| 577 | + | ||
| 578 | + // Get the binding, from that get the port type. | ||
| 579 | + $primaryBinding = $port['binding']; | ||
| 580 | + $primaryBinding = preg_replace("/^(.*:)/", '', $primaryBinding); | ||
| 581 | + $portType = $this->bindings[$primaryBinding]['type']; | ||
| 582 | + $portType = preg_replace("/^(.*:)/", '', $portType); | ||
| 583 | + $style = $this->bindings[$primaryBinding]['style']; | ||
| 584 | + | ||
| 585 | + // XXX currentPortType is BAD | ||
| 586 | + foreach ($this->portTypes[$portType] as $opname => $operation) { | ||
| 587 | + $binding = $this->bindings[$primaryBinding]['operations'][$opname]; | ||
| 588 | + if (isset($binding['soapAction'])) { | ||
| 589 | + $soapaction = $binding['soapAction']; | ||
| 590 | + } else { | ||
| 591 | + $soapaction = null; | ||
| 592 | + } | ||
| 593 | + if (isset($binding['style'])) { | ||
| 594 | + $opstyle = $binding['style']; | ||
| 595 | + } else { | ||
| 596 | + $opstyle = $style; | ||
| 597 | + } | ||
| 598 | + $use = $binding['input']['use']; | ||
| 599 | + if ($use == 'encoded') { | ||
| 600 | + $namespace = $binding['input']['namespace']; | ||
| 601 | + } else { | ||
| 602 | + $bindingType = $this->bindings[$primaryBinding]['type']; | ||
| 603 | + $ns = $this->portTypes[$bindingType][$opname]['input']['namespace']; | ||
| 604 | + $namespace = $this->namespaces[$ns]; | ||
| 605 | + } | ||
| 606 | + | ||
| 607 | + $args = ''; | ||
| 608 | + $argarray = ''; | ||
| 609 | + $comments = ''; | ||
| 610 | + $wrappers = ''; | ||
| 611 | + foreach ($operation['input'] as $argname => $argtype) { | ||
| 612 | + if ($argname == 'message') { | ||
| 613 | + foreach ($this->messages[$argtype] as $_argname => $_argtype) { | ||
| 614 | + if ($opstyle == 'document' && $use == 'literal' && | ||
| 615 | + $_argtype['name'] == 'parameters') { | ||
| 616 | + // The type or element refered to is used for | ||
| 617 | + // parameters. | ||
| 618 | + $elattrs = null; | ||
| 619 | + $element = $_argtype['element']; | ||
| 620 | + $el = $this->elements[$_argtype['namespace']][$_argtype['type']]; | ||
| 621 | + | ||
| 622 | + if ($el['complex']) { | ||
| 623 | + $namespace = $this->namespaces[$_argtype['namespace']]; | ||
| 624 | + // XXX need to wrap the parameters in a | ||
| 625 | + // SOAP_Value. | ||
| 626 | + } | ||
| 627 | + if (isset($el['elements'])) { | ||
| 628 | + foreach ($el['elements'] as $elname => $elattrs) { | ||
| 629 | + // Is the element a complex type? | ||
| 630 | + if (isset($this->complexTypes[$elattrs['namespace']][$elname])) { | ||
| 631 | + $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname); | ||
| 632 | + } else { | ||
| 633 | + $this->_addArg($args, $argarray, $elname); | ||
| 634 | + } | ||
| 635 | + } | ||
| 636 | + } | ||
| 637 | + if ($el['complex'] && $argarray) { | ||
| 638 | + $wrapname = '{' . $this->namespaces[$_argtype['namespace']].'}' . $el['name']; | ||
| 639 | + $comments .= " \${$el['name']} =& new SOAP_Value('$wrapname', false, \$v = array($argarray));\n"; | ||
| 640 | + $argarray = "'{$el['name']}' => \${$el['name']}"; | ||
| 641 | + } | ||
| 642 | + } else { | ||
| 643 | + if (isset($_argtype['element'])) { | ||
| 644 | + // Element argument. | ||
| 645 | + $comments .= $this->_elementArg($args, $argarray, $_argtype, $_argtype['type']); | ||
| 646 | + } else { | ||
| 647 | + // Complex type argument. | ||
| 648 | + $comments .= $this->_complexTypeArg($args, $argarray, $_argtype, $_argname); | ||
| 649 | + } | ||
| 650 | + } | ||
| 651 | + } | ||
| 652 | + } | ||
| 653 | + } | ||
| 654 | + | ||
| 655 | + // Validate entries. | ||
| 656 | + | ||
| 657 | + // Operation names are function names, so try to make sure it's | ||
| 658 | + // legal. This could potentially cause collisions, but let's try | ||
| 659 | + // to make everything callable and see how many problems that | ||
| 660 | + // causes. | ||
| 661 | + $opname_php = preg_replace('/[ .\-\(\)]+/', '_', $opname); | ||
| 662 | + if (!$this->_validateString($opname_php)) { | ||
| 663 | + return null; | ||
| 664 | + } | ||
| 665 | + | ||
| 666 | + if ($argarray) { | ||
| 667 | + $argarray = "array($argarray)"; | ||
| 668 | + } else { | ||
| 669 | + $argarray = 'null'; | ||
| 670 | + } | ||
| 671 | + | ||
| 672 | + $class .= " function &$opname_php($args)\n {\n$comments$wrappers" . | ||
| 673 | + " \$result = \$this->call('$opname',\n" . | ||
| 674 | + " \$v = $argarray,\n" . | ||
| 675 | + " array('namespace' => '$namespace',\n" . | ||
| 676 | + " 'soapaction' => '$soapaction',\n" . | ||
| 677 | + " 'style' => '$opstyle',\n" . | ||
| 678 | + " 'use' => '$use'" . | ||
| 679 | + ($this->trace?",\n 'trace' => 1" : '') . "));\n" . | ||
| 680 | + " return \$result;\n" . | ||
| 681 | + " }\n"; | ||
| 682 | + } | ||
| 683 | + | ||
| 684 | + $class .= "}\n"; | ||
| 685 | + | ||
| 686 | + return $class; | ||
| 687 | + } | ||
| 688 | + | ||
| 689 | + function generateAllProxies() | ||
| 690 | + { | ||
| 691 | + $proxycode = ''; | ||
| 692 | + foreach (array_keys($this->services[$this->service]['ports']) as $key) { | ||
| 693 | + $port =& $this->services[$this->service]['ports'][$key]; | ||
| 694 | + $proxycode .= $this->generateProxyCode($port); | ||
| 695 | + } | ||
| 696 | + return $proxycode; | ||
| 697 | + } | ||
| 698 | + | ||
| 699 | + function &getProxy($port = '', $name = '') | ||
| 700 | + { | ||
| 701 | + if ($this->__isfault()) { | ||
| 702 | + $fault =& $this->__getfault(); | ||
| 703 | + return $fault; | ||
| 704 | + } | ||
| 705 | + | ||
| 706 | + $multiport = count($this->services[$this->service]['ports']) > 1; | ||
| 707 | + | ||
| 708 | + if (!$port) { | ||
| 709 | + reset($this->services[$this->service]['ports']); | ||
| 710 | + $port = current($this->services[$this->service]['ports']); | ||
| 711 | + } | ||
| 712 | + | ||
| 713 | + if ($multiport || $port) { | ||
| 714 | + $classname = 'WebService_' . $this->service . '_' . $port['name']; | ||
| 715 | + } else { | ||
| 716 | + $classname = 'WebService_' . $this->service; | ||
| 717 | + } | ||
| 718 | + | ||
| 719 | + if ($name) { | ||
| 720 | + $classname = $name . '_' . $classname; | ||
| 721 | + } | ||
| 722 | + | ||
| 723 | + $classname = preg_replace('/[ .\-\(\)]+/', '_', $classname); | ||
| 724 | + if (!class_exists($classname)) { | ||
| 725 | + $proxy = $this->generateProxyCode($port, $classname); | ||
| 726 | + require_once 'SOAP/Client.php'; | ||
| 727 | + eval($proxy); | ||
| 728 | + } | ||
| 729 | + $proxy =& new $classname; | ||
| 730 | + | ||
| 731 | + return $proxy; | ||
| 732 | + } | ||
| 733 | + | ||
| 734 | + function &_getComplexTypeForElement($name, $namespace) | ||
| 735 | + { | ||
| 736 | + $t = null; | ||
| 737 | + if (isset($this->ns[$namespace]) && | ||
| 738 | + isset($this->elements[$this->ns[$namespace]][$name]['type'])) { | ||
| 739 | + | ||
| 740 | + $type = $this->elements[$this->ns[$namespace]][$name]['type']; | ||
| 741 | + $ns = $this->elements[$this->ns[$namespace]][$name]['namespace']; | ||
| 742 | + | ||
| 743 | + if (isset($this->complexTypes[$ns][$type])) { | ||
| 744 | + $t = $this->complexTypes[$ns][$type]; | ||
| 745 | + } | ||
| 746 | + } | ||
| 747 | + return $t; | ||
| 748 | + } | ||
| 749 | + | ||
| 750 | + function getComplexTypeNameForElement($name, $namespace) | ||
| 751 | + { | ||
| 752 | + $t = $this->_getComplexTypeForElement($name, $namespace); | ||
| 753 | + if ($t) { | ||
| 754 | + return $t['name']; | ||
| 755 | + } | ||
| 756 | + return null; | ||
| 757 | + } | ||
| 758 | + | ||
| 759 | + function getComplexTypeChildType($ns, $name, $child_ns, $child_name) | ||
| 760 | + { | ||
| 761 | + // is the type an element? | ||
| 762 | + $t = $this->_getComplexTypeForElement($name, $ns); | ||
| 763 | + if ($t) { | ||
| 764 | + // no, get it from complex types directly | ||
| 765 | + if (isset($t['elements'][$child_name]['type'])) | ||
| 766 | + return $t['elements'][$child_name]['type']; | ||
| 767 | + } | ||
| 768 | + return null; | ||
| 769 | + } | ||
| 770 | + | ||
| 771 | + function getSchemaType($type, $name, $type_namespace) | ||
| 772 | + { | ||
| 773 | + // see if it's a complex type so we can deal properly with | ||
| 774 | + // SOAPENC:arrayType. | ||
| 775 | + if ($name && $type) { | ||
| 776 | + // XXX TODO: | ||
| 777 | + // look up the name in the wsdl and validate the type. | ||
| 778 | + foreach ($this->complexTypes as $ns => $types) { | ||
| 779 | + if (array_key_exists($type, $types)) { | ||
| 780 | + if (array_key_exists('type', $types[$type])) { | ||
| 781 | + list($arraytype_ns, $arraytype, $array_depth) = isset($types[$type]['arrayType'])? | ||
| 782 | + $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType']) | ||
| 783 | + : array($this->namespaces[$types[$type]['namespace']], null, 0); | ||
| 784 | + return array($types[$type]['type'], $arraytype, $arraytype_ns, $array_depth); | ||
| 785 | + } | ||
| 786 | + if (array_key_exists('arrayType', $types[$type])) { | ||
| 787 | + list($arraytype_ns, $arraytype, $array_depth) = | ||
| 788 | + $this->_getDeepestArrayType($types[$type]['namespace'], $types[$type]['arrayType']); | ||
| 789 | + return array('Array', $arraytype, $arraytype_ns, $array_depth); | ||
| 790 | + } | ||
| 791 | + if (array_key_exists('elements', $types[$type]) && | ||
| 792 | + array_key_exists($name, $types[$type]['elements'])) { | ||
| 793 | + $type = $types[$type]['elements']['type']; | ||
| 794 | + return array($type, null, $this->namespaces[$types[$type]['namespace']], null); | ||
| 795 | + } | ||
| 796 | + } | ||
| 797 | + } | ||
| 798 | + } | ||
| 799 | + if ($type && $type_namespace) { | ||
| 800 | + $arrayType = null; | ||
| 801 | + // XXX TODO: | ||
| 802 | + // this code currently handles only one way of encoding array types in wsdl | ||
| 803 | + // need to do a generalized function to figure out complex types | ||
| 804 | + $p = $this->ns[$type_namespace]; | ||
| 805 | + if ($p && | ||
| 806 | + array_key_exists($p, $this->complexTypes) && | ||
| 807 | + array_key_exists($type, $this->complexTypes[$p])) { | ||
| 808 | + if ($arrayType = $this->complexTypes[$p][$type]['arrayType']) { | ||
| 809 | + $type = 'Array'; | ||
| 810 | + } elseif ($this->complexTypes[$p][$type]['order']=='sequence' && | ||
| 811 | + array_key_exists('elements', $this->complexTypes[$p][$type])) { | ||
| 812 | + reset($this->complexTypes[$p][$type]['elements']); | ||
| 813 | + // assume an array | ||
| 814 | + if (count($this->complexTypes[$p][$type]['elements']) == 1) { | ||
| 815 | + $arg = current($this->complexTypes[$p][$type]['elements']); | ||
| 816 | + $arrayType = $arg['type']; | ||
| 817 | + $type = 'Array'; | ||
| 818 | + } else { | ||
| 819 | + foreach ($this->complexTypes[$p][$type]['elements'] as $element) { | ||
| 820 | + if ($element['name'] == $type) { | ||
| 821 | + $arrayType = $element['type']; | ||
| 822 | + $type = $element['type']; | ||
| 823 | + } | ||
| 824 | + } | ||
| 825 | + } | ||
| 826 | + } else { | ||
| 827 | + $type = 'Struct'; | ||
| 828 | + } | ||
| 829 | + return array($type, $arrayType, $type_namespace, null); | ||
| 830 | + } | ||
| 831 | + } | ||
| 832 | + return array(null, null, null, null); | ||
| 833 | + } | ||
| 834 | + | ||
| 835 | + /** | ||
| 836 | + * Recurse through the WSDL structure looking for the innermost array type | ||
| 837 | + * of multi-dimensional arrays. | ||
| 838 | + * | ||
| 839 | + * Takes a namespace prefix and a type, which can be in the form 'type' or | ||
| 840 | + * 'type[]', and returns the full namespace URI, the type of the most | ||
| 841 | + * deeply nested array type found, and the number of levels of nesting. | ||
| 842 | + * | ||
| 843 | + * @access private | ||
| 844 | + * @return mixed array or nothing | ||
| 845 | + */ | ||
| 846 | + function _getDeepestArrayType($nsPrefix, $arrayType) | ||
| 847 | + { | ||
| 848 | + static $trail = array(); | ||
| 849 | + | ||
| 850 | + $arrayType = ereg_replace('\[\]$', '', $arrayType); | ||
| 851 | + | ||
| 852 | + // Protect against circular references XXX We really need to remove | ||
| 853 | + // trail from this altogether (it's very inefficient and in the wrong | ||
| 854 | + // place!) and put circular reference checking in when the WSDL info | ||
| 855 | + // is generated in the first place | ||
| 856 | + if (array_search($nsPrefix . ':' . $arrayType, $trail)) { | ||
| 857 | + return array(null, null, -count($trail)); | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + if (array_key_exists($nsPrefix, $this->complexTypes) && | ||
| 861 | + array_key_exists($arrayType, $this->complexTypes[$nsPrefix]) && | ||
| 862 | + array_key_exists('arrayType', $this->complexTypes[$nsPrefix][$arrayType])) { | ||
| 863 | + $trail[] = $nsPrefix . ':' . $arrayType; | ||
| 864 | + $result = $this->_getDeepestArrayType($this->complexTypes[$nsPrefix][$arrayType]['namespace'], | ||
| 865 | + $this->complexTypes[$nsPrefix][$arrayType]['arrayType']); | ||
| 866 | + return array($result[0], $result[1], $result[2] + 1); | ||
| 867 | + } | ||
| 868 | + return array($this->namespaces[$nsPrefix], $arrayType, 0); | ||
| 869 | + } | ||
| 870 | + | ||
| 871 | +} | ||
| 872 | + | ||
| 873 | +class SOAP_WSDL_Cache extends SOAP_Base | ||
| 874 | +{ | ||
| 875 | + // Cache settings | ||
| 876 | + | ||
| 877 | + /** | ||
| 878 | + * Use WSDL cache | ||
| 879 | + * | ||
| 880 | + * @var boolean | ||
| 881 | + */ | ||
| 882 | + var $_cacheUse = null; | ||
| 883 | + | ||
| 884 | + /** | ||
| 885 | + * Cache max lifetime (in seconds) | ||
| 886 | + * | ||
| 887 | + * @var int | ||
| 888 | + */ | ||
| 889 | + var $_cacheMaxAge = null; | ||
| 890 | + | ||
| 891 | + /** | ||
| 892 | + * SOAP_WSDL_Cache constructor | ||
| 893 | + * | ||
| 894 | + * @param boolean use caching | ||
| 895 | + * @param int cache max lifetime (in seconds) | ||
| 896 | + * @access public | ||
| 897 | + */ | ||
| 898 | + function SOAP_WSDL_Cache($cacheUse = WSDL_CACHE_USE, | ||
| 899 | + $cacheMaxAge = WSDL_CACHE_MAX_AGE) | ||
| 900 | + { | ||
| 901 | + parent::SOAP_Base('WSDLCACHE'); | ||
| 902 | + $this->_cacheUse = $cacheUse; | ||
| 903 | + $this->_cacheMaxAge = $cacheMaxAge; | ||
| 904 | + } | ||
| 905 | + | ||
| 906 | + /** | ||
| 907 | + * _cacheDir | ||
| 908 | + * return the path to the cache, if it doesn't exist, make it | ||
| 909 | + */ | ||
| 910 | + function _cacheDir() | ||
| 911 | + { | ||
| 912 | + $dir = getenv("WSDLCACHE"); | ||
| 913 | + if (!$dir) $dir = " ./wsdlcache"; | ||
| 914 | + @mkdir($dir, 0700); | ||
| 915 | + return $dir; | ||
| 916 | + } | ||
| 917 | + | ||
| 918 | + /** | ||
| 919 | + * Retrieves a file from cache if it exists, otherwise retreive from net, | ||
| 920 | + * add to cache, and return from cache. | ||
| 921 | + * | ||
| 922 | + * @param string URL to WSDL | ||
| 923 | + * @param array proxy parameters | ||
| 924 | + * @param int expected MD5 of WSDL URL | ||
| 925 | + * @access public | ||
| 926 | + * @return string data | ||
| 927 | + */ | ||
| 928 | + function get($wsdl_fname, $proxy_params = array(), $cache = 0) | ||
| 929 | + { | ||
| 930 | + $cachename = $md5_wsdl = $file_data = ''; | ||
| 931 | + if ($this->_cacheUse) { | ||
| 932 | + // Try to retrieve WSDL from cache | ||
| 933 | + $cachename = SOAP_WSDL_Cache::_cacheDir() . '/' . md5($wsdl_fname). ' .wsdl'; | ||
| 934 | + if (file_exists($cachename)) { | ||
| 935 | + $wf = fopen($cachename, 'rb'); | ||
| 936 | + if ($wf) { | ||
| 937 | + // Reading cached file | ||
| 938 | + $file_data = fread($wf, filesize($cachename)); | ||
| 939 | + $md5_wsdl = md5($file_data); | ||
| 940 | + fclose($wf); | ||
| 941 | + } | ||
| 942 | + if ($cache) { | ||
| 943 | + if ($cache != $md5_wsdl) { | ||
| 944 | + return $this->_raiseSoapFault('WSDL Checksum error!', $wsdl_fname); | ||
| 945 | + } | ||
| 946 | + } else { | ||
| 947 | + $fi = stat($cachename); | ||
| 948 | + $cache_mtime = $fi[8]; | ||
| 949 | + //print cache_mtime, time() | ||
| 950 | + if ($cache_mtime + $this->_cacheMaxAge < time()) { | ||
| 951 | + // expired | ||
| 952 | + $md5_wsdl = ''; // refetch | ||
| 953 | + } | ||
| 954 | + } | ||
| 955 | + } | ||
| 956 | + } | ||
| 957 | + | ||
| 958 | + if (!$md5_wsdl) { | ||
| 959 | + // Not cached or not using cache. Retrieve WSDL from URL | ||
| 960 | + | ||
| 961 | + // is it a local file? | ||
| 962 | + // this section should be replace by curl at some point | ||
| 963 | + if (!preg_match('/^(https?|file):\/\//', $wsdl_fname)) { | ||
| 964 | + if (!file_exists($wsdl_fname)) { | ||
| 965 | + return $this->_raiseSoapFault("Unable to read local WSDL $wsdl_fname", $wsdl_fname); | ||
| 966 | + } | ||
| 967 | + if (function_exists('file_get_contents')) { | ||
| 968 | + $file_data = file_get_contents($wsdl_fname); | ||
| 969 | + } else { | ||
| 970 | + $file_data = implode('',file($wsdl_fname)); | ||
| 971 | + } | ||
| 972 | + } else { | ||
| 973 | + $uri = explode('?', $wsdl_fname); | ||
| 974 | + $rq =& new HTTP_Request($uri[0], $proxy_params); | ||
| 975 | + // the user agent HTTP_Request uses fouls things up | ||
| 976 | + if (isset($uri[1])) { | ||
| 977 | + $rq->addRawQueryString($uri[1]); | ||
| 978 | + } | ||
| 979 | + | ||
| 980 | + if (isset($proxy_params['proxy_host']) && | ||
| 981 | + isset($proxy_params['proxy_port']) && | ||
| 982 | + isset($proxy_params['proxy_user']) && | ||
| 983 | + isset($proxy_params['proxy_pass'])) { | ||
| 984 | + $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port'], | ||
| 985 | + $proxy_params['proxy_user'], $proxy_params['proxy_pass']); | ||
| 986 | + } elseif (isset($proxy_params['proxy_host']) && | ||
| 987 | + isset($proxy_params['proxy_port'])) { | ||
| 988 | + $rq->setProxy($proxy_params['proxy_host'], $proxy_params['proxy_port']); | ||
| 989 | + } | ||
| 990 | + | ||
| 991 | + $result = $rq->sendRequest(); | ||
| 992 | + if (PEAR::isError($result)) { | ||
| 993 | + return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname," . $rq->getResponseCode(), $wsdl_fname); | ||
| 994 | + } | ||
| 995 | + $file_data = $rq->getResponseBody(); | ||
| 996 | + if (!$file_data) { | ||
| 997 | + return $this->_raiseSoapFault("Unable to retrieve WSDL $wsdl_fname, no http body", $wsdl_fname); | ||
| 998 | + } | ||
| 999 | + } | ||
| 1000 | + | ||
| 1001 | + $md5_wsdl = md5($file_data); | ||
| 1002 | + | ||
| 1003 | + if ($this->_cacheUse) { | ||
| 1004 | + $fp = fopen($cachename, "wb"); | ||
| 1005 | + fwrite($fp, $file_data); | ||
| 1006 | + fclose($fp); | ||
| 1007 | + } | ||
| 1008 | + } | ||
| 1009 | + if ($this->_cacheUse && $cache && $cache != $md5_wsdl) { | ||
| 1010 | + return $this->_raiseSoapFault("WSDL Checksum error!", $wsdl_fname); | ||
| 1011 | + } | ||
| 1012 | + return $file_data; | ||
| 1013 | + } | ||
| 1014 | + | ||
| 1015 | +} | ||
| 1016 | + | ||
| 1017 | +class SOAP_WSDL_Parser extends SOAP_Base | ||
| 1018 | +{ | ||
| 1019 | + | ||
| 1020 | + /** | ||
| 1021 | + * Define internal arrays of bindings, ports, operations, | ||
| 1022 | + * messages, etc. | ||
| 1023 | + */ | ||
| 1024 | + var $currentMessage; | ||
| 1025 | + var $currentOperation; | ||
| 1026 | + var $currentPortType; | ||
| 1027 | + var $currentBinding; | ||
| 1028 | + var $currentPort; | ||
| 1029 | + | ||
| 1030 | + /** | ||
| 1031 | + * Parser vars. | ||
| 1032 | + */ | ||
| 1033 | + var $cache; | ||
| 1034 | + | ||
| 1035 | + var $tns = null; | ||
| 1036 | + var $soapns = array('soap'); | ||
| 1037 | + var $uri = ''; | ||
| 1038 | + var $wsdl = null; | ||
| 1039 | + | ||
| 1040 | + var $status = ''; | ||
| 1041 | + var $element_stack = array(); | ||
| 1042 | + var $parentElement = ''; | ||
| 1043 | + | ||
| 1044 | + var $schema = ''; | ||
| 1045 | + var $schemaStatus = ''; | ||
| 1046 | + var $schema_stack = array(); | ||
| 1047 | + var $currentComplexType; | ||
| 1048 | + var $schema_element_stack = array(); | ||
| 1049 | + var $currentElement; | ||
| 1050 | + | ||
| 1051 | + /** | ||
| 1052 | + * constructor | ||
| 1053 | + */ | ||
| 1054 | + function SOAP_WSDL_Parser($uri, &$wsdl, $docs = false) | ||
| 1055 | + { | ||
| 1056 | + parent::SOAP_Base('WSDLPARSER'); | ||
| 1057 | + $this->cache =& new SOAP_WSDL_Cache($wsdl->cacheUse, $wsdl->cacheMaxAge); | ||
| 1058 | + $this->uri = $uri; | ||
| 1059 | + $this->wsdl = &$wsdl; | ||
| 1060 | + $this->docs = $docs; | ||
| 1061 | + $this->parse($uri); | ||
| 1062 | + } | ||
| 1063 | + | ||
| 1064 | + function parse($uri) | ||
| 1065 | + { | ||
| 1066 | + // Check whether content has been read. | ||
| 1067 | + $fd = $this->cache->get($uri, $this->wsdl->proxy); | ||
| 1068 | + if (PEAR::isError($fd)) { | ||
| 1069 | + return $this->_raiseSoapFault($fd); | ||
| 1070 | + } | ||
| 1071 | + | ||
| 1072 | + // Create an XML parser. | ||
| 1073 | + $parser = xml_parser_create(); | ||
| 1074 | + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); | ||
| 1075 | + xml_set_object($parser, $this); | ||
| 1076 | + xml_set_element_handler($parser, 'startElement', 'endElement'); | ||
| 1077 | + if ($this->docs) { | ||
| 1078 | + xml_set_character_data_handler($parser, 'characterData'); | ||
| 1079 | + } | ||
| 1080 | + | ||
| 1081 | + if (!xml_parse($parser, $fd, true)) { | ||
| 1082 | + $detail = sprintf('XML error on line %d: %s', | ||
| 1083 | + xml_get_current_line_number($parser), | ||
| 1084 | + xml_error_string(xml_get_error_code($parser))); | ||
| 1085 | + return $this->_raiseSoapFault("Unable to parse WSDL file $uri\n$detail"); | ||
| 1086 | + } | ||
| 1087 | + xml_parser_free($parser); | ||
| 1088 | + return true; | ||
| 1089 | + } | ||
| 1090 | + | ||
| 1091 | + /** | ||
| 1092 | + * start-element handler | ||
| 1093 | + */ | ||
| 1094 | + function startElement($parser, $name, $attrs) | ||
| 1095 | + { | ||
| 1096 | + // Get element prefix. | ||
| 1097 | + $qname =& new QName($name); | ||
| 1098 | + if ($qname->ns) { | ||
| 1099 | + $ns = $qname->ns; | ||
| 1100 | + if ($ns && ((!$this->tns && strcasecmp($qname->name, 'definitions') == 0) || $ns == $this->tns)) { | ||
| 1101 | + $name = $qname->name; | ||
| 1102 | + } | ||
| 1103 | + } | ||
| 1104 | + $this->currentTag = $qname->name; | ||
| 1105 | + $this->parentElement = ''; | ||
| 1106 | + $stack_size = count($this->element_stack); | ||
| 1107 | + if ($stack_size) { | ||
| 1108 | + $this->parentElement = $this->element_stack[$stack_size - 1]; | ||
| 1109 | + } | ||
| 1110 | + $this->element_stack[] = $this->currentTag; | ||
| 1111 | + | ||
| 1112 | + // Find status, register data. | ||
| 1113 | + switch ($this->status) { | ||
| 1114 | + case 'types': | ||
| 1115 | + // sect 2.2 wsdl:types | ||
| 1116 | + // children: xsd:schema | ||
| 1117 | + $parent_tag = ''; | ||
| 1118 | + $stack_size = count($this->schema_stack); | ||
| 1119 | + if ($stack_size) { | ||
| 1120 | + $parent_tag = $this->schema_stack[$stack_size - 1]; | ||
| 1121 | + } | ||
| 1122 | + | ||
| 1123 | + switch ($qname->name) { | ||
| 1124 | + case 'schema': | ||
| 1125 | + // No parent should be in the stack. | ||
| 1126 | + if (!$parent_tag || $parent_tag == 'types') { | ||
| 1127 | + if (array_key_exists('targetNamespace', $attrs)) { | ||
| 1128 | + $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']); | ||
| 1129 | + } else { | ||
| 1130 | + $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns); | ||
| 1131 | + } | ||
| 1132 | + $this->wsdl->complexTypes[$this->schema] = array(); | ||
| 1133 | + $this->wsdl->elements[$this->schema] = array(); | ||
| 1134 | + } | ||
| 1135 | + break; | ||
| 1136 | + | ||
| 1137 | + case 'complexType': | ||
| 1138 | + if ($parent_tag == 'schema') { | ||
| 1139 | + $this->currentComplexType = $attrs['name']; | ||
| 1140 | + if (!isset($attrs['namespace'])) { | ||
| 1141 | + $attrs['namespace'] = $this->schema; | ||
| 1142 | + } | ||
| 1143 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType] = $attrs; | ||
| 1144 | + if (array_key_exists('base', $attrs)) { | ||
| 1145 | + $qn =& new QName($attrs['base']); | ||
| 1146 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name; | ||
| 1147 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $qn->ns; | ||
| 1148 | + } else { | ||
| 1149 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; | ||
| 1150 | + } | ||
| 1151 | + $this->schemaStatus = 'complexType'; | ||
| 1152 | + } else { | ||
| 1153 | + $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = true; | ||
| 1154 | + } | ||
| 1155 | + break; | ||
| 1156 | + | ||
| 1157 | + case 'element': | ||
| 1158 | + if (isset($attrs['type'])) { | ||
| 1159 | + $qn =& new QName($attrs['type']); | ||
| 1160 | + $attrs['type'] = $qn->name; | ||
| 1161 | + if ($qn->ns && array_key_exists($qn->ns, $this->wsdl->namespaces)) { | ||
| 1162 | + $attrs['namespace'] = $qn->ns; | ||
| 1163 | + } | ||
| 1164 | + } | ||
| 1165 | + | ||
| 1166 | + $parentElement = ''; | ||
| 1167 | + $stack_size = count($this->schema_element_stack); | ||
| 1168 | + if ($stack_size > 0) { | ||
| 1169 | + $parentElement = $this->schema_element_stack[$stack_size - 1]; | ||
| 1170 | + } | ||
| 1171 | + | ||
| 1172 | + if (isset($attrs['ref'])) { | ||
| 1173 | + $qn =& new QName($attrs['ref']); | ||
| 1174 | + $this->currentElement = $qn->name; | ||
| 1175 | + } else { | ||
| 1176 | + $this->currentElement = $attrs['name']; | ||
| 1177 | + } | ||
| 1178 | + $this->schema_element_stack[] = $this->currentElement; | ||
| 1179 | + if (!isset($attrs['namespace'])) { | ||
| 1180 | + $attrs['namespace'] = $this->schema; | ||
| 1181 | + } | ||
| 1182 | + | ||
| 1183 | + if ($parent_tag == 'schema') { | ||
| 1184 | + $this->wsdl->elements[$this->schema][$this->currentElement] = $attrs; | ||
| 1185 | + $this->wsdl->elements[$this->schema][$this->currentElement]['complex'] = false; | ||
| 1186 | + $this->schemaStatus = 'element'; | ||
| 1187 | + } elseif ($this->currentComplexType) { | ||
| 1188 | + // we're inside a complexType | ||
| 1189 | + if ((isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order']) && | ||
| 1190 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] == 'sequence') | ||
| 1191 | + && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array') { | ||
| 1192 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['arrayType'] = isset($attrs['type']) ? $attrs['type'] : null; | ||
| 1193 | + } | ||
| 1194 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement] = $attrs; | ||
| 1195 | + } else { | ||
| 1196 | + $this->wsdl->elements[$this->schema][$parentElement]['elements'][$this->currentElement] = $attrs; | ||
| 1197 | + } | ||
| 1198 | + break; | ||
| 1199 | + | ||
| 1200 | + case 'complexContent': | ||
| 1201 | + case 'simpleContent': | ||
| 1202 | + break; | ||
| 1203 | + | ||
| 1204 | + case 'extension': | ||
| 1205 | + case 'restriction': | ||
| 1206 | + if ($this->schemaStatus == 'complexType') { | ||
| 1207 | + if (!empty($attrs['base'])) { | ||
| 1208 | + $qn =& new QName($attrs['base']); | ||
| 1209 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = $qn->name; | ||
| 1210 | + | ||
| 1211 | + // Types that extend from other types aren't | ||
| 1212 | + // *of* those types. Reflect this by denoting | ||
| 1213 | + // which type they extend. I'm leaving the | ||
| 1214 | + // 'type' setting here since I'm not sure what | ||
| 1215 | + // removing it might break at the moment. | ||
| 1216 | + if ($qname->name == 'extension') { | ||
| 1217 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['extends'] = $qn->name; | ||
| 1218 | + } | ||
| 1219 | + } else { | ||
| 1220 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; | ||
| 1221 | + } | ||
| 1222 | + } | ||
| 1223 | + break; | ||
| 1224 | + | ||
| 1225 | + case 'sequence': | ||
| 1226 | + if ($this->schemaStatus == 'complexType') { | ||
| 1227 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; | ||
| 1228 | + if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { | ||
| 1229 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; | ||
| 1230 | + } | ||
| 1231 | + } | ||
| 1232 | + break; | ||
| 1233 | + | ||
| 1234 | + case 'all': | ||
| 1235 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; | ||
| 1236 | + if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { | ||
| 1237 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; | ||
| 1238 | + } | ||
| 1239 | + break; | ||
| 1240 | + | ||
| 1241 | + case 'choice': | ||
| 1242 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['order'] = $qname->name; | ||
| 1243 | + if (!isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'])) { | ||
| 1244 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; | ||
| 1245 | + } | ||
| 1246 | + | ||
| 1247 | + case 'attribute': | ||
| 1248 | + if ($this->schemaStatus == 'complexType') { | ||
| 1249 | + if (isset($attrs['name'])) { | ||
| 1250 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['attribute'][$attrs['name']] = $attrs; | ||
| 1251 | + } else { | ||
| 1252 | + if (isset($attrs['ref'])) { | ||
| 1253 | + $q =& new QName($attrs['ref']); | ||
| 1254 | + foreach ($attrs as $k => $v) { | ||
| 1255 | + if ($k != 'ref' && strstr($k, $q->name)) { | ||
| 1256 | + $vq =& new QName($v); | ||
| 1257 | + if ($q->name == 'arrayType') { | ||
| 1258 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name. $vq->arrayInfo; | ||
| 1259 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Array'; | ||
| 1260 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['namespace'] = $vq->ns; | ||
| 1261 | + } else { | ||
| 1262 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType][$q->name] = $vq->name; | ||
| 1263 | + } | ||
| 1264 | + } | ||
| 1265 | + } | ||
| 1266 | + } | ||
| 1267 | + } | ||
| 1268 | + } | ||
| 1269 | + break; | ||
| 1270 | + } | ||
| 1271 | + | ||
| 1272 | + $this->schema_stack[] = $qname->name; | ||
| 1273 | + break; | ||
| 1274 | + | ||
| 1275 | + case 'message': | ||
| 1276 | + // sect 2.3 wsdl:message child wsdl:part | ||
| 1277 | + switch ($qname->name) { | ||
| 1278 | + case 'part': | ||
| 1279 | + $qn = null; | ||
| 1280 | + if (isset($attrs['type'])) { | ||
| 1281 | + $qn =& new QName($attrs['type']); | ||
| 1282 | + } elseif (isset($attrs['element'])) { | ||
| 1283 | + $qn =& new QName($attrs['element']); | ||
| 1284 | + } | ||
| 1285 | + if ($qn) { | ||
| 1286 | + $attrs['type'] = $qn->name; | ||
| 1287 | + $attrs['namespace'] = $qn->ns; | ||
| 1288 | + } | ||
| 1289 | + $this->wsdl->messages[$this->currentMessage][$attrs['name']] = $attrs; | ||
| 1290 | + // error in wsdl | ||
| 1291 | + | ||
| 1292 | + case 'documentation': | ||
| 1293 | + break; | ||
| 1294 | + | ||
| 1295 | + default: | ||
| 1296 | + break; | ||
| 1297 | + } | ||
| 1298 | + break; | ||
| 1299 | + | ||
| 1300 | + case 'portType': | ||
| 1301 | + // sect 2.4 | ||
| 1302 | + switch ($qname->name) { | ||
| 1303 | + case 'operation': | ||
| 1304 | + // attributes: name | ||
| 1305 | + // children: wsdl:input wsdl:output wsdl:fault | ||
| 1306 | + $this->currentOperation = $attrs['name']; | ||
| 1307 | + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation] = $attrs; | ||
| 1308 | + break; | ||
| 1309 | + | ||
| 1310 | + case 'input': | ||
| 1311 | + case 'output': | ||
| 1312 | + case 'fault': | ||
| 1313 | + // wsdl:input wsdl:output wsdl:fault | ||
| 1314 | + // attributes: name message parameterOrder(optional) | ||
| 1315 | + if ($this->currentOperation) { | ||
| 1316 | + if (isset($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name])) { | ||
| 1317 | + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = array_merge($this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name], $attrs); | ||
| 1318 | + } else { | ||
| 1319 | + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name] = $attrs; | ||
| 1320 | + } | ||
| 1321 | + if (array_key_exists('message', $attrs)) { | ||
| 1322 | + $qn =& new QName($attrs['message']); | ||
| 1323 | + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['message'] = $qn->name; | ||
| 1324 | + $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation][$name]['namespace'] = $qn->ns; | ||
| 1325 | + } | ||
| 1326 | + } | ||
| 1327 | + break; | ||
| 1328 | + | ||
| 1329 | + case 'documentation': | ||
| 1330 | + break; | ||
| 1331 | + | ||
| 1332 | + default: | ||
| 1333 | + break; | ||
| 1334 | + } | ||
| 1335 | + break; | ||
| 1336 | + | ||
| 1337 | + case 'binding': | ||
| 1338 | + $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL; | ||
| 1339 | + switch ($ns) { | ||
| 1340 | + case SCHEMA_SOAP: | ||
| 1341 | + // this deals with wsdl section 3 soap binding | ||
| 1342 | + switch ($qname->name) { | ||
| 1343 | + case 'binding': | ||
| 1344 | + // sect 3.3 | ||
| 1345 | + // soap:binding, attributes: transport(required), style(optional, default = document) | ||
| 1346 | + // if style is missing, it is assumed to be 'document' | ||
| 1347 | + if (!isset($attrs['style'])) { | ||
| 1348 | + $attrs['style'] = 'document'; | ||
| 1349 | + } | ||
| 1350 | + $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs); | ||
| 1351 | + break; | ||
| 1352 | + | ||
| 1353 | + case 'operation': | ||
| 1354 | + // sect 3.4 | ||
| 1355 | + // soap:operation, attributes: soapAction(required), style(optional, default = soap:binding:style) | ||
| 1356 | + if (!isset($attrs['style'])) { | ||
| 1357 | + $attrs['style'] = $this->wsdl->bindings[$this->currentBinding]['style']; | ||
| 1358 | + } | ||
| 1359 | + if (isset($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation])) { | ||
| 1360 | + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = array_merge($this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation], $attrs); | ||
| 1361 | + } else { | ||
| 1362 | + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->currentOperation] = $attrs; | ||
| 1363 | + } | ||
| 1364 | + break; | ||
| 1365 | + | ||
| 1366 | + case 'body': | ||
| 1367 | + // sect 3.5 | ||
| 1368 | + // soap:body attributes: | ||
| 1369 | + // part - optional. listed parts must appear in body, missing means all parts appear in body | ||
| 1370 | + // use - required. encoded|literal | ||
| 1371 | + // encodingStyle - optional. space seperated list of encodings (uri's) | ||
| 1372 | + $this->wsdl->bindings[$this->currentBinding] | ||
| 1373 | + ['operations'][$this->currentOperation][$this->opStatus] = $attrs; | ||
| 1374 | + break; | ||
| 1375 | + | ||
| 1376 | + case 'fault': | ||
| 1377 | + // sect 3.6 | ||
| 1378 | + // soap:fault attributes: name use encodingStyle namespace | ||
| 1379 | + $this->wsdl->bindings[$this->currentBinding] | ||
| 1380 | + ['operations'][$this->currentOperation][$this->opStatus] = $attrs; | ||
| 1381 | + break; | ||
| 1382 | + | ||
| 1383 | + case 'header': | ||
| 1384 | + // sect 3.7 | ||
| 1385 | + // soap:header attributes: message part use encodingStyle namespace | ||
| 1386 | + $this->wsdl->bindings[$this->currentBinding] | ||
| 1387 | + ['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs; | ||
| 1388 | + break; | ||
| 1389 | + | ||
| 1390 | + case 'headerfault': | ||
| 1391 | + // sect 3.7 | ||
| 1392 | + // soap:header attributes: message part use encodingStyle namespace | ||
| 1393 | + $header = count($this->wsdl->bindings[$this->currentBinding] | ||
| 1394 | + ['operations'][$this->currentOperation][$this->opStatus]['headers'])-1; | ||
| 1395 | + $this->wsdl->bindings[$this->currentBinding] | ||
| 1396 | + ['operations'][$this->currentOperation][$this->opStatus]['headers'][$header]['fault'] = $attrs; | ||
| 1397 | + break; | ||
| 1398 | + | ||
| 1399 | + case 'documentation': | ||
| 1400 | + break; | ||
| 1401 | + | ||
| 1402 | + default: | ||
| 1403 | + // error! not a valid element inside binding | ||
| 1404 | + break; | ||
| 1405 | + } | ||
| 1406 | + break; | ||
| 1407 | + | ||
| 1408 | + case SCHEMA_WSDL: | ||
| 1409 | + // XXX verify correct namespace | ||
| 1410 | + // for now, default is the 'wsdl' namespace | ||
| 1411 | + // other possible namespaces include smtp, http, etc. for alternate bindings | ||
| 1412 | + switch ($qname->name) { | ||
| 1413 | + case 'operation': | ||
| 1414 | + // sect 2.5 | ||
| 1415 | + // wsdl:operation attributes: name | ||
| 1416 | + $this->currentOperation = $attrs['name']; | ||
| 1417 | + break; | ||
| 1418 | + | ||
| 1419 | + case 'output': | ||
| 1420 | + case 'input': | ||
| 1421 | + case 'fault': | ||
| 1422 | + // sect 2.5 | ||
| 1423 | + // wsdl:input attributes: name | ||
| 1424 | + $this->opStatus = $qname->name; | ||
| 1425 | + break; | ||
| 1426 | + | ||
| 1427 | + case 'documentation': | ||
| 1428 | + break; | ||
| 1429 | + | ||
| 1430 | + default: | ||
| 1431 | + break; | ||
| 1432 | + } | ||
| 1433 | + break; | ||
| 1434 | + | ||
| 1435 | + case SCHEMA_WSDL_HTTP: | ||
| 1436 | + switch ($qname->name) { | ||
| 1437 | + case 'binding': | ||
| 1438 | + // sect 4.4 | ||
| 1439 | + // http:binding attributes: verb | ||
| 1440 | + // parent: wsdl:binding | ||
| 1441 | + $this->wsdl->bindings[$this->currentBinding] = array_merge($this->wsdl->bindings[$this->currentBinding], $attrs); | ||
| 1442 | + break; | ||
| 1443 | + | ||
| 1444 | + case 'operation': | ||
| 1445 | + // sect 4.5 | ||
| 1446 | + // http:operation attributes: location | ||
| 1447 | + // parent: wsdl:operation | ||
| 1448 | + $this->wsdl->bindings[$this->currentBinding]['operations'] | ||
| 1449 | + [$this->currentOperation] = $attrs; | ||
| 1450 | + break; | ||
| 1451 | + | ||
| 1452 | + case 'urlEncoded': | ||
| 1453 | + // sect 4.6 | ||
| 1454 | + // http:urlEncoded attributes: location | ||
| 1455 | + // parent: wsdl:input wsdl:output etc. | ||
| 1456 | + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus] | ||
| 1457 | + [$this->currentOperation]['uri'] = 'urlEncoded'; | ||
| 1458 | + break; | ||
| 1459 | + | ||
| 1460 | + case 'urlReplacement': | ||
| 1461 | + // sect 4.7 | ||
| 1462 | + // http:urlReplacement attributes: location | ||
| 1463 | + // parent: wsdl:input wsdl:output etc. | ||
| 1464 | + $this->wsdl->bindings[$this->currentBinding]['operations'][$this->opStatus] | ||
| 1465 | + [$this->currentOperation]['uri'] = 'urlReplacement'; | ||
| 1466 | + break; | ||
| 1467 | + | ||
| 1468 | + case 'documentation': | ||
| 1469 | + break; | ||
| 1470 | + | ||
| 1471 | + default: | ||
| 1472 | + // error | ||
| 1473 | + break; | ||
| 1474 | + } | ||
| 1475 | + | ||
| 1476 | + case SCHEMA_MIME: | ||
| 1477 | + // sect 5 | ||
| 1478 | + // all mime parts are children of wsdl:input, wsdl:output, etc. | ||
| 1479 | + // unsuported as of yet | ||
| 1480 | + switch ($qname->name) { | ||
| 1481 | + case 'content': | ||
| 1482 | + // sect 5.3 mime:content | ||
| 1483 | + // <mime:content part="nmtoken"? type="string"?/> | ||
| 1484 | + // part attribute only required if content is child of multipart related, | ||
| 1485 | + // it contains the name of the part | ||
| 1486 | + // type attribute contains the mime type | ||
| 1487 | + case 'multipartRelated': | ||
| 1488 | + // sect 5.4 mime:multipartRelated | ||
| 1489 | + case 'part': | ||
| 1490 | + case 'mimeXml': | ||
| 1491 | + // sect 5.6 mime:mimeXml | ||
| 1492 | + // <mime:mimeXml part="nmtoken"?/> | ||
| 1493 | + // | ||
| 1494 | + case 'documentation': | ||
| 1495 | + break; | ||
| 1496 | + | ||
| 1497 | + default: | ||
| 1498 | + // error | ||
| 1499 | + break; | ||
| 1500 | + } | ||
| 1501 | + | ||
| 1502 | + case SCHEMA_DIME: | ||
| 1503 | + // DIME is defined in: | ||
| 1504 | + // http://gotdotnet.com/team/xml_wsspecs/dime/WSDL-Extension-for-DIME.htm | ||
| 1505 | + // all DIME parts are children of wsdl:input, wsdl:output, etc. | ||
| 1506 | + // unsuported as of yet | ||
| 1507 | + switch ($qname->name) { | ||
| 1508 | + case 'message': | ||
| 1509 | + // sect 4.1 dime:message | ||
| 1510 | + // appears in binding section | ||
| 1511 | + $this->wsdl->bindings[$this->currentBinding]['dime'] = $attrs; | ||
| 1512 | + break; | ||
| 1513 | + | ||
| 1514 | + default: | ||
| 1515 | + break; | ||
| 1516 | + } | ||
| 1517 | + | ||
| 1518 | + default: | ||
| 1519 | + break; | ||
| 1520 | + } | ||
| 1521 | + break; | ||
| 1522 | + | ||
| 1523 | + case 'service': | ||
| 1524 | + $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL; | ||
| 1525 | + | ||
| 1526 | + switch ($qname->name) { | ||
| 1527 | + case 'port': | ||
| 1528 | + // sect 2.6 wsdl:port attributes: name binding | ||
| 1529 | + $this->currentPort = $attrs['name']; | ||
| 1530 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort] = $attrs; | ||
| 1531 | + // XXX hack to deal with binding namespaces | ||
| 1532 | + $qn =& new QName($attrs['binding']); | ||
| 1533 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['binding'] = $qn->name; | ||
| 1534 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['namespace'] = $qn->ns; | ||
| 1535 | + break; | ||
| 1536 | + | ||
| 1537 | + case 'address': | ||
| 1538 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['address'] = $attrs; | ||
| 1539 | + // what TYPE of port is it? SOAP or HTTP? | ||
| 1540 | + $ns = $qname->ns ? $this->wsdl->namespaces[$qname->ns] : SCHEMA_WSDL; | ||
| 1541 | + switch ($ns) { | ||
| 1542 | + case SCHEMA_WSDL_HTTP: | ||
| 1543 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='http'; | ||
| 1544 | + break; | ||
| 1545 | + | ||
| 1546 | + case SCHEMA_SOAP: | ||
| 1547 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap'; | ||
| 1548 | + break; | ||
| 1549 | + | ||
| 1550 | + default: | ||
| 1551 | + // Shouldn't happen, we'll assume SOAP. | ||
| 1552 | + $this->wsdl->services[$this->currentService]['ports'][$this->currentPort]['type']='soap'; | ||
| 1553 | + } | ||
| 1554 | + | ||
| 1555 | + break; | ||
| 1556 | + | ||
| 1557 | + case 'documentation': | ||
| 1558 | + break; | ||
| 1559 | + | ||
| 1560 | + default: | ||
| 1561 | + break; | ||
| 1562 | + } | ||
| 1563 | + } | ||
| 1564 | + | ||
| 1565 | + // Top level elements found under wsdl:definitions. | ||
| 1566 | + switch ($qname->name) { | ||
| 1567 | + case 'import': | ||
| 1568 | + // sect 2.1.1 wsdl:import attributes: namespace location | ||
| 1569 | + if ((isset($attrs['location']) || isset($attrs['schemaLocation'])) && | ||
| 1570 | + !isset($this->wsdl->imports[$attrs['namespace']])) { | ||
| 1571 | + $uri = isset($attrs['location']) ? $attrs['location'] : $attrs['schemaLocation']; | ||
| 1572 | + $location = @parse_url($uri); | ||
| 1573 | + if (!isset($location['scheme'])) { | ||
| 1574 | + $base = @parse_url($this->uri); | ||
| 1575 | + $uri = $this->mergeUrl($base, $uri); | ||
| 1576 | + } | ||
| 1577 | + | ||
| 1578 | + $this->wsdl->imports[$attrs['namespace']] = $attrs; | ||
| 1579 | + $import_parser_class = get_class($this); | ||
| 1580 | + $import_parser =& new $import_parser_class($uri, $this->wsdl, $this->docs); | ||
| 1581 | + if ($import_parser->fault) { | ||
| 1582 | + unset($this->wsdl->imports[$attrs['namespace']]); | ||
| 1583 | + return false; | ||
| 1584 | + } | ||
| 1585 | + $this->currentImport = $attrs['namespace']; | ||
| 1586 | + } | ||
| 1587 | + // Continue on to the 'types' case - lack of break; is | ||
| 1588 | + // intentional. | ||
| 1589 | + | ||
| 1590 | + case 'types': | ||
| 1591 | + // sect 2.2 wsdl:types | ||
| 1592 | + $this->status = 'types'; | ||
| 1593 | + break; | ||
| 1594 | + | ||
| 1595 | + case 'schema': | ||
| 1596 | + // We can hit this at the top level if we've been asked to | ||
| 1597 | + // import an XSD file. | ||
| 1598 | + if (!empty($attrs['targetNamespace'])) { | ||
| 1599 | + $this->schema = $this->wsdl->getNamespaceAttributeName($attrs['targetNamespace']); | ||
| 1600 | + } else { | ||
| 1601 | + $this->schema = $this->wsdl->getNamespaceAttributeName($this->wsdl->tns); | ||
| 1602 | + } | ||
| 1603 | + $this->wsdl->complexTypes[$this->schema] = array(); | ||
| 1604 | + $this->wsdl->elements[$this->schema] = array(); | ||
| 1605 | + $this->schema_stack[] = $qname->name; | ||
| 1606 | + $this->status = 'types'; | ||
| 1607 | + break; | ||
| 1608 | + | ||
| 1609 | + case 'message': | ||
| 1610 | + // sect 2.3 wsdl:message attributes: name children:wsdl:part | ||
| 1611 | + $this->status = 'message'; | ||
| 1612 | + if (isset($attrs['name'])) { | ||
| 1613 | + $this->currentMessage = $attrs['name']; | ||
| 1614 | + $this->wsdl->messages[$this->currentMessage] = array(); | ||
| 1615 | + } | ||
| 1616 | + break; | ||
| 1617 | + | ||
| 1618 | + case 'portType': | ||
| 1619 | + // sect 2.4 wsdl:portType | ||
| 1620 | + // attributes: name | ||
| 1621 | + // children: wsdl:operation | ||
| 1622 | + $this->status = 'portType'; | ||
| 1623 | + $this->currentPortType = $attrs['name']; | ||
| 1624 | + $this->wsdl->portTypes[$this->currentPortType] = array(); | ||
| 1625 | + break; | ||
| 1626 | + | ||
| 1627 | + case 'binding': | ||
| 1628 | + // sect 2.5 wsdl:binding attributes: name type | ||
| 1629 | + // children: wsdl:operation soap:binding http:binding | ||
| 1630 | + if ($qname->ns && $qname->ns != $this->tns) { | ||
| 1631 | + break; | ||
| 1632 | + } | ||
| 1633 | + $this->status = 'binding'; | ||
| 1634 | + $this->currentBinding = $attrs['name']; | ||
| 1635 | + $qn =& new QName($attrs['type']); | ||
| 1636 | + $this->wsdl->bindings[$this->currentBinding]['type'] = $qn->name; | ||
| 1637 | + $this->wsdl->bindings[$this->currentBinding]['namespace'] = $qn->ns; | ||
| 1638 | + break; | ||
| 1639 | + | ||
| 1640 | + case 'service': | ||
| 1641 | + // sect 2.7 wsdl:service attributes: name children: ports | ||
| 1642 | + $this->currentService = $attrs['name']; | ||
| 1643 | + $this->wsdl->services[$this->currentService]['ports'] = array(); | ||
| 1644 | + $this->status = 'service'; | ||
| 1645 | + break; | ||
| 1646 | + | ||
| 1647 | + case 'definitions': | ||
| 1648 | + // sec 2.1 wsdl:definitions | ||
| 1649 | + // attributes: name targetNamespace xmlns:* | ||
| 1650 | + // children: wsdl:import wsdl:types wsdl:message wsdl:portType wsdl:binding wsdl:service | ||
| 1651 | + $this->wsdl->definition = $attrs; | ||
| 1652 | + foreach ($attrs as $key => $value) { | ||
| 1653 | + if (strstr($key, 'xmlns:') !== false) { | ||
| 1654 | + $qn =& new QName($key); | ||
| 1655 | + // XXX need to refactor ns handling. | ||
| 1656 | + $this->wsdl->namespaces[$qn->name] = $value; | ||
| 1657 | + $this->wsdl->ns[$value] = $qn->name; | ||
| 1658 | + if ($key == 'targetNamespace' || | ||
| 1659 | + strcasecmp($value,SOAP_SCHEMA) == 0) { | ||
| 1660 | + $this->soapns[] = $qn->name; | ||
| 1661 | + } else { | ||
| 1662 | + if (in_array($value, $this->_XMLSchema)) { | ||
| 1663 | + $this->wsdl->xsd = $value; | ||
| 1664 | + } | ||
| 1665 | + } | ||
| 1666 | + } | ||
| 1667 | + } | ||
| 1668 | + if (isset($ns) && $ns) { | ||
| 1669 | + $namespace = 'xmlns:' . $ns; | ||
| 1670 | + if (!$this->wsdl->definition[$namespace]) { | ||
| 1671 | + return $this->_raiseSoapFault("parse error, no namespace for $namespace", $this->uri); | ||
| 1672 | + } | ||
| 1673 | + $this->tns = $ns; | ||
| 1674 | + } | ||
| 1675 | + break; | ||
| 1676 | + } | ||
| 1677 | + } | ||
| 1678 | + | ||
| 1679 | + /** | ||
| 1680 | + * end-element handler. | ||
| 1681 | + */ | ||
| 1682 | + function endElement($parser, $name) | ||
| 1683 | + { | ||
| 1684 | + $stacksize = count($this->element_stack); | ||
| 1685 | + if ($stacksize) { | ||
| 1686 | + if ($this->element_stack[$stacksize - 1] == 'definitions') { | ||
| 1687 | + $this->status = ''; | ||
| 1688 | + } | ||
| 1689 | + array_pop($this->element_stack); | ||
| 1690 | + } | ||
| 1691 | + | ||
| 1692 | + if (stristr($name, 'schema')) { | ||
| 1693 | + array_pop($this->schema_stack); | ||
| 1694 | + $this->schema = ''; | ||
| 1695 | + } | ||
| 1696 | + | ||
| 1697 | + if ($this->schema) { | ||
| 1698 | + array_pop($this->schema_stack); | ||
| 1699 | + if (count($this->schema_stack) <= 1) { | ||
| 1700 | + /* Correct the type for sequences with multiple | ||
| 1701 | + * elements. */ | ||
| 1702 | + if (isset($this->currentComplexType) && isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type']) | ||
| 1703 | + && $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] == 'Array' | ||
| 1704 | + && array_key_exists('elements', $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]) | ||
| 1705 | + && count($this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements']) > 1) { | ||
| 1706 | + $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['type'] = 'Struct'; | ||
| 1707 | + } | ||
| 1708 | + } | ||
| 1709 | + if (stristr($name, 'complexType')) { | ||
| 1710 | + $this->currentComplexType = ''; | ||
| 1711 | + if (count($this->schema_element_stack)) { | ||
| 1712 | + $this->currentElement = array_pop($this->schema_element_stack); | ||
| 1713 | + } else { | ||
| 1714 | + $this->currentElement = ''; | ||
| 1715 | + } | ||
| 1716 | + } elseif (stristr($name, 'element')) { | ||
| 1717 | + if (count($this->schema_element_stack)) { | ||
| 1718 | + $this->currentElement = array_pop($this->schema_element_stack); | ||
| 1719 | + } else { | ||
| 1720 | + $this->currentElement = ''; | ||
| 1721 | + } | ||
| 1722 | + } | ||
| 1723 | + } | ||
| 1724 | + } | ||
| 1725 | + | ||
| 1726 | + /** | ||
| 1727 | + * Element content handler. | ||
| 1728 | + */ | ||
| 1729 | + function characterData($parser, $data) | ||
| 1730 | + { | ||
| 1731 | + // Store the documentation in the WSDL file. | ||
| 1732 | + if ($this->currentTag == 'documentation') { | ||
| 1733 | + $data = trim(preg_replace('/\s+/', ' ', $data)); | ||
| 1734 | + if (!strlen($data)) { | ||
| 1735 | + return; | ||
| 1736 | + } | ||
| 1737 | + | ||
| 1738 | + switch ($this->status) { | ||
| 1739 | + case 'service': | ||
| 1740 | + $ptr =& $this->wsdl->services[$this->currentService]; | ||
| 1741 | + break; | ||
| 1742 | + | ||
| 1743 | + case 'portType': | ||
| 1744 | + $ptr =& $this->wsdl->portTypes[$this->currentPortType][$this->currentOperation]; | ||
| 1745 | + break; | ||
| 1746 | + | ||
| 1747 | + case 'binding': | ||
| 1748 | + $ptr =& $this->wsdl->bindings[$this->currentBinding]; | ||
| 1749 | + break; | ||
| 1750 | + | ||
| 1751 | + case 'message': | ||
| 1752 | + $ptr =& $this->wsdl->messages[$this->currentMessage]; | ||
| 1753 | + break; | ||
| 1754 | + | ||
| 1755 | + case 'operation': | ||
| 1756 | + break; | ||
| 1757 | + | ||
| 1758 | + case 'types': | ||
| 1759 | + if (isset($this->currentComplexType) && | ||
| 1760 | + isset($this->wsdl->complexTypes[$this->schema][$this->currentComplexType])) { | ||
| 1761 | + if ($this->currentElement) { | ||
| 1762 | + $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]['elements'][$this->currentElement]; | ||
| 1763 | + } else { | ||
| 1764 | + $ptr =& $this->wsdl->complexTypes[$this->schema][$this->currentComplexType]; | ||
| 1765 | + } | ||
| 1766 | + } | ||
| 1767 | + break; | ||
| 1768 | + } | ||
| 1769 | + | ||
| 1770 | + if (isset($ptr)) { | ||
| 1771 | + if (!isset($ptr['documentation'])) { | ||
| 1772 | + $ptr['documentation'] = ''; | ||
| 1773 | + } else { | ||
| 1774 | + $ptr['documentation'] .= ' '; | ||
| 1775 | + } | ||
| 1776 | + $ptr['documentation'] .= $data; | ||
| 1777 | + } | ||
| 1778 | + } | ||
| 1779 | + } | ||
| 1780 | + | ||
| 1781 | + /** | ||
| 1782 | + * $parsed is an array returned by parse_url(). | ||
| 1783 | + * | ||
| 1784 | + * @access private | ||
| 1785 | + */ | ||
| 1786 | + function mergeUrl($parsed, $path) | ||
| 1787 | + { | ||
| 1788 | + if (!is_array($parsed)) { | ||
| 1789 | + return false; | ||
| 1790 | + } | ||
| 1791 | + | ||
| 1792 | + $uri = ''; | ||
| 1793 | + if (!empty($parsed['scheme'])) { | ||
| 1794 | + $sep = (strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'); | ||
| 1795 | + $uri = $parsed['scheme'] . $sep; | ||
| 1796 | + } | ||
| 1797 | + | ||
| 1798 | + if (isset($parsed['pass'])) { | ||
| 1799 | + $uri .= "$parsed[user]:$parsed[pass]@"; | ||
| 1800 | + } elseif (isset($parsed['user'])) { | ||
| 1801 | + $uri .= "$parsed[user]@"; | ||
| 1802 | + } | ||
| 1803 | + | ||
| 1804 | + if (isset($parsed['host'])) { | ||
| 1805 | + $uri .= $parsed['host']; | ||
| 1806 | + } | ||
| 1807 | + if (isset($parsed['port'])) { | ||
| 1808 | + $uri .= ":$parsed[port]"; | ||
| 1809 | + } | ||
| 1810 | + if ($path[0] != '/' && isset($parsed['path'])) { | ||
| 1811 | + if ($parsed['path'][strlen($parsed['path']) - 1] != '/') { | ||
| 1812 | + $path = dirname($parsed['path']) . '/' . $path; | ||
| 1813 | + } else { | ||
| 1814 | + $path = $parsed['path'] . $path; | ||
| 1815 | + } | ||
| 1816 | + $path = $this->_normalize($path); | ||
| 1817 | + } | ||
| 1818 | + $sep = $path[0] == '/' ? '' : '/'; | ||
| 1819 | + $uri .= $sep . $path; | ||
| 1820 | + | ||
| 1821 | + return $uri; | ||
| 1822 | + } | ||
| 1823 | + | ||
| 1824 | + function _normalize($path_str) | ||
| 1825 | + { | ||
| 1826 | + $pwd = ''; | ||
| 1827 | + $strArr = preg_split('/(\/)/', $path_str, -1, PREG_SPLIT_NO_EMPTY); | ||
| 1828 | + $pwdArr = ''; | ||
| 1829 | + $j = 0; | ||
| 1830 | + for ($i = 0; $i < count($strArr); $i++) { | ||
| 1831 | + if ($strArr[$i] != ' ..') { | ||
| 1832 | + if ($strArr[$i] != ' .') { | ||
| 1833 | + $pwdArr[$j] = $strArr[$i]; | ||
| 1834 | + $j++; | ||
| 1835 | + } | ||
| 1836 | + } else { | ||
| 1837 | + array_pop($pwdArr); | ||
| 1838 | + $j--; | ||
| 1839 | + } | ||
| 1840 | + } | ||
| 1841 | + $pStr = implode('/', $pwdArr); | ||
| 1842 | + $pwd = (strlen($pStr) > 0) ? ('/' . $pStr) : '/'; | ||
| 1843 | + return $pwd; | ||
| 1844 | + } | ||
| 1845 | + | ||
| 1846 | +} | ||
| 1847 | + | ||
| 1848 | +/** | ||
| 1849 | + * Parses the types and methods used in web service objects into the internal | ||
| 1850 | + * data structures used by SOAP_WSDL. | ||
| 1851 | + * | ||
| 1852 | + * Assumes the SOAP_WSDL class is unpopulated to start with. | ||
| 1853 | + * | ||
| 1854 | + * @author Chris Coe <info@intelligentstreaming.com> | ||
| 1855 | + */ | ||
| 1856 | +class SOAP_WSDL_ObjectParser extends SOAP_Base | ||
| 1857 | +{ | ||
| 1858 | + /** | ||
| 1859 | + * Target namespace for the WSDL document will have the following | ||
| 1860 | + * prefix. | ||
| 1861 | + */ | ||
| 1862 | + var $tnsPrefix = 'tns'; | ||
| 1863 | + | ||
| 1864 | + /** | ||
| 1865 | + * Reference to the SOAP_WSDL object to populate. | ||
| 1866 | + */ | ||
| 1867 | + var $wsdl = null; | ||
| 1868 | + | ||
| 1869 | + /** Constructor | ||
| 1870 | + * | ||
| 1871 | + * @param $objects Reference to the object or array of objects to parse | ||
| 1872 | + * @param $wsdl Reference to the SOAP_WSDL object to populate | ||
| 1873 | + * @param $targetNamespace The target namespace of schema types etc. | ||
| 1874 | + * @param $service_name Name of the WSDL <service> | ||
| 1875 | + * @param $service_desc Optional description of the WSDL <service> | ||
| 1876 | + */ | ||
| 1877 | + function SOAP_WSDL_ObjectParser(&$objects, &$wsdl, $targetNamespace, $service_name, $service_desc = '') | ||
| 1878 | + { | ||
| 1879 | + parent::SOAP_Base('WSDLOBJECTPARSER'); | ||
| 1880 | + | ||
| 1881 | + $this->wsdl = &$wsdl; | ||
| 1882 | + | ||
| 1883 | + // Set up the SOAP_WSDL object | ||
| 1884 | + $this->_initialise($service_name); | ||
| 1885 | + | ||
| 1886 | + // Parse each web service object | ||
| 1887 | + $wsdl_ref = (is_array($objects)? $objects : array(&$objects)); | ||
| 1888 | + | ||
| 1889 | + foreach ($wsdl_ref as $ref_item) { | ||
| 1890 | + if (!is_object($ref_item)) | ||
| 1891 | + return $this->_raiseSoapFault('Invalid web service object passed to object parser', 'urn:' . get_class($object)); | ||
| 1892 | + | ||
| 1893 | + if ($this->_parse($ref_item, $targetNamespace, $service_name) != true) | ||
| 1894 | + break; | ||
| 1895 | + } | ||
| 1896 | + | ||
| 1897 | + // Build bindings from abstract data. | ||
| 1898 | + if ($this->fault == null) { | ||
| 1899 | + $this->_generateBindingsAndServices($targetNamespace, $service_name, $service_desc); | ||
| 1900 | + } | ||
| 1901 | + } | ||
| 1902 | + | ||
| 1903 | + /** | ||
| 1904 | + * Initialise the SOAP_WSDL tree (destructive). | ||
| 1905 | + * | ||
| 1906 | + * If the object has already been initialised, the only effect | ||
| 1907 | + * will be to change the tns namespace to the new service name. | ||
| 1908 | + * | ||
| 1909 | + * @param $service_name Name of the WSDL <service> | ||
| 1910 | + * @access private | ||
| 1911 | + */ | ||
| 1912 | + function _initialise($service_name) | ||
| 1913 | + { | ||
| 1914 | + // Set up the basic namespaces that all WSDL definitions use. | ||
| 1915 | + $this->wsdl->namespaces['wsdl'] = SCHEMA_WSDL; // WSDL language | ||
| 1916 | + $this->wsdl->namespaces['soap'] = SCHEMA_SOAP; // WSDL SOAP bindings | ||
| 1917 | + $this->wsdl->namespaces[$this->tnsPrefix] = 'urn:' . $service_name; // Target namespace | ||
| 1918 | + $this->wsdl->namespaces['xsd'] = array_search('xsd', $this->_namespaces); // XML Schema | ||
| 1919 | + $this->wsdl->namespaces['SOAP-ENC'] = array_search('SOAP-ENC', $this->_namespaces); // SOAP types | ||
| 1920 | + | ||
| 1921 | + // XXX Refactor $namespace/$ns for Shane :-) | ||
| 1922 | + unset($this->wsdl->ns['urn:' . $service_name]); | ||
| 1923 | + $this->wsdl->ns += array_flip($this->wsdl->namespaces); | ||
| 1924 | + | ||
| 1925 | + // Imports are not implemented in WSDL generation from classes. | ||
| 1926 | + // *** <wsdl:import> *** | ||
| 1927 | + } | ||
| 1928 | + | ||
| 1929 | + /** | ||
| 1930 | + * Parser - takes a single object to add to tree | ||
| 1931 | + * (non-destructive). | ||
| 1932 | + * | ||
| 1933 | + * @param $object Reference to the object to parse | ||
| 1934 | + * @param $service_name Name of the WSDL <service> | ||
| 1935 | + * @access private | ||
| 1936 | + */ | ||
| 1937 | + function _parse(&$object, $schemaNamespace, $service_name) | ||
| 1938 | + { | ||
| 1939 | + // Create namespace prefix for the schema | ||
| 1940 | + // XXX not very elegant :-( | ||
| 1941 | + | ||
| 1942 | + list($schPrefix, $foo) = $this->_getTypeNs('{' . $schemaNamespace.'}'); | ||
| 1943 | + unset($foo); | ||
| 1944 | + | ||
| 1945 | + // Parse all the types defined by the object in whatever | ||
| 1946 | + // schema language we are using (currently __typedef arrays) | ||
| 1947 | + // *** <wsdl:types> *** | ||
| 1948 | + | ||
| 1949 | + foreach ($object->__typedef as $typeName => $typeValue) { | ||
| 1950 | + // Get/create namespace definition | ||
| 1951 | + | ||
| 1952 | + list($nsPrefix, $typeName) = $this->_getTypeNs($typeName); | ||
| 1953 | + | ||
| 1954 | + // Create type definition | ||
| 1955 | + | ||
| 1956 | + $this->wsdl->complexTypes[$schPrefix][$typeName] = array('name' => $typeName); | ||
| 1957 | + $thisType =& $this->wsdl->complexTypes[$schPrefix][$typeName]; | ||
| 1958 | + | ||
| 1959 | + // According to Dmitri's documentation, __typedef comes in two | ||
| 1960 | + // flavors: | ||
| 1961 | + // Array = array(array("item" => "value")) | ||
| 1962 | + // Struct = array("item1" => "value1", "item2" => "value2", ...) | ||
| 1963 | + | ||
| 1964 | + if (is_array($typeValue)) { | ||
| 1965 | + if (is_array(current($typeValue)) && count($typeValue) == 1 | ||
| 1966 | + && count(current($typeValue)) == 1) { | ||
| 1967 | + // It's an array | ||
| 1968 | + | ||
| 1969 | + $thisType['type'] = 'Array'; | ||
| 1970 | + list($nsPrefix, $typeName) = $this->_getTypeNs(current(current($typeValue))); | ||
| 1971 | + $thisType['namespace'] = $nsPrefix; | ||
| 1972 | + $thisType['arrayType'] = $typeName . '[]'; | ||
| 1973 | + } elseif (!is_array(current($typeValue))) { | ||
| 1974 | + // It's a struct | ||
| 1975 | + | ||
| 1976 | + $thisType['type'] = 'Struct'; | ||
| 1977 | + $thisType['order'] = 'all'; | ||
| 1978 | + $thisType['namespace'] = $nsPrefix; | ||
| 1979 | + $thisType['elements'] = array(); | ||
| 1980 | + | ||
| 1981 | + foreach ($typeValue as $elementName => $elementType) { | ||
| 1982 | + list($nsPrefix, $typeName) = $this->_getTypeNs($elementType); | ||
| 1983 | + $thisType['elements'][$elementName]['name'] = $elementName; | ||
| 1984 | + $thisType['elements'][$elementName]['type'] = $typeName; | ||
| 1985 | + $thisType['elements'][$elementName]['namespace'] = $nsPrefix; | ||
| 1986 | + } | ||
| 1987 | + } else { | ||
| 1988 | + // It's erroneous | ||
| 1989 | + return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object)); | ||
| 1990 | + } | ||
| 1991 | + } else { | ||
| 1992 | + // It's erroneous | ||
| 1993 | + return $this->_raiseSoapFault("The type definition for $nsPrefix:$typeName is invalid.", 'urn:' . get_class($object)); | ||
| 1994 | + } | ||
| 1995 | + } | ||
| 1996 | + | ||
| 1997 | + // Create an empty element array with the target namespace | ||
| 1998 | + // prefix, to match the results of WSDL parsing. | ||
| 1999 | + | ||
| 2000 | + $this->wsdl->elements[$schPrefix] = array(); | ||
| 2001 | + | ||
| 2002 | + // Populate tree with message information | ||
| 2003 | + // *** <wsdl:message> *** | ||
| 2004 | + | ||
| 2005 | + foreach ($object->__dispatch_map as $operationName => $messages) { | ||
| 2006 | + foreach ($messages as $messageType => $messageParts) { | ||
| 2007 | + unset($thisMessage); | ||
| 2008 | + | ||
| 2009 | + switch ($messageType) { | ||
| 2010 | + case 'in': | ||
| 2011 | + $this->wsdl->messages[$operationName . 'Request'] = array(); | ||
| 2012 | + $thisMessage =& $this->wsdl->messages[$operationName . 'Request']; | ||
| 2013 | + break; | ||
| 2014 | + | ||
| 2015 | + case 'out': | ||
| 2016 | + $this->wsdl->messages[$operationName . 'Response'] = array(); | ||
| 2017 | + $thisMessage =& $this->wsdl->messages[$operationName . 'Response']; | ||
| 2018 | + break; | ||
| 2019 | + | ||
| 2020 | + case 'alias': | ||
| 2021 | + // Do nothing | ||
| 2022 | + break; | ||
| 2023 | + | ||
| 2024 | + default: | ||
| 2025 | + // Error condition | ||
| 2026 | + break; | ||
| 2027 | + } | ||
| 2028 | + | ||
| 2029 | + if (isset($thisMessage)) { | ||
| 2030 | + foreach ($messageParts as $partName => $partType) { | ||
| 2031 | + list ($nsPrefix, $typeName) = $this->_getTypeNs($partType); | ||
| 2032 | + | ||
| 2033 | + $thisMessage[$partName] = array( | ||
| 2034 | + 'name' => $partName, | ||
| 2035 | + 'type' => $typeName, | ||
| 2036 | + 'namespace' => $nsPrefix | ||
| 2037 | + ); | ||
| 2038 | + } | ||
| 2039 | + } | ||
| 2040 | + } | ||
| 2041 | + } | ||
| 2042 | + | ||
| 2043 | + // Populate tree with portType information | ||
| 2044 | + // XXX Current implementation only supports one portType that | ||
| 2045 | + // encompasses all of the operations available. | ||
| 2046 | + // *** <wsdl:portType> *** | ||
| 2047 | + | ||
| 2048 | + if (!isset($this->wsdl->portTypes[$service_name . 'Port'])) { | ||
| 2049 | + $this->wsdl->portTypes[$service_name . 'Port'] = array(); | ||
| 2050 | + } | ||
| 2051 | + $thisPortType =& $this->wsdl->portTypes[$service_name . 'Port']; | ||
| 2052 | + | ||
| 2053 | + foreach ($object->__dispatch_map as $operationName => $messages) { | ||
| 2054 | + $thisPortType[$operationName] = array('name' => $operationName); | ||
| 2055 | + | ||
| 2056 | + foreach ($messages as $messageType => $messageParts) { | ||
| 2057 | + switch ($messageType) { | ||
| 2058 | + case 'in': | ||
| 2059 | + $thisPortType[$operationName]['input'] = array( | ||
| 2060 | + 'message' => $operationName . 'Request', | ||
| 2061 | + 'namespace' => $this->tnsPrefix); | ||
| 2062 | + break; | ||
| 2063 | + | ||
| 2064 | + case 'out': | ||
| 2065 | + $thisPortType[$operationName]['output'] = array( | ||
| 2066 | + 'message' => $operationName . 'Response', | ||
| 2067 | + 'namespace' => $this->tnsPrefix); | ||
| 2068 | + break; | ||
| 2069 | + } | ||
| 2070 | + } | ||
| 2071 | + } | ||
| 2072 | + | ||
| 2073 | + return true; | ||
| 2074 | + } | ||
| 2075 | + | ||
| 2076 | + /** | ||
| 2077 | + * Take all the abstract WSDL data and build concrete bindings and | ||
| 2078 | + * services (destructive). | ||
| 2079 | + * | ||
| 2080 | + * XXX Current implementation discards $service_desc. | ||
| 2081 | + * | ||
| 2082 | + * @param $schemaNamespace Namespace for types etc. | ||
| 2083 | + * @param $service_name Name of the WSDL <service> | ||
| 2084 | + * @param $service_desc Optional description of the WSDL <service> | ||
| 2085 | + * @access private | ||
| 2086 | + */ | ||
| 2087 | + function _generateBindingsAndServices($schemaNamespace, $service_name, $service_desc = '') | ||
| 2088 | + { | ||
| 2089 | + // Populate tree with bindings information | ||
| 2090 | + // XXX Current implementation only supports one binding that | ||
| 2091 | + // matches the single portType and all of its operations. | ||
| 2092 | + // XXX Is this the correct use of $schemaNamespace here? | ||
| 2093 | + // *** <wsdl:binding> *** | ||
| 2094 | + | ||
| 2095 | + $this->wsdl->bindings[$service_name . 'Binding'] = array( | ||
| 2096 | + 'type' => $service_name . 'Port', | ||
| 2097 | + 'namespace' => $this->tnsPrefix, | ||
| 2098 | + 'style' => 'rpc', | ||
| 2099 | + 'transport' => SCHEMA_SOAP_HTTP, | ||
| 2100 | + 'operations' => array()); | ||
| 2101 | + $thisBinding =& $this->wsdl->bindings[$service_name . 'Binding']; | ||
| 2102 | + | ||
| 2103 | + foreach ($this->wsdl->portTypes[$service_name . 'Port'] as $operationName => $operationData) { | ||
| 2104 | + $thisBinding['operations'][$operationName] = array( | ||
| 2105 | + 'soapAction' => $schemaNamespace . '#' . $operationName, | ||
| 2106 | + 'style' => $thisBinding['style']); | ||
| 2107 | + | ||
| 2108 | + foreach (array('input', 'output') as $messageType) | ||
| 2109 | + if (isset($operationData[$messageType])) { | ||
| 2110 | + $thisBinding['operations'][$operationName][$messageType] = array( | ||
| 2111 | + 'use' => 'encoded', | ||
| 2112 | + 'namespace' => $schemaNamespace, | ||
| 2113 | + 'encodingStyle' => SOAP_SCHEMA_ENCODING); | ||
| 2114 | + } | ||
| 2115 | + } | ||
| 2116 | + | ||
| 2117 | + // Populate tree with service information | ||
| 2118 | + // XXX Current implementation supports one service which groups | ||
| 2119 | + // all of the ports together, one port per binding | ||
| 2120 | + // XXX What about https? | ||
| 2121 | + // *** <wsdl:service> *** | ||
| 2122 | + | ||
| 2123 | + $this->wsdl->services[$service_name . 'Service'] = array('ports' => array()); | ||
| 2124 | + $thisService =& $this->wsdl->services[$service_name . 'Service']['ports']; | ||
| 2125 | + | ||
| 2126 | + foreach ($this->wsdl->bindings as $bindingName => $bindingData) { | ||
| 2127 | + $thisService[$bindingData['type']] = array( | ||
| 2128 | + 'name' => $bindingData['type'], | ||
| 2129 | + 'binding' => $bindingName, | ||
| 2130 | + 'namespace' => $this->tnsPrefix, | ||
| 2131 | + 'address' => array('location' => | ||
| 2132 | + 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] . | ||
| 2133 | + (isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')), | ||
| 2134 | + 'type' => 'soap'); | ||
| 2135 | + } | ||
| 2136 | + | ||
| 2137 | + // Set service | ||
| 2138 | + $this->wsdl->set_service($service_name . 'Service'); | ||
| 2139 | + $this->wsdl->uri = $this->wsdl->namespaces[$this->tnsPrefix]; | ||
| 2140 | + | ||
| 2141 | + // Create WSDL definition | ||
| 2142 | + // *** <wsdl:definitions> *** | ||
| 2143 | + | ||
| 2144 | + $this->wsdl->definition = array( | ||
| 2145 | + 'name' => $service_name, | ||
| 2146 | + 'targetNamespace' => $this->wsdl->namespaces[$this->tnsPrefix], | ||
| 2147 | + 'xmlns' => SCHEMA_WSDL); | ||
| 2148 | + | ||
| 2149 | + foreach ($this->wsdl->namespaces as $nsPrefix => $namespace) { | ||
| 2150 | + $this->wsdl->definition['xmlns:' . $nsPrefix] = $namespace; | ||
| 2151 | + } | ||
| 2152 | + } | ||
| 2153 | + | ||
| 2154 | + /** | ||
| 2155 | + * This function is adapted from Dmitri V's implementation of | ||
| 2156 | + * DISCO/WSDL generation. It separates namespace from type name in | ||
| 2157 | + * a __typedef key and creates a new namespace entry in the WSDL | ||
| 2158 | + * structure if the namespace has not been used before. The | ||
| 2159 | + * namespace prefix and type name are returned. If no namespace is | ||
| 2160 | + * specified, xsd is assumed. | ||
| 2161 | + * | ||
| 2162 | + * We will not need this function anymore once __typedef is | ||
| 2163 | + * eliminated. | ||
| 2164 | + */ | ||
| 2165 | + function _getTypeNs($type) | ||
| 2166 | + { | ||
| 2167 | + preg_match_all("'\{(.*)\}'sm", $type, $m); | ||
| 2168 | + if (isset($m[1][0]) && $m[1][0] != '') { | ||
| 2169 | + if (!array_key_exists($m[1][0], $this->wsdl->ns)) { | ||
| 2170 | + $ns_pref = 'ns' . count($this->wsdl->namespaces); | ||
| 2171 | + $this->wsdl->ns[$m[1][0]] = $ns_pref; | ||
| 2172 | + $this->wsdl->namespaces[$ns_pref] = $m[1][0]; | ||
| 2173 | + } | ||
| 2174 | + $typens = $this->wsdl->ns[$m[1][0]]; | ||
| 2175 | + $type = ereg_replace($m[0][0], '', $type); | ||
| 2176 | + } else { | ||
| 2177 | + $typens = 'xsd'; | ||
| 2178 | + } | ||
| 2179 | + | ||
| 2180 | + return array($typens, $type); | ||
| 2181 | + } | ||
| 2182 | + | ||
| 2183 | +} |
thirdparty/pear/SOAP/example/attachment.php
0 → 100644
| 1 | +<?php | ||
| 2 | +require_once("SOAP/Client.php"); | ||
| 3 | +require_once("SOAP/test/test.utility.php"); | ||
| 4 | +require_once("SOAP/Value.php"); | ||
| 5 | + | ||
| 6 | +$filename = 'attachment.php'; | ||
| 7 | +$v = new SOAP_Attachment('test','text/plain',$filename); | ||
| 8 | +$methodValue = new SOAP_Value('testattach', 'Struct', array($v)); | ||
| 9 | + | ||
| 10 | +$client = new SOAP_Client('mailto:user@domain.com'); | ||
| 11 | +# calling with mime | ||
| 12 | +$resp = $client->call('echoMimeAttachment',array($v), | ||
| 13 | + array('attachments'=>'Mime', | ||
| 14 | + 'namespace'=>'http://soapinterop.org/', | ||
| 15 | + 'from'=>'user@domain.com', | ||
| 16 | + 'host'=>'smtp.domain.com')); | ||
| 17 | +print $client->wire."\n\n\n"; | ||
| 18 | +print_r($resp); | ||
| 19 | + | ||
| 20 | +# calling with DIME | ||
| 21 | +$resp = $client->call('echoMimeAttachment',array($v)); | ||
| 22 | +# DIME has null spaces, change them so we can see the wire | ||
| 23 | +$wire = str_replace("\0",'*',$client->wire); | ||
| 24 | +print $wire."\n\n\n"; | ||
| 25 | +print_r($resp); | ||
| 26 | +?> | ||
| 0 | \ No newline at end of file | 27 | \ No newline at end of file |
thirdparty/pear/SOAP/example/client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This file contains an example SOAP client that calls methods on the example | ||
| 4 | + * SOAP server in this same directory. | ||
| 5 | + * | ||
| 6 | + * PHP versions 4 and 5 | ||
| 7 | + * | ||
| 8 | + * LICENSE: This source file is subject to version 2.02 of the PHP license, | ||
| 9 | + * that is bundled with this package in the file LICENSE, and is available at | ||
| 10 | + * through the world-wide-web at http://www.php.net/license/2_02.txt. If you | ||
| 11 | + * did not receive a copy of the PHP license and are unable to obtain it | ||
| 12 | + * through the world-wide-web, please send a note to license@php.net so we can | ||
| 13 | + * mail you a copy immediately. | ||
| 14 | + * | ||
| 15 | + * @category Web Services | ||
| 16 | + * @package SOAP | ||
| 17 | + * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | ||
| 18 | + * @copyright 2003-2005 The PHP Group | ||
| 19 | + * @license http://www.php.net/license/2_02.txt PHP License 2.02 | ||
| 20 | + * @link http://pear.php.net/package/SOAP | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +require 'SOAP/Client.php'; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * This client runs against the example server in SOAP/example/server.php. It | ||
| 27 | + * does not use WSDL to run these requests, but that can be changed easily by | ||
| 28 | + * simply adding '?wsdl' to the end of the url. | ||
| 29 | + */ | ||
| 30 | +$soapclient = new SOAP_Client('http://localhost/SOAP/example/server.php'); | ||
| 31 | +// This namespace is the same as declared in server.php. | ||
| 32 | +$options = array('namespace' => 'urn:SOAP_Example_Server', | ||
| 33 | + 'trace' => 1); | ||
| 34 | + | ||
| 35 | +$ret = $soapclient->call('echoStringSimple', | ||
| 36 | + $params = array('inputStringSimple' => 'this is a test string'), | ||
| 37 | + $options); | ||
| 38 | +// print $soapclient->__get_wire(); | ||
| 39 | +print_r($ret); | ||
| 40 | +echo "<br>\n"; | ||
| 41 | + | ||
| 42 | +$ret = $soapclient->call('echoString', | ||
| 43 | + $params = array('inputString' => 'this is a test string'), | ||
| 44 | + $options); | ||
| 45 | +print_r($ret); | ||
| 46 | +echo "<br>\n"; | ||
| 47 | + | ||
| 48 | +$ret = $soapclient->call('divide', | ||
| 49 | + $params = array('dividend' => 22, 'divisor' => 7), | ||
| 50 | + $options); | ||
| 51 | +// print $soapclient->__get_wire(); | ||
| 52 | +if (PEAR::isError($ret)) { | ||
| 53 | + echo 'Error: ' . $ret->getMessage() . "<br>\n"; | ||
| 54 | +} else { | ||
| 55 | + echo 'Quotient is ' . $ret . "<br>\n"; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +$ret = $soapclient->call('divide', | ||
| 59 | + $params = array('dividend' => 22, 'divisor' => 0), | ||
| 60 | + $options); | ||
| 61 | +if (PEAR::isError($ret)) { | ||
| 62 | + echo 'Error: ' . $ret->getMessage() . "<br>\n"; | ||
| 63 | +} else { | ||
| 64 | + echo 'Quotient is ' . $ret . "<br>\n"; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | + | ||
| 68 | +// SOAPStruct is defined in the following file. | ||
| 69 | +require_once 'example_types.php'; | ||
| 70 | + | ||
| 71 | +$struct = new SOAPStruct('test string', 123, 123.123); | ||
| 72 | + | ||
| 73 | +/* Send an object, get an object back. Tell the client to translate to classes | ||
| 74 | + * we provide if possible. */ | ||
| 75 | +$soapclient->_auto_translation = true; | ||
| 76 | +/* You can explicitly set the translation for a specific | ||
| 77 | + * class. auto_translation works for all cases, but opens ANY class in the | ||
| 78 | + * script to be used as a data type, and may not be desireable. Both can be | ||
| 79 | + * used on client or server. */ | ||
| 80 | +$soapclient->__set_type_translation('{http://soapinterop.org/xsd}SOAPStruct', | ||
| 81 | + 'SOAPStruct'); | ||
| 82 | +$ret = $soapclient->call('echoStruct', | ||
| 83 | + $p = array('inputStruct' => $struct->__to_soap()), | ||
| 84 | + $options); | ||
| 85 | +// print $soapclient->__get_wire(); | ||
| 86 | +print_r($ret); | ||
| 87 | + | ||
| 88 | +/** | ||
| 89 | + * PHP doesn't support multiple OUT parameters in function calls, so we must | ||
| 90 | + * do a little work to make it happen here. This requires knowledge on the | ||
| 91 | + * developers part to figure out how they want to deal with it. | ||
| 92 | + */ | ||
| 93 | +$ret = $soapclient->call('echoStructAsSimpleTypes', | ||
| 94 | + $p = array('inputStruct' => $struct->__to_soap()), | ||
| 95 | + $options); | ||
| 96 | +if (PEAR::isError($ret)) { | ||
| 97 | + echo 'Error: ' . $ret->getMessage() . "<br>\n"; | ||
| 98 | +} else { | ||
| 99 | + list($string, $int, $float) = array_values($ret); | ||
| 100 | + echo "varString: $string<br>\nvarInt: $int<br>\nvarFloat: $float<br>\n"; | ||
| 101 | +} |
thirdparty/pear/SOAP/example/com_client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: com_client.php,v 1.3 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | +// SOAPStruct is defined in the following file | ||
| 22 | +require_once 'example_types.php'; | ||
| 23 | + | ||
| 24 | +/* just a simple example of using MS SOAP on win32 as a client | ||
| 25 | + to the php server. */ | ||
| 26 | + | ||
| 27 | +//load COM SOAP client object | ||
| 28 | +$soapclient = new COM("MSSOAP.SoapClient30"); | ||
| 29 | + | ||
| 30 | +//connect to web service | ||
| 31 | +$soapclient->mssoapinit("http://localhost/SOAP/example/server.php?wsdl"); | ||
| 32 | + | ||
| 33 | +//obtain result from web service method | ||
| 34 | +$ret = $soapclient->echoString("This is a test!"); | ||
| 35 | +print("$ret\n"); | ||
| 36 | + | ||
| 37 | +$ret = $soapclient->echoStringSimple("This is another test!"); | ||
| 38 | +print("$ret\n"); | ||
| 39 | + | ||
| 40 | +# the following causes an exception in the COM extension | ||
| 41 | + | ||
| 42 | +#$ret = $soapclient->divide(22,7); | ||
| 43 | +#print $soapclient->faultcode; | ||
| 44 | +#print $soapclient->faultstring; | ||
| 45 | +#print("22/7=$ret\n"); | ||
| 46 | +#print_r($ret); | ||
| 47 | +#$ret = $soapclient->divide(22,0); | ||
| 48 | +#print("22/0=$ret\n"); | ||
| 49 | + | ||
| 50 | +#$struct = new SOAPStruct('test string',123,123.123); | ||
| 51 | +#$ret = $soapclient->echoStruct($struct); | ||
| 52 | +#print_r($ret); | ||
| 53 | + | ||
| 54 | +#$ret = $soapclient->echoStructAsSimpleTypes($struct); | ||
| 55 | +#print_r($ret); | ||
| 56 | + | ||
| 57 | +?> | ||
| 0 | \ No newline at end of file | 58 | \ No newline at end of file |
thirdparty/pear/SOAP/example/disco_server.php
0 → 100644
| 1 | +<? | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Author: Dmitri Vinogradov <dimitri@vinogradov.de> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: disco_server.php,v 1.5 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | + | ||
| 21 | +/* | ||
| 22 | + This example shows how to mark up a server object so that | ||
| 23 | + wsdl files may be dynamicaly generated by the soap | ||
| 24 | + server. This also provides access to a generated DISCO document. | ||
| 25 | + The fact that this example has an MP3 class is in no way | ||
| 26 | + related to DISCO. ;) | ||
| 27 | + | ||
| 28 | + DISCO: http://msdn.microsoft.com/msdnmag/issues/02/02/xml/default.aspx | ||
| 29 | + | ||
| 30 | + A url accessing this server would look like: | ||
| 31 | + | ||
| 32 | + http://localhost/disco_server.php?wsdl (generate WSDL file) | ||
| 33 | + http://localhost/disco_server.php (GET request generates DISCO) | ||
| 34 | + http://localhost/disco_server.php (POST for normal soap requests) | ||
| 35 | +*/ | ||
| 36 | + | ||
| 37 | +error_reporting(E_ALL); | ||
| 38 | +require_once 'SOAP/Server.php'; | ||
| 39 | + | ||
| 40 | +class MP3DB_Class { | ||
| 41 | + var $__dispatch_map = array(); | ||
| 42 | + var $__typedef = array(); | ||
| 43 | + | ||
| 44 | + function MP3DB_Class () { | ||
| 45 | + /** | ||
| 46 | + * the only way to describe all methods in WSDL (messages, | ||
| 47 | + * PortType-operations and bindings) is to use __dispatch_map | ||
| 48 | + * to describe every method (even methods using simple data | ||
| 49 | + * types in 'in' and 'out' parameters...) | ||
| 50 | + */ | ||
| 51 | + | ||
| 52 | + $this->__dispatch_map['SayHallo'] = | ||
| 53 | + array( | ||
| 54 | + 'in' => array('input' => 'string'), | ||
| 55 | + 'out' => array('return' => 'string') | ||
| 56 | + ); | ||
| 57 | + | ||
| 58 | + $this->__dispatch_map['SayThisNTimes'] = | ||
| 59 | + array( | ||
| 60 | + 'in' => array('SayThis'=>'string','NTimes' => 'int'), | ||
| 61 | + 'out' => array('return' => '{urn:MP3DB}ArrayOfStrings') | ||
| 62 | + ); | ||
| 63 | + | ||
| 64 | + $this->__dispatch_map['GetMP3Tracks'] = | ||
| 65 | + array( | ||
| 66 | + 'in' => array('query' => 'string'), | ||
| 67 | + 'out' => array('return' => '{urn:MP3DB}GetMP3TracksResult') | ||
| 68 | + ); | ||
| 69 | + | ||
| 70 | + $this->__dispatch_map['AddMP3Track'] = | ||
| 71 | + array( | ||
| 72 | + 'in' => array('MP3Track' => '{urn:MP3DB}MP3Track'), | ||
| 73 | + 'out' => array('return' => '{urn:MP3DB}AddMP3TrackResult') | ||
| 74 | + ); | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * I use __typedef to describe userdefined Types in WSDL. | ||
| 78 | + * Structs and one-dimensional arrays are supported: | ||
| 79 | + * Struct example: $this->__typedef['TypeName'] = array('VarName' => 'xsdType', ... ); | ||
| 80 | + * or $this->__typedef['TypeName'] = array('VarName' => '{namespace}SomeOtherType'); | ||
| 81 | + * Array example: $this->__typedef['TypeName'] = array(array('item' => 'xsdType')); | ||
| 82 | + * or $this->__typedef['TypeName'] = array(array('item' => '{namespace}SomeOtherType')); | ||
| 83 | + */ | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * Struct 'MP3Track' | ||
| 87 | + */ | ||
| 88 | + $this->__typedef['MP3Track'] = | ||
| 89 | + array( | ||
| 90 | + 'Title' => 'string', | ||
| 91 | + 'Artist' => 'string', | ||
| 92 | + 'Album' => 'string', | ||
| 93 | + 'Year' => 'int', | ||
| 94 | + 'Genre' => 'int', | ||
| 95 | + 'Comment' => 'string', | ||
| 96 | + 'Composer' => 'string', | ||
| 97 | + 'Orig_Artist' => 'string', | ||
| 98 | + 'URL' => 'string', | ||
| 99 | + 'Encoded_by' => 'string' | ||
| 100 | + ); | ||
| 101 | + | ||
| 102 | + | ||
| 103 | + | ||
| 104 | + /** | ||
| 105 | + * MP3TracksArray - array of 'MP3Track' structs | ||
| 106 | + */ | ||
| 107 | + $this->__typedef['MP3TracksArray'] = | ||
| 108 | + array( | ||
| 109 | + array( | ||
| 110 | + 'item' => '{urn:MP3DB}MP3Track' | ||
| 111 | + ) | ||
| 112 | + ); | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * Struct 'MethodDebug' | ||
| 116 | + */ | ||
| 117 | + $this->__typedef['MethodDebug'] = | ||
| 118 | + array( | ||
| 119 | + 'rc' => 'boolean', | ||
| 120 | + 'ErrNo' => 'int', | ||
| 121 | + 'Error' => 'string' | ||
| 122 | + ); | ||
| 123 | + | ||
| 124 | + /** | ||
| 125 | + * return Struct of method GetMP3Tracks | ||
| 126 | + */ | ||
| 127 | + $this->__typedef['GetMP3TracksResult'] = | ||
| 128 | + array( | ||
| 129 | + 'MethodDebug' => '{urn:MP3DB}MethodDebug', | ||
| 130 | + 'MP3Tracks' => '{urn:MP3DB}MP3TracksArray' | ||
| 131 | + ); | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * return Struct of method AddMP3Track | ||
| 135 | + */ | ||
| 136 | + $this->__typedef['AddMP3TrackResult'] = | ||
| 137 | + array( | ||
| 138 | + 'MethodDebug' => '{urn:MP3DB}MethodDebug' | ||
| 139 | + ); | ||
| 140 | + | ||
| 141 | + /** | ||
| 142 | + * Array of strings | ||
| 143 | + */ | ||
| 144 | + $this->__typedef['ArrayOfStrings'] = | ||
| 145 | + array( | ||
| 146 | + array('item'=>'string') | ||
| 147 | + ); | ||
| 148 | + | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + | ||
| 152 | + function SayHallo($name) { | ||
| 153 | + return "Hallo, " . $name; | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + | ||
| 157 | + function SayThisNTimes($SayThis,$NTimes) { | ||
| 158 | + for ($i = 0; $i < $NTimes; $i++) { | ||
| 159 | + $return[$i] = $SayThis . " $i"; | ||
| 160 | + } | ||
| 161 | + return new SOAP_Value('return','{urn:MP3DB}ArrayOfStrings',$return); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + | ||
| 165 | + function GetMP3Tracks($query = "") { | ||
| 166 | + for($i = 0; $i < 5; $i++) { | ||
| 167 | + $this->MP3Tracks[$i] = new SOAP_Value( | ||
| 168 | + 'item', | ||
| 169 | + '{urn:MP3DB}MP3Track', | ||
| 170 | + array( | ||
| 171 | + "Title" => new SOAP_Value("Title","string","some track $i"), | ||
| 172 | + "Artist" => new SOAP_Value("Artist","string","some artist $i"), | ||
| 173 | + "Album" => new SOAP_Value("Album","string","some album $i"), | ||
| 174 | + "Year" => new SOAP_Value("Year","int",(integer)1999), | ||
| 175 | + "Genre" => new SOAP_Value("Genre","int",(integer)100), | ||
| 176 | + "Comment" => new SOAP_Value("Comment","string","blabla $i"), | ||
| 177 | + "Composer" => new SOAP_Value("Composer","string",""), | ||
| 178 | + "Orig_Artist" => new SOAP_Value("Orig_Artist","string",""), | ||
| 179 | + "URL" => new SOAP_Value("URL","string",""), | ||
| 180 | + "Encoded_by" => new SOAP_Value("Encoded_by","string","") | ||
| 181 | + ) | ||
| 182 | + ); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + $MethodDebug["rc"] = new SOAP_Value("rc","boolean",true); | ||
| 186 | + $MethodDebug["ErrNo"] = new SOAP_Value("ErrNo","int",(integer)0); | ||
| 187 | + $MethodDebug["Error"] = new SOAP_Value("Error","string",""); | ||
| 188 | + | ||
| 189 | + return new SOAP_Value('return','{urn:MP3DB}GetMP3TracksResult',array( | ||
| 190 | + "MethodDebug" => new SOAP_Value('MethodDebug','{urn:MP3DB}MethodDebug',$MethodDebug), | ||
| 191 | + "MP3Tracks" => new SOAP_Value('MP3Tracks','{urn:MP3DB}MP3TracksArray',$this->MP3Tracks) | ||
| 192 | + ) | ||
| 193 | + ); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + | ||
| 197 | + function AddMP3Track($MP3Track) { | ||
| 198 | + # well, lets imagine here some code for adding given mp3track to db or whatever... | ||
| 199 | + $MethodDebug["rc"] = new SOAP_Value("rc","boolean",true); | ||
| 200 | + $MethodDebug["ErrNo"] = new SOAP_Value("ErrNo","int",(integer)0); | ||
| 201 | + $MethodDebug["Error"] = new SOAP_Value("Error","string",""); | ||
| 202 | + | ||
| 203 | + return new SOAP_Value('return','{urn:MP3DB}AddMP3TrackResult',array( | ||
| 204 | + "MethodDebug" => new SOAP_Value('MethodDebug','{urn:MP3DB}MethodDebug',$MethodDebug) | ||
| 205 | + ) | ||
| 206 | + ); | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + | ||
| 210 | + function __dispatch($methodname) { | ||
| 211 | + if (isset($this->__dispatch_map[$methodname])) | ||
| 212 | + return $this->__dispatch_map[$methodname]; | ||
| 213 | + return NULL; | ||
| 214 | + } | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +$server = new SOAP_Server; | ||
| 218 | +$server->_auto_translation = true; | ||
| 219 | +$MP3DB_Class = new MP3DB_Class(); | ||
| 220 | +$server->addObjectMap($MP3DB_Class,'urn:MP3DB'); | ||
| 221 | + | ||
| 222 | + | ||
| 223 | +if (isset($_SERVER['REQUEST_METHOD']) && | ||
| 224 | + $_SERVER['REQUEST_METHOD']=='POST') { | ||
| 225 | + $server->service($HTTP_RAW_POST_DATA); | ||
| 226 | +} else { | ||
| 227 | + require_once 'SOAP/Disco.php'; | ||
| 228 | + $disco = new SOAP_DISCO_Server($server,"MP3DB"); | ||
| 229 | + header("Content-type: text/xml"); | ||
| 230 | + if (isset($_SERVER['QUERY_STRING']) && | ||
| 231 | + strcasecmp($_SERVER['QUERY_STRING'],'wsdl')==0) { | ||
| 232 | + echo $disco->getWSDL(); | ||
| 233 | + } else { | ||
| 234 | + echo $disco->getDISCO(); | ||
| 235 | + } | ||
| 236 | + exit; | ||
| 237 | +} | ||
| 238 | +?> | ||
| 0 | \ No newline at end of file | 239 | \ No newline at end of file |
thirdparty/pear/SOAP/example/email_client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: email_client.php,v 1.4 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +/* | ||
| 23 | +This reads a message from stdin, and calls the soap server defined | ||
| 24 | + | ||
| 25 | +You can use this from qmail by creating a .qmail-soaptest file with: | ||
| 26 | + | /usr/bin/php /path/to/email_server.php | ||
| 27 | +*/ | ||
| 28 | + | ||
| 29 | +# include the email server class | ||
| 30 | +require_once 'SOAP/Server/Email.php'; | ||
| 31 | + | ||
| 32 | +$server = new SOAP_Server_Email; | ||
| 33 | + | ||
| 34 | +# read stdin | ||
| 35 | +$fin = fopen('php://stdin','rb'); | ||
| 36 | +if (!$fin) exit(0); | ||
| 37 | + | ||
| 38 | +$email = ''; | ||
| 39 | +while (!feof($fin) && $data = fread($fin, 8096)) { | ||
| 40 | + $email .= $data; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +fclose($fin); | ||
| 44 | + | ||
| 45 | + | ||
| 46 | +$response = $server->client($email); | ||
| 47 | + | ||
| 48 | +print_r($response); | ||
| 49 | + | ||
| 50 | +?> | ||
| 0 | \ No newline at end of file | 51 | \ No newline at end of file |
thirdparty/pear/SOAP/example/email_gateway.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: email_gateway.php,v 1.5 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +/* | ||
| 23 | +This reads a message from stdin, and passes the request to | ||
| 24 | +a soap server residing on a web server, sends the response | ||
| 25 | +out as an email | ||
| 26 | + | ||
| 27 | +You can use this from qmail by creating a .qmail-soapgateway file with: | ||
| 28 | + | /usr/bin/php /path/to/email_server.php | ||
| 29 | +*/ | ||
| 30 | + | ||
| 31 | +# include the email server class | ||
| 32 | +require_once 'SOAP/Server/Email_Gateway.php'; | ||
| 33 | + | ||
| 34 | +# read stdin | ||
| 35 | +$fin = fopen('php://stdin','rb'); | ||
| 36 | +if (!$fin) exit(0); | ||
| 37 | + | ||
| 38 | +$email = ''; | ||
| 39 | +while (!feof($fin) && $data = fread($fin, 8096)) { | ||
| 40 | + $email .= $data; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +fclose($fin); | ||
| 44 | + | ||
| 45 | +# doit! | ||
| 46 | +$server = new SOAP_Server_Email_Gateway(); | ||
| 47 | +$server->service($data, 'http://localhost/soap/example/server.php'); | ||
| 48 | +?> | ||
| 0 | \ No newline at end of file | 49 | \ No newline at end of file |
thirdparty/pear/SOAP/example/email_pop_gateway.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: email_pop_gateway.php,v 1.6 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +/* include the Email server class, which knows how to | ||
| 23 | + parse a standard email as a soap message */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Server/Email_Gateway.php'; | ||
| 26 | + | ||
| 27 | +/* include a class to access POP3 */ | ||
| 28 | + | ||
| 29 | +require_once 'Net/POP3.php'; | ||
| 30 | + | ||
| 31 | +/* create the SOAP Server object */ | ||
| 32 | + | ||
| 33 | +$server = new SOAP_Server_Email_Gateway('http://localhost/soap_interop/server_round2.php'); | ||
| 34 | + | ||
| 35 | +/* tell server to translate to classes we provide if possible */ | ||
| 36 | +$server->_auto_translation = true; | ||
| 37 | + | ||
| 38 | +require_once 'example_server.php'; | ||
| 39 | + | ||
| 40 | +$soapclass = new SOAP_Example_Server(); | ||
| 41 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +/* Connect to a POP3 server and read the messages */ | ||
| 45 | + | ||
| 46 | +$pop3 =& new Net_POP3(); | ||
| 47 | +if ($pop3->connect('localhost', 110)) { | ||
| 48 | + if ($pop3->login('username', 'password')) { | ||
| 49 | + $listing = $pop3->getListing(); | ||
| 50 | + | ||
| 51 | + /* now loop through each message, and call the | ||
| 52 | + SOAP server with that message */ | ||
| 53 | + | ||
| 54 | + foreach ($listing as $msg) { | ||
| 55 | + | ||
| 56 | + $email = $pop3->getMsg($msg['msg_id']); | ||
| 57 | + | ||
| 58 | + /* this is where we actually handle the SOAP | ||
| 59 | + response. The SOAP::Server::Email class we | ||
| 60 | + are using will send the SOAP response to | ||
| 61 | + the sender via email. */ | ||
| 62 | + | ||
| 63 | + if ($email) $server->service($email); | ||
| 64 | + | ||
| 65 | + #$pop3->deleteMsg($msg['msg_id']); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + $pop3->disconnect(); | ||
| 69 | +} | ||
| 70 | +?> |
thirdparty/pear/SOAP/example/email_pop_server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: email_pop_server.php,v 1.6 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +/* include the Email server class, which knows how to | ||
| 23 | + parse a standard email as a soap message */ | ||
| 24 | + | ||
| 25 | +require_once 'SOAP/Server/Email.php'; | ||
| 26 | + | ||
| 27 | +/* include a class to access POP3 */ | ||
| 28 | + | ||
| 29 | +require_once 'Net/POP3.php'; | ||
| 30 | + | ||
| 31 | +/* create the SOAP Server object */ | ||
| 32 | + | ||
| 33 | +$server = new SOAP_Server_Email; | ||
| 34 | + | ||
| 35 | +/* tell server to translate to classes we provide if possible */ | ||
| 36 | +$server->_auto_translation = true; | ||
| 37 | + | ||
| 38 | +require_once 'example_server.php'; | ||
| 39 | + | ||
| 40 | +$soapclass = new SOAP_Example_Server(); | ||
| 41 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +/* Connect to a POP3 server and read the messages */ | ||
| 45 | + | ||
| 46 | +$pop3 =& new Net_POP3(); | ||
| 47 | +if ($pop3->connect('localhost', 110)) { | ||
| 48 | + if ($pop3->login('username', 'password')) { | ||
| 49 | + $listing = $pop3->getListing(); | ||
| 50 | + | ||
| 51 | + /* now loop through each message, and call the | ||
| 52 | + SOAP server with that message */ | ||
| 53 | + | ||
| 54 | + foreach ($listing as $msg) { | ||
| 55 | + | ||
| 56 | + $email = $pop3->getMsg($msg['msg_id']); | ||
| 57 | + | ||
| 58 | + /* this is where we actually handle the SOAP | ||
| 59 | + response. The SOAP::Server::Email class we | ||
| 60 | + are using will send the SOAP response to | ||
| 61 | + the sender via email. */ | ||
| 62 | + | ||
| 63 | + if ($email) { | ||
| 64 | + $server->client($email); | ||
| 65 | + | ||
| 66 | + $pop3->deleteMsg($msg['msg_id']); | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + $pop3->disconnect(); | ||
| 71 | +} | ||
| 72 | +?> |
thirdparty/pear/SOAP/example/email_server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: email_server.php,v 1.5 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +/* | ||
| 23 | +This reads a message from stdin, and calls the soap server defined | ||
| 24 | + | ||
| 25 | +You can use this from qmail by creating a .qmail-soaptest file with: | ||
| 26 | + | /usr/bin/php /path/to/email_server.php | ||
| 27 | +*/ | ||
| 28 | + | ||
| 29 | +# include the email server class | ||
| 30 | +require_once 'SOAP/Server/Email.php'; | ||
| 31 | + | ||
| 32 | +$server = new SOAP_Server_Email; | ||
| 33 | + | ||
| 34 | +/* tell server to translate to classes we provide if possible */ | ||
| 35 | +$server->_auto_translation = true; | ||
| 36 | + | ||
| 37 | +require_once 'example_server.php'; | ||
| 38 | + | ||
| 39 | +$soapclass = new SOAP_Example_Server(); | ||
| 40 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 41 | + | ||
| 42 | +# read stdin | ||
| 43 | +$fin = fopen('php://stdin','rb'); | ||
| 44 | +if (!$fin) exit(0); | ||
| 45 | + | ||
| 46 | +$email = ''; | ||
| 47 | +while (!feof($fin) && $data = fread($fin, 8096)) { | ||
| 48 | + $email .= $data; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +fclose($fin); | ||
| 52 | + | ||
| 53 | +# doit! | ||
| 54 | +$server->service($email); | ||
| 55 | + | ||
| 56 | +?> | ||
| 0 | \ No newline at end of file | 57 | \ No newline at end of file |
thirdparty/pear/SOAP/example/example_server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: example_server.php,v 1.5 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +// first, include the SOAP/Server class | ||
| 23 | +require_once 'SOAP/Value.php'; | ||
| 24 | +require_once 'SOAP/Fault.php'; | ||
| 25 | + | ||
| 26 | +// SOAPStruct is defined in the following file | ||
| 27 | +require_once 'example_types.php'; | ||
| 28 | + | ||
| 29 | +// create a class for your soap functions | ||
| 30 | +class SOAP_Example_Server { | ||
| 31 | + /** | ||
| 32 | + * The dispactch map does not need to be used, but aids | ||
| 33 | + * the server class in knowing what parameters are used | ||
| 34 | + * with the functions. This is the ONLY way to have | ||
| 35 | + * multiple OUT parameters. If you use a dispatch map, you | ||
| 36 | + * MUST add ALL functions you wish to allow be called. If | ||
| 37 | + * you do not use a dispatch map, then any public function | ||
| 38 | + * can be called from soap (in php4, we consider this to be | ||
| 39 | + * any function in the class unless it starts with underscore, | ||
| 40 | + * php5 support is not complete yet in this regard). | ||
| 41 | + * if you do not define in/out parameters, the function can be | ||
| 42 | + * called with parameters, but no validation on parameters will | ||
| 43 | + * occure. | ||
| 44 | + */ | ||
| 45 | + var $__dispatch_map = array(); | ||
| 46 | + | ||
| 47 | + function SOAP_Example_Server() { | ||
| 48 | + /** | ||
| 49 | + * when generating wsdl for a server, you have to define | ||
| 50 | + * any special complex types that you use (ie classes). | ||
| 51 | + * using a namespace id before the type will create an | ||
| 52 | + * xml schema with the targetNamespace for the type | ||
| 53 | + * multiple types with the same namespace will appear | ||
| 54 | + * in the same schema section. types with different | ||
| 55 | + * namespaces will be in seperate schema sections. | ||
| 56 | + * the following SOAPStruct typedef cooresponds to the | ||
| 57 | + * SOAPStruct class above. | ||
| 58 | + */ | ||
| 59 | + $this->__typedef['{http://soapinterop.org/xsd}SOAPStruct'] = | ||
| 60 | + array( | ||
| 61 | + 'varString' => 'string', | ||
| 62 | + 'varInt' => 'int', | ||
| 63 | + 'varFloat' => 'float' | ||
| 64 | + ); | ||
| 65 | + | ||
| 66 | + // an aliased function with multiple out parameters | ||
| 67 | + $this->__dispatch_map['echoStructAsSimpleTypes'] = | ||
| 68 | + array('in' => array('inputStruct' => '{http://soapinterop.org/xsd}SOAPStruct'), | ||
| 69 | + 'out' => array('outputString' => 'string', 'outputInteger' => 'int', 'outputFloat' => 'float'), | ||
| 70 | + 'alias' => 'myEchoStructAsSimpleTypes' | ||
| 71 | + ); | ||
| 72 | + $this->__dispatch_map['echoStringSimple'] = | ||
| 73 | + array('in' => array('inputStringSimple' => 'string'), | ||
| 74 | + 'out' => array('outputStringSimple' => 'string'), | ||
| 75 | + ); | ||
| 76 | + $this->__dispatch_map['echoString'] = | ||
| 77 | + array('in' => array('inputString' => 'string'), | ||
| 78 | + 'out' => array('outputString' => 'string'), | ||
| 79 | + ); | ||
| 80 | + $this->__dispatch_map['divide'] = | ||
| 81 | + array('in' => array('dividend' => 'int', 'divisor' => 'int'), | ||
| 82 | + 'out' => array('outputFloat' => 'float'), | ||
| 83 | + ); | ||
| 84 | + $this->__dispatch_map['echoStruct'] = | ||
| 85 | + array('in' => array('inputStruct' => '{http://soapinterop.org/xsd}SOAPStruct'), | ||
| 86 | + 'out' => array('outputStruct' => '{http://soapinterop.org/xsd}SOAPStruct'), | ||
| 87 | + ); | ||
| 88 | + | ||
| 89 | + $this->__dispatch_map['echoMimeAttachment'] = array(); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /* this private function is called on by SOAP_Server to determine any | ||
| 93 | + special dispatch information that might be necessary. This, for example, | ||
| 94 | + can be used to set up a dispatch map for functions that return multiple | ||
| 95 | + OUT parameters */ | ||
| 96 | + function __dispatch($methodname) { | ||
| 97 | + if (isset($this->__dispatch_map[$methodname])) | ||
| 98 | + return $this->__dispatch_map[$methodname]; | ||
| 99 | + return NULL; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + // a simple echoString function | ||
| 103 | + function echoStringSimple($inputString) | ||
| 104 | + { | ||
| 105 | + return $inputString; | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + // an explicit echostring function | ||
| 109 | + function echoString($inputString) | ||
| 110 | + { | ||
| 111 | + return new SOAP_Value('outputString','string',$inputString); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + function divide($dividend, $divisor) | ||
| 115 | + { | ||
| 116 | + // the soap server would normally catch errors like this | ||
| 117 | + // and return a fault, but this is how you do it yourself. | ||
| 118 | + if ($divisor == 0) | ||
| 119 | + return new SOAP_Fault('You cannot divide by zero', 'Client'); | ||
| 120 | + else | ||
| 121 | + return $dividend / $divisor; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + function echoStruct($inputStruct) | ||
| 125 | + { | ||
| 126 | + return $inputStruct->__to_soap('outputStruct'); | ||
| 127 | + #return new SOAP_Value('outputStruct','{http://soapinterop.org/xsd}SOAPStruct',$inputStruct); | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + /** | ||
| 131 | + * echoStructAsSimpleTypes | ||
| 132 | + * takes a SOAPStruct as input, and returns each of its elements | ||
| 133 | + * as OUT parameters | ||
| 134 | + * | ||
| 135 | + * this function is also aliased so you have to call it with | ||
| 136 | + * echoStructAsSimpleTypes | ||
| 137 | + * | ||
| 138 | + * SOAPStruct is defined as: | ||
| 139 | + * | ||
| 140 | + * struct SOAPStruct: | ||
| 141 | + * string varString | ||
| 142 | + * integer varInt | ||
| 143 | + * float varFloat | ||
| 144 | + * | ||
| 145 | + */ | ||
| 146 | + function myEchoStructAsSimpleTypes($struct) | ||
| 147 | + { | ||
| 148 | + # convert a SOAPStruct to an array | ||
| 149 | + return array( | ||
| 150 | + new SOAP_Value('outputString','string',$struct->varString), | ||
| 151 | + new SOAP_Value('outputInteger','int',$struct->varInt), | ||
| 152 | + new SOAP_Value('outputFloat','float',$struct->varFloat) | ||
| 153 | + ); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + function echoMimeAttachment($stuff) | ||
| 157 | + { | ||
| 158 | + return new SOAP_Attachment('return','application/octet-stream',NULL,$stuff); | ||
| 159 | + } | ||
| 160 | +} | ||
| 161 | + | ||
| 162 | +?> | ||
| 0 | \ No newline at end of file | 163 | \ No newline at end of file |
thirdparty/pear/SOAP/example/example_types.php
0 → 100644
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * This is a data type that is used in SOAP Interop testing, but is here as an | ||
| 4 | + * example of using complex types. When the class is deserialized from a SOAP | ||
| 5 | + * message, it's constructor IS NOT CALLED! So your type classes need to | ||
| 6 | + * behave in a way that will work with that. | ||
| 7 | + * | ||
| 8 | + * Some types may need more explicit serialization for SOAP. The __to_soap | ||
| 9 | + * function allows you to be very explicit in building the SOAP_Value | ||
| 10 | + * structures. The soap library does not call this directly, you would call | ||
| 11 | + * it from your soap server class, echoStruct in the server class is an | ||
| 12 | + * example of doing this. | ||
| 13 | + */ | ||
| 14 | +class SOAPStruct { | ||
| 15 | + | ||
| 16 | + var $varString; | ||
| 17 | + var $varInt; | ||
| 18 | + var $varFloat; | ||
| 19 | + | ||
| 20 | + function SOAPStruct($s = null, $i = null, $f = null) | ||
| 21 | + { | ||
| 22 | + $this->varString = $s; | ||
| 23 | + $this->varInt = $i; | ||
| 24 | + $this->varFloat = $f; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + function &__to_soap($name = 'inputStruct', $header = false, | ||
| 28 | + $mustUnderstand = 0, | ||
| 29 | + $actor = 'http://schemas.xmlsoap.org/soap/actor/next') | ||
| 30 | + { | ||
| 31 | + $inner[] =& new SOAP_Value('varString', 'string', $this->varString); | ||
| 32 | + $inner[] =& new SOAP_Value('varInt', 'int', $this->varInt); | ||
| 33 | + $inner[] =& new SOAP_Value('varFloat', 'float', $this->varFloat); | ||
| 34 | + | ||
| 35 | + if ($header) { | ||
| 36 | + $value =& new SOAP_Header($name,'{http://soapinterop.org/xsd}SOAPStruct',$inner,$mustUnderstand,$actor); | ||
| 37 | + } else { | ||
| 38 | + $value =& new SOAP_Value($name,'{http://soapinterop.org/xsd}SOAPStruct',$inner); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + return $value; | ||
| 42 | + } | ||
| 43 | +} |
thirdparty/pear/SOAP/example/server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: server.php,v 1.10 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +// first, include the SOAP/Server class | ||
| 23 | +require_once 'SOAP/Server.php'; | ||
| 24 | + | ||
| 25 | +$server = new SOAP_Server; | ||
| 26 | +/* tell server to translate to classes we provide if possible */ | ||
| 27 | +$server->_auto_translation = true; | ||
| 28 | + | ||
| 29 | +require_once 'example_server.php'; | ||
| 30 | + | ||
| 31 | +$soapclass = new SOAP_Example_Server(); | ||
| 32 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 33 | + | ||
| 34 | +if (isset($_SERVER['REQUEST_METHOD']) && | ||
| 35 | + $_SERVER['REQUEST_METHOD']=='POST') { | ||
| 36 | + $server->service($HTTP_RAW_POST_DATA); | ||
| 37 | +} else { | ||
| 38 | + require_once 'SOAP/Disco.php'; | ||
| 39 | + $disco = new SOAP_DISCO_Server($server,'ServerExample'); | ||
| 40 | + header("Content-type: text/xml"); | ||
| 41 | + if (isset($_SERVER['QUERY_STRING']) && | ||
| 42 | + strcasecmp($_SERVER['QUERY_STRING'],'wsdl')==0) { | ||
| 43 | + echo $disco->getWSDL(); | ||
| 44 | + } else { | ||
| 45 | + echo $disco->getDISCO(); | ||
| 46 | + } | ||
| 47 | + exit; | ||
| 48 | +} | ||
| 49 | +?> | ||
| 0 | \ No newline at end of file | 50 | \ No newline at end of file |
thirdparty/pear/SOAP/example/server2.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: server2.php,v 1.3 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +// first, include the SOAP/Server class | ||
| 23 | +require_once 'SOAP/Server.php'; | ||
| 24 | + | ||
| 25 | +$server = new SOAP_Server; | ||
| 26 | +/* tell server to translate to classes we provide if possible */ | ||
| 27 | +$server->_auto_translation = true; | ||
| 28 | + | ||
| 29 | +/* This is a simple example of implementing a custom | ||
| 30 | + call handler. If you do this, the soap server will ignore | ||
| 31 | + objects or functions added to it, and will call your handler | ||
| 32 | + for **ALL** soap calls the server receives, wether the call | ||
| 33 | + is defined in your WSDL or not. The handler receives two | ||
| 34 | + arguments, the method name being called, and the arguments | ||
| 35 | + sent for that call. | ||
| 36 | +*/ | ||
| 37 | +function myCallHandler($methodname, $args) | ||
| 38 | +{ | ||
| 39 | + global $soapclass; | ||
| 40 | + return @call_user_func_array(array($soapclass, $methodname),$args); | ||
| 41 | +} | ||
| 42 | +$server->setCallHandler('myCallHandler',false); | ||
| 43 | + | ||
| 44 | +require_once 'example_server.php'; | ||
| 45 | + | ||
| 46 | +$soapclass = new SOAP_Example_Server(); | ||
| 47 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 48 | + | ||
| 49 | +if (isset($_SERVER['REQUEST_METHOD']) && | ||
| 50 | + $_SERVER['REQUEST_METHOD']=='POST') { | ||
| 51 | + $server->service($HTTP_RAW_POST_DATA); | ||
| 52 | +} else { | ||
| 53 | + require_once 'SOAP/Disco.php'; | ||
| 54 | + $disco = new SOAP_DISCO_Server($server,'ServerExample'); | ||
| 55 | + header("Content-type: text/xml"); | ||
| 56 | + if (isset($_SERVER['QUERY_STRING']) && | ||
| 57 | + strcasecmp($_SERVER['QUERY_STRING'],'wsdl')==0) { | ||
| 58 | + echo $disco->getWSDL(); | ||
| 59 | + } else { | ||
| 60 | + echo $disco->getDISCO(); | ||
| 61 | + } | ||
| 62 | + exit; | ||
| 63 | +} | ||
| 64 | +?> | ||
| 0 | \ No newline at end of file | 65 | \ No newline at end of file |
thirdparty/pear/SOAP/example/smtp.php
0 → 100644
| 1 | +<? | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: smtp.php,v 1.5 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | +// include soap client class | ||
| 22 | +include("SOAP/Client.php"); | ||
| 23 | + | ||
| 24 | +$soapclient = new SOAP_Client("mailto:user@domain.com"); | ||
| 25 | +$options = array('namespace'=>'http://soapinterop.org/','from'=>'user@domain.com','host'=>'localhost'); | ||
| 26 | +$return = $soapclient->call("echoString",array("inputString"=>"this is a test"), $options); | ||
| 27 | +$return = $soapclient->call("echoStringArray",array('inputStringArray' => array('good','bad','ugly')), $options); | ||
| 28 | +// don't expect much of a result! | ||
| 29 | +print_r($return); | ||
| 30 | +print "<br>\n".$soapclient->wire; | ||
| 31 | +?> | ||
| 32 | + |
thirdparty/pear/SOAP/example/stockquote.php
0 → 100644
| 1 | +<html><body> | ||
| 2 | +<? | ||
| 3 | +// | ||
| 4 | +// +----------------------------------------------------------------------+ | ||
| 5 | +// | PHP Version 4 | | ||
| 6 | +// +----------------------------------------------------------------------+ | ||
| 7 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 8 | +// +----------------------------------------------------------------------+ | ||
| 9 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 10 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 11 | +// | available at through the world-wide-web at | | ||
| 12 | +// | http://www.php.net/license/2_02.txt. | | ||
| 13 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 14 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 15 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 16 | +// +----------------------------------------------------------------------+ | ||
| 17 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more | | ||
| 18 | +// | Authors: Dietrich Ayala <dietrich@ganx4.com> Original Author | | ||
| 19 | +// +----------------------------------------------------------------------+ | ||
| 20 | +// | ||
| 21 | +// $Id: stockquote.php,v 1.7 2005/03/10 23:16:40 yunosh Exp $ | ||
| 22 | +// | ||
| 23 | +// include soap client class | ||
| 24 | +include("SOAP/Client.php"); | ||
| 25 | + | ||
| 26 | +print "<br>\n<strong>wsdl:</strong>"; | ||
| 27 | +$wsdl = new SOAP_WSDL("http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl"); | ||
| 28 | +$soapclient = $wsdl->getProxy(); | ||
| 29 | +print_r($soapclient->getQuote("ibm")); | ||
| 30 | +print "\n\n"; | ||
| 31 | + | ||
| 32 | +if (extension_loaded('overload')) { | ||
| 33 | + print "\n<br><strong>overloaded:</strong>"; | ||
| 34 | + $ret = $soapclient->getQuote("ibm"); | ||
| 35 | + print_r($ret); | ||
| 36 | + print "\n\n"; | ||
| 37 | +} | ||
| 38 | +unset($soapclient); | ||
| 39 | + | ||
| 40 | +print "\n<br><strong>non wsdl:</strong>"; | ||
| 41 | +$soapclient = new SOAP_Client("http://services.xmethods.net:80/soap"); | ||
| 42 | +$namespace = "urn:xmethods-delayed-quotes"; | ||
| 43 | +/** | ||
| 44 | + * some soap servers require a Soapaction http header. PEAR::SOAP does | ||
| 45 | + * not use them in any way, other to send them if you supply them. | ||
| 46 | + * soapaction is deprecated in later SOAP versions. | ||
| 47 | + */ | ||
| 48 | +$soapaction = "urn:xmethods-delayed-quotes#getQuote"; | ||
| 49 | +$ret = $soapclient->call("getQuote",array("symbol"=>"ibm"),$namespace,$soapaction); | ||
| 50 | +print_r($ret); | ||
| 51 | +print "\n\n"; | ||
| 52 | +unset($soapclient); | ||
| 53 | + | ||
| 54 | +?> | ||
| 55 | +</html></body> |
thirdparty/pear/SOAP/example/tcp_client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Hanna <iordy_at_iordy_dot_com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: tcp_client.php,v 1.3 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +require_once('SOAP/Client.php'); | ||
| 23 | + | ||
| 24 | +# client | ||
| 25 | +$soapclient = new SOAP_Client("tcp://127.0.0.1:82"); | ||
| 26 | + | ||
| 27 | +# namespace | ||
| 28 | +$options = array('namespace' => 'urn:SOAP_Example_Server', 'trace' => 1); | ||
| 29 | + | ||
| 30 | +# one | ||
| 31 | +$params = array("string" => "this is string 1"); | ||
| 32 | +$ret1 = $soapclient->call("echoString", $params, $options); | ||
| 33 | +# echo "WIRE: \n".$soapclient->__get_wire(); | ||
| 34 | +print_r($ret1); | ||
| 35 | +echo "<br />\n"; | ||
| 36 | + | ||
| 37 | +# two | ||
| 38 | +$params = array("string" => "this is string 2"); | ||
| 39 | +$ret2 = $soapclient->call("echoString", $params, $options); | ||
| 40 | +# echo "WIRE: \n".$soapclient->__get_wire(); | ||
| 41 | +print_r($ret2); | ||
| 42 | +echo "<br />\n"; | ||
| 43 | + | ||
| 44 | +?> | ||
| 0 | \ No newline at end of file | 45 | \ No newline at end of file |
thirdparty/pear/SOAP/example/tcp_daemon.pl
0 → 100644
| 1 | +#!/usr/bin/perl -w | ||
| 2 | +use strict; | ||
| 3 | + | ||
| 4 | +=head1 Simple SOAP TCP Server | ||
| 5 | + | ||
| 6 | + Simple SOAP TCP Server with test class (just to check things are working) | ||
| 7 | + | ||
| 8 | + Before you run this test server you will need some perl classes, namely: | ||
| 9 | + SOAP::Lite | ||
| 10 | + Hook::LexWrap (if you want to see some debugging) | ||
| 11 | + | ||
| 12 | + Flee off to the CPAN if you need them :) | ||
| 13 | + | ||
| 14 | + To run type 'perl <filename>' and if you dont get any errors, it's time | ||
| 15 | + to go write some code to connect. | ||
| 16 | +=cut | ||
| 17 | + | ||
| 18 | +use SOAP::Transport::TCP qw(trace); | ||
| 19 | +use Data::Dumper; | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +############# | ||
| 23 | +## if you want to see incoming/outgoing raw xml | ||
| 24 | +## uncomment the following. | ||
| 25 | + | ||
| 26 | +#use Hook::LexWrap; | ||
| 27 | +#wrap *IO::SessionData::read, post => \&show_read; | ||
| 28 | +#wrap *IO::SessionData::write, post => \&show_write; | ||
| 29 | + | ||
| 30 | +## | ||
| 31 | +############# | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +my $daemon = SOAP::Transport::TCP::Server->new( | ||
| 35 | + LocalAddr => '127.0.0.1', | ||
| 36 | + LocalPort => '82', | ||
| 37 | + Listen => 5, | ||
| 38 | + Reuse => 1 | ||
| 39 | +); | ||
| 40 | + | ||
| 41 | +# dispatch | ||
| 42 | +$daemon->dispatch_to('SOAP_Example_Server'); | ||
| 43 | +$daemon->handle; | ||
| 44 | + | ||
| 45 | +############# | ||
| 46 | +## callback functions for Hook::LexWrap; | ||
| 47 | +## | ||
| 48 | + | ||
| 49 | +# show incoming xml | ||
| 50 | +sub show_read { | ||
| 51 | + print $/,'## read ##',$/; | ||
| 52 | + print Dumper($_[0]); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +# show outgoing xml | ||
| 56 | +sub show_write { | ||
| 57 | + print $/,'## write ##',$/; | ||
| 58 | + print Dumper($_[0]); | ||
| 59 | +} | ||
| 60 | +################################################################################ | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + | ||
| 64 | +################################################################################ | ||
| 65 | +# SOAP_Example_Server | ||
| 66 | +# Simple test class, method test returns double what you send to it, thats all! | ||
| 67 | +################################################################################ | ||
| 68 | +package SOAP_Example_Server; | ||
| 69 | + | ||
| 70 | +sub echoString { | ||
| 71 | + return $_[1] x 2; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +1; |
thirdparty/pear/SOAP/example/tcp_server.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: tcp_server.php,v 1.4 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | + | ||
| 22 | +// first, include the SOAP/Server class | ||
| 23 | +require_once 'SOAP/Server/TCP.php'; | ||
| 24 | +set_time_limit(0); | ||
| 25 | + | ||
| 26 | +$server = new SOAP_Server_TCP("127.0.0.1",82); | ||
| 27 | +/* tell server to translate to classes we provide if possible */ | ||
| 28 | +$server->_auto_translation = true; | ||
| 29 | + | ||
| 30 | +require_once 'example_server.php'; | ||
| 31 | + | ||
| 32 | +$soapclass = new SOAP_Example_Server(); | ||
| 33 | +$server->addObjectMap($soapclass,'urn:SOAP_Example_Server'); | ||
| 34 | +$server->run(); | ||
| 35 | +?> | ||
| 0 | \ No newline at end of file | 36 | \ No newline at end of file |
thirdparty/pear/SOAP/example/wsdl_client.php
0 → 100644
| 1 | +<?php | ||
| 2 | +// | ||
| 3 | +// +----------------------------------------------------------------------+ | ||
| 4 | +// | PHP Version 4 | | ||
| 5 | +// +----------------------------------------------------------------------+ | ||
| 6 | +// | Copyright (c) 1997-2003 The PHP Group | | ||
| 7 | +// +----------------------------------------------------------------------+ | ||
| 8 | +// | This source file is subject to version 2.02 of the PHP license, | | ||
| 9 | +// | that is bundled with this package in the file LICENSE, and is | | ||
| 10 | +// | available at through the world-wide-web at | | ||
| 11 | +// | http://www.php.net/license/2_02.txt. | | ||
| 12 | +// | If you did not receive a copy of the PHP license and are unable to | | ||
| 13 | +// | obtain it through the world-wide-web, please send a note to | | ||
| 14 | +// | license@php.net so we can mail you a copy immediately. | | ||
| 15 | +// +----------------------------------------------------------------------+ | ||
| 16 | +// | Authors: Shane Caraveo <Shane@Caraveo.com> | | ||
| 17 | +// +----------------------------------------------------------------------+ | ||
| 18 | +// | ||
| 19 | +// $Id: wsdl_client.php,v 1.3 2005/03/10 23:16:40 yunosh Exp $ | ||
| 20 | +// | ||
| 21 | +include("SOAP/Client.php"); | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * this client runs against the example server in SOAP/example/server.php | ||
| 25 | + * it does not use WSDL to run these requests, but that can be changed easily by simply | ||
| 26 | + * adding '?wsdl' to the end of the url. | ||
| 27 | + */ | ||
| 28 | +$wsdl = new SOAP_WSDL("http://localhost/SOAP/example/server.php?wsdl"); | ||
| 29 | +$soapclient = $wsdl->getProxy(); | ||
| 30 | + | ||
| 31 | +$ret = $soapclient->echoStringSimple("this is a test string"); | ||
| 32 | +#print $soapclient->__get_wire(); | ||
| 33 | +print_r($ret);echo "<br>\n"; | ||
| 34 | + | ||
| 35 | +$ret = $soapclient->echoString("this is a test string"); | ||
| 36 | +print_r($ret);echo "<br>\n"; | ||
| 37 | + | ||
| 38 | +$ret = $soapclient->divide(22,7); | ||
| 39 | +# print $soapclient->__get_wire(); | ||
| 40 | +if (PEAR::isError($ret)) | ||
| 41 | + print("Error: " . $ret->getMessage() . "<br>\n"); | ||
| 42 | +else | ||
| 43 | + print("Quotient is " . $ret . "<br>\n"); | ||
| 44 | + | ||
| 45 | +$ret = $soapclient->divide(22,0); | ||
| 46 | +if (PEAR::isError($ret)) | ||
| 47 | + print("Error: " . $ret->getMessage() . "<br>\n"); | ||
| 48 | +else | ||
| 49 | + print("Quotient is " . $ret . "<br>\n"); | ||
| 50 | + | ||
| 51 | + | ||
| 52 | +// SOAPStruct is defined in the following file | ||
| 53 | +require_once 'example_types.php'; | ||
| 54 | + | ||
| 55 | +$struct = new SOAPStruct('test string',123,123.123); | ||
| 56 | + | ||
| 57 | +/* send an object, get an object back */ | ||
| 58 | +/* tell client to translate to classes we provide if possible */ | ||
| 59 | +$soapclient->_auto_translation = true; | ||
| 60 | +/* or you can explicitly set the translation for | ||
| 61 | + a specific class. auto_translation works for all cases, | ||
| 62 | + but opens ANY class in the script to be used as a data type, | ||
| 63 | + and may not be desireable. both can be used on client or | ||
| 64 | + server */ | ||
| 65 | +$soapclient->__set_type_translation('{http://soapinterop.org/xsd}SOAPStruct','SOAPStruct'); | ||
| 66 | +$ret = $soapclient->echoStruct($struct->__to_soap()); | ||
| 67 | +#print $soapclient->__get_wire(); | ||
| 68 | +print_r($ret); | ||
| 69 | + | ||
| 70 | +/** | ||
| 71 | + * PHP doesn't support multiple OUT parameters in function calls, so we | ||
| 72 | + * must do a little work to make it happen here. This requires knowledge on the | ||
| 73 | + * developers part to figure out how they want to deal with it. | ||
| 74 | + */ | ||
| 75 | +$ret = $soapclient->echoStructAsSimpleTypes($struct->__to_soap()); | ||
| 76 | +if (PEAR::isError($ret)) { | ||
| 77 | + print("Error: " . $ret->getMessage() . "<br>\n"); | ||
| 78 | +} else { | ||
| 79 | + list($string, $int, $float) = array_values($ret); | ||
| 80 | +} | ||
| 81 | +echo "varString: $string<br>\nvarInt: $int<br>\nvarFloat: $float<br>\n"; | ||
| 82 | + | ||
| 83 | +?> | ||
| 0 | \ No newline at end of file | 84 | \ No newline at end of file |
thirdparty/pear/SOAP/tools/genproxy.php
0 → 100644
| 1 | +<?php | ||
| 2 | +error_reporting(E_ALL); | ||
| 3 | +require_once 'SOAP/WSDL.php'; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * genproxy | ||
| 7 | + * | ||
| 8 | + * a command line tool for generating SOAP proxies from WSDL files | ||
| 9 | + * | ||
| 10 | + * genproxy.php http://site/foo.wsdl > foo.php | ||
| 11 | + * | ||
| 12 | + */ | ||
| 13 | + | ||
| 14 | +function do_wsdl($uri) { | ||
| 15 | + $wsdl =& new SOAP_WSDL($uri); | ||
| 16 | + print $wsdl->generateAllProxies(); | ||
| 17 | +} | ||
| 18 | +echo "<?php\n\nrequire_once 'SOAP/Client.php';\n\n"; | ||
| 19 | +do_wsdl($_SERVER['argv'][1]); | ||
| 20 | +echo "\n?>"; | ||
| 21 | +?> | ||
| 0 | \ No newline at end of file | 22 | \ No newline at end of file |