Index: /trunk/wp-admin/includes/class-wp-upgrader.php
===================================================================
--- /trunk/wp-admin/includes/class-wp-upgrader.php	(revision 13685)
+++ /trunk/wp-admin/includes/class-wp-upgrader.php	(revision 13686)
@@ -470,8 +470,8 @@
 		$results = array();
 
-		$this->plugin_count = count($plugins);
-		$this->plugin_current = 0;
+		$this->update_count = count($plugins);
+		$this->update_current = 0;
 		foreach ( $plugins as $plugin ) {
-			$this->plugin_current++;
+			$this->update_current++;
 			$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true);
 
@@ -683,4 +683,80 @@
 	}
 
+	function bulk_upgrade($themes) {
+
+		$this->init();
+		$this->bulk = true;
+		$this->upgrade_strings();
+
+		$current = get_site_transient( 'update_themes' );
+
+		add_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
+		add_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
+		add_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
+
+		$this->skin->header();
+
+		// Connect to the Filesystem first.
+		$res = $this->fs_connect( array(WP_CONTENT_DIR) );
+		if ( ! $res ) {
+			$this->skin->footer();
+			return false;
+		}
+
+		$this->maintenance_mode(true);
+
+		$results = array();
+
+		$this->update_count = count($themes);
+		$this->update_current = 0;
+		foreach ( $themes as $theme ) {
+			$this->update_current++;
+
+			if ( !isset( $current->response[ $theme ] ) ) {
+				$this->skin->set_result(false);
+				$this->skin->before();
+				$this->skin->error('up_to_date');
+				$this->skin->after();
+				$results[$theme] = false;
+				continue;
+			}
+
+			$this->skin->theme_info = $this->theme_info($theme);
+
+			// Get the URL to the zip file
+			$r = $current->response[ $theme ];
+
+			$options = array(
+							'package' => $r['package'],
+							'destination' => WP_CONTENT_DIR . '/themes',
+							'clear_destination' => true,
+							'clear_working' => true,
+							'hook_extra' => array(
+												'theme' => $theme
+												)
+							);
+
+			$result = $this->run($options);
+
+			$results[$theme] = $this->result;
+
+			// Prevent credentials auth screen from displaying multiple times
+			if ( false === $result )
+				break;
+		} //end foreach $plugins
+		$this->maintenance_mode(false);
+		$this->skin->footer();
+
+		// Cleanup our hooks, incase something else does a upgrade on this connection.
+		remove_filter('upgrader_pre_install', array(&$this, 'current_before'), 10, 2);
+		remove_filter('upgrader_post_install', array(&$this, 'current_after'), 10, 2);
+		remove_filter('upgrader_clear_destination', array(&$this, 'delete_old_theme'), 10, 4);
+
+		// Force refresh of theme update information
+		delete_site_transient('update_themes');
+
+		return $results;
+	}
+
 	function current_before($return, $theme) {
 
@@ -693,5 +769,6 @@
 			return $return;
 		//Change to maintainence mode now.
-		$this->maintenance_mode(true);
+		if ( ! $this->bulk )
+			$this->maintenance_mode(true);
 
 		return $return;
@@ -715,5 +792,6 @@
 
 		//Time to remove maintainence mode
-		$this->maintenance_mode(false);
+		if ( ! $this->bulk )
+			$this->maintenance_mode(false);
 		return $return;
 	}
@@ -734,8 +812,13 @@
 	}
 
