Beispiel #1
0
 /**
  * Preform handshaking with HTTPS proxy using CONNECT method
  *
  * @param string  $host
  * @param integer $port
  * @param string  $http_ver
  * @param array   $headers
  */
 protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
 {
     $request = "CONNECT {$host}:{$port} HTTP/{$http_ver}\r\n" . "Host: " . $this->config['proxy_host'] . "\r\n";
     // Add the user-agent header
     if (isset($this->config['useragent'])) {
         $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
     }
     // If the proxy-authorization header is set, send it to proxy but remove
     // it from headers sent to target host
     if (isset($headers['proxy-authorization'])) {
         $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
         unset($headers['proxy-authorization']);
     }
     $request .= "\r\n";
     // Send the request
     if (!@fwrite($this->socket, $request)) {
         throw new EHttpClientException(Yii::t('EHttpClient', "Error writing request to proxy server"));
     }
     // Read response headers only
     $response = '';
     $gotStatus = false;
     while ($line = @fgets($this->socket)) {
         $gotStatus = $gotStatus || strpos($line, 'HTTP') !== false;
         if ($gotStatus) {
             $response .= $line;
             if (!chop($line)) {
                 break;
             }
         }
     }
     // Check that the response from the proxy is 200
     if (EHttpResponse::extractCode($response) != 200) {
         throw new EHttpClientException(Yii::t('EHttpClient', "Unable to connect to HTTPS proxy. Server response: " . $response));
     }
     // If all is good, switch socket to secure mode. We have to fall back
     // through the different modes
     $modes = array(STREAM_CRYPTO_METHOD_TLS_CLIENT, STREAM_CRYPTO_METHOD_SSLv3_CLIENT, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, STREAM_CRYPTO_METHOD_SSLv2_CLIENT);
     $success = false;
     foreach ($modes as $mode) {
         $success = stream_socket_enable_crypto($this->socket, true, $mode);
         if ($success) {
             break;
         }
     }
     if (!$success) {
         throw new EHttpClientException(Yii::t('EHttpClient', "Unable to connect to" . " HTTPS server through proxy: could not negotiate secure connection."));
     }
 }
 /**
  * Read response from server
  *
  * @return string
  */
 public function read()
 {
     // First, read headers only
     $response = '';
     $gotStatus = false;
     while ($line = @fgets($this->socket)) {
         $gotStatus = $gotStatus || strpos($line, 'HTTP') !== false;
         if ($gotStatus) {
             $response .= $line;
             if (!chop($line)) {
                 break;
             }
         }
     }
     $statusCode = EHttpResponse::extractCode($response);
     // Handle 100 and 101 responses internally by restarting the read again
     if ($statusCode == 100 || $statusCode == 101) {
         return $this->read();
     }
     /**
      * Responses to HEAD requests and 204 or 304 responses are not expected
      * to have a body - stop reading here
      */
     if ($statusCode == 304 || $statusCode == 204 || $this->method == EHttpClient::HEAD) {
         return $response;
     }
     // Check headers to see what kind of connection / transfer encoding we have
     $headers = EHttpResponse::extractHeaders($response);
     // if the connection is set to close, just read until socket closes
     if (isset($headers['connection']) && $headers['connection'] == 'close') {
         while ($buff = @fread($this->socket, 8192)) {
             $response .= $buff;
         }
         $this->close();
         // Else, if we got a transfer-encoding header (chunked body)
     } elseif (isset($headers['transfer-encoding'])) {
         if ($headers['transfer-encoding'] == 'chunked') {
             do {
                 $chunk = '';
                 $line = @fgets($this->socket);
                 $chunk .= $line;
                 $hexchunksize = ltrim(chop($line), '0');
                 $hexchunksize = strlen($hexchunksize) ? strtolower($hexchunksize) : 0;
                 $chunksize = hexdec(chop($line));
                 if (dechex($chunksize) != $hexchunksize) {
                     @fclose($this->socket);
                     throw new EHttpClientException(Yii::t('EHttpClient', 'Invalid chunk size "' . $hexchunksize . '" unable to read chunked body'));
                 }
                 $left_to_read = $chunksize;
                 while ($left_to_read > 0) {
                     $line = @fread($this->socket, $left_to_read);
                     $chunk .= $line;
                     $left_to_read -= strlen($line);
                 }
                 $chunk .= @fgets($this->socket);
                 $response .= $chunk;
             } while ($chunksize > 0);
         } else {
             throw new EHttpClientException(Yii::t('EHttpClient', 'Cannot handle "' . $headers['transfer-encoding'] . '" transfer encoding'));
         }
         // Else, if we got the content-length header, read this number of bytes
     } elseif (isset($headers['content-length'])) {
         $left_to_read = $headers['content-length'];
         $chunk = '';
         while ($left_to_read > 0) {
             $chunk = @fread($this->socket, $left_to_read);
             $left_to_read -= strlen($chunk);
             $response .= $chunk;
         }
         // Fallback: just read the response (should not happen)
     } else {
         while ($buff = @fread($this->socket, 8192)) {
             $response .= $buff;
         }
         $this->close();
     }
     return $response;
 }