SOAP
[ class tree: SOAP ] [ index: SOAP ] [ all elements ]

Source for file Base.php

Documentation is available at Base.php

  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: Base.php,v 1.49 2005/05/28 23:07:51 yunosh Exp $
  21. //
  22.  
  23. /**
  24.  * SOAP_OBJECT_STRUCT makes PEAR::SOAP use objects for SOAP structures rather
  25.  * than arrays.  This has been done to provide a closer match to php-soap.  If
  26.  * the old behaviour is needed, set to false.  The old behaviour is
  27.  * deprecated.
  28.  *
  29.  * @global bool $GLOBALS['SOAP_OBJECT_STRUCT'] 
  30.  */
  31. $GLOBALS['SOAP_OBJECT_STRUCT'= true;
  32.  
  33. /**
  34.  * SOAP_RAW_CONVERT makes PEAR::SOAP attempt to determine what SOAP type a PHP
  35.  * string COULD be.  This may result in slightly better interoperability when
  36.  * you are not using WSDL, and are being lazy and not using SOAP_Value to
  37.  * define types for your values.
  38.  *
  39.  * @global bool $GLOBALS['SOAP_RAW_CONVERT'] 
  40.  */
  41. $GLOBALS['SOAP_RAW_CONVERT'= false;
  42.  
  43. require_once 'PEAR.php';
  44. require_once 'SOAP/Type/dateTime.php';
  45. require_once 'SOAP/Type/hexBinary.php';
  46.  
  47. // optional features
  48. $GLOBALS['SOAP_options'= array();
  49.  
  50. @include_once 'Mail/mimePart.php';
  51. @include_once 'Mail/mimeDecode.php';
  52. if (class_exists('Mail_mimePart')) {
  53.     $GLOBALS['SOAP_options']['Mime'= 1;
  54.     define('MAIL_MIMEPART_CRLF'"\r\n");
  55. }
  56.  
  57. @include_once 'Net/DIME.php';
  58. if (class_exists('Net_DIME_Message')) {
  59.     $GLOBALS['SOAP_options']['DIME'= 1;
  60. }
  61.  
  62. /**
  63.  * Enable debugging information?
  64.  *
  65.  * @global bool $GLOBALS['SOAP_DEBUG'] 
  66.  * @name $SOAP_DEBUG
  67.  */
  68. $GLOBALS['SOAP_DEBUG'= false;
  69.  
  70. if (!function_exists('version_compare'||
  71.     version_compare(phpversion()'4.1''<')) {
  72.     die("requires PHP 4.1 or higher\n");
  73. }
  74. if (version_compare(phpversion()'4.1''>='&&
  75.     version_compare(phpversion()'4.2''<')) {
  76.     define('FLOAT''double');
  77. else {
  78.     define('FLOAT''float');
  79. }
  80.  
  81. if (!defined('INF')) {
  82.     define('INF'1.8e307);
  83. }
  84. if (!defined('NAN')) {
  85.     define('NAN'0.0);
  86. }
  87.  
  88. define('SOAP_LIBRARY_VERSION''0.8.0RC4');
  89. define('SOAP_LIBRARY_NAME',    'PEAR-SOAP 0.8.0RC4-devel');
  90.  
  91. // Set schema version.
  92. define('SOAP_XML_SCHEMA_VERSION',  'http://www.w3.org/2001/XMLSchema');
  93. define('SOAP_XML_SCHEMA_INSTANCE''http://www.w3.org/2001/XMLSchema-instance');
  94. define('SOAP_XML_SCHEMA_1999',     'http://www.w3.org/1999/XMLSchema');
  95. define('SOAP_SCHEMA',              'http://schemas.xmlsoap.org/wsdl/soap/');
  96. define('SOAP_SCHEMA_ENCODING',     'http://schemas.xmlsoap.org/soap/encoding/');
  97. define('SOAP_ENVELOP',             'http://schemas.xmlsoap.org/soap/envelope/');
  98.  
  99. define('SCHEMA_DISCO',             'http://schemas.xmlsoap.org/disco/');
  100. define('SCHEMA_DISCO_SCL',         'http://schemas.xmlsoap.org/disco/scl/');
  101.  
  102. define('SCHEMA_SOAP',              'http://schemas.xmlsoap.org/wsdl/soap/');
  103. define('SCHEMA_SOAP_HTTP',         'http://schemas.xmlsoap.org/soap/http');
  104. define('SCHEMA_WSDL_HTTP',         'http://schemas.xmlsoap.org/wsdl/http/');
  105. define('SCHEMA_MIME',              'http://schemas.xmlsoap.org/wsdl/mime/');
  106. define('SCHEMA_WSDL',              'http://schemas.xmlsoap.org/wsdl/');
  107. define('SCHEMA_DIME',              'http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/');
  108. define('SCHEMA_CONTENT',           'http://schemas.xmlsoap.org/ws/2002/04/content-type/');
  109. define('SCHEMA_REF',               'http://schemas.xmlsoap.org/ws/2002/04/reference/');
  110.  
  111. define('SOAP_DEFAULT_ENCODING',  'UTF-8');
  112.  
  113. if (!function_exists('is_a')) {
  114.     function is_a(&$object$class_name)
  115.     {
  116.         if (strtolower(get_class($object)) == $class_name{
  117.             return true;
  118.         }
  119.         return is_subclass_of($object$class_name);
  120.     }
  121. }
  122.  
  123. if (!class_exists('stdClass')) {
  124.     /* PHP5 doesn't define this? */
  125.     class stdClass {
  126.         function __constructor({}
  127.     }
  128. }
  129.  
  130. class SOAP_Base_Object extends PEAR
  131. {
  132.     /**
  133.      * Store debugging information in $_debug_data?
  134.      *
  135.      * @see $debug_data, SOAP_Base
  136.      * @var boolean $_debug_flag 
  137.      */
  138.     var $_debug_flag = false;
  139.  
  140.     /**
  141.      * String containing debugging information if $_debug_flag is true.
  142.      *
  143.      * @access public
  144.      * @see $debug_flag, SOAP_Base
  145.      * @var string $_debug_data 
  146.      */
  147.     var $_debug_data '';
  148.  
  149.     /**
  150.      * Supported encodings, limited by XML extension.
  151.      *
  152.      * @var array $_encodings 
  153.      */
  154.     var $_encodings = array('ISO-8859-1''US-ASCII''UTF-8');
  155.  
  156.     /**
  157.      * Fault code.
  158.      *
  159.      * @var string $_myfaultcode 
  160.      */
  161.     var $_myfaultcode '';
  162.  
  163.     /**
  164.      * Recent PEAR_Error object.
  165.      *
  166.      * @var PEAR_Error $fault 
  167.      */
  168.     var $fault = null;
  169.  
  170.     /**
  171.      * Constructor.
  172.      *
  173.      * @see $debug_data, _debug()
  174.      *
  175.      * @param string $faultcode  Error code.
  176.      */
  177.     function SOAP_Base_Object($faultcode 'Client')
  178.     {
  179.         $this->_myfaultcode $faultcode;
  180.         $this->_debug_flag $GLOBALS['SOAP_DEBUG'];
  181.         parent::PEAR('SOAP_Fault');
  182.     }
  183.  
  184.     /**
  185.      * Raises a SOAP error.
  186.      *
  187.      * Please refer to the SOAP definition for an impression of what a certain
  188.      * parameter stands for.
  189.      *
  190.      * Use $debug_flag to store errors to the member variable $debug_data
  191.      *
  192.      * @see $debug_flag, $debug_data, SOAP_Fault
  193.      *
  194.      * @param string|object $str  Error message or object.
  195.      * @param string $detail      Detailed error message.
  196.      * @param string $actorURI 
  197.      * @param mixed $code 
  198.      * @param mixed $mode 
  199.      * @param mixed $options 
  200.      * @param boolean $skipmsg 
  201.      */
  202.     function &_raiseSoapFault($str$detail ''$actorURI ''$code = null,
  203.                               $mode = null$options = null$skipmsg = false)
  204.     {
  205.         // Pass through previous faults.
  206.         $is_instance = isset($this);
  207.         if (is_object($str)) {
  208.             $fault =$str;
  209.         else {
  210.             if (!$code{
  211.                 $code $is_instance $this->_myfaultcode 'Client';
  212.             }
  213.             $fault =new SOAP_Fault($str,
  214.                                      $code,
  215.                                      $actorURI,
  216.                                      $detail,
  217.                                      $mode,
  218.                                      $options);
  219.         }
  220.         if ($is_instance{
  221.             $this->fault =$fault;
  222.         }
  223.  
  224.         return $fault;
  225.     }
  226.  
  227.     function __isfault()
  228.     {
  229.         return $this->fault != null;
  230.     }
  231.  
  232.     function &__getfault()
  233.     {
  234.         return $this->fault;
  235.     }
  236.  
  237.     /**
  238.      * Adds a string to the debug data.
  239.      *
  240.      * @param string $string  Debugging message.
  241.      */
  242.     function _debug($string)
  243.     {
  244.         if ($this->_debug_flag{
  245.             $this->_debug_data .= get_class($this': ' .
  246.                 str_replace('>'">\r\n"$string"\n";
  247.         }
  248.     }
  249.  
  250. }
  251.  
  252. /**
  253.  * Common base class of all SOAP classes.
  254.  *
  255.  * @access   public
  256.  * @package  SOAP
  257.  * @author   Shane Caraveo <shane@php.net> Conversion to PEAR and updates
  258.  */
  259. class SOAP_Base extends SOAP_Base_Object
  260. {
  261.     var $_XMLSchema = array('http://www.w3.org/2001/XMLSchema',
  262.                             'http://www.w3.org/1999/XMLSchema');
  263.     var $_XMLSchemaVersion 'http://www.w3.org/2001/XMLSchema';
  264.  
  265.     // load types into typemap array
  266.     var $_typemap = array(
  267.         'http://www.w3.org/2001/XMLSchema' => array(
  268.             'string' => 'string',
  269.             'boolean' => 'boolean',
  270.             'float' => FLOAT,
  271.             'double' => FLOAT,
  272.             'decimal' => FLOAT,
  273.             'duration' => 'integer',
  274.             'dateTime' => 'string',
  275.             'time' => 'string',
  276.             'date' => 'string',
  277.             'gYearMonth' => 'integer',
  278.             'gYear' => 'integer',
  279.             'gMonthDay' => 'integer',
  280.             'gDay' => 'integer',
  281.             'gMonth' => 'integer',
  282.             'hexBinary' => 'string',
  283.             'base64Binary' => 'string',
  284.             // derived datatypes
  285.             'normalizedString' => 'string',
  286.             'token' => 'string',
  287.             'language' => 'string',
  288.             'NMTOKEN' => 'string',
  289.             'NMTOKENS' => 'string',
  290.             'Name' => 'string',
  291.             'NCName' => 'string',
  292.             'ID' => 'string',
  293.             'IDREF' => 'string',
  294.             'IDREFS' => 'string',
  295.             'ENTITY' => 'string',
  296.             'ENTITIES' => 'string',
  297.             'integer' => 'integer',
  298.             'nonPositiveInteger' => 'integer',
  299.             'negativeInteger' => 'integer',
  300.             'long' => 'integer',
  301.             'int' => 'integer',
  302.             'short' => 'integer',
  303.             'byte' => 'string',
  304.             'nonNegativeInteger' => 'integer',
  305.             'unsignedLong' => 'integer',
  306.             'unsignedInt' => 'integer',
  307.             'unsignedShort' => 'integer',
  308.             'unsignedByte' => 'integer',
  309.             'positiveInteger'  => 'integer',
  310.             'anyType' => 'string',
  311.             'anyURI' => 'string',
  312.             'QName' => 'string'
  313.         ),
  314.         'http://www.w3.org/1999/XMLSchema' => array(
  315.             'i4' => 'integer',
  316.             'int' => 'integer',
  317.             'boolean' => 'boolean',
  318.             'string' => 'string',
  319.             'double' => FLOAT,
  320.             'float' => FLOAT,
  321.             'dateTime' => 'string',
  322.             'timeInstant' => 'string',
  323.             'base64Binary' => 'string',
  324.             'base64' => 'string',
  325.             'ur-type' => 'string'
  326.         ),
  327.         'http://schemas.xmlsoap.org/soap/encoding/' => array(
  328.             'base64' => 'string',
  329.             'array' => 'array',
  330.             'Array' => 'array',
  331.             'Struct' => 'array')
  332.     );
  333.  
  334.     /**
  335.      * Default class name to use for decoded response objects.
  336.      *
  337.      * @var string $_defaultObjectClassname 
  338.      */
  339.     var $_defaultObjectClassname 'stdClass';
  340.  
  341.     // Load namespace URIs into an array of URI => prefix.
  342.     var $_namespaces;
  343.     var $_namespace;
  344.  
  345.     var $_xmlEntities = array('&' => '&amp;',
  346.                               '<' => '&lt;',
  347.                               '>' => '&gt;',
  348.                               "'" => '&apos;',
  349.                               '"' => '&quot;');
  350.  
  351.     var $_doconversion = false;
  352.  
  353.     var $__attachments = array();
  354.  
  355.     var $_wsdl = null;
  356.  
  357.     /**
  358.      * True if we use section 5 encoding, or false if this is literal.
  359.      *
  360.      * @var boolean $_section5 
  361.      */
  362.     var $_section5 = true;
  363.  
  364.     // Handle type to class mapping.
  365.     var $_auto_translation = false;
  366.     var $_type_translation = array();
  367.  
  368.     /**
  369.      * Holds references to all elements that have been serialized already.
  370.      *
  371.      * @var array $_serialized 
  372.      */
  373.     var $_serialized = array();
  374.  
  375.     /**
  376.      * Constructor.
  377.      *
  378.      * @see $debug_data, _debug()
  379.      *
  380.      * @param string $faultcode  Error code.
  381.      */
  382.     function SOAP_Base($faultcode 'Client')
  383.     {
  384.         parent::SOAP_Base_Object($faultcode);
  385.         $this->_resetNamespaces();
  386.     }
  387.  
  388.     function _resetNamespaces()
  389.     {
  390.         $this->_namespaces = array(
  391.             'http://schemas.xmlsoap.org/soap/envelope/' => 'SOAP-ENV',
  392.             'http://www.w3.org/2001/XMLSchema' => 'xsd',
  393.             'http://www.w3.org/2001/XMLSchema-instance' => 'xsi',
  394.             'http://schemas.xmlsoap.org/soap/encoding/' => 'SOAP-ENC');
  395.     }
  396.  
  397.     /**
  398.      * Sets the schema version used in the SOAP message.
  399.      *
  400.      * @access private
  401.      * @see $_XMLSchema
  402.      *
  403.      * @param string $schemaVersion  The schema version.
  404.      */
  405.     function _setSchemaVersion($schemaVersion)
  406.     {
  407.         if (!in_array($schemaVersion$this->_XMLSchema)) {
  408.             return $this->_raiseSoapFault("unsuported XMLSchema $schemaVersion");
  409.         }
  410.         $this->_XMLSchemaVersion $schemaVersion;
  411.         $tmpNS array_flip($this->_namespaces);
  412.         $tmpNS['xsd'$this->_XMLSchemaVersion;
  413.         $tmpNS['xsi'$this->_XMLSchemaVersion '-instance';
  414.         $this->_namespaces array_flip($tmpNS);
  415.     }
  416.  
  417.     function _getNamespacePrefix($ns)
  418.     {
  419.         if ($this->_namespace && $ns == $this->_namespace{
  420.             return '';
  421.         }
  422.         if (isset($this->_namespaces[$ns])) {
  423.             return $this->_namespaces[$ns];
  424.         }
  425.         $prefix 'ns' count($this->_namespaces);
  426.         $this->_namespaces[$ns$prefix;
  427.         return $prefix;
  428.     }
  429.  
  430.     function _getNamespaceForPrefix($prefix)
  431.     {
  432.         $flipped array_flip($this->_namespaces);
  433.         if (isset($flipped[$prefix])) {
  434.             return $flipped[$prefix];
  435.         }
  436.         return null;
  437.     }
  438.  
  439.     function _isSoapValue(&$value)
  440.     {
  441.         return is_a($value'SOAP_Value');
  442.     }
  443.  
  444.     function _serializeValue(&$value$name ''$type = false,
  445.                              $elNamespace = null$typeNamespace = null,
  446.                              $options = array()$attributes = array(),
  447.                              $artype '')
  448.     {
  449.         $namespaces = array();
  450.         $arrayType $array_depth $xmlout_value = null;
  451.         $typePrefix $elPrefix $xmlout_offset $xmlout_arrayType '';
  452.         $xmlout_type $xmlns $ptype $array_type_ns '';
  453.  
  454.         if (!$name || is_numeric($name)) {
  455.             $name 'item';
  456.         }
  457.  
  458.         if ($this->_wsdl{
  459.             list($ptype$arrayType$array_type_ns$array_depth)
  460.                 = $this->_wsdl->getSchemaType($type$name$typeNamespace);
  461.         }
  462.  
  463.         if (!$arrayType{
  464.             $arrayType $artype;
  465.         }
  466.         if (!$ptype{
  467.             $ptype $this->_getType($value);
  468.         }
  469.         if (!$type{
  470.             $type $ptype;
  471.         }
  472.  
  473.         if (strcasecmp($ptype'Struct'== 0 ||
  474.             strcasecmp($type'Struct'== 0{
  475.             // Struct
  476.             $vars = null;
  477.             if (is_object($value)) {
  478.                 $vars get_object_vars($value);
  479.             else {
  480.                 $vars &$value;
  481.             }
  482.             if (is_array($vars)) {
  483.                 foreach (array_keys($varsas $k{
  484.                     // Hide private vars.
  485.                     if ($k[0== '_'continue;
  486.                     if (is_object($vars[$k])) {
  487.                         if (is_a($vars[$k]'SOAP_Value')) {
  488.                             $xmlout_value .= $vars[$k]->serialize($this);
  489.                         else {
  490.                             // XXX get the members and serialize them instead
  491.                             // converting to an array is more overhead than we
  492.                             // should really do.
  493.                             $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k])$kfalse$this->_section5 ? null : $elNamespace);
  494.                         }
  495.                     else {
  496.                         $xmlout_value .= $this->_serializeValue($vars[$k]$kfalse$this->_section5 ? null : $elNamespace);
  497.                     }
  498.                 }
  499.             }
  500.         elseif (strcasecmp($ptype'Array'== 0 ||
  501.                   strcasecmp($type'Array'== 0{
  502.             // Array.
  503.             $typeNamespace SOAP_SCHEMA_ENCODING;
  504.             $orig_type $type;
  505.             $type 'Array';
  506.             $numtypes = 0;
  507.             // XXX this will be slow on larger arrays.  Basically, it flattens
  508.             // arrays to allow us to serialize multi-dimensional arrays.  We
  509.             // only do this if arrayType is set, which will typically only
  510.             // happen if we are using WSDL
  511.             if (isset($options['flatten']||
  512.                 ($arrayType &&
  513.                  (strchr($arrayType','|| strstr($arrayType'][')))) {
  514.                 $numtypes $this->_multiArrayType($value$arrayType,
  515.                                                    $ar_size$xmlout_value);
  516.             }
  517.  
  518.             $array_type $array_type_prefix '';
  519.             if ($numtypes != 1{
  520.                 $arrayTypeQName =new QName($arrayType);
  521.                 $arrayType $arrayTypeQName->name;
  522.                 $array_types = array();
  523.                 $array_val = null;
  524.  
  525.                 // Protect against recursive arrays.
  526.                 $count_serialized count($this->_serialized);
  527.                 var_dump($this->_serialized$value);
  528.                 for ($i = 0; $i $count_serialized$i++{
  529.                     if ($this->_serialized[$i=== $value{
  530.                         break;
  531.                     }
  532.                 }
  533.                 $this->_serialized[count($this->_serialized)=$value;
  534.  
  535.                 // Serialize each array element.
  536.                 $ar_size count($value);
  537.                 foreach ($value as $array_val{
  538.                     var_dump($array_val);
  539.                     if ($this->_isSoapValue($array_val)) {
  540.                         $array_type $array_val->type;
  541.                         $array_types[$array_type= 1;
  542.                         $array_type_ns $array_val->type_namespace;
  543.                         $xmlout_value .= $this->_serializeValue($array_val$array_val->name$array_type$array_type_ns);
  544.                     else {
  545.                         $array_type $this->_getType($array_val);
  546.                         $array_types[$array_type= 1;
  547.                         $xmlout_value .= $this->_serializeValue($array_val'item'$array_type$this->_section5 ? null : $elNamespace);
  548.                     }
  549.                 }
  550.  
  551.                 $xmlout_offset ' SOAP-ENC:offset="[0]"';
  552.                 if (!$arrayType{
  553.                     $numtypes count($array_types);
  554.                     if ($numtypes == 1{
  555.                         $arrayType $array_type;
  556.                     }
  557.                     // Using anyType is more interoperable.
  558.                     if ($array_type == 'Struct'{
  559.                         $array_type '';
  560.                     elseif ($array_type == 'Array'{
  561.                         $arrayType 'anyType';
  562.                         $array_type_prefix 'xsd';
  563.                     else {
  564.                         if (!$arrayType{
  565.                             $arrayType $array_type;
  566.                         }
  567.                     }
  568.                 }
  569.             }
  570.             if (!$arrayType || $numtypes > 1{
  571.                 // Should reference what schema we're using.
  572.                 $arrayType 'xsd:anyType';
  573.             else {
  574.                 if ($array_type_ns{
  575.                     $array_type_prefix $this->_getNamespacePrefix($array_type_ns);
  576.                 elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) {
  577.                     $array_type_prefix $this->_namespaces[$this->_XMLSchemaVersion];
  578.                 }
  579.                 if ($array_type_prefix{
  580.                     $arrayType $array_type_prefix ':' $arrayType;
  581.                 }
  582.             }
  583.  
  584.             $xmlout_arrayType ' SOAP-ENC:arrayType="' $arrayType;
  585.             if ($array_depth != null{
  586.                 for ($i = 0; $i $array_depth$i++{
  587.                     $xmlout_arrayType .= '[]';
  588.                 }
  589.             }
  590.             $xmlout_arrayType .= "[$ar_size]\"";
  591.         elseif ($this->_isSoapValue($value)) {
  592.             $xmlout_value =$value->serialize($this);
  593.         elseif ($type == 'string'{
  594.             $xmlout_value htmlspecialchars($value);
  595.         elseif ($type == 'rawstring'{
  596.             $xmlout_value =$value;
  597.         elseif ($type == 'boolean'{
  598.             $xmlout_value $value 'true' 'false';
  599.         else {
  600.             $xmlout_value =$value;
  601.         }
  602.  
  603.         // Add namespaces.
  604.         if ($elNamespace{
  605.             $elPrefix $this->_getNamespacePrefix($elNamespace);
  606.             if ($elPrefix{
  607.                 $xmlout_name = "$elPrefix:$name";
  608.             else {
  609.                 $xmlout_name $name;
  610.             }
  611.         else {
  612.             $xmlout_name $name;
  613.         }
  614.  
  615.         if ($typeNamespace{
  616.             $typePrefix $this->_getNamespacePrefix($typeNamespace);
  617.             if ($typePrefix{
  618.                 $xmlout_type = "$typePrefix:$type";
  619.             else {
  620.                 $xmlout_type $type;
  621.             }
  622.         elseif ($type &&
  623.                   isset($this->_typemap[$this->_XMLSchemaVersion][$type])) {
  624.             $typePrefix $this->_namespaces[$this->_XMLSchemaVersion];
  625.             if ($typePrefix{
  626.                 $xmlout_type = "$typePrefix:$type";
  627.             else {
  628.                 $xmlout_type $type;
  629.             }
  630.         }
  631.  
  632.         // Handle additional attributes.
  633.         $xml_attr '';
  634.         if (count($attributes)) {
  635.             foreach ($attributes as $k => $v{
  636.                 $kqn =new QName($k);
  637.                 $vqn =new QName($v);
  638.                 $xml_attr .= ' ' $kqn->fqn('="' $vqn->fqn('"';
  639.             }
  640.         }
  641.  
  642.         // Store the attachment for mime encoding.
  643.         if (isset($options['attachment'])) {
  644.             $this->__attachments[$options['attachment'];
  645.         }
  646.  
  647.         if ($this->_section5{
  648.             if ($xmlout_type{
  649.                 $xmlout_type = " xsi:type=\"$xmlout_type\"";
  650.             }
  651.             if (is_null($xmlout_value)) {
  652.                 $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" .
  653.                     "$xml_attr xsi:nil=\"true\"/>";
  654.             else {
  655.                 $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" .
  656.                     "$xmlout_offset$xml_attr>$xmlout_value</$xmlout_name>";
  657.             }
  658.         else {
  659.             if (is_null($xmlout_value)) {
  660.                 $xml = "\r\n<$xmlout_name$xmlns$xml_attr/>";
  661.             else {
  662.                 $xml = "\r\n<$xmlout_name$xmlns$xml_attr>" .
  663.                     $xmlout_value . "</$xmlout_name>";
  664.             }
  665.         }
  666.  
  667.         return $xml;
  668.     }
  669.  
  670.     /**
  671.      * Converts a PHP type to a SOAP type.
  672.      *
  673.      * @access   private
  674.      *
  675.      * @param string $value  The value to inspect.
  676.      *
  677.      * @return string  The value's SOAP type.
  678.      */
  679.     function _getType(&$value)
  680.     {
  681.         global $SOAP_OBJECT_STRUCT$SOAP_RAW_CONVERT;
  682.  
  683.         $type gettype($value);
  684.         switch ($type{
  685.         case 'object':
  686.             if (is_a($value'soap_value')) {
  687.                 $type $value->type;
  688.             else {
  689.                 $type 'Struct';
  690.             }
  691.             break;
  692.  
  693.         case 'array':
  694.             // Hashes are always handled as structs.
  695.             if ($this->_isHash($value)) {
  696.                 $type 'Struct';
  697.             else {
  698.                 $ar_size count($value);
  699.                 reset($value);
  700.                 $key1 key($value);
  701.                 if ($ar_size > 0 && is_a($key1'SOAP_Value')) {
  702.                     // FIXME: for non-wsdl structs that are all the same type
  703.                     $key2 key($value);
  704.                     if ($ar_size > 1 &&
  705.                         $this->_isSoapValue($key1&&
  706.                         $this->_isSoapValue($key2&&
  707.                         $key1->name != $key2->name{
  708.                         // This is a struct, not an array.
  709.                         $type 'Struct';
  710.                     else {
  711.                         $type 'Array';
  712.                     }
  713.                 else {
  714.                     $type 'Array';
  715.                 }
  716.             }
  717.             break;
  718.  
  719.         case 'integer':
  720.         case 'long':
  721.             $type 'int';
  722.             break;
  723.  
  724.         case 'boolean':
  725.             break;
  726.  
  727.         case 'double':
  728.             // double is deprecated in PHP 4.2 and later.
  729.             $type 'float';
  730.             break;
  731.  
  732.         case 'null':
  733.             $type '';
  734.             break;
  735.  
  736.         case 'string':
  737.             if ($SOAP_RAW_CONVERT{
  738.                 if (is_numeric($value)) {
  739.                     if (strstr($value'.')) {
  740.                         $type 'float';
  741.                     else {
  742.                         $type 'int';
  743.                     }
  744.                 else {
  745.                     if (SOAP_Type_hexBinary::is_hexbin($value)) {
  746.                         $type 'hexBinary';
  747.                     else {
  748.                         if ($this->_isBase64($value)) {
  749.                             $type 'base64Binary';
  750.                         else {
  751.                             $dt =new SOAP_Type_dateTime($value);
  752.                             if ($dt->toUnixtime(!= -1{
  753.                                 $type 'dateTime';
  754.                             }
  755.                         }
  756.                     }
  757.                 }
  758.             }
  759.             break;
  760.  
  761.         default:
  762.             break;
  763.         }
  764.  
  765.         return $type;
  766.     }
  767.  
  768.     function _multiArrayType(&$value&$type&$size&$xml)
  769.     {
  770.         $sz count($value);
  771.         if (is_array($value)) {
  772.             // Seems we have a multi dimensional array, figure it out if we
  773.             // do.
  774.             $c count($value);
  775.             for ($i = 0; $i $c$i++{
  776.                 $this->_multiArrayType($value[$i]$type$size$xml);
  777.             }
  778.  
  779.             if ($size{
  780.                 $size $sz',' $size;
  781.             else {
  782.                 $size $sz;
  783.             }
  784.  
  785.             return 1;
  786.         else {
  787.             if (is_object($value)) {
  788.                 $type $value->type;
  789.                 $xml .= $value->serialize($this);
  790.             else {
  791.                 $type $this->_getType($value);
  792.                 $xml .= $this->_serializeValue($value'item'$type);
  793.             }
  794.         }
  795.         $size = null;
  796.  
  797.         return 1;
  798.     }
  799.  
  800.     /**
  801.      * Returns whether a string is base64 encoded data.
  802.      *
  803.      * @param string $value  The string to check.
  804.      *
  805.      * @return boolean  True if the specified value seems to be base64 encoded.
  806.      */
  807.     function _isBase64(&$value)
  808.     {
  809.         $l strlen($value);
  810.         if ($l{
  811.             return $value[$l - 1== '=' &&
  812.                 preg_match('/[A-Za-z=\/\+]+/'$value);
  813.         }
  814.         return false;
  815.     }
  816.  
  817.     /**
  818.      * Returns whether a type is a base64 type.
  819.      *
  820.      * @param string $type  A type name.
  821.      *
  822.      * @return boolean  True if the type name is a base64 type.
  823.      */
  824.     function _isBase64Type($type)
  825.     {
  826.         return $type == 'base64' || $type == 'base64Binary';
  827.     }
  828.  
  829.     /**
  830.      * Returns whether an array is a hash.
  831.      *
  832.      * @param array $a  An array to check.
  833.      *
  834.      * @return boolean  True if the specified array is a hash.
  835.      */
  836.     function _isHash(&$a)
  837.     {
  838.         // I really dislike having to loop through this in PHP code, really
  839.         // large arrays will be slow.  We need a C function to do this.
  840.         $names = array();
  841.         $it = 0;
  842.         foreach ($a as $k => $v{
  843.             // Checking the type is faster than regexp.
  844.             $t gettype($k);
  845.             if ($t != 'integer'{
  846.                 return true;
  847.             elseif ($this->_isSoapValue($v)) {
  848.                 $names[$v->name= 1;
  849.             }
  850.             // If someone has a large hash they should really be defining the
  851.             // type.
  852.             if ($it++ > 10{
  853.                 return false;
  854.             }
  855.         }
  856.         return count($names)>1;
  857.     }
  858.  
  859.     function &_un_htmlentities($string)
  860.     {
  861.         $trans_tbl get_html_translation_table(HTML_ENTITIES);
  862.         $trans_tbl array_flip($trans_tbl);
  863.         return strtr($string$trans_tbl);
  864.     }
  865.  
  866.     function &_decode(&$soapval)
  867.     {
  868.         global $SOAP_OBJECT_STRUCT;
  869.  
  870.         if (!$this->_isSoapValue($soapval)) {
  871.             return $soapval;
  872.         elseif (is_array($soapval->value)) {
  873.             if ($SOAP_OBJECT_STRUCT && $soapval->type != 'Array'{
  874.                 $classname $this->_defaultObjectClassname;
  875.                 if (isset($this->_type_translation[$soapval->tqn->fqn()])) {
  876.                     // This will force an error in PHP if the class does not
  877.                     // exist.
  878.                     $classname $this->_type_translation[$soapval->tqn->fqn()];
  879.                 elseif (isset($this->_type_translation[$soapval->type])) {
  880.                     // This will force an error in PHP if the class does not
  881.                     // exist.
  882.                     $classname $this->_type_translation[$soapval->type];
  883.                 elseif ($this->_auto_translation{
  884.                     if (class_exists($soapval->type)) {
  885.                         $classname $soapval->type;
  886.                     elseif ($this->_wsdl{
  887.                         $t $this->_wsdl->getComplexTypeNameForElement($soapval->name$soapval->namespace);
  888.                         if ($t && class_exists($t)) {
  889.                             $classname $t;
  890.                         }
  891.                     }
  892.                 }
  893.                 $return =new $classname;
  894.             else {
  895.                 $return = array();
  896.             }
  897.  
  898.             $counter = 1;
  899.             $isstruct !$SOAP_OBJECT_STRUCT || !is_array($return);
  900.             foreach ($soapval->value as $item{
  901.                 if (is_object($return)) {
  902.                     if ($this->_wsdl{
  903.                         // Get this child's WSDL information.
  904.                         // /$soapval->ns/$soapval->type/$item->ns/$item->name
  905.                         $child_type $this->_wsdl->getComplexTypeChildType(
  906.                             $soapval->namespace,
  907.                             $soapval->name,
  908.                             $item->namespace,
  909.                             $item->name);
  910.                         if ($child_type{
  911.                             $item->type = $child_type;
  912.                         }
  913.                     }
  914.                     if (!$isstruct || $item->type == 'Array'{
  915.                         if (isset($return->{$item->name}&&
  916.                             is_object($return->{$item->name})) {
  917.                             $return->{$item->name=$this->_decode($item);
  918.                         elseif (isset($return->{$item->name}&&
  919.                                   is_array($return->{$item->name})) {
  920.                             $return->{$item->name}[=$this->_decode($item);
  921.                         elseif (is_array($return)) {
  922.                             $return[=$this->_decode($item);
  923.                         else {
  924.                             $return->{$item->name=$this->_decode($item);
  925.                         }
  926.                     elseif (isset($return->{$item->name})) {
  927.                         $isstruct = false;
  928.                         if (count(get_object_vars($return)) == 1{
  929.                             $d =$this->_decode($item);
  930.                             $return = array($return->{$item->name}$d);
  931.                         else {
  932.                             $d =$this->_decode($item);
  933.                             $return->{$item->name= array($return->{$item->name}$d);
  934.                         }
  935.                     else {
  936.                         $return->{$item->name=$this->_decode($item);
  937.                     }
  938.                     // Set the attributes as members in the class.
  939.                     if (method_exists($return'__set_attribute')) {
  940.                         foreach ($soapval->attributes as $key => $value{
  941.                             call_user_func_array(array(&$return,
  942.                                                        '__set_attribute'),
  943.                                                  array($key$value));
  944.                         }
  945.                     }
  946.                 else {
  947.                     if ($soapval->arrayType && $this->_isSoapValue($item)) {
  948.                         if ($this->_isBase64Type($item->type&&
  949.                             !$this->_isBase64Type($soapval->arrayType)) {
  950.                             // Decode the value if we're losing the base64
  951.                             // type information.
  952.                             $item->value = base64_decode($item->value);
  953.                         }
  954.                         $item->type = $soapval->arrayType;
  955.                     }
  956.                     if (!$isstruct{
  957.                         $return[=$this->_decode($item);
  958.                     elseif (isset($return[$item->name])) {
  959.                         $isstruct = false;
  960.                         $d =$this->_decode($item);
  961.                         $return = array($return[$item->name]$d);
  962.                     else {
  963.                         $return[$item->name=$this->_decode($item);
  964.                     }
  965.                 }
  966.             }
  967.  
  968.             return $return;
  969.         }
  970.  
  971.         if ($soapval->type == 'boolean'{
  972.             if ($soapval->value != '0' &&
  973.                 strcasecmp($soapval->value'false'!= 0{
  974.                 $soapval->value = true;
  975.             else {
  976.                 $soapval->value = false;
  977.             }
  978.         elseif ($soapval->type &&
  979.                   isset($this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type])) {
  980.             // If we can, set variable type.
  981.             settype($soapval->value,
  982.                     $this->_typemap[SOAP_XML_SCHEMA_VERSION][$soapval->type]);
  983.         }
  984.  
  985.         if ($this->_isBase64Type($soapval->type)) {
  986.             return base64_decode($soapval->value);
  987.         else {
  988.             return $soapval->value;
  989.         }
  990.     }
  991.  
  992.     /**
  993.      * Creates the SOAP envelope with the SOAP envelop data.
  994.      *
  995.      * @access private
  996.      *
  997.      * @param 
  998.      * @param array $headers 
  999.      * @param string $encoding 
  1000.      * @param array $options 
  1001.      *
  1002.      * @return string 
  1003.      */
  1004.     function &_makeEnvelope(&$method&$headers,
  1005.                             $encoding = SOAP_DEFAULT_ENCODING,
  1006.                             $options = array())
  1007.     {
  1008.         $smsg $header_xml $ns_string '';
  1009.  
  1010.         if ($headers{
  1011.             $c count($headers);
  1012.             for ($i = 0; $i $c$i++{
  1013.                 $header_xml .= $headers[$i]->serialize($this);
  1014.             }
  1015.             $header_xml = "<SOAP-ENV:Header>\r\n$header_xml\r\n</SOAP-ENV:Header>\r\n";
  1016.         }
  1017.  
  1018.         if (!isset($options['input']|| $options['input'== 'parse'{
  1019.             if (is_array($method)) {
  1020.                 $c count($method);
  1021.                 for ($i = 0; $i $c$i++{
  1022.                     $smsg .= $method[$i]->serialize($this);
  1023.                 }
  1024.             else {
  1025.                 $smsg =$method->serialize($this);
  1026.             }
  1027.         else {
  1028.             $smsg =$method;
  1029.         }
  1030.         $body "<SOAP-ENV:Body>\r\n" $smsg "\r\n</SOAP-ENV:Body>\r\n";
  1031.  
  1032.         foreach ($this->_namespaces as $k => $v{
  1033.             $ns_string .= " xmlns:$v=\"$k\"\r\n";
  1034.         }
  1035.         if ($this->_namespace{
  1036.             $ns_string .= " xmlns=\"{$this->_namespace}\"\r\n";
  1037.         }
  1038.  
  1039.         /* If 'use' == 'literal', we do not put in the encodingStyle.  This is
  1040.          * denoted by $this->_section5 being false.  'use' can be defined at a
  1041.          * more granular level than we are dealing with here, so this does not
  1042.          * work for all services. */
  1043.         $xml = "<?xml version=\"1.0\" encoding=\"$encoding\"?>\r\n\r\n".
  1044.             "<SOAP-ENV:Envelope $ns_string".
  1045.             ($this->_section5 ? ' SOAP-ENV:encodingStyle="' SOAP_SCHEMA_ENCODING . '"' '').
  1046.             ">\r\n".
  1047.             "$header_xml$body</SOAP-ENV:Envelope>\r\n";
  1048.  
  1049.         return $xml;
  1050.     }
  1051.  
  1052.     function &_makeMimeMessage(&$xml$encoding = SOAP_DEFAULT_ENCODING)
  1053.     {
  1054.         global $SOAP_options;
  1055.  
  1056.         if (!isset($SOAP_options['Mime'])) {
  1057.             return $this->_raiseSoapFault('Mime is not installed');
  1058.         }
  1059.  
  1060.         // Encode any attachments.
  1061.         // See http://www.w3.org/TR/SOAP-attachments
  1062.         // Now we have to mime encode the message.
  1063.         $params = array('content_type' => 'multipart/related; type=text/xml');
  1064.         $msg =new Mail_mimePart(''$params);
  1065.  
  1066.         // Add the xml part.
  1067.         $params['content_type''text/xml';
  1068.         $params['charset'$encoding;
  1069.         $params['encoding''base64';
  1070.         $msg->addSubPart($xml$params);
  1071.  
  1072.         // Add the attachements
  1073.         $c count($this->__attachments);
  1074.         for ($i = 0; $i $c$i++{
  1075.             $attachment =$this->__attachments[$i];
  1076.             $msg->addSubPart($attachment['body']$attachment);
  1077.         }
  1078.  
  1079.         return $msg->encode();
  1080.     }
  1081.  
  1082.     // TODO: this needs to be used from the Transport system.
  1083.     function &_makeDIMEMessage(&$xml)
  1084.     {
  1085.         global $SOAP_options;
  1086.  
  1087.         if (!isset($SOAP_options['DIME'])) {
  1088.             return $this->_raiseSoapFault('DIME is not installed');
  1089.         }
  1090.  
  1091.         // Encode any attachments.
  1092.         // See http://search.ietf.org/internet-drafts/draft-nielsen-dime-soap-00.txt
  1093.         // Now we have to DIME encode the message
  1094.         $dime =new Net_DIME_Message();
  1095.         $msg =$dime->encodeData($xmlSOAP_ENVELOPnullNET_DIME_TYPE_URI);
  1096.  
  1097.         // Add the attachments.
  1098.         $c count($this->__attachments);
  1099.         for ($i = 0; $i $c$i++{
  1100.             $attachment =$this->__attachments[$i];
  1101.             $msg .= $dime->encodeData($attachment['body'],
  1102.                                       $attachment['content_type'],
  1103.                                       $attachment['cid'],
  1104.                                       NET_DIME_TYPE_MEDIA);
  1105.         }
  1106.         $msg .= $dime->endMessage();
  1107.  
  1108.         return $msg;
  1109.     }
  1110.  
  1111.     function _decodeMimeMessage(&$data&$headers&$attachments)
  1112.     {
  1113.         global $SOAP_options;
  1114.  
  1115.         if (!isset($SOAP_options['Mime'])) {
  1116.             $this->_raiseSoapFault('Mime Unsupported, install PEAR::Mail::Mime''''''Server');
  1117.             return;
  1118.         }
  1119.  
  1120.         $params['include_bodies'= true;
  1121.         $params['decode_bodies']  = true;
  1122.         $params['decode_headers'= true;
  1123.  
  1124.         // Lame thing to have to do for decoding.
  1125.         $decoder =new Mail_mimeDecode($data);
  1126.         $structure $decoder->decode($params);
  1127.  
  1128.         if (isset($structure->body)) {
  1129.             $data $structure->body;
  1130.             $headers $structure->headers;
  1131.  
  1132.             return;
  1133.         elseif (isset($structure->parts)) {
  1134.             $data $structure->parts[0]->body;
  1135.             $headers array_merge($structure->headers,
  1136.                                    $structure->parts[0]->headers);
  1137.             if (count($structure->parts> 1{
  1138.                 $mime_parts array_splice($structure->parts,1);
  1139.                 // Prepare the parts for the SOAP parser.
  1140.  
  1141.                 $c count($mime_parts);
  1142.                 for ($i = 0; $i $c$i++{
  1143.                     $p =$mime_parts[$i];
  1144.                     if (isset($p->headers['content-location'])) {
  1145.                         // TODO: modify location per SwA note section 3
  1146.                         // http://www.w3.org/TR/SOAP-attachments
  1147.                         $attachments[$p->headers['content-location']] $p->body;
  1148.                     else {
  1149.                         $cid 'cid:' substr($p->headers['content-id']1-2);
  1150.                         $attachments[$cid$p->body;
  1151.                     }
  1152.                 }
  1153.             }
  1154.  
  1155.             return;
  1156.         }
  1157.  
  1158.         $this->_raiseSoapFault('Mime parsing error''''''Server');
  1159.     }
  1160.  
  1161.     function _decodeDIMEMessage(&$data&$headers&$attachments)
  1162.     {
  1163.         global $SOAP_options;
  1164.  
  1165.         if (!isset($SOAP_options['DIME'])) {
  1166.             $this->_raiseSoapFault('DIME Unsupported, install PEAR::Net::DIME''''''Server');
  1167.             return;
  1168.         }
  1169.  
  1170.         // This SHOULD be moved to the transport layer, e.g. PHP itself should
  1171.         // handle parsing DIME ;)
  1172.         $dime =new Net_DIME_Message();
  1173.         $err $dime->decodeData($data);
  1174.         if (PEAR::isError($err)) {
  1175.             $this->_raiseSoapFault('Failed to decode the DIME message!''''''Server');
  1176.             return;
  1177.         }
  1178.         if (strcasecmp($dime->parts[0]['type']SOAP_ENVELOP!= 0{
  1179.             $this->_raiseSoapFault('DIME record 1 is not a SOAP envelop!''''''Server');
  1180.             return;
  1181.         }
  1182.  
  1183.         $data $dime->parts[0]['data'];
  1184.         // Fake it for now.
  1185.         $headers['content-type''text/xml';
  1186.         $c count($dime->parts);
  1187.         for ($i = 0; $i $c$i++{
  1188.             $part =$dime->parts[$i];
  1189.             // We need to handle URI's better.
  1190.             $id strncmp($part['id']'cid:'4)
  1191.                 ? 'cid:' $part['id']
  1192.                 : $part['id'];
  1193.             $attachments[$id$part['data'];
  1194.         }
  1195.     }
  1196.  
  1197.     function __set_type_translation($type$class = null)
  1198.     {
  1199.         $tq =new QName($type);
  1200.         if (!$class{
  1201.             $class $tq->name;
  1202.         }
  1203.         $this->_type_translation[$type]=$class;
  1204.     }
  1205.  
  1206. }
  1207.  
  1208. /**
  1209.  * Class used to handle QNAME values in XML.
  1210.  *
  1211.  * @access   public
  1212.  * @package  SOAP
  1213.  * @author   Shane Caraveo <shane@php.net> Conversion to PEAR and updates
  1214.  */
  1215. class QName
  1216. {
  1217.     var $name = '';
  1218.     var $ns = '';
  1219.     var $namespace='';
  1220.  
  1221.     function QName($name$namespace '')
  1222.     {
  1223.         if ($name && $name[0== '{'{
  1224.             preg_match('/\{(.*?)\}(.*)/'$name$m);
  1225.             $this->name = $m[2];
  1226.             $this->namespace = $m[1];
  1227.         elseif (substr_count($name':'== 1{
  1228.             $s explode(':'$name);
  1229.             $s array_reverse($s);
  1230.             $this->name = $s[0];
  1231.             $this->ns = $s[1];
  1232.             $this->namespace = $namespace;
  1233.         else {
  1234.             $this->name = $name;
  1235.             $this->namespace = $namespace;
  1236.         }
  1237.  
  1238.         // A little more magic than should be in a qname.
  1239.         $p strpos($this->name'[');
  1240.         if ($p{
  1241.             // TODO: Need to re-examine this logic later.
  1242.             // Chop off [].
  1243.             $this->arraySize explode(','substr($this->name$p + 1-$p - 2));
  1244.             $this->arrayInfo substr($this->name$p);
  1245.             $this->name = substr($this->name0$p);
  1246.         }
  1247.     }
  1248.  
  1249.     function fqn()
  1250.     {
  1251.         if ($this->namespace{
  1252.             return '{' $this->namespace . '}' $this->name;
  1253.         elseif ($this->ns{
  1254.             return $this->ns . ':' $this->name;
  1255.         }
  1256.         return $this->name;
  1257.     }
  1258.  
  1259. }

Documentation generated on Mon, 11 Mar 2019 14:20:02 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.