-	function theme_info() {
-		if ( empty($this->result['destination_name']) )
-			return false;
-		return get_theme_data(WP_CONTENT_DIR . '/themes/' . $this->result['destination_name'] . '/style.css');
+	function theme_info($theme = null) {
+
+		if ( empty($theme) ) {
+			if ( !empty($this->result['destination_name']) )
+				$theme = $this->result['destination_name'];
+			else
+				return false;
+		}
+		return get_theme_data(WP_CONTENT_DIR . '/themes/' . $theme . '/style.css');
 	}
 
@@ -827,5 +910,10 @@
 		if ( is_object($upgrader) )
 			$this->upgrader =& $upgrader;
-	}
+		$this->add_strings();
+	}
+
+	function add_strings() {
+	}
+
 	function set_result($result) {
 		$this->result = $result;
@@ -950,9 +1038,9 @@
  * @since 3.0
  */
-class Bulk_Plugin_Upgrader_Skin extends WP_Upgrader_Skin {
+class Bulk_Upgrader_Skin extends WP_Upgrader_Skin {
 	var $in_loop = false;
 	var $error = false;
 
-	function Plugin_Upgrader_Skin($args = array()) {
+	function Bulk_Upgrader_Skin($args = array()) {
 		return $this->__construct($args);
 	}
@@ -964,5 +1052,11 @@
 		parent::__construct($args);
 	}
-	
+
+	function add_strings() {
+		$this->upgrader->strings['skin_update_failed_error'] = __('An error occured while updating %1$s: <strong>%2$s</strong>.');
+		$this->upgrader->strings['skin_update_failed'] = __('The update of %1$s failed.');
+		$this->upgrader->strings['skin_update_successful'] = __('%1$s updated successfully. <a onclick="%2$s" href="#">See Details</a>.');
+	}
+
 	function feedback($string) {
 		if ( isset( $this->upgrader->strings[$string] ) )
@@ -1005,22 +1099,23 @@
 	}
 
-	function before() {
+	function before($title = '') {
 		$this->in_loop = true;
-		printf( '<h4>' . __('Updating Plugin %1$s (%2$d/%3$d)') . '</h4>',  $this->plugin_info['Title'], $this->upgrader->plugin_current, $this->upgrader->plugin_count);
-		echo '<div class="update-messages" style="display:none" id="progress-' . esc_attr($this->upgrader->plugin_current) . '"><p>';
+		printf( '<h4>' . $this->upgrader->strings['skin_before_update_header'] . '</h4>',  $title, $this->upgrader->update_current, $this->upgrader->update_count);
+		echo '<div class="update-messages" style="display:none" id="progress-' . esc_attr($this->upgrader->update_current) . '"><p>';
 		$this->flush_output();
 	}
 
-	function after() {
+	function after($title = '') {
 		echo '</p></div>';
 		if ( $this->error || ! $this->result ) {
 			if ( $this->error )
-				echo '<div class="error"><p>' . sprintf(__('An error occured while updating %1$s: <strong>%2$s</strong>.'), $this->plugin_info['Title'], $this->error) . '</p></div>';
+				echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed'], $title, $this->error) . '</p></div>';
 			else
-				echo '<div class="error"><p>' . sprintf(__('The update of %1$s failed.'), $this->plugin_info['Title']) . '</p></div>';
-			echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js($this->upgrader->plugin_current) . '\').show();</script>';
+				echo '<div class="error"><p>' . sprintf($this->upgrader->strings['skin_update_failed'], $title) . '</p></div>';
+
+			echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').show();</script>';
 		}
 		if ( !empty($this->result) && !is_wp_error($this->result) ) {
-			echo '<div class="updated"><p>' . sprintf(__('%1$s updated successfully. <a onclick="%2$s" href="#">See Details</a>.'), $this->plugin_info['Title'], 'jQuery(\'#progress-' . esc_js($this->upgrader->plugin_current) . '\').toggle(); return false;') . '</p></div>';
+			echo '<div class="updated"><p>' . sprintf($this->upgrader->strings['skin_update_successful'], $title, 'jQuery(\'#progress-' . esc_js($this->upgrader->update_current) . '\').toggle(); return false;') . '</p></div>';
 		}
 		$this->reset();
@@ -1037,5 +1132,44 @@
 		flush();
 	}
-
+}
+
+class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin {
+	var $plugin_info = array(); // Plugin_Upgrader::bulk() will fill this in.
+	function Plugin_Upgrader_Skin($args = array()) {
+		parent::__construct($args);
+	}
+
+	function add_strings() {
+		parent::add_strings();
+		$this->upgrader->strings['skin_before_update_header'] = __('Updating Plugin %1$s (%2$d/%3$d)');
+	}
+
+	function before() {
+		parent::before($this->plugin_info['Title']);
+	}
+
+	function after() {
+		parent::after($this->plugin_info['Title']);
+	}
+}
+
+class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin {
+	var $theme_info = array(); // Theme_Upgrader::bulk() will fill this in.
+	function Theme_Upgrader_Skin($args = array()) {
+		parent::__construct($args);
+	}
+
+	function add_strings() {
+		parent::add_strings();
+		$this->upgrader->strings['skin_before_update_header'] = __('Updating Theme %1$s (%2$d/%3$d)');
+	}
+
+	function before() {
+		parent::before($this->theme_info['Name']);
+	}
+
+	function after() {
+		parent::after($this->theme_info['Name']);
+	}
 }
 
Index: /trunk/wp-admin/update-core.php
===================================================================
--- /trunk/wp-admin/update-core.php	(revision 13685)
+++ /trunk/wp-admin/update-core.php	(revision 13686)
@@ -442,5 +442,4 @@
 	screen_icon('themes');
 	echo '<h2>' . esc_html__('Update Themes') . '</h2>';
-	echo "<p>@TODO: Sorry, This part of the functionality hasnt been written yet.</p>";
 	echo "<iframe src='$url' style='width: 100%; height:100%; min-height:850px;'></iframe>";
 	echo '</div>';
Index: /trunk/wp-admin/update.php
===================================================================
--- /trunk/wp-admin/update.php	(revision 13685)
+++ /trunk/wp-admin/update.php	(revision 13686)
@@ -43,5 +43,4 @@
 
 		iframe_footer();
-		exit;
 			
 	} elseif ( 'upgrade-plugin' == $action ) {
@@ -164,5 +163,30 @@
 
 		include('admin-footer.php');
-
+	} elseif ( 'update-selected-themes' == $action ) {
+		if ( ! current_user_can( 'update_themes' ) )
+			wp_die( __( 'You do not have sufficient permissions to update themes for this blog.' ) );
+
+		check_admin_referer( 'bulk-update-themes' );
+
+		if ( isset( $_GET['themes'] ) )
+			$themes = explode( ',', stripslashes($_GET['themes']) );
+		elseif ( isset( $_POST['checked'] ) )
+			$themes = (array) $_POST['checked'];
+		else
+			$themes = array();
+
+		$themes = array_map('urldecode', $themes);
+
+		$url = 'update.php?action=update-selected-themes&amp;themess=' . urlencode(implode(',', $themes));
+		$nonce = 'bulk-update-themes';
+
+		require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
+		wp_enqueue_script('jquery');
+		iframe_header();
+
+		$upgrader = new Theme_Upgrader( new Bulk_Theme_Upgrader_Skin( compact( 'nonce', 'url' ) ) );
+		$upgrader->bulk_upgrade( $themes );
+
+		iframe_footer();
 	} elseif ( 'install-theme' == $action ) {
 
