Index: wp-admin/admin-ajax.php
===================================================================
--- wp-admin/admin-ajax.php	(revision 7061)
+++ wp-admin/admin-ajax.php	(working copy)
@@ -534,6 +534,11 @@
 	$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
 	die(get_sample_permalink_html($post_id, $_POST['new_slug']));
 break;
+case 'plugin-install':
+	require_once( ABSPATH . WPINC . '/rss.php' );
+	require_once( ABSPATH . '/wp-admin/includes/plugin-install.php' );
+	installplugin_display();
+break;
 default :
 	do_action( 'wp_ajax_' . $_POST['action'] );
 	die('0');
Index: wp-admin/includes/plugin-install.php
===================================================================
--- wp-admin/includes/plugin-install.php	(revision 0)
+++ wp-admin/includes/plugin-install.php	(revision 0)
@@ -0,0 +1,124 @@
+<?php
+
+add_action('installplugin_sources','get_installplugin_sources');
+function get_installplugin_sources($sources){
+	$sources['featured'] = array( 'title' => __('Featured Plugins'), 'callback' => 'installplugin_featured');
+	$sources['popular'] = array( 'title' => __('Popular Plugins'), 'callback' => 'installplugin_popular');
+	$sources['updated'] = array( 'title' => __('Recently Updated'), 'callback' => 'installplugin_updated');
+	$sources['newest'] = array( 'title' => __('Newest Plugins'), 'callback'=> 'installplugin_newest');
+	$sources['custom'] = array( 'title' => __('Custom Search'), 'callback' => 'installplugin_custom');
+	return $sources;
+}
+
+function installplugin_display(){
+	$show_values = apply_filters('installplugin_sources', array());
+
+	$show_selected = isset($_REQUEST['show']) ? $_REQUEST['show'] : false;
+	if( ! isset($show_values[$show_selected]) )
+		$show_selected = 'featured';
+
+	$plugins = @call_user_func($show_values[ $show_selected ]['callback']);
+
+	if ( ! is_array($plugins) )
+		return;
+
+	if( empty($plugins) ){
+		echo '<h3>' . __('No Plugins Found') . '</h3>';
+	} else {
+		foreach($plugins as $plugin){
+			extract($plugin);
+			$ilink = 'update.php?action=install-plugin&plugin=' . urlencode($latestzip);
+			$ilink = wp_nonce_url($ilink, 'install-plugin_' . $latestzip);
+			echo "<h3>$title</h3>\n";
+			echo "<p><span><a href='$link' target='_blank'>" . __('Visit Homepage') . 
+					"</a> | <a href='$dlink' target='_blank'>" . __('Download Page') . 
+					"</a> | <a href='$ilink'>" . __('Install Now') . "</a></span></p>";
+			echo "<p>$description</p>\n";
+		}
+	}
+}
+
+function installplugin_featured(){
+	return array(); //TODO: Need a API for wordpress.org for this :)
+}
+function installplugin_popular(){
+	return installplugin_wporg('http://wordpress.org/extend/plugins/rss/browse/popular/');
+}
+function installplugin_newest(){
+	return installplugin_wporg('http://wordpress.org/extend/plugins/rss/browse/new/');
+}
+function installplugin_updated(){
+	return installplugin_wporg('http://wordpress.org/extend/plugins/rss/browse/updated/');
+}
+function installplugin_custom(){
+	//REQUEST used as GET = Web interface, POST = Ajax
+	if( isset($_REQUEST['term']) && ! empty($_REQUEST['term']) ){
+		$term = urldecode($_REQUEST['term']);
+		echo '<p>' . sprintf(__('Displaying a selection from the %s category'), $term) . '</p>';
+		return installplugin_wporg('http://wordpress.org/extend/plugins/rss/tags/' . $term);
+	}
+
+	$tags = installplugin_custom_tags();
+	
+	echo "<p>" . __('Please select a Category to view plugins from.') . "</p>";
+	
+	echo "<div id='tag-list'>";
+	
+	foreach($tags as $tag){
+		$num = sprintf(__('%s plugins'), $tag['num']);
+		echo "<a href='plugin-install.php?show=custom&term={$tag['tag']}' onclick='return showSelection(\"custom\", \"{$tag['tag']}\")' title='$num' rel='tag' style='font-size: {$tag['size']}pt;'>{$tag['tag']}</a> ";
+	}
+	
+	echo "</div>";
+}
+function installplugin_custom_tags(){
+	//TODO: Needs Caching
+	//TODO: Needs a API on Wordpress.org :)
+	$url = 'http://wordpress.org/extend/plugins/tags/';
+	$html = file_get_contents($url); //TODO: Replace.
+	$html = substr( $html, strpos($html,'<div id="hottags">'));
+	
+	preg_match_all("|<a href='.*/([a-zA-Z0-9]+)' title='(\d+) topics' rel='tag' style='font-size: ([\d\.]+)pt;'>.*</a>|i", $html, $mat);
+
+	$tags = array();
+	
+	for($i = 0; $i < count($mat[1]); $i++)
+		$tags[] = array('tag' => $mat[1][$i], 'num' => $mat[2][$i], 'size' => $mat[3][$i]);
+	
+	return $tags;
+}
+
+function installplugin_wporg($feedurl){
+	$plugins = array();
+	$items = @fetch_rss( $feedurl );
+	if( ! $items || empty($items->items) )
+		return $plugins;
+	
+	foreach($items->items as $item){
+		// current bbPress feed item titles are: user on "topic title"
+		if ( preg_match( '/"(.*)"/s', $item['title'], $matches ) )
+			$title = $matches[1];
+		else // but let's make it forward compatible if things change
+			$title = $item['title'];
+		$title = wp_specialchars( $title );
+
+		$description = wp_specialchars( strip_tags(html_entity_decode($item['description'], ENT_QUOTES)) );
+
+		list($link, $frag) = explode( '#', $item['link'] );
+
+		$link = clean_url($link);
+		$link = rtrim($link, '/');
+		$dlink = $link . '/download/';
+		
+		if( preg_match("|\/([a-zA-Z\-0-9]+)$|", $link, $slug) )
+			$slug = $slug[1];
+		else
+			$slug = '';
+		
+		$latestzip = 'http://downloads.wordpress.org/plugin/' . $slug . '.zip';
+		
+		$plugins[] = array('title' => $title, 'link' => $link, 'dlink' => $dlink, 'description' => $description, 'slug' => $slug, 'latestzip' => $latestzip);
+	}
+	return $plugins;
+}
+?>
\ No newline at end of file
Index: wp-admin/includes/update.php
===================================================================
--- wp-admin/includes/update.php	(revision 7061)
+++ wp-admin/includes/update.php	(working copy)
@@ -192,4 +192,70 @@
 	delete_option('update_plugins');
 }
 
