home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / SOAP / Client.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  27.5 KB  |  856 lines

  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(zend_version(), 0, 1) > 1) {
  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.  * or, if using PHP 5+ or the overload extension:<code>
  72.  *   $soapclient = new SOAP_Client( string path [ , boolean wsdl] );
  73.  *   echo $soapclient->methodname( [ array parameters] );
  74.  * </code>
  75.  *
  76.  * Originally based on SOAPx4 by Dietrich Ayala
  77.  * http://dietrich.ganx4.com/soapx4
  78.  *
  79.  * @access   public
  80.  * @package  SOAP
  81.  * @author   Shane Caraveo <shane@php.net> Conversion to PEAR and updates
  82.  * @author   Stig Bakken <ssb@fast.no> Conversion to PEAR
  83.  * @author   Dietrich Ayala <dietrich@ganx4.com> Original Author
  84.  */
  85. class SOAP_Client extends SOAP_Client_Overload
  86. {
  87.     /**
  88.      * Communication endpoint.
  89.      *
  90.      * Currently the following transport formats are supported:
  91.      *  - HTTP
  92.      *  - SMTP
  93.      *
  94.      * Example endpoints:
  95.      *   http://www.example.com/soap/server.php
  96.      *   https://www.example.com/soap/server.php
  97.      *   mailto:soap@example.com
  98.      *
  99.      * @see SOAP_Client()
  100.      * @var string
  101.      */
  102.     var $_endpoint = '';
  103.  
  104.     /**
  105.      * The SOAP PORT name that is used by the client.
  106.      *
  107.      * @var string
  108.      */
  109.     var $_portName = '';
  110.  
  111.     /**
  112.      * Endpoint type e.g. 'wdsl'.
  113.      *
  114.      * @var string
  115.      */
  116.     var $_endpointType = '';
  117.  
  118.     /**
  119.      * The received xml.
  120.      *
  121.      * @var string
  122.      */
  123.     var $xml;
  124.  
  125.     /**
  126.      * The outgoing and incoming data stream for debugging.
  127.      *
  128.      * @var string
  129.      */
  130.     var $wire;
  131.  
  132.     /**
  133.      * The outgoing data stream for debugging.
  134.      *
  135.      * @var string
  136.      */
  137.     var $_last_request = null;
  138.  
  139.     /**
  140.      * The incoming data stream for debugging.
  141.      *
  142.      * @var string
  143.      */
  144.     var $_last_response = null;
  145.  
  146.     /**
  147.      * Options.
  148.      *
  149.      * @var array
  150.      */
  151.     var $_options = array('trace' => false);
  152.  
  153.     /**
  154.      * The character encoding used for XML parser, etc.
  155.      *
  156.      * @var string
  157.      */
  158.     var $_encoding = SOAP_DEFAULT_ENCODING;
  159.  
  160.     /**
  161.      * The array of SOAP_Headers that we are sending.
  162.      *
  163.      * @var array
  164.      */
  165.     var $headersOut = null;
  166.  
  167.     /**
  168.      * The headers we recieved back in the response.
  169.      *
  170.      * @var array
  171.      */
  172.     var $headersIn = null;
  173.  
  174.     /**
  175.      * Options for the HTTP_Request class (see HTTP/Request.php).
  176.      *
  177.      * @var array
  178.      */
  179.     var $_proxy_params = array();
  180.  
  181.     /**
  182.      * The SOAP_Transport instance.
  183.      *
  184.      * @var SOAP_Transport
  185.      */
  186.     var $_soap_transport = null;
  187.  
  188.     /**
  189.      * Constructor.
  190.      *
  191.      * @access public
  192.      *
  193.      * @param string $endpoint       An URL.
  194.      * @param boolean $wsdl          Whether the endpoint is a WSDL file.
  195.      * @param string $portName       The service's port name to use.
  196.      * @param array $proxy_params    Options for the HTTP_Request class
  197.      *                               @see HTTP_Request
  198.      * @param boolean|string $cache  Use WSDL caching? The cache directory if
  199.      *                               a string.
  200.      */
  201.     function SOAP_Client($endpoint, $wsdl = false, $portName = false,
  202.                          $proxy_params = array(), $cache = false)
  203.     {
  204.         parent::SOAP_Base('Client');
  205.  
  206.         $this->_endpoint = $endpoint;
  207.         $this->_portName = $portName;
  208.         $this->_proxy_params = $proxy_params;
  209.  
  210.         // This hack should perhaps be removed as it might cause unexpected
  211.         // behaviour.
  212.         $wsdl = $wsdl
  213.             ? $wsdl
  214.             : strtolower(substr($endpoint, -4)) == 'wsdl';
  215.  
  216.         // make values
  217.         if ($wsdl) {
  218.             $this->_endpointType = 'wsdl';
  219.             // instantiate wsdl class
  220.             $this->_wsdl = new SOAP_WSDL($this->_endpoint,
  221.                                          $this->_proxy_params,
  222.                                          $cache);
  223.             if ($this->_wsdl->fault) {
  224.                 $this->_raiseSoapFault($this->_wsdl->fault);
  225.             }
  226.         }
  227.     }
  228.  
  229.     function _reset()
  230.     {
  231.         $this->xml = null;
  232.         $this->wire = null;
  233.         $this->_last_request = null;
  234.         $this->_last_response = null;
  235.         $this->headersIn = null;
  236.         $this->headersOut = null;
  237.     }
  238.  
  239.     /**
  240.      * Sets the character encoding.
  241.      *
  242.      * Limited to 'UTF-8', 'US_ASCII' and 'ISO-8859-1'.
  243.      *
  244.      * @access public
  245.      *
  246.      * @param string encoding
  247.      *
  248.      * @return mixed  SOAP_Fault on error.
  249.      */
  250.     function setEncoding($encoding)
  251.     {
  252.         if (in_array($encoding, $this->_encodings)) {
  253.             $this->_encoding = $encoding;
  254.             return;
  255.         }
  256.         return $this->_raiseSoapFault('Invalid Encoding');
  257.     }
  258.  
  259.     /**
  260.      * Adds a header to the envelope.
  261.      *
  262.      * @access public
  263.      *
  264.      * @param SOAP_Header $soap_value  A SOAP_Header or an array with the
  265.      *                                 elements 'name', 'namespace',
  266.      *                                 'mustunderstand', and 'actor' to send
  267.      *                                 as a header.
  268.      */
  269.     function addHeader($soap_value)
  270.     {
  271.         // Add a new header to the message.
  272.         if (is_a($soap_value, 'SOAP_Header')) {
  273.             $this->headersOut[] = $soap_value;
  274.         } elseif (is_array($soap_value)) {
  275.             // name, value, namespace, mustunderstand, actor
  276.             $this->headersOut[] = new SOAP_Header($soap_value[0],
  277.                                                   null,
  278.                                                   $soap_value[1],
  279.                                                   $soap_value[2],
  280.                                                   $soap_value[3]);
  281.         } else {
  282.             $this->_raiseSoapFault('Invalid parameter provided to addHeader().  Must be an array or a SOAP_Header.');
  283.         }
  284.     }
  285.  
  286.     /**
  287.      * Calls a method on the SOAP endpoint.
  288.      *
  289.      * The namespace parameter is overloaded to accept an array of options
  290.      * that can contain data necessary for various transports if it is used as
  291.      * an array, it MAY contain a namespace value and a soapaction value.  If
  292.      * it is overloaded, the soapaction parameter is ignored and MUST be
  293.      * placed in the options array.  This is done to provide backwards
  294.      * compatibility with current clients, but may be removed in the future.
  295.      * The currently supported values are:<pre>
  296.      *   namespace
  297.      *   soapaction
  298.      *   timeout (HTTP socket timeout)
  299.      *   transfer-encoding (SMTP, Content-Transfer-Encoding: header)
  300.      *   from (SMTP, From: header)
  301.      *   subject (SMTP, Subject: header)
  302.      *   headers (SMTP, hash of extra SMTP headers)
  303.      * </pre>
  304.      *
  305.      * @access public
  306.      *
  307.      * @param string $method           The method to call.
  308.      * @param array $params            The method parameters.
  309.      * @param string|array $namespace  Namespace or hash with options.
  310.      * @param string $soapAction
  311.      *
  312.      * @return mixed  The method result or a SOAP_Fault on error.
  313.      */
  314.     function &call($method, &$params, $namespace = false, $soapAction = false)
  315.     {
  316.         $this->headersIn = null;
  317.         $this->_last_request = null;
  318.         $this->_last_response = null;
  319.         $this->wire = null;
  320.         $this->xml = null;
  321.  
  322.         $soap_data = $this->_generate($method, $params, $namespace, $soapAction);
  323.         if (PEAR::isError($soap_data)) {
  324.             $fault = $this->_raiseSoapFault($soap_data);
  325.             return $fault;
  326.         }
  327.  
  328.         // _generate() may have changed the endpoint if the WSDL has more
  329.         // than one service, so we need to see if we need to generate a new
  330.         // transport to hook to a different URI.  Since the transport protocol
  331.         // can also change, we need to get an entirely new object.  This could
  332.         // probably be optimized.
  333.         if (!$this->_soap_transport ||
  334.             $this->_endpoint != $this->_soap_transport->url) {
  335.             $this->_soap_transport =& SOAP_Transport::getTransport($this->_endpoint);
  336.             if (PEAR::isError($this->_soap_transport)) {
  337.                 $fault =& $this->_soap_transport;
  338.                 $this->_soap_transport = null;
  339.                 $fault = $this->_raiseSoapFault($fault);
  340.                 return $fault;
  341.             }
  342.         }
  343.         $this->_soap_transport->encoding = $this->_encoding;
  344.  
  345.         // Send the message.
  346.         $transport_options = array_merge_recursive($this->_proxy_params,
  347.                                                    $this->_options);
  348.         $this->xml = $this->_soap_transport->send($soap_data, $transport_options);
  349.  
  350.         // Save the wire information for debugging.
  351.         if ($this->_options['trace']) {
  352.             $this->_last_request = $this->_soap_transport->outgoing_payload;
  353.             $this->_last_response = $this->_soap_transport->incoming_payload;
  354.             $this->wire = $this->getWire();
  355.         }
  356.         if ($this->_soap_transport->fault) {
  357.             $fault = $this->_raiseSoapFault($this->xml);
  358.             return $fault;
  359.         }
  360.  
  361.         if (isset($this->_options['result']) &&
  362.             $this->_options['result'] != 'parse') {
  363.             return $this->xml;
  364.         }
  365.  
  366.         $this->__result_encoding = $this->_soap_transport->result_encoding;
  367.  
  368.         $result = &$this->parseResponse($this->xml, $this->__result_encoding,
  369.                                         $this->_soap_transport->attachments);
  370.         return $result;
  371.     }
  372.  
  373.     /**
  374.      * Sets an option to use with the transport layers.
  375.      *
  376.      * For example:
  377.      * <code>
  378.      * $soapclient->setOpt('curl', CURLOPT_VERBOSE, 1)
  379.      * </code>
  380.      * to pass a specific option to curl if using an SSL connection.
  381.      *
  382.      * @access public
  383.      *
  384.      * @param string $category  Category to which the option applies or option
  385.      *                          name.
  386.      * @param string $option    An option name if $category is a category name,
  387.      *                          an option value if $category is an option name.
  388.      * @param string $value     An option value if $category is a category
  389.      *                          name.
  390.      */
  391.     function setOpt($category, $option, $value = null)
  392.     {
  393.         if (!is_null($value)) {
  394.             if (!isset($this->_options[$category])) {
  395.                 $this->_options[$category] = array();
  396.             }
  397.             $this->_options[$category][$option] = $value;
  398.         } else {
  399.             $this->_options[$category] = $option;
  400.         }
  401.     }
  402.  
  403.     /**
  404.      * Call method supporting the overload extension.
  405.      *
  406.      * If the overload extension is loaded, you can call the client class with
  407.      * a soap method name:
  408.      * <code>
  409.      * $soap = new SOAP_Client(....);
  410.      * $value = $soap->getStockQuote('MSFT');
  411.      * </code>
  412.      *
  413.      * @access public
  414.      *
  415.      * @param string $method        The method to call.
  416.      * @param array $params         The method parameters.
  417.      * @param mixed $return_value   Will get the method's return value
  418.      *                              assigned.
  419.      *
  420.      * @return boolean  Always true.
  421.      */
  422.     function _call($method, $params, &$return_value)
  423.     {
  424.         // Overloading lowercases the method name, we need to look into the
  425.         // WSDL and try to find the correct method name to get the correct
  426.         // case for the call.
  427.         if ($this->_wsdl) {
  428.             $this->_wsdl->matchMethod($method);
  429.         }
  430.  
  431.         $return_value =& $this->call($method, $params);
  432.  
  433.         return true;
  434.     }
  435.  
  436.     /**
  437.      * @deprecated Use getLastRequest().
  438.      */
  439.     function &__getlastrequest()
  440.     {
  441.         $request = $this->getLastRequest();
  442.         return $request;
  443.     }
  444.  
  445.     /**
  446.      * Returns the XML content of the last SOAP request.
  447.      *
  448.      * @return string  The last request.
  449.      */
  450.     function getLastRequest()
  451.     {
  452.         return $this->_last_request;
  453.     }
  454.  
  455.     /**
  456.      * @deprecated Use getLastResponse().
  457.      */
  458.     function &__getlastresponse()
  459.     {
  460.         $response =& $this->getLastResponse;
  461.         return $response;
  462.     }
  463.  
  464.     /**
  465.      * Returns the XML content of the last SOAP response.
  466.      *
  467.      * @return string  The last response.
  468.      */
  469.     function getLastResponse()
  470.     {
  471.         return $this->_last_response;
  472.     }
  473.  
  474.     /**
  475.      * @deprecated Use setUse().
  476.      */
  477.     function __use($use)
  478.     {
  479.         $this->setUse($use);
  480.     }
  481.  
  482.     /**
  483.      * Sets the SOAP encoding.
  484.      *
  485.      * @param string $use  Either 'literal' or 'encoded' (section 5).
  486.      */
  487.     function setUse($use)
  488.     {
  489.         $this->_options['use'] = $use;
  490.     }
  491.  
  492.     /**
  493.      * @deprecated Use setStyle().
  494.      */
  495.     function __style($style)
  496.     {
  497.         $this->setStyle($style);
  498.     }
  499.  
  500.     /**
  501.      * Sets the SOAP encoding style.
  502.      *
  503.      * @param string $style  Either 'document' or 'rpc'.
  504.      */
  505.     function setStyle($style)
  506.     {
  507.         $this->_options['style'] = $style;
  508.     }
  509.  
  510.     /**
  511.      * @deprecated Use setTrace().
  512.      */
  513.     function __trace($level)
  514.     {
  515.         $this->setTrace($level);
  516.     }
  517.  
  518.     /**
  519.      * Sets whether to trace the traffic on the transport level.
  520.      *
  521.      * @see getWire()
  522.      *
  523.      * @param boolean $trace
  524.      */
  525.     function setTrace($trace)
  526.     {
  527.         $this->_options['trace'] = $trace;
  528.     }
  529.  
  530.     function _generate($method, &$params, $namespace = false,
  531.                        $soapAction = false)
  532.     {
  533.         $this->fault = null;
  534.         $this->_options['input'] = 'parse'; 
  535.         $this->_options['result'] = 'parse';
  536.         $this->_options['parameters'] = false;
  537.  
  538.         if ($params && gettype($params) != 'array') {
  539.             $params = array($params);
  540.         }
  541.  
  542.         if (gettype($namespace) == 'array') {
  543.             foreach ($namespace as $optname => $opt) {
  544.                 $this->_options[strtolower($optname)] = $opt;
  545.             }
  546.             if (isset($this->_options['namespace'])) {
  547.                 $namespace = $this->_options['namespace'];
  548.             } else {
  549.                 $namespace = false;
  550.             }
  551.         } else {
  552.             // We'll place $soapAction into our array for usage in the
  553.             // transport.
  554.             $this->_options['soapaction'] = $soapAction;
  555.             $this->_options['namespace'] = $namespace;
  556.         }
  557.  
  558.         if ($this->_endpointType == 'wsdl') {
  559.             $this->_setSchemaVersion($this->_wsdl->xsd);
  560.  
  561.             // Get port name.
  562.             if (!$this->_portName) {
  563.                 $this->_portName = $this->_wsdl->getPortName($method);
  564.             }
  565.             if (PEAR::isError($this->_portName)) {
  566.                 return $this->_raiseSoapFault($this->_portName);
  567.             }
  568.  
  569.             // Get endpoint.
  570.             $this->_endpoint = $this->_wsdl->getEndpoint($this->_portName);
  571.             if (PEAR::isError($this->_endpoint)) {
  572.                 return $this->_raiseSoapFault($this->_endpoint);
  573.             }
  574.  
  575.             // Get operation data.
  576.             $opData = $this->_wsdl->getOperationData($this->_portName, $method);
  577.  
  578.             if (PEAR::isError($opData)) {
  579.                 return $this->_raiseSoapFault($opData);
  580.             }
  581.             $namespace = $opData['namespace'];
  582.             $this->_options['style'] = $opData['style'];
  583.             $this->_options['use'] = $opData['input']['use'];
  584.             $this->_options['soapaction'] = $opData['soapAction'];
  585.  
  586.             // Set input parameters.
  587.             if ($this->_options['input'] == 'parse') {
  588.                 $this->_options['parameters'] = $opData['parameters'];
  589.                 $nparams = array();
  590.                 if (isset($opData['input']['parts']) &&
  591.                     count($opData['input']['parts'])) {
  592.                     foreach ($opData['input']['parts'] as $name => $part) {
  593.                         $xmlns = '';
  594.                         $attrs = array();
  595.                         // Is the name a complex type?
  596.                         if (isset($part['element'])) {
  597.                             $xmlns = $this->_wsdl->namespaces[$part['namespace']];
  598.                             $part = $this->_wsdl->elements[$part['namespace']][$part['type']];
  599.                             $name = $part['name'];
  600.                         }
  601.                         if (isset($params[$name]) ||
  602.                             $this->_wsdl->getDataHandler($name, $part['namespace'])) {
  603.                             $nparams[$name] =& $params[$name];
  604.                         } else {
  605.                             // We now force an associative array for
  606.                             // parameters if using WSDL.
  607.                             return $this->_raiseSoapFault("The named parameter $name is not in the call parameters.");
  608.                         }
  609.                         if (gettype($nparams[$name]) != 'object' ||
  610.                             !is_a($nparams[$name], 'SOAP_Value')) {
  611.                             // Type is likely a qname, split it apart, and get
  612.                             // the type namespace from WSDL.
  613.                             $qname = new QName($part['type']);
  614.                             if ($qname->ns) {
  615.                                 $type_namespace = $this->_wsdl->namespaces[$qname->ns];
  616.                             } elseif (isset($part['namespace'])) {
  617.                                 $type_namespace = $this->_wsdl->namespaces[$part['namespace']];
  618.                             } else {
  619.                                 $type_namespace = null;
  620.                             }
  621.                             $qname->namespace = $type_namespace;
  622.                             $pqname = $name;
  623.                             if ($xmlns) {
  624.                                 $pqname = '{' . $xmlns . '}' . $name;
  625.                             }
  626.                             $nparams[$name] = new SOAP_Value($pqname,
  627.                                                               $qname->fqn(),
  628.                                                               $nparams[$name],
  629.                                                               $attrs);
  630.                         } else {
  631.                             // WSDL fixups to the SOAP value.
  632.                         }
  633.                     }
  634.                 }
  635.                 $params =& $nparams;
  636.                 unset($nparams);
  637.             }
  638.         } else {
  639.             $this->_setSchemaVersion(SOAP_XML_SCHEMA_VERSION);
  640.         }
  641.  
  642.         // Serialize the message.
  643.         $this->_section5 = (!isset($this->_options['use']) ||
  644.                             $this->_options['use'] != 'literal');
  645.  
  646.         if (!isset($this->_options['style']) ||
  647.             $this->_options['style'] == 'rpc') {
  648.             $this->_options['style'] = 'rpc';
  649.             $this->docparams = true;
  650.             $mqname = new QName($method, $namespace);
  651.             $methodValue = new SOAP_Value($mqname->fqn(), 'Struct', $params);
  652.             $soap_msg = $this->makeEnvelope($methodValue,
  653.                                             $this->headersOut,
  654.                                             $this->_encoding,
  655.                                             $this->_options);
  656.         } else {
  657.             if (!$params) {
  658.                 $mqname = new QName($method, $namespace);
  659.                 $mynull = null;
  660.                 $params = new SOAP_Value($mqname->fqn(), 'Struct', $mynull);
  661.             } elseif ($this->_options['input'] == 'parse') {
  662.                 if (is_array($params)) {
  663.                     $nparams = array();
  664.                     $keys = array_keys($params);
  665.                     foreach ($keys as $k) {
  666.                         if (gettype($params[$k]) != 'object') {
  667.                             $nparams[] = new SOAP_Value($k,
  668.                                                         false,
  669.                                                         $params[$k]);
  670.                         } else {
  671.                             $nparams[] =& $params[$k];
  672.                         }
  673.                     }
  674.                     $params =& $nparams;
  675.                 }
  676.                 if ($this->_options['parameters']) {
  677.                     $mqname = new QName($method, $namespace);
  678.                     $params = new SOAP_Value($mqname->fqn(),
  679.                                              'Struct',
  680.                                              $params);
  681.                 }
  682.             }
  683.             $soap_msg = $this->makeEnvelope($params,
  684.                                             $this->headersOut,
  685.                                             $this->_encoding,
  686.                                             $this->_options);
  687.         }
  688.         unset($this->headersOut);
  689.  
  690.         if (PEAR::isError($soap_msg)) {
  691.             return $this->_raiseSoapFault($soap_msg);
  692.         }
  693.  
  694.         // Handle MIME or DIME encoding.
  695.         // TODO: DIME encoding should move to the transport, do it here for
  696.         // now and for ease of getting it done.
  697.         if (count($this->_attachments)) {
  698.             if ((isset($this->_options['attachments']) &&
  699.                  $this->_options['attachments'] == 'Mime') ||
  700.                 isset($this->_options['Mime'])) {
  701.                 $soap_msg = $this->_makeMimeMessage($soap_msg, $this->_encoding);
  702.             } else {
  703.                 // default is dime
  704.                 $soap_msg = $this->_makeDIMEMessage($soap_msg, $this->_encoding);
  705.                 $this->_options['headers']['Content-Type'] = 'application/dime';
  706.             }
  707.             if (PEAR::isError($soap_msg)) {
  708.                 return $this->_raiseSoapFault($soap_msg);
  709.             }
  710.         }
  711.  
  712.         // Instantiate client.
  713.         if (is_array($soap_msg)) {
  714.             $soap_data = $soap_msg['body'];
  715.             if (count($soap_msg['headers'])) {
  716.                 if (isset($this->_options['headers'])) {
  717.                     $this->_options['headers'] = array_merge($this->_options['headers'], $soap_msg['headers']);
  718.                 } else {
  719.                     $this->_options['headers'] = $soap_msg['headers'];
  720.                 }
  721.             }
  722.         } else {
  723.             $soap_data = $soap_msg;
  724.         }
  725.  
  726.         return $soap_data;
  727.     }
  728.  
  729.     /**
  730.      * @deprecated Use parseResponse().
  731.      */
  732.     function &__parse(&$response, $encoding, &$attachments)
  733.     {
  734.         return $this->parseResponse($response, $encoding, $attachments);
  735.     }
  736.  
  737.     /**
  738.      * Parses a SOAP response.
  739.      *
  740.      * @see SOAP_Parser::
  741.      *
  742.      * @param string $response    XML content of SOAP response.
  743.      * @param string $encoding    Character set encoding, defaults to 'UTF-8'.
  744.      * @param array $attachments  List of attachments.
  745.      */
  746.     function &parseResponse($response, $encoding, &$attachments)
  747.     {
  748.         // Parse the response.
  749.         $response =& new SOAP_Parser($response, $encoding, $attachments);
  750.         if ($response->fault) {
  751.             $fault =& $this->_raiseSoapFault($response->fault);
  752.             return $fault;
  753.         }
  754.  
  755.         // Return array of parameters.
  756.         $return =& $response->getResponse();
  757.         $headers =& $response->getHeaders();
  758.         if ($headers) {
  759.             $this->headersIn =& $this->_decodeResponse($headers, false);
  760.         }
  761.  
  762.         $decoded = &$this->_decodeResponse($return);
  763.         return $decoded;
  764.     }
  765.  
  766.     /**
  767.     *   Converts a complex SOAP_Value into a PHP Array
  768.     *
  769.     *   @param SOAP_Value   $response   value object
  770.     *   @param boolean      $shift      FIXME
  771.     *   @return Array
  772.     */
  773.     function &_decodeResponse($response, $shift = true)
  774.     {
  775.         if (!$response) {
  776.             $decoded = null;
  777.             return $decoded;
  778.         }
  779.  
  780.         // Check for valid response.
  781.         if (PEAR::isError($response)) {
  782.             $fault =& $this->_raiseSoapFault($response);
  783.             return $fault;
  784.         } elseif (!is_a($response, 'soap_value')) {
  785.             $fault =& $this->_raiseSoapFault("Didn't get SOAP_Value object back from client");
  786.             return $fault;
  787.         }
  788.  
  789.         // Decode to native php datatype.
  790.         $returnArray =& $this->_decode($response);
  791.  
  792.         // Fault?
  793.         if (PEAR::isError($returnArray)) {
  794.             $fault =& $this->_raiseSoapFault($returnArray);
  795.             return $fault;
  796.         }
  797.  
  798.         if (is_object($returnArray) &&
  799.             strcasecmp(get_class($returnArray), 'stdClass') == 0) {
  800.             $returnArray = get_object_vars($returnArray);
  801.         }
  802.         if (is_array($returnArray)) {
  803.             if (isset($returnArray['faultcode']) ||
  804.                 isset($returnArray['SOAP-ENV:faultcode'])) {
  805.                 $faultcode = $faultstring = $faultdetail = $faultactor = '';
  806.                 foreach ($returnArray as $k => $v) {
  807.                     if (stristr($k, 'faultcode')) $faultcode = $v;
  808.                     if (stristr($k, 'faultstring')) $faultstring = $v;
  809.                     if (stristr($k, 'detail')) $faultdetail = $v;
  810.                     if (stristr($k, 'faultactor')) $faultactor = $v;
  811.                 }
  812.                 $fault =& $this->_raiseSoapFault($faultstring, $faultdetail, $faultactor, $faultcode);
  813.                 return $fault;
  814.             }
  815.             // Return array of return values.
  816.             if ($shift && count($returnArray) == 1) {
  817.                 $decoded = array_shift($returnArray);
  818.                 return $decoded;
  819.             }
  820.             return $returnArray;
  821.         }
  822.         return $returnArray;
  823.     }
  824.  
  825.     /**
  826.      * @deprecated Use getWire().
  827.      */
  828.     function __get_wire()
  829.     {
  830.         return $this->getWire();
  831.     }
  832.  
  833.     /**
  834.      * Returns the outgoing and incoming traffic on the transport level.
  835.      *
  836.      * Tracing has to be enabled.
  837.      *
  838.      * @see setTrace()
  839.      *
  840.      * @return string  The complete traffic between the client and the server.
  841.      */
  842.     function getWire()
  843.     {
  844.         if ($this->_options['trace'] &&
  845.             ($this->_last_request || $this->_last_response)) {
  846.             return "OUTGOING:\n\n" .
  847.                 $this->_last_request .
  848.                 "\n\nINCOMING\n\n" .
  849.                 preg_replace("/></",">\r\n<", $this->_last_response);
  850.         }
  851.  
  852.         return null;
  853.     }
  854.  
  855. }
  856.