[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/include/Zend/Http/Client/Adapter/ -> Proxy.php (source)

   1  <?php
   2  
   3  /**
   4   * Zend Framework
   5   *
   6   * LICENSE
   7   *
   8   * This source file is subject to the new BSD license that is bundled
   9   * with this package in the file LICENSE.txt.
  10   * It is also available through the world-wide-web at this URL:
  11   * http://framework.zend.com/license/new-bsd
  12   * If you did not receive a copy of the license and are unable to
  13   * obtain it through the world-wide-web, please send an email
  14   * to [email protected] so we can send you a copy immediately.
  15   *
  16   * @category   Zend
  17   * @package    Zend_Http
  18   * @subpackage Client_Adapter
  19   * @version    $Id: Proxy.php 24818 2012-05-28 18:49:53Z rob $
  20   * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  21   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  22   */
  23  
  24  /**
  25   * @see Zend_Uri_Http
  26   */
  27  require_once  'Zend/Uri/Http.php';
  28  /**
  29   * @see Zend_Http_Client
  30   */
  31  require_once  'Zend/Http/Client.php';
  32  /**
  33   * @see Zend_Http_Client_Adapter_Socket
  34   */
  35  require_once  'Zend/Http/Client/Adapter/Socket.php';
  36  
  37  /**
  38   * HTTP Proxy-supporting Zend_Http_Client adapter class, based on the default
  39   * socket based adapter.
  40   *
  41   * Should be used if proxy HTTP access is required. If no proxy is set, will
  42   * fall back to Zend_Http_Client_Adapter_Socket behavior. Just like the
  43   * default Socket adapter, this adapter does not require any special extensions
  44   * installed.
  45   *
  46   * @category   Zend
  47   * @package    Zend_Http
  48   * @subpackage Client_Adapter
  49   * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  50   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  51   */
  52  class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
  53  {
  54      /**
  55       * Parameters array
  56       *
  57       * @var array
  58       */
  59      protected $config = array(
  60          'ssltransport'  => 'ssl',
  61          'sslcert'       => null,
  62          'sslpassphrase' => null,
  63          'sslusecontext' => false,
  64          'proxy_host'    => '',
  65          'proxy_port'    => 8080,
  66          'proxy_user'    => '',
  67          'proxy_pass'    => '',
  68          'proxy_auth'    => Zend_Http_Client::AUTH_BASIC,
  69          'persistent'    => false
  70      );
  71  
  72      /**
  73       * Whether HTTPS CONNECT was already negotiated with the proxy or not
  74       *
  75       * @var boolean
  76       */
  77      protected $negotiated = false;
  78      
  79      /**
  80       * Stores the last CONNECT handshake request
  81       * 
  82       * @var string
  83       */
  84      protected $connectHandshakeRequest;
  85  
  86      /**
  87       * Connect to the remote server
  88       *
  89       * Will try to connect to the proxy server. If no proxy was set, will
  90       * fall back to the target server (behave like regular Socket adapter)
  91       *
  92       * @param string  $host
  93       * @param int     $port
  94       * @param boolean $secure
  95       */
  96      public function connect($host, $port = 80, $secure = false)
  97      {
  98          // If no proxy is set, fall back to Socket adapter
  99          if (! $this->config['proxy_host']) {
 100              return parent::connect($host, $port, $secure);
 101          }
 102  
 103          /* Url might require stream context even if proxy connection doesn't */
 104          if ($secure) {
 105              $this->config['sslusecontext'] = true;
 106          }
 107  
 108          // Connect (a non-secure connection) to the proxy server
 109          return parent::connect(
 110              $this->config['proxy_host'],
 111              $this->config['proxy_port'],
 112              false
 113          );
 114      }
 115  
 116      /**
 117       * Send request to the proxy server
 118       *
 119       * @param string        $method
 120       * @param Zend_Uri_Http $uri
 121       * @param string        $http_ver
 122       * @param array         $headers
 123       * @param string        $body
 124       * @return string Request as string
 125       */
 126      public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
 127      {
 128          // If no proxy is set, fall back to default Socket adapter
 129          if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
 130  
 131          // Make sure we're properly connected
 132          if (! $this->socket) {
 133              require_once  'Zend/Http/Client/Adapter/Exception.php';
 134              throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
 135          }
 136  
 137          $host = $this->config['proxy_host'];
 138          $port = $this->config['proxy_port'];
 139  
 140          if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) {
 141              require_once  'Zend/Http/Client/Adapter/Exception.php';
 142              throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
 143          }
 144  
 145          // Add Proxy-Authorization header
 146          if ($this->config['proxy_user']) {
 147              // Check to see if one already exists
 148              $hasProxyAuthHeader = false;
 149              foreach ($headers as $k => $v) {
 150                  if ($k == 'proxy-authorization' || preg_match("/^proxy-authorization:/i", $v) ) {
 151                      $hasProxyAuthHeader = true;
 152                      break;
 153                  }
 154              }
 155              if (!$hasProxyAuthHeader) {
 156                  $headers[] = 'Proxy-authorization: ' . Zend_Http_Client::encodeAuthHeader(
 157                      $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
 158                  );
 159              }
 160          }
 161  
 162          // if we are proxying HTTPS, preform CONNECT handshake with the proxy
 163          if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
 164              $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
 165              $this->negotiated = true;
 166          }
 167  
 168          // Save request method for later
 169          $this->method = $method;
 170  
 171          // Build request headers
 172          if ($this->negotiated) {
 173              $path = $uri->getPath();
 174              if ($uri->getQuery()) {
 175                  $path .= '?' . $uri->getQuery();
 176              }
 177              $request = "$method $path HTTP/$http_ver\r\n";
 178          } else {
 179              $request = "$method $uri HTTP/$http_ver\r\n";
 180          }
 181  
 182          // Add all headers to the request string
 183          foreach ($headers as $k => $v) {
 184              if (is_string($k)) $v = "$k: $v";
 185              $request .= "$v\r\n";
 186          }
 187  
 188          if(is_resource($body)) {
 189              $request .= "\r\n";
 190          } else {
 191              // Add the request body
 192              $request .= "\r\n" . $body;
 193          }
 194  
 195          // Send the request
 196          if (! @fwrite($this->socket, $request)) {
 197              require_once  'Zend/Http/Client/Adapter/Exception.php';
 198              throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
 199          }
 200  
 201          if(is_resource($body)) {
 202              if(stream_copy_to_stream($body, $this->socket) == 0) {
 203                  require_once  'Zend/Http/Client/Adapter/Exception.php';
 204                  throw new Zend_Http_Client_Adapter_Exception('Error writing request to server');
 205              }
 206          }
 207  
 208          return $request;
 209      }
 210  
 211      /**
 212       * Preform handshaking with HTTPS proxy using CONNECT method
 213       *
 214       * @param string  $host
 215       * @param integer $port
 216       * @param string  $http_ver
 217       * @param array   $headers
 218       */
 219      protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
 220      {
 221          $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
 222                     "Host: " . $this->config['proxy_host'] . "\r\n";
 223  
 224          // Process provided headers, including important ones to CONNECT request
 225          foreach ( $headers as $k=>$v ) {
 226              switch ( strtolower(substr($v,0,strpos($v,':'))) ) {
 227                  case 'proxy-authorization':
 228                      // break intentionally omitted
 229                  case 'user-agent':
 230                      $request .= $v . "\r\n";
 231                      break;
 232                  default:
 233                      break;
 234              }
 235          }
 236          $request .= "\r\n";
 237          
 238          // @see ZF-3189
 239          $this->connectHandshakeRequest = $request;
 240  
 241          // Send the request
 242          if (! @fwrite($this->socket, $request)) {
 243              require_once  'Zend/Http/Client/Adapter/Exception.php';
 244              throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
 245          }
 246  
 247          // Read response headers only
 248          $response = '';
 249          $gotStatus = false;
 250          while ($line = @fgets($this->socket)) {
 251              $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
 252              if ($gotStatus) {
 253                  $response .= $line;
 254                  if (!chop($line)) break;
 255              }
 256          }
 257  
 258          // Check that the response from the proxy is 200
 259          if (Zend_Http_Response::extractCode($response) != 200) {
 260              require_once  'Zend/Http/Client/Adapter/Exception.php';
 261              throw new Zend_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
 262          }
 263  
 264          // If all is good, switch socket to secure mode. We have to fall back
 265          // through the different modes
 266          $modes = array(
 267              STREAM_CRYPTO_METHOD_TLS_CLIENT,
 268              STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
 269              STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
 270              STREAM_CRYPTO_METHOD_SSLv2_CLIENT
 271          );
 272  
 273          $success = false;
 274          foreach($modes as $mode) {
 275              $success = stream_socket_enable_crypto($this->socket, true, $mode);
 276              if ($success) break;
 277          }
 278  
 279          if (! $success) {
 280                  require_once  'Zend/Http/Client/Adapter/Exception.php';
 281                  throw new Zend_Http_Client_Adapter_Exception("Unable to connect to" .
 282                      " HTTPS server through proxy: could not negotiate secure connection.");
 283          }
 284      }
 285  
 286      /**
 287       * Close the connection to the server
 288       *
 289       */
 290      public function close()
 291      {
 292          parent::close();
 293          $this->negotiated = false;
 294      }
 295  
 296      /**
 297       * Destructor: make sure the socket is disconnected
 298       *
 299       */
 300      public function __destruct()
 301      {
 302          if ($this->socket) $this->close();
 303      }
 304  }


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1