Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.612
diff -u -r1.612 system.module
--- modules/system/system.module	2 Aug 2008 19:01:02 -0000	1.612
+++ modules/system/system.module	20 Aug 2008 03:59:55 -0000
@@ -55,7 +55,7 @@
       $output .= '<li>' . t('support for enabling and disabling <a href="@themes">themes</a>, which determine the design and presentation of your site. Drupal comes packaged with several core themes and additional contributed themes are available at the <a href="@drupal-themes">Drupal.org theme page</a>.', array('@themes' => url('admin/build/themes'), '@drupal-themes' => 'http://drupal.org/project/themes')) . '</li>';
       $output .= '<li>' . t('a robust <a href="@cache-settings">caching system</a> that allows the efficient re-use of previously-constructed web pages and web page components. Drupal stores the pages requested by anonymous users in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, Drupal\'s caching system may significantly increase the speed of your site.', array('@cache-settings' => url('admin/settings/performance'))) . '</li>';
       $output .= '<li>' . t('a set of routine administrative operations that rely on a correctly-configured <a href="@cron">cron maintenance task</a> to run automatically. A number of other modules, including the feed aggregator, and search also rely on <a href="@cron">cron maintenance tasks</a>. For more information, see the online handbook entry for <a href="@handbook">configuring cron jobs</a>.', array('@cron' => url('admin/reports/status'), '@handbook' => 'http://drupal.org/cron')) . '</li>';
-      $output .= '<li>' . t('basic configuration options for your site, including <a href="@date-settings">date and time settings</a>, <a href="@file-system">file system settings</a>, <a href="@clean-url">clean URL support</a>, <a href="@site-info">site name and other information</a>, and a <a href="@site-maintenance">site maintenance</a> function for taking your site temporarily offline.', array('@date-settings' => url('admin/settings/date-time'), '@file-system' => url('admin/settings/file-system'), '@clean-url' => url('admin/settings/clean-urls'), '@site-info' => url('admin/settings/site-information'), '@site-maintenance' => url('admin/settings/site-maintenance'))) . '</li></ul>';
+      $output .= '<li>' . t('basic configuration options for your site, including <a href="@date-settings">date and time settings</a>, <a href="@file-system">file system settings</a>, <a href="@clean-url">clean URL support</a>, <a href="@proxy-server">proxy server settings</a>, <a href="@site-info">site name and other information</a>, and a <a href="@site-maintenance">site maintenance</a> function for taking your site temporarily off-line.', array('@date-settings' => url('admin/settings/date-time'), '@file-system' => url('admin/settings/file-system'), '@clean-url' => url('admin/settings/clean-urls'), '@proxy-server' => url('admin/settings/proxy'), '@site-info' => url('admin/settings/site-information'), '@site-maintenance' => url('admin/settings/site-maintenance'))) .'</li></ul>';
       $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@system">System module</a>.', array('@system' => 'http://drupal.org/handbook/modules/system/')) . '</p>';
       return $output;
     case 'admin':
@@ -97,6 +97,8 @@
       return t('An advanced action offers additional configuration options which may be filled out below. Changing the <em>Description</em> field is recommended, in order to better identify the precise action taking place. This description will be displayed in modules such as the trigger module when assigning actions to system events, so it is best if it is as descriptive as possible (for example, "Send e-mail to Moderation Team" rather than simply "Send e-mail").');
     case 'admin/settings/ip-blocking':
       return '<p>' . t('IP addresses listed here are blocked from your site before any modules are loaded. You may add IP addresses to the list, or delete existing entries.') . '</p>';
+    case 'admin/settings/proxy':
+      return '<p>' . t('Here you can configure if Drupal will use a proxy server when connecting to other sites on the Internet.') . '</p>';
     case 'admin/reports/status':
       return '<p>' . t("Here you can find a short overview of your site's parameters as well as any problems detected with your installation. It may be useful to copy and paste this information into support requests filed on drupal.org's support forums and project issue queues.") . '</p>';
   }
@@ -548,6 +550,13 @@
     'page arguments' => array('system_performance_settings'),
     'access arguments' => array('administer site configuration'),
   );