+function wp_install_plugin($package, $feedback = '') {
+	global $wp_filesystem;
+
+	if ( !empty($feedback) )
+		add_filter('update_feedback', $feedback);
+
+	if ( empty($package) )
+		return new WP_Error('empty_url', __('Invalid URL given'));
+
+	// Is a filesystem accessor setup?
+	if ( ! $wp_filesystem || !is_object($wp_filesystem) )
+		WP_Filesystem();
+
+	if ( ! is_object($wp_filesystem) )
+		return new WP_Error('fs_unavailable', __('Could not access filesystem.'));
+
+	if ( $wp_filesystem->errors->get_error_code() ) 
+		return new WP_Error('fs_error', __('Filesystem error'), $wp_filesystem->errors);
+
+	// Download the package
+	apply_filters('update_feedback', __("Downloading installer from $package"));
+	$file = download_url($package);
+
+	if ( !$file )
+		return new WP_Error('download_failed', __('Download failed.'));
+
+	$name = basename($package, '.zip');
+	$working_dir = ABSPATH . 'wp-content/upgrade/' . $name;
+
+	// Clean up working directory
+	$wp_filesystem->delete($working_dir, true);
+
+	apply_filters('update_feedback', __("Unpacking the files"));
+	// Unzip package to working directory
+	$result = unzip_file($file, $working_dir);
+	if ( is_wp_error($result) ) {
+		unlink($file);
+		$wp_filesystem->delete($working_dir, true);
+		return $result;
+	}
+
+	// Once installed, delete the package
+	unlink($file);
+
+
+	//TODO: Check if the plugin is allready installed.	
+	// Remove the existing plugin.
+	//apply_filters('update_feedback', __("Removing the old version of the plugin"));
+	//$wp_filesystem->delete(ABSPATH . PLUGINDIR . "/$plugin");
+	//$plugin_dir = dirname(ABSPATH . PLUGINDIR . "/$plugin");
+
+	// If plugin is in its own directory, recursively delete the directory.
+	//if ( '.' != $plugin_dir && ABSPATH . PLUGINDIR != $plugin_dir )
+	//	$wp_filesystem->delete($plugin_dir, true);
+
+	apply_filters('update_feedback', __("Installing the files"));
+	// Copy new version of plugin into place.
+	copy_dir($working_dir, ABSPATH . PLUGINDIR);
+
+	// Remove working directory
+	$wp_filesystem->delete($working_dir, true);
+
+	// Force refresh of plugin update information
+	//delete_option('update_plugins');
+}
+
 ?>
