Index: wp-admin/includes/file.php
===================================================================
--- wp-admin/includes/file.php	(revision 9492)
+++ wp-admin/includes/file.php	(working copy)
@@ -482,6 +482,14 @@
 	if ( 0 == count($archive_files) )
 		return new WP_Error('empty_archive', __('Empty archive'));
 
+	//Prepend another directory level if there are files in the root directory of the zip
+	foreach ( $archive_files as $archive_file ) {
+		if ( false === strpos($archive_file['filename'], '/') ) {
+			$to = trailingslashit($to) . basename($file, '.zip');
+			break;
+		}
+	}
+
 	$path = explode('/', untrailingslashit($to));
 	for ( $i = count($path); $i > 0; $i-- ) { //>0 = first element is empty allways for paths starting with '/'
 		$tmppath = implode('/', array_slice($path, 0, $i) );
@@ -558,6 +566,54 @@
 }
 
 /**
+ * Locates the lowest safe directory in a Plugin folder to copy to the plugins directory.
+ *
+ * Note: Desination directory will allways be unique.
+ *
+ * @since 2.7.0
+ *
+ * @param string $from the Working directory of the plugin files
+ * @param string $to the proposed destination for the for the plugin files
+ * @return array an array of the keys 'from' and 'to' for the actual copy.
+ */
+function update_pluginfiles_base_dir($from, $to) {
+	$files = list_files($from);
+
+	//Remove non-php files
+	foreach ( (array)$files as $key => $file ) 
+		if ( ! preg_match('!.php$!i', $file) )
+			unset($files[$key]);
+
+	//remove non-plugin files
+	foreach ( (array)$files as $key => $file ) {
+		$details = get_plugin_data($file, false, false);
+		if ( empty($details['Name']) )
+			unset($files[$key]);
+	}
+
+	if ( empty($files) )
+		return false;
+
+	//Left with paths to files which ARE plugins.
+	$min_num = 100; //assume no zips with deeper paths will come along
+	$min_file = '';
+	foreach ( (array)$files as $key => $file ) {
+		$this_num = substr_count($file, '/');
+		if ( $this_num < $min_num ) {
+			$min_file = $file;
+			$min_num = $this_num;
+		}
+	}
+	unset($min_num);
+
+	$from = dirname($min_file);
+	//Ensure its a unique install folder, Upgrades delete the folder prior to this.
+	$to = dirname($to) . '/' . wp_unique_filename(dirname($to), basename($to));
+
+	return compact('from', 'to');
+}
+
+/**
  * {@internal Missing Short Description}}
  *
  * @since unknown
Index: wp-admin/includes/plugin-install.php
===================================================================
--- wp-admin/includes/plugin-install.php	(revision 9492)
+++ wp-admin/includes/plugin-install.php	(working copy)
@@ -745,37 +745,34 @@
 		return $result;
 	}
 
-	//Get a list of the directories in the working directory before we delete it, We need to know the new folder for the plugin
+	apply_filters('install_feedback', __('Installing the plugin'));
+	
 	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
 
-	if( $wp_filesystem->exists( $plugins_dir . $filelist[0] ) ) {
-		$wp_filesystem->delete($working_dir, true);
-		return new WP_Error('install_folder_exists', __('Folder allready exists.'), $filelist[0] );
-	}
+	//find base plugin directory
+	$res = update_pluginfiles_base_dir($working_dir . '/' . $filelist[0], $plugins_dir . $filelist[0]);
 
-	apply_filters('install_feedback', __('Installing the plugin'));
+	//Create folder if not exists.
+	if( ! $wp_filesystem->exists( $res['to'] ) )
+		if ( ! $wp_filesystem->mkdir( $res['to'] ) )
+			return new WP_Error('mkdir_failed', __('Could not create directory'), $res['to']);	
+
 	// Copy new version of plugin into place.
-	$result = copy_dir($working_dir, $plugins_dir);
+	$result = copy_dir($res['from'], $res['to']);
 	if ( is_wp_error($result) ) {
 		$wp_filesystem->delete($working_dir, true);
 		return $result;
 	}
 
-	//Get a list of the directories in the working directory before we delete it, We need to know the new folder for the plugin
-	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
-
 	// Remove working directory
 	$wp_filesystem->delete($working_dir, true);
 
-	if( empty($filelist) )
-		return false; //We couldnt find any files in the working dir, therefor no plugin installed? Failsafe backup.
-
-	$folder = $filelist[0];
+	$folder = trailingslashit(str_replace($plugins_dir, '', $res['to']));
 	$plugin = get_plugins('/' . $folder); //Ensure to pass with leading slash
 	$pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list
 
 	//Return the plugin files name.
-	return  $folder . '/' . $pluginfiles[0];
+	return $folder . $pluginfiles[0];
 }
 
 /**
@@ -840,37 +837,34 @@
 		return $result;
 	}
 
-	//Get a list of the directories in the working directory before we delete it, We need to know the new folder for the plugin
+	apply_filters('install_feedback', __('Installing the plugin'));
+	
 	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
 
-	if( $wp_filesystem->exists( $plugins_dir . $filelist[0] ) ) {
-		$wp_filesystem->delete($working_dir, true);
-		return new WP_Error('install_folder_exists', __('Folder allready exists.'), $filelist[0] );
-	}
+	//find base plugin directory
+	$res = update_pluginfiles_base_dir($working_dir . '/' . $filelist[0], $plugins_dir . $filelist[0]);
 
-	apply_filters('install_feedback', __('Installing the plugin'));
+	//Create folder if not exists.
+	if( ! $wp_filesystem->exists( $res['to'] ) )
+		if ( ! $wp_filesystem->mkdir( $res['to'] ) )
+			return new WP_Error('mkdir_failed', __('Could not create directory'), $res['to']);	
+
 	// Copy new version of plugin into place.
-	$result = copy_dir($working_dir, $plugins_dir);
+	$result = copy_dir($res['from'], $res['to']);
 	if ( is_wp_error($result) ) {
 		$wp_filesystem->delete($working_dir, true);
 		return $result;
 	}
 
-	//Get a list of the directories in the working directory before we delete it, We need to know the new folder for the plugin
-	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
-
 	// Remove working directory
 	$wp_filesystem->delete($working_dir, true);
 
-	if( empty($filelist) )
-		return false; //We couldnt find any files in the working dir, therefor no plugin installed? Failsafe backup.
-
-	$folder = $filelist[0];
+	$folder = trailingslashit(str_replace($plugins_dir, '', $res['to']));
 	$plugin = get_plugins('/' . $folder); //Ensure to pass with leading slash
 	$pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list
 
 	//Return the plugin files name.
-	return  $folder . '/' . $pluginfiles[0];
+	return $folder . $pluginfiles[0];
 }
 
-?>
+?>
\ No newline at end of file
Index: wp-admin/includes/update.php
===================================================================
--- wp-admin/includes/update.php	(revision 9492)
+++ wp-admin/includes/update.php	(working copy)
@@ -241,30 +241,36 @@
 	}
 
 	apply_filters('update_feedback', __('Installing the latest version'));
+
+	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
+
+	//find base plugin directory
+	$res = update_pluginfiles_base_dir($working_dir . '/' . $filelist[0], $plugins_dir . $filelist[0]);
+
+	//Create folder if not exists.
+	if( ! $wp_filesystem->exists( $res['to'] ) )
+		if ( ! $wp_filesystem->mkdir( $res['to'] ) )
+			return new WP_Error('mkdir_failed', __('Could not create directory'), $res['to']);	
+
 	// Copy new version of plugin into place.
-	$result = copy_dir($working_dir, $plugins_dir);
+	$result = copy_dir($res['from'], $res['to']);
 	if ( is_wp_error($result) ) {
 		$wp_filesystem->delete($working_dir, true);
 		return $result;
 	}
 
-	//Get a list of the directories in the working directory before we delete it, We need to know the new folder for the plugin
-	$filelist = array_keys( $wp_filesystem->dirlist($working_dir) );
-
 	// Remove working directory
 	$wp_filesystem->delete($working_dir, true);
 
 	// Force refresh of plugin update information
 	delete_option('update_plugins');
 
-	if( empty($filelist) )
-		return false; //We couldnt find any files in the working dir, therefor no plugin installed? Failsafe backup.
-
-	$folder = $filelist[0];
+	$folder = trailingslashit(str_replace($plugins_dir, '', $res['to']));
 	$plugin = get_plugins('/' . $folder); //Ensure to pass with leading slash
 	$pluginfiles = array_keys($plugin); //Assume the requested plugin is the first in the list
 
-	return  $folder . '/' . $pluginfiles[0];
+	//Return the plugin files name.
+	return $folder . $pluginfiles[0];
 }
 
 function wp_update_theme($theme, $feedback = '') {

