Index: modules/update/update.manager.inc
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.manager.inc,v
retrieving revision 1.27
diff -u -p -r1.27 update.manager.inc
--- modules/update/update.manager.inc	1 Dec 2010 00:23:36 -0000	1.27
+++ modules/update/update.manager.inc	1 Dec 2010 01:36:07 -0000
@@ -56,6 +56,12 @@
  *   The form array for selecting which projects to update.
  */
 function update_manager_update_form($form, $form_state = array(), $context) {
+  $form = array();
+
+  if (!_update_manager_check_backends($form, 'update')) {
+    return $form;
+  }
+
   $form['#theme'] = 'update_manager_update_form';
 
   $available = update_get_available(TRUE);
@@ -351,6 +357,12 @@ function update_manager_download_batch_f
  * file transfer credentials and attempt to complete the update.
  */
 function update_manager_update_ready_form($form, &$form_state) {
+  $form = array();
+
+  if (!_update_manager_check_backends($form, 'update')) {
+    return $form;
+  }
+
   $form['backup'] = array(
     '#prefix' => '<strong>',
     '#markup' => t('Back up your database and site before you continue. <a href="@backup_url">Learn how</a>.', array('@backup_url' => url('http://drupal.org/node/22281'))),
@@ -457,9 +469,18 @@ function update_manager_update_ready_for
 function update_manager_install_form($form, &$form_state, $context) {
   $form = array();
 
+  if (!_update_manager_check_backends($form, 'install')) {
+    return $form;
+  }
+
   $form['help_text'] = array(
     '#prefix' => '<p>',
-    '#markup' => t('To install a new module or theme, either enter the URL of an archive file you wish to install, or upload the archive file that you have downloaded. You can find <a href="@module_url">modules</a> and <a href="@theme_url">themes</a> at <a href="@drupal_org_url">http://drupal.org</a>.<br/>The following archive extensions are supported: %extensions.', array('@module_url' => 'http://drupal.org/project/modules', '@theme_url' => 'http://drupal.org/project/themes', '@drupal_org_url' => 'http://drupal.org', '%extensions' => archiver_get_extensions())),
+    '#markup' => t('You can find <a href="@module_url">modules</a> and <a href="@theme_url">themes</a> on <a href="@drupal_org_url">drupal.org</a>. The following file extensions are supported: %extensions.', array(
+      '@module_url' => 'http://drupal.org/project/modules',
+      '@theme_url' => 'http://drupal.org/project/themes',
+      '@drupal_org_url' => 'http://drupal.org',
+      '%extensions' => archiver_get_extensions(),
+    )),
     '#suffix' => '</p>',
   );
 
@@ -491,6 +512,77 @@ function update_manager_install_form($fo
 }
 
 /**
+ * Checks for file transfer backends and prepares a form fragment about them.
+ *
+ * @param array $form
+ *   Reference to the form array we're building.
+ * @param string $operation
+ *   The Update manager operation we're in the middle of. Can be either
+ *   'update' or 'install'. Use to provide operation-specific interface text.
+ *
+ * @return
+ *   TRUE if the Update manager should continue to the next step in the
+ *   workflow, or FALSE if we've hit a fatal configuration and must halt the
+ *   workflow.
+ */
+function _update_manager_check_backends(&$form, $operation) {
+  // Do a preliminary check to see if file transfers will be performed locally.
+  // See update_manager_update_ready_form_submit().
+  $local_transfers_allowed = fileowner(drupal_tempnam('temporary://', 'update_')) == fileowner(conf_path());
+
+  // If file transfers will be performed locally, we do not need to display any
+  // warnings or notices to the user and should automatically continue the
+  // workflow, since we won't be using a FileTransfer backend that requires
+  // user input or a specific server configuration.
+  if ($local_transfers_allowed) {
+    return TRUE;
+  }
+
+  // Otherwise, show the available backends.
+  $form['available_backends'] = array(
+    '#prefix' => '<p>',
+    '#suffix' => '</p>',
+  );
+
+  $available_backends = drupal_get_filetransfer_info();
+  if (empty($available_backends)) {
+    if ($operation == 'update') {
+      $form['available_backends']['#markup'] = t('Your server does not support updating modules and themes from this administrative interface. You can instead update modules and themes by uploading the new versions directly to the server, as described in the <a href="@handbook_url">handbook</a>.', array('@handbook_url' => 'http://drupal.org/getting-started/install-contrib'));
+    }
+    else {
+      $form['available_backends']['#markup'] = t('Your server does not support installing modules and themes from this administrative interface. You can instead install modules and themes by uploading them directly to the server, as described in the <a href="@handbook_url">handbook</a>.', array('@handbook_url' => 'http://drupal.org/getting-started/install-contrib'));
+    }
+    return FALSE;
+  }
+
+  $backend_names = array();
+  foreach ($available_backends as $backend) {
+    $backend_names[] = $backend['title'];
+  }
+  if ($operation == 'update') {
+    $form['available_backends']['#markup'] = format_plural(
+      count($available_backends),
+      '<strong>Note:</strong> Updating modules and themes from this administrative interface will require <strong>@backends access</strong> to your server. See the <a href="@handbook_url">handbook</a> for other installation methods.',
+      '<strong>Note:</strong> Updating modules and themes from this administrative interface will require access to your server via one of the following methods: <strong>@backends</strong>. See the <a href="@handbook_url">handbook</a> for other installation methods.',
+      array(
+        '@backends' => implode(', ', $backend_names),
+        '@handbook_url' => 'http://drupal.org/getting-started/install-contrib',
+      ));
+  }
+  else {
+    $form['available_backends']['#markup'] = format_plural(
+      count($available_backends),
+      '<strong>Note:</strong> Installing modules and themes from this administrative interface will require <strong>@backends access</strong> to your server. See the <a href="@handbook_url">handbook</a> for other installation methods.',
+      '<strong>Note:</strong> Installing modules and themes from this administrative interface will require access to your server via one of the following methods: <strong>@backends</strong>. See the <a href="@handbook_url">handbook</a> for other installation methods.',
+      array(
+        '@backends' => implode(', ', $backend_names),
+        '@handbook_url' => 'http://drupal.org/getting-started/install-contrib',
+      ));
+  }
+  return TRUE;
+}
+
+/**
  * Validate the form for installing a new project via the update manager.
  */
 function update_manager_install_form_validate($form, &$form_state) {
Index: modules/update/update.test
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.test,v
retrieving revision 1.20
diff -u -p -r1.20 update.test
--- modules/update/update.test	23 Oct 2010 15:48:45 -0000	1.20
+++ modules/update/update.test	1 Dec 2010 02:09:59 -0000
@@ -618,9 +618,9 @@ class UpdateTestUploadCase extends Updat
   function testFileNameExtensionMerging() {
     $this->drupalGet('admin/modules/install');    
     // Make sure the bogus extension supported by update_test.module is there.
-    $this->assertPattern('/archive extensions are supported:.*update-test-extension/', t("Found 'update-test-extension' extension"));
+    $this->assertPattern('/file extensions are supported:.*update-test-extension/', t("Found 'update-test-extension' extension"));
     // Make sure it didn't clobber the first option from core.
-    $this->assertPattern('/archive extensions are supported:.*tar/', t("Found 'tar' extension"));
+    $this->assertPattern('/file extensions are supported:.*tar/', t("Found 'tar' extension"));
   }
 
   /**
