Index: includes/filetransfer/local.inc
===================================================================
RCS file: includes/filetransfer/local.inc
diff -N includes/filetransfer/local.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ includes/filetransfer/local.inc	26 Oct 2009 05:12:25 -0000
@@ -0,0 +1,77 @@
+<?php
+// $Id$
+
+/**
+ * The local connection class for copying files as the httpd user.
+ */
+class FileTransferLocal extends FileTransfer implements FileTransferChmodInterface {
+
+  function connect() {
+    // No-op
+  }
+
+  static function factory($jail, $settings) {
+    return new FileTransferLocal($jail);
+  }
+
+  protected function copyFileJailed($source, $destination) {
+    if (@!copy($source, $destination)) {
+      throw new FileTransferException('Cannot copy %source to %destination.', NULL, array('%source' => $source, '%destination' => $destination));
+    }
+  }
+
+  protected function createDirectoryJailed($directory) {
+    if (!is_dir($directory) && @!mkdir($directory, 0777, TRUE)) {
+      throw new FileTransferException('Cannot create directory %directory.', NULL, array('%directory' => $directory));
+    }
+  }
+
+  protected function removeDirectoryJailed($directory) {
+    if (!is_dir($directory)) {
+      // Programmer error assertion, not something we expect users to see.
+      throw new FileTransferException('removeDirectoryJailed() called with a path (%directory) that is not a directory.', NULL, array('%directory' => $directory));
+    }
+    foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory), RecursiveIteratorIterator::CHILD_FIRST) as $filename => $file) {
+      if ($file->isDir()) {
+        if (@!rmdir($filename)) {
+          throw new FileTransferException('Cannot remove directory %directory.', NULL, array('%directory' => $filename));
+        }
+      }
+      elseif ($file->isFile()) {
+        if (@!unlink($filename)) {
+          throw new FileTransferException('Cannot remove file %file.', NULL, array('%file' => $filename));
+        }
+      }
+    }
+    if (@!rmdir($directory)) {
+      throw new FileTransferException('Cannot remove directory %directory.', NULL, array('%directory' => $directory));
+    }
+  }
+
+  protected function removeFileJailed($file) {
+    if (@!unlink($file)) {
+      throw new FileTransferException('Cannot remove file %file.', NULL, array('%file' => $file));
+    }
+  }
+  
+  public function isDirectory($path) {
+    return is_dir($path);
+  }
+
+  public function isFile($path) {
+    return is_file($path);
+  }
+
+  public function chmodJailed($path, $mode, $recursive) {
+    if ($recursive && is_dir($path)) {
+      foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST) as $filename => $file) {
+        if (@!chmod($filename, $mode)) {
+          throw new FileTransferException('Cannot chmod %path.', NULL, array('%path' => $filename));
+        }
+      }
+    }
+    elseif (@!chmod($path, $mode)) {
+      throw new FileTransferException('Cannot chmod %path.', NULL, array('%path' => $path));
+    }
+  }
+}
Index: modules/update/update.manager.inc
===================================================================
RCS file: /Users/wright/drupal/local_repo/drupal/modules/update/update.manager.inc,v
retrieving revision 1.4
diff -u -p -r1.4 update.manager.inc
--- modules/update/update.manager.inc	24 Oct 2009 11:43:42 -0000	1.4
+++ modules/update/update.manager.inc	26 Oct 2009 05:44:47 -0000
@@ -418,14 +418,30 @@ function update_manager_confirm_update_f
     foreach ($projects as $project => $url) {
       $project_location = $directory . '/' . $project;
       $updater = Updater::factory($project_location);
+      $project_real_location = drupal_realpath($project_location);
       $updates[] = array(
         'project' => $project,
         'updater_name' => get_class($updater),
-        'local_url' => drupal_realpath($project_location),
+        'local_url' => $project_real_location,
       );
     }
 
-    system_run_authorized('update_authorize_run_update', drupal_get_path('module', 'update') . '/update.authorize.inc', array($updates));
+    // If the owner of the last directory we extracted is the same as the
+    // owner of our configuration directory (e.g. sites/default) where we're
+    // trying to install the code, there's no need to prompt for FTP/SSH
+    // credentials. Instead, we instantiate a FileTransferLocal and invoke
+    // update_authorize_run_update() directly.
+    if (fileowner($project_real_location) == fileowner(conf_path())) {
+      module_load_include('inc', 'update', 'update.authorize');
+      $filetransfer = new FileTransferLocal(DRUPAL_ROOT);
+      update_authorize_run_update($filetransfer, $updates);
+    }
+    // Otherwise, go through the regular workflow to prompt for FTP/SSH
+    // credentials and invoke update_authorize_run_update() indirectly with
+    // whatever FileTransfer object authorize.php creates for us.
+    else {
+      system_run_authorized('update_authorize_run_update', drupal_get_path('module', 'update') . '/update.authorize.inc', array($updates));
+    }
   }
 }
 
@@ -565,13 +581,29 @@ function update_manager_install_form_sub
     return;
   }
   
+  $project_real_location = drupal_realpath($project_location);
   $arguments = array(
     'project' => $project,
     'updater_name' => get_class($updater),
-    'local_url' => drupal_realpath($project_location),
+    'local_url' => $project_real_location,
   );
 
-  return system_run_authorized('update_authorize_run_install', drupal_get_path('module', 'update') . '/update.authorize.inc', $arguments);
+  // If the owner of the directory we extracted is the same as the
+  // owner of our configuration directory (e.g. sites/default) where we're
+  // trying to install the code, there's no need to prompt for FTP/SSH
+  // credentials. Instead, we instantiate a FileTransferLocal and invoke
+  // update_authorize_run_install() directly.
+  if (fileowner($project_real_location) == fileowner(conf_path())) {
+    module_load_include('inc', 'update', 'update.authorize');
+    $filetransfer = new FileTransferLocal(DRUPAL_ROOT);
+    call_user_func_array('update_authorize_run_install', array_merge(array($filetransfer), $arguments));
+  }
+  // Otherwise, go through the regular workflow to prompt for FTP/SSH
+  // credentials and invoke update_authorize_run_install() indirectly with
+  // whatever FileTransfer object authorize.php creates for us.
+  else {
+    system_run_authorized('update_authorize_run_install', drupal_get_path('module', 'update') . '/update.authorize.inc', $arguments);
+  }
 }
 
 /**