Index: wp-admin/plugin-install.php
===================================================================
--- wp-admin/plugin-install.php	(revision 0)
+++ wp-admin/plugin-install.php	(revision 0)
@@ -0,0 +1,99 @@
+<?php
+require_once('admin.php');
+require_once('includes/plugin-install.php');
+
+$title = __('Get More Plugins');
+$parent_file = 'plugins.php';
+
+//wp_reset_vars(array('show')); //Does it do both POST and GET?
+
+add_action('admin_head','installplugin_head');
+function installplugin_head(){ ?>
+<style>
+.plugin-install-search-types{
+	background-color:#eaf3fa;
+	width: 200px;
+	border:inset thin #000;
+	float: left;
+	clear: left;
+}
+.plugin-install-plugins{
+	background-color:#eaf3fa;
+	border:inset thin #000;
+	margin-left: 210px;
+}
+.plugin-install-search-types ul{
+	list-style: none;
+}
+.plugin-install-search-types li{
+	margin-left: -30px;
+	margin-right: 10px;
+	font-size: 1.2em;
+	padding:0;
+}
+.plugin-install-search-types li:hover{
+	background-color: #e1e4f1;
+}
+.plugin-install-search-types li.selected{
+	background-color: #fff;
+}
+.plugin-install-search-types a {
+	display:block;
+	padding:3px;
+	margin: 0;
+}
+</style>
+<script type="text/javascript">
+function showSelection(selection, selectedterm){
+	if( selectedterm == undefined)
+		var selectedterm = '';
+
+	jQuery('.plugin-install-search-types ul li').removeClass('selected');
+	jQuery('#plugin-install-search-' + selection).addClass('selected');
+	
+	jQuery('.plugin-install-plugins').html('<p><strong><?php _e('Loading Plugin list..') ?></strong></p>');
+	jQuery.post("admin-ajax.php",
+		{ action: "plugin-install", show: selection, term: selectedterm },
+		function(data){
+			jQuery('.plugin-install-plugins').html(data);
+		}
+	);
+	
+	return false;
+}
+</script>
+<?php
+}//End head items.
+
+require_once('admin-header.php');
+?>
+<div class="wrap">
+<h2><?php _e('Get more Plugins'); ?></h2>
+<p><?php _e('Plugins extend and expand the functionality of WordPress. Once a plugin is installed, You may activate on the Plugins tab.'); ?></p>
+</div>
+
+<div class="wrap">
+	<div class='plugin-install-search-types'>
+		<ul>
+			<?php
+			$show_values = apply_filters('installplugin_sources', array());
+			$show_selected = isset($_REQUEST['show']) ? $_REQUEST['show'] : false;
+			if( ! isset($show_values[$show_selected]) )
+				$show_selected = 'featured';
+
+			foreach ( $show_values as $show_value => $info ){
+				$show_value = attribute_escape( $show_value );
+				$show_text = wp_specialchars( $info['title'] );
+				$class = ($show_value == $show_selected) ? ' class="selected"' : '';
+				echo "<li id='plugin-install-search-{$show_value}'$class><a href='plugin-browse.php?show=$show_value' onclick='return showSelection(\"$show_value\")'>$show_text</a></li>";
+			}
+			?>
+		</ul>
+	</div>
+	<div class='plugin-install-plugins'>
+		<?php
+			installplugin_display();
+		?>
+	</div>
+</div>
+<?php include('admin-footer.php') ?>
\ No newline at end of file
Index: wp-admin/update.php
===================================================================
--- wp-admin/update.php	(revision 7061)
+++ wp-admin/update.php	(working copy)
@@ -1,117 +1,154 @@
-<?php
-
-require_once('admin.php');
-
-if ( !current_user_can('edit_plugins') )
-                wp_die('<p>'.__('You do not have sufficient permissions to update plugins for this blog.').'</p>');
-
-function request_filesystem_credentials($form_post, $type = '') {
-	if ( empty($type) )
-		$type = get_filesystem_method();
-
-	if ( 'direct' == $type )
-		return array();
-
-	if ( !empty($_POST['password']) && !empty($_POST['username']) && !empty($_POST['hostname']) ) {
-		$credentials = array('hostname' => $_POST['hostname'], 'username' => $_POST['username'],
-			'password' => $_POST['password'], 'ssl' => $_POST['ssl']);
-		$stored_credentials = $credentials;
-		unset($stored_credentials['password']);
-		update_option('ftp_credentials', $stored_credentials);
-		return $credentials;
-	}
-	$hostname = '';
-	$username = '';
-	$password = '';
-	$ssl = '';
-	if ( $credentials = get_option('ftp_credentials') )
-		extract($credentials, EXTR_OVERWRITE);
-?>
-<form action="<?php echo $form_post ?>" method="post">
-<div class="wrap">
-<h2><?php _e('FTP Connection Information') ?></h2>
-<p><?php _e('To perform the requested update, FTP connection information is required.') ?></p>
-<table class="form-table">
-<tr valign="top">
-<th scope="row"><?php _e('Hostname:') ?></th>
-<td><input name="hostname" type="text" id="hostname" value="<?php echo attribute_escape($hostname) ?>" size="40" /></td>
-</tr>
-<tr valign="top">
-<th scope="row"><?php _e('Username:') ?></th>
-<td><input name="username" type="text" id="username" value="<?php echo attribute_escape($username) ?>" size="40" /></td>
-</tr>
-<tr valign="top">
-<th scope="row"><?php _e('Password:') ?></th>
-<td><input name="password" type="text" id="password" value="<?php echo attribute_escape($password) ?>" size="40" /></td>
-</tr>
-<tr valign="top">
-<th scope="row"><?php _e('Use SSL:') ?></th>
-<td>
-<select name="ssl" id="ssl">
-<?php
-foreach ( array(0 => __('No'), 1 => __('Yes')) as $key => $value ) :
-	$selected = ($ssl == $value) ? 'selected="selected"' : '';
-	echo "\n\t<option value='$key' $selected>" . $value . '</option>';
-endforeach;
-?>
-</select>
-</td>
-</tr>
-</table>
-<p class="submit">
-<input type="submit" name="submit" value="<?php _e('Proceed'); ?>" />
-</p>
-</div>
-</form>
-<?php
-	return false;
-}
-
-function show_message($message) {
-	if ( is_wp_error($message) )
-		$message = $message->get_error_message();
-	echo "<p>$message</p>";
-}
-
-function do_plugin_upgrade($plugin) {
-	global $wp_filesystem;
-
-	$credentials = request_filesystem_credentials("update.php?action=upgrade-plugin&plugin=$plugin");
-	if ( false === $credentials )
-		return;
-	echo '<div class="wrap">';
-	echo '<h2>' . __('Upgrade Plugin') . '</h2>';
-	WP_Filesystem($credentials);
-	// TODO: look for auth and connect error codes and direct back to credentials form.
-	if ( $wp_filesystem->errors->get_error_code() ) {
-		foreach ( $wp_filesystem->errors->get_error_messages() as $message )
-			show_message($message);
-		echo '</div>';
-		return;
-	}
-
-	$result = wp_update_plugin($plugin, 'show_message');
-
-	if ( is_wp_error($result) )
-		show_message($result);
-	else
-		echo __('Plugin upgraded successfully');
-	echo '</div>';
-}
-
-if ( isset($_GET['action']) ) {
-	if ( isset($_GET['plugin']) )
-		$plugin = trim($_GET['plugin']);
-
-	if ( 'upgrade-plugin' == $_GET['action'] ) {
-		//check-admin_referer('upgrade-plugin_' . $plugin);
-		$title = __('Upgrade Plugin');
-		$parent_file = 'plugins.php';
-		require_once('admin-header.php');
-		do_plugin_upgrade($plugin);
-		include('admin-footer.php');
-	} 
-
-}
-
+<?php
+
+require_once('admin.php');
+
+if ( !current_user_can('edit_plugins') )
+                wp_die('<p>'.__('You do not have sufficient permissions to update plugins for this blog.').'</p>');
+
+function request_filesystem_credentials($form_post, $type = '') {
+	if ( empty($type) )
+		$type = get_filesystem_method();
+
+	if ( 'direct' == $type )
+		return array();
+
+	if ( !empty($_POST['password']) && !empty($_POST['username']) && !empty($_POST['hostname']) ) {
+		$credentials = array('hostname' => $_POST['hostname'], 'username' => $_POST['username'],
+			'password' => $_POST['password'], 'ssl' => $_POST['ssl']);
+		$stored_credentials = $credentials;
+		unset($stored_credentials['password']);
+		update_option('ftp_credentials', $stored_credentials);
+		return $credentials;
+	}
+	$hostname = '';
+	$username = '';
+	$password = '';
+	$ssl = '';
+	if ( $credentials = get_option('ftp_credentials') )
+		extract($credentials, EXTR_OVERWRITE);
+?>
+<form action="<?php echo $form_post ?>" method="post">
+<div class="wrap">
+<h2><?php _e('FTP Connection Information') ?></h2>
+<p><?php _e('To perform the requested update, FTP connection information is required.') ?></p>
+<table class="form-table">
+<tr valign="top">
+<th scope="row"><?php _e('Hostname:') ?></th>
+<td><input name="hostname" type="text" id="hostname" value="<?php echo attribute_escape($hostname) ?>" size="40" /></td>
+</tr>
+<tr valign="top">
+<th scope="row"><?php _e('Username:') ?></th>
+<td><input name="username" type="text" id="username" value="<?php echo attribute_escape($username) ?>" size="40" /></td>
+</tr>
+<tr valign="top">
+<th scope="row"><?php _e('Password:') ?></th>
+<td><input name="password" type="text" id="password" value="<?php echo attribute_escape($password) ?>" size="40" /></td>
+</tr>
+<tr valign="top">
+<th scope="row"><?php _e('Use SSL:') ?></th>
+<td>
+<select name="ssl" id="ssl">
+<?php
+foreach ( array(0 => __('No'), 1 => __('Yes')) as $key => $value ) :
+	$selected = ($ssl == $value) ? 'selected="selected"' : '';
+	echo "\n\t<option value='$key' $selected>" . $value . '</option>';
+endforeach;
+?>
+</select>
+</td>
+</tr>
+</table>
+<p class="submit">
+<input type="submit" name="submit" value="<?php _e('Proceed'); ?>" />
+</p>
+</div>
+</form>
+<?php
+	return false;
+}
+
+function show_message($message) {
+	if ( is_wp_error($message) )
+		$message = $message->get_error_message();
+	echo "<p>$message</p>";
+}
+
+function do_plugin_upgrade($plugin) {
+	global $wp_filesystem;
+
+	$credentials = request_filesystem_credentials("update.php?action=upgrade-plugin&plugin=$plugin");
+	if ( false === $credentials )
+		return;
+	echo '<div class="wrap">';
+	echo '<h2>' . __('Upgrade Plugin') . '</h2>';
+	WP_Filesystem($credentials);
+	// TODO: look for auth and connect error codes and direct back to credentials form.
+	if ( $wp_filesystem->errors->get_error_code() ) {
+		foreach ( $wp_filesystem->errors->get_error_messages() as $message )
+			show_message($message);
+		echo '</div>';
+		return;
+	}
+
+	$result = wp_update_plugin($plugin, 'show_message');
+
+	if ( is_wp_error($result) )
+		show_message($result);
+	else
+		echo __('Plugin upgraded successfully');
+	echo '</div>';
+}
+
+function do_plugin_install($url) {
+	global $wp_filesystem;
+
+	$credentials = request_filesystem_credentials('plugin-install.php?action=install-plugin&plugin=' . urlencode($url));
+	if ( false === $credentials )
+		return;
+	echo '<div class="wrap">';
+	echo '<h2>' . __('Install Plugin') . '</h2>';
+	WP_Filesystem($credentials);
+	// TODO: look for auth and connect error codes and direct back to credentials form.
+	if ( $wp_filesystem->errors->get_error_code() ) {
+		foreach ( $wp_filesystem->errors->get_error_messages() as $message )
+			show_message($message);
+		echo '</div>';
+		return;
+	}
+
+	$result = wp_install_plugin($url, 'show_message');
+
+	if ( is_wp_error($result) )
+		show_message($result);
+	else
+		echo __('Plugin installed successfully');
+	echo '</div>';
+}
+
+if ( isset($_GET['action']) ) {
+	if ( isset($_GET['plugin']) )
+		$plugin = trim($_GET['plugin']);
+
+	if ( 'upgrade-plugin' == $_GET['action'] ) {
+		//check-admin_referer('upgrade-plugin_' . $plugin);
+		$title = __('Upgrade Plugin');
+		$parent_file = 'plugins.php';
+		require_once('admin-header.php');
+		do_plugin_upgrade($plugin);
+		include('admin-footer.php');
+	} elseif ( 'install-plugin' == $_GET['action'] ){
+		
+		$plugin = urldecode($plugin);
+		check_admin_referer('install-plugin_' . $plugin);
+		
+		$title = __('Install Plugins');
+		$parent_file = 'plugins.php';
+		
+		require_once('admin-header.php');
+		do_plugin_install($plugin);
+		include('admin-footer.php');
+	}
+
+}
+
 ?>
\ No newline at end of file

