Commit b9b50e851b324f67e81d6cfc6c2cd3a4e2212b92

Authored by Conrad Vermeulen
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('&' => '&amp;',
  333 + '<' => '&lt;',
  334 + '>' => '&gt;',
  335 + "'" => '&apos;',
  336 + '"' => '&quot;');
  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('&' => '&amp;',
  333 + '<' => '&lt;',
  334 + '>' => '&gt;',
  335 + "'" => '&apos;',
  336 + '"' => '&quot;');
  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 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 ( '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', "'" => '&apos;', '"' => '&quot;' );
  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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 22 \ No newline at end of file
... ...