[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/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$
  20   * @copyright  Copyright (c) 2005-2010 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-2010 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       * Connect to the remote server
  81       *
  82       * Will try to connect to the proxy server. If no proxy was set, will
  83       * fall back to the target server (behave like regular Socket adapter)
  84       *
  85       * @param string  $host
  86       * @param int     $port
  87       * @param boolean $secure
  88       */
  89      public function connect($host, $port = 80, $secure = false)
  90      {
  91          // If no proxy is set, fall back to Socket adapter
  92          if (! $this->config['proxy_host']) {
  93              return parent::connect($host, $port, $secure);
  94          }
  95          
  96          /* Url might require stream context even if proxy connection doesn't */
  97          if ($secure) {
  98              $this->config['sslusecontext'] = true;
  99          }
 100  
 101          // Connect (a non-secure connection) to the proxy server
 102          return parent::connect(
 103              $this->config['proxy_host'],
 104              $this->config['proxy_port'],
 105              false
 106          );
 107      }
 108  
 109      /**
 110       * Send request to the proxy server
 111       *
 112       * @param string        $method
 113       * @param Zend_Uri_Http $uri
 114       * @param string        $http_ver
 115       * @param array         $headers
 116       * @param string        $body
 117       * @return string Request as string
 118       */
 119      public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
 120      {
 121          // If no proxy is set, fall back to default Socket adapter
 122          if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
 123  
 124          // Make sure we're properly connected
 125          if (! $this->socket) {
 126              require_once 'Zend/Http/Client/Adapter/Exception.php';
 127              throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
 128          }
 129  
 130          $host = $this->config['proxy_host'];
 131          $port = $this->config['proxy_port'];
 132  
 133          if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) {
 134              require_once 'Zend/Http/Client/Adapter/Exception.php';
 135              throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
 136          }
 137  
 138          // Add Proxy-Authorization header
 139          if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization'])) {
 140              $headers['proxy-authorization'] = Zend_Http_Client::encodeAuthHeader(
 141                  $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
 142              );
 143          }
 144  
 145          // if we are proxying HTTPS, preform CONNECT handshake with the proxy
 146          if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
 147              $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
 148              $this->negotiated = true;
 149          }
 150  
 151          // Save request method for later
 152          $this->method = $method;
 153  
 154          // Build request headers
 155          if ($this->negotiated) {
 156              $path = $uri->getPath();
 157              if ($uri->getQuery()) {
 158                  $path .= '?' . $uri->getQuery();
 159              }
 160              $request = "$method $path HTTP/$http_ver\r\n";
 161          } else {
 162              $request = "$method $uri HTTP/$http_ver\r\n";
 163          }
 164  
 165          // Add all headers to the request string
 166          foreach ($headers as $k => $v) {
 167              if (is_string($k)) $v = "$k: $v";
 168              $request .= "$v\r\n";
 169          }
 170  
 171          if(is_resource($body)) {
 172              $request .= "\r\n";
 173          } else {
 174              // Add the request body
 175              $request .= "\r\n" . $body;
 176          }
 177          
 178          // Send the request
 179          if (! @fwrite($this->socket, $request)) {
 180              require_once 'Zend/Http/Client/Adapter/Exception.php';
 181              throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
 182          }
 183          
 184          if(is_resource($body)) {
 185              if(stream_copy_to_stream($body, $this->socket) == 0) {
 186                  require_once 'Zend/Http/Client/Adapter/Exception.php';
 187                  throw new Zend_Http_Client_Adapter_Exception('Error writing request to server');
 188              }
 189          }
 190          
 191          return $request;
 192      }
 193  
 194      /**
 195       * Preform handshaking with HTTPS proxy using CONNECT method
 196       *
 197       * @param string  $host
 198       * @param integer $port
 199       * @param string  $http_ver
 200       * @param array   $headers
 201       */
 202      protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
 203      {
 204          $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
 205                     "Host: " . $this->config['proxy_host'] . "\r\n";
 206  
 207          // Add the user-agent header
 208          if (isset($this->config['useragent'])) {
 209              $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
 210          }
 211  
 212          // If the proxy-authorization header is set, send it to proxy but remove
 213          // it from headers sent to target host
 214          if (isset($headers['proxy-authorization'])) {
 215              $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
 216              unset($headers['proxy-authorization']);
 217          }
 218  
 219          $request .= "\r\n";
 220  
 221          // Send the request
 222          if (! @fwrite($this->socket, $request)) {
 223              require_once 'Zend/Http/Client/Adapter/Exception.php';
 224              throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
 225          }
 226  
 227          // Read response headers only
 228          $response = '';
 229          $gotStatus = false;
 230          while ($line = @fgets($this->socket)) {
 231              $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
 232              if ($gotStatus) {
 233                  $response .= $line;
 234                  if (!chop($line)) break;
 235              }
 236          }
 237  
 238          // Check that the response from the proxy is 200
 239          if (Zend_Http_Response::extractCode($response) != 200) {
 240              require_once 'Zend/Http/Client/Adapter/Exception.php';
 241              throw new Zend_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
 242          }
 243  
 244          // If all is good, switch socket to secure mode. We have to fall back
 245          // through the different modes
 246          $modes = array(
 247              STREAM_CRYPTO_METHOD_TLS_CLIENT,
 248              STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
 249              STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
 250              STREAM_CRYPTO_METHOD_SSLv2_CLIENT
 251          );
 252  
 253          $success = false;
 254          foreach($modes as $mode) {
 255              $success = stream_socket_enable_crypto($this->socket, true, $mode);
 256              if ($success) break;
 257          }
 258  
 259          if (! $success) {
 260                  require_once 'Zend/Http/Client/Adapter/Exception.php';
 261                  throw new Zend_Http_Client_Adapter_Exception("Unable to connect to" .
 262                      " HTTPS server through proxy: could not negotiate secure connection.");
 263          }
 264      }
 265  
 266      /**
 267       * Close the connection to the server
 268       *
 269       */
 270      public function close()
 271      {
 272          parent::close();
 273          $this->negotiated = false;
 274      }
 275  
 276      /**
 277       * Destructor: make sure the socket is disconnected
 278       *
 279       */
 280      public function __destruct()
 281      {
 282          if ($this->socket) $this->close();
 283      }
 284  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1