diff -u -p -r1.1222 common.inc
--- includes/common.inc	17 Sep 2010 14:53:21 -0000	1.1222
+++ includes/common.inc	18 Sep 2010 11:21:55 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: common.inc,v 1.1222 2010/09/17 14:53:21 dries Exp $
+// $Id: common.inc,v 1.1221 2010/09/16 20:14:49 dries Exp $
 
 /**
  * @file
@@ -767,7 +767,7 @@ function drupal_access_denied() {
  *   - data
  *       A string containing the response body that was received.
  */
-function drupal_http_request($url, array $options = array()) {
+function drupal_http_request($url, array $options = array(), $fp_in = NULL) {
   $result = new stdClass();
 
   // Parse the URL and make sure we can handle the schema.
@@ -785,12 +785,11 @@ function drupal_http_request($url, array
     return $result;
   }
 
-  timer_start(__FUNCTION__);
-
   // Merge the default options.
   $options += array(
     'headers' => array(),
     'method' => 'GET',
+    'protocol' => 'HTTP/1.0',
     'data' => NULL,
     'max_redirects' => 3,
     'timeout' => 30.0,
@@ -799,21 +798,67 @@ function drupal_http_request($url, array
   // stream_socket_client() requires timeout to be a float.
   $options['timeout'] = (float) $options['timeout'];
 
+  // Merge the default headers.
+  $options['headers'] += array(
+    'User-Agent' => 'Drupal (+http://drupal.org/)',
+  );
+  // RFC 2616: "... non-standard ports MUST, default ports MAY be included ...".
+  // When port is implicit (standard port), allow Header Host without information
+  // for port, else some rewrite rules could be broken when checking the host
+  // that do not take into account the port number.
+  $options['headers']['Host']  = $uri['host'];
+  if (isset($uri['port'])){
+      $options['headers']['Host'] .= ":" . $uri['port'];
+  }
+
+  // Proxy setup - normal sites don't need a proxy.
+  $proxy_server = variable_get('proxy_server', '');
+  if ($proxy_server && _drupal_http_use_proxy($uri['host'])) {
+    // Since the url is passed as the path, we won't use the parsed query.
+    unset($uri['query']);
+    $uri['path'] = $url;
+    // Set the scheme so we open a socket to the proxy server.
+    if ($uri['scheme'] == 'https'){
+        $uri['scheme'] = 'proxy_https';
+    }
+    else{
+        $uri['scheme'] = 'proxy_http';
+    }
+    if ($proxy_username = variable_get('proxy_username', '')) {
+      $proxy_password = variable_get('proxy_password', '');
+      // As described by RFC-2617 for Basic Authentication Scheme.
+      // Digest Access Authentication Scheme is not supported (by now)
+      $options['headers']['Proxy-Authorization'] = 'Basic ' . base64_encode($proxy_username . (!empty($proxy_password) ? ":" . $proxy_password : ''));
+    }
+    // Some proxies reject requests with any User-Agent headers, while others
+    // require a specific one.
+    $proxy_user_agent = variable_get('proxy_user_agent', '');
+    // The default value matches neither condition.
+    if ($proxy_user_agent === NULL) {
+      unset($options['headers']['User-Agent']);
+    }
+    elseif ($proxy_user_agent) {
+      $options['headers']['User-Agent'] = $proxy_user_agent;
+    }
+  }
+
+  timer_start(__FUNCTION__);
+
   switch ($uri['scheme']) {
+    case 'proxy_http':
+    case 'proxy_https':
+      // Make the socket connection to a proxy server.
+      $socket = 'tcp://' . $proxy_server . ':' . variable_get('proxy_port', 8080);
+      break;
     case 'http':
     case 'feed':
-      $port = isset($uri['port']) ? $uri['port'] : 80;
-      $socket = 'tcp://' . $uri['host'] . ':' . $port;
-      // RFC 2616: "non-standard ports MUST, default ports MAY be included".
-      // We don't add the standard port to prevent from breaking rewrite rules
-      // checking the host that do not take into account the port number.
-      $options['headers']['Host'] = $uri['host'] . ($port != 80 ? ':' . $port : '');
+      $socket  = 'tcp://' . $uri['host'] . ':';
+      $socket .= isset($uri['port']) ? $uri['port'] : 80;
       break;
     case 'https':
       // Note: Only works when PHP is compiled with OpenSSL support.
-      $port = isset($uri['port']) ? $uri['port'] : 443;
-      $socket = 'ssl://' . $uri['host'] . ':' . $port;
-      $options['headers']['Host'] = $uri['host'] . ($port != 443 ? ':' . $port : '');
+      $socket  = 'ssl://' . $uri['host'] . ':';
+      $socket .= isset($uri['port']) ? $uri['port'] : 443;
       break;
     default:
       $result->error = 'invalid schema ' . $uri['scheme'];
@@ -821,12 +866,14 @@ function drupal_http_request($url, array
       return $result;
   }
 
-  if (empty($options['context'])) {
-    $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout']);
-  }
-  else {
-    // Create a stream with context. Allows verification of a SSL certificate.
-    $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], STREAM_CLIENT_CONNECT, $options['context']);
+  if (!($fp = $fp_in)){
+      if (empty($options['context'])) {
+          $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout']);
+      }
+      else {
+          // Create a stream with context. Allows verification of a SSL certificate.
+          $fp = @stream_socket_client($socket, $errno, $errstr, $options['timeout'], STREAM_CLIENT_CONNECT, $options['context']);
+      }
   }
 
   // Make sure the socket opened properly.
@@ -834,7 +881,9 @@ function drupal_http_request($url, array
     // When a network error occurs, we use a negative number so it does not
     // clash with the HTTP status codes.
     $result->code = -$errno;
-    $result->error = trim($errstr) ? trim($errstr) : t('Error opening socket @socket', array('@socket' => $socket));
+    $result->error = trim($errstr)
+                   ? trim($errstr)
+                   : t('Error opening socket @socket', array('@socket' => $socket));
 
     // Mark that this request failed. This will trigger a check of the web
     // server's ability to make outgoing HTTP requests the next time that
@@ -845,17 +894,28 @@ function drupal_http_request($url, array
     return $result;
   }
 
+  // As described by RFC-2817
+  switch ($uri['scheme']) {
+    case 'proxy_https':
+        $options_connect = $options;
+        $options_connect['method']   = 'CONNECT';
+        $options_connect['protocol'] = 'HTTP/1.1';
+       if (!($return_connect = drupal_http_request($options['headers']['Host'], $options_connect, $fp))){
+            if (!$fp_in){
+               fclose($fp);
+            }
+            return $result_connect;
+        }
+        stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);
+      break;
+  }
+  
   // Construct the path to act on.
   $path = isset($uri['path']) ? $uri['path'] : '/';
   if (isset($uri['query'])) {
     $path .= '?' . $uri['query'];
   }
 
-  // Merge the default headers.
-  $options['headers'] += array(
-    'User-Agent' => 'Drupal (+http://drupal.org/)',
-  );
-
   // Only add Content-Length if we actually have any content or if it is a POST
   // or PUT request. Some non-standard servers get confused by Content-Length in
   // at least HEAD/GET requests, and Squid always requires Content-Length in
@@ -881,7 +941,7 @@ function drupal_http_request($url, array
     $options['headers']['User-Agent'] = drupal_generate_test_ua($test_info['test_run_id']);
   }
 
-  $request = $options['method'] . ' ' . $path . " HTTP/1.0\r\n";
+  $request = $options['method'] . ' ' . $path . " " . $options['protocol'] . "\r\n";
   foreach ($options['headers'] as $name => $value) {
     $request .= $name . ': ' . trim($value) . "\r\n";
   }
@@ -914,7 +974,9 @@ function drupal_http_request($url, array
     $info = stream_get_meta_data($fp);
     $alive = !$info['eof'] && !$info['timed_out'] && $chunk;
   }
-  fclose($fp);
+  if (!$fp_in){
+      fclose($fp);
+  }
 
   if ($info['timed_out']) {
     $result->code = HTTP_REQUEST_TIMEOUT;
@@ -1022,6 +1084,18 @@ function drupal_http_request($url, array
 
   return $result;
 }
+
+/**
+ * Helper function for determining hosts excluded from needing a proxy.
+ *
+ * @return
+ *   TRUE if a proxy should be used for this host.
+ */
+function _drupal_http_use_proxy($host) {
+  $proxy_exceptions = variable_get('proxy_exceptions', array('localhost', '127.0.0.1'));
+  return !in_array(strtolower($host), $proxy_exceptions, TRUE);
+}
+
 /**
  * @} End of "HTTP handling".
  */
diff -u -p -r1.50 default.settings.php
--- sites/default/default.settings.php	8 Aug 2010 19:35:49 -0000	1.50
+++ sites/default/default.settings.php	18 Sep 2010 11:22:02 -0000
@@ -429,3 +429,18 @@ ini_set('session.cookie_lifetime', 20000
  * Remove the leading hash signs to disable.
  */
 # $conf['allow_authorize_operations'] = FALSE;
+
+/**
+ * External access proxy settings:
+ *
+ * If your site must access the internet via a web proxy then you can enter
+ * the proxy settings here. Currently only basic authentication is supported
+ * by using the username and password variables. The proxy_exceptions variable
+ * is an array of host names to be accessed directly, not via proxy.
+ */
+# $conf['proxy_server'] = '';
+# $conf['proxy_port'] = 8080;
+# $conf['proxy_username'] = '';
+# $conf['proxy_password'] = '';
+# $conf['proxy_exceptions'] = array('127.0.0.1', 'localhost');
+