+  $items['admin/settings/proxy'] = array(
+    'title' => 'Proxy server',
+    'description' => 'Configure settings when the site is behind a proxy server.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('system_proxy_settings'),
+    'access arguments' => array('administer site configuration'),
+  );
   $items['admin/settings/file-system'] = array(
     'title' => 'File system',
     'description' => 'Tell Drupal where to store uploaded files and how they are accessed.',
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.84
diff -u -r1.84 system.admin.inc
--- modules/system/system.admin.inc	9 Aug 2008 12:41:23 -0000	1.84
+++ modules/system/system.admin.inc	20 Aug 2008 03:59:55 -0000
@@ -1439,6 +1439,59 @@
 }
 
 /**
+ * Form builder; Configure the site proxy settings.
+ *
+ * @ingroup forms
+ * @see system_settings_form()
+ */
+function system_proxy_settings() {
+
+  $form['proxy_server'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Proxy host name'),
+    '#default_value' => variable_get('proxy_server', ''),
+    '#description' => t('The host name of the proxy server, eg. localhost. If this is empty, it will be assumed that there is already an existing connection to the Internet.')
+  );
+  $form['proxy_port'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Port number'),
+    '#default_value' => variable_get('proxy_port', 8080),
+    '#description' => t('The port number of the proxy server, eg. 8080.'),
+  );
+  $form['proxy_username'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Username'),
+    '#default_value' => variable_get('proxy_username', ''),
+    '#description' => t('The username used to authenticate with the proxy server.'),
+  );
+  $form['proxy_password'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Password'),
+    '#default_value' => variable_get('proxy_password', ''),
+    '#description' => t('The password used to connect to the proxy server. This is kept as plain text.', '')
+  );
+  $form['proxy_exceptions'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Exceptions'),
+    '#default_value' => variable_get('proxy_exceptions', 'localhost'),
+    '#description' => t("A comma seperated list of sites that don't require use of the proxy server.")
+  );
+  $form['#validate'][] = 'system_proxy_settings_validate';
+
+  return system_settings_form($form);
+}
+
+/**
+ * Validate the submitted proxy form.
+ */
+function system_proxy_settings_validate($form, &$form_state) {
+  // TCP allows the port to be between 0 and 65536 inclusive
+  if (!is_numeric($form_state['values']['proxy_port']) || $form_state['values']['proxy_port'] < 0 || $form_state['values']['proxy_port'] >= 65536) {
+    form_set_error('proxy_port', t('The proxy port is invalid. It must be a number between 0 and 65535.'));
+  }
+}
+
+/**
  * Form builder; Configure the site file handling.
  *
  * @ingroup forms
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.787
diff -u -r1.787 common.inc
--- includes/common.inc	17 Aug 2008 11:08:23 -0000	1.787
+++ includes/common.inc	20 Aug 2008 03:59:55 -0000
@@ -442,11 +442,20 @@
     return $result;
   }
 
+  $proxy_required = !empty(variable_get('proxy_server', '')) && (stripos(variable_get('proxy_exceptions', ''), $uri['host']) === FALSE);
   switch ($uri['scheme']) {
     case 'http':
       $port = isset($uri['port']) ? $uri['port'] : 80;
       $host = $uri['host'] . ($port != 80 ? ':' . $port : '');
-      $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
+      if ($proxy_required) {
+        $proxy_server = variable_get('proxy_server', '');
+        $proxy_port = variable_get('proxy_port', 8080);
+        $fp = @fsockopen($proxy_server, $proxy_port, $errno, $errstr, 15);
+      }
+      else {
+        $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
+      }
+
       break;
     case 'https':
       // Note: Only works for PHP 4.3 compiled with OpenSSL.
@@ -469,9 +478,14 @@
   }
 
   // Construct the path to act on.
-  $path = isset($uri['path']) ? $uri['path'] : '/';
-  if (isset($uri['query'])) {
-    $path .= '?' . $uri['query'];
+  if ($proxy_required) {
+    $path = $url;
+  }
+  else {
+    $path = isset($uri['path']) ? $uri['path'] : '/';
+    if (isset($uri['query'])) {
+      $path .= '?'. $uri['query'];
+    }
   }
 
   // Create HTTP request.
@@ -489,6 +503,14 @@
     $defaults['Authorization'] = 'Authorization: Basic ' . base64_encode($uri['user'] . (!empty($uri['pass']) ? ":" . $uri['pass'] : ''));
   }
 
+  // If the proxy server required a username then attempt to authenticate with it
+  if ($proxy_required && !empty(variable_get('proxy_username', ''))) {
+    $username = variable_get('proxy_username', '');
+    $password = variable_get('proxy_password', '');
+    $auth_string = base64_encode($username . ($password != '' ? ':'. $password : ''));
+    $defaults['Proxy-Authorization'] = 'Proxy-Authorization: Basic '. $auth_string ."\r\n";
+  }
+
   // If the database prefix is being used by SimpleTest to run the tests in a copied
   // database then set the user-agent header to the database prefix so that any
   // calls to other Drupal pages will run the SimpleTest prefixed database. The
@@ -576,6 +598,7 @@
   $result->code = $code;
   return $result;
 }
+
 /**
  * @} End of "HTTP handling".
  */
