diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a65b417
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+lib
diff --git a/commands/pm/package_handler/wget.inc b/commands/pm/package_handler/wget.inc
index b23ce21..7d0a1eb 100644
--- a/commands/pm/package_handler/wget.inc
+++ b/commands/pm/package_handler/wget.inc
@@ -46,57 +46,39 @@ function package_handler_download_project(&$request, $release) {
     }
   }
 
-  // Chdir to the download location.
-  $olddir = getcwd();
-  drush_op('chdir', $request['base_project_path']);
-
   // Dev snapshots can be cached for 4 hours and releases for 1 year.
   $max_age = strpos($release['download_link'], '-dev') !== FALSE ? 3600*4 : 86400*365;
-  $path = drush_download_file($release['download_link'], $max_age);
   $filename = basename($release['download_link']);
+  $path = drush_download_file($release['download_link'], $request['base_project_path'] . $filename, $max_age);
   if ($path || drush_get_context('DRUSH_SIMULATE')) {
     drush_log("Downloading " . $filename . " was successful.");
   }
   else {
-    drush_op('chdir', $olddir);
     return drush_set_error('DRUSH_PM_DOWNLOAD_FAILED', 'Unable to download ' . $filename . ' to ' . $request['base_project_path'] . ' from '. $release['download_link']);
   }
 
   // Check Md5 hash.
   if (drush_op('md5_file', $path) != $release['mdhash'] && !drush_get_context('DRUSH_SIMULATE')) {
     drush_set_error('DRUSH_PM_FILE_CORRUPT', "File $filename is corrupt (wrong md5 checksum).");
-    drush_op('chdir', $olddir);
     return FALSE;
   }
   else {
     drush_log("Md5 checksum of $filename verified.");
   }
 
-  $tarpath = basename($path, '.tar.gz');
-  $tarpath = basename($tarpath, '.tgz');
-  $tarpath .= '.tar';
-  // Decompress and untar in two steps as tar -xzf does not work on windows.
-  drush_shell_exec("gzip --decompress --stdout %s > %s", $path, $tarpath);
-  drush_shell_exec("tar -xf %s", $tarpath);
+  // Extract the tarball.
+  $file_list = drush_tarball_extract($path, $request['base_project_path']);
 
   // Move untarred directory to project_dir, if distinct.
   if (($request['project_type'] == 'core') || (($request['project_type'] == 'profile') && (drush_get_option('variant', 'core') == 'core'))) {
     // Obtain the dodgy project_dir for drupal core.
-    // We use a separate tar -tf instead of -xvf above because
-    // the output is not the same in Mac.
-    drush_shell_exec("tar -tf %s", $tarpath);
-    $output = drush_shell_exec_output();
-    $project_dir = drush_trim_path($output[0]);
+    $project_dir = drush_trim_path($file_list[0]);
     if ($request['project_dir'] != $project_dir) {
       $path = $request['base_project_path'];
       drush_move_dir($path . '/'. $project_dir, $path . '/' . $request['project_dir']);
     }
   }
 
-  // Cleanup. Remove the tar file and set previous working directory.
-  drush_op('unlink', $tarpath);
-  drush_op('chdir', $olddir);
-
   return TRUE;
 }
 
diff --git a/commands/pm/pm.drush.inc b/commands/pm/pm.drush.inc
index eb98a5d..c156f5f 100644
--- a/commands/pm/pm.drush.inc
+++ b/commands/pm/pm.drush.inc
@@ -1325,9 +1325,9 @@ function _drush_pm_releasenotes($requests, $print_status = TRUE, $tmpfile = NULL
         @$dom = DOMDocument::loadHTML($data->data);
       }
       else {
-        $path = _drush_download_file($release_page_url);
-        @$dom = DOMDocument::loadHTMLFile($path);
-        @unlink($path);
+        $filename = drush_download_file($release_page_url);
+        @$dom = DOMDocument::loadHTMLFile($filename);
+        @unlink($filename);
         if ($dom === FALSE) {
           drush_log(dt("Error while requesting the release notes page for !project project.", array('!project' => $key)), 'error');
           continue;
@@ -1712,7 +1712,8 @@ function _drush_pm_get_release_history_xml($request) {
   // bootstrapped.
   $url = drush_get_option('source', 'http://updates.drupal.org/release-history') . '/' . $request['name'] . '/' . $request['drupal_version'];
   drush_log('Downloading release history from ' . $url);
-  if ($path = drush_download_file($url, drush_get_option('cache-duration-releasexml', 24*3600))) {
+  // Some hosts have allow_url_fopen disabled.
+  if ($path = drush_download_file($url, NULL, drush_get_option('cache-duration-releasexml', 24*3600))) {
     $xml = simplexml_load_file($path);
   }
   if (!$xml) {
diff --git a/commands/runserver/runserver-drupal.inc b/commands/runserver/runserver-drupal.inc
new file mode 100644
index 0000000..385d362
--- /dev/null
+++ b/commands/runserver/runserver-drupal.inc
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ *   Classes extending the httpserver library that provide Drupal specific
+ *   behaviours.
+ */
+
+/**
+ * Extends the HTTPServer class, handling request routing and environment.
+ */
+class DrupalServer extends HTTPServer {
+  public $http_host;
+
+  /**
+   * This is the equivalent of .htaccess, passing requests to files if they
+   * exist, and all other requests to index.php. We also set a number
+   * of CGI environment variables here.  
+   */
+  function route_request($request) {
+    $cgi_env = array();
+
+    // Handle static files and php scripts accessed directly
+    $uri = $request->uri;
+    $doc_root = DRUPAL_ROOT;
+    $path = $doc_root . $uri;
+    if (is_file(realpath($path))) {
+      if (preg_match('#\.php$#', $uri)) {
+        // SCRIPT_NAME is equal to uri if it does exist on disk
+        $cgi_env['SCRIPT_NAME'] = $uri;
+        return $this->get_php_response($request, $path, $cgi_env);
+      }
+      return $this->get_static_response($request, $path);
+    }
+
+    // We pass in the effective base_url to our auto_prepend_script via the cgi
+    // environment. This allows Drupal to generate working URLs to this http
+    // server, whilst finding the correct multisite from the HTTP_HOST header.
+    $cgi_env['RUNSERVER_BASE_URL'] = 'http://localhost:' . $this->port;
+    
+    // We pass in an array of $conf overrides using the same approach.
+    // By default we set drupal_http_request_fails to FALSE, as the httpserver
+    // is unable to process simultanious requests on some systems.
+    // This is available as an option for developers to pass in their own
+    // favorite $conf overrides (e.g. disabling css aggregation). 
+    $conf_inject = drush_get_option('conf-inject', array('drupal_http_request_fails' => FALSE));
+    $cgi_env['RUNSERVER_CONF'] = urlencode(serialize($conf_inject));
+
+    // Rewrite clean-urls
+    $cgi_env['QUERY_STRING'] = 'q=' . ltrim($uri, '/');
+    if ($request->query_string != "") {
+      $cgi_env['QUERY_STRING'] .= '&' . $request->query_string;
+    }
+
+    $cgi_env['SCRIPT_NAME'] = '/index.php';
+    $cgi_env['HTTP_HOST'] = $cgi_env['SERVER_NAME'] = $this->http_host;
+
+    return $this->get_php_response($request, $doc_root . '/index.php', $cgi_env);
+  }
+}
diff --git a/commands/runserver/runserver-prepend.php b/commands/runserver/runserver-prepend.php
new file mode 100644
index 0000000..8f89d94
--- /dev/null
+++ b/commands/runserver/runserver-prepend.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @file
+ * This file is included using the php "auto_prepend_file" option whenever
+ * Drupal is used with runserver.
+ * We use this to inject some specific changes so Drupal works correctly in
+ * this environment.
+ */
+
+// We set the base_url so that Drupal generates correct URLs for runserver
+// (e.g. http://localhost:8888/...), but can still select and serve a specific
+// site in a multisite configuration (e.g. http://mysite.com/...).
+$base_url = $_SERVER['RUNSERVER_BASE_URL'];
+
+/**
+ * Configuration added here will apply to all sites.
+ * This can be a useful place to apply generic development settings.
+ * We hijack system_boot (which core system module does not implement) as
+ * a convenient place to inject values into the $conf array.
+ */
+if (!function_exists('system_boot')) {
+  // Check function_exists as a safety net in case it is added in future.
+  function system_boot() {
+    global $conf;
+    $conf_inject = unserialize(urldecode($_SERVER['RUNSERVER_CONF']));
+    // Merge in the injected conf, overriding existing items.
+    $conf = array_merge($conf, $conf_inject);
+  }
+}
\ No newline at end of file
diff --git a/commands/runserver/runserver.drush.inc b/commands/runserver/runserver.drush.inc
new file mode 100644
index 0000000..473f831
--- /dev/null
+++ b/commands/runserver/runserver.drush.inc
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ *   Built in http server commands.
+ *   
+ *   This uses an excellent php http server library developed by Jesse Young
+ *   with support from the Envaya project.
+ *   See https://github.com/youngj/httpserver/ and http://envaya.org/.
+ */
+
+/**
+ * Supported version of httpserver. This is displayed in the manual install help.
+ */
+define('DRUSH_HTTPSERVER_VERSION', '354b9142bf0cfd73063e28604d11288304531cd6');
+
+/**
+ * Directory name for httpserver. This is displayed in the manual install help.
+ */
+define('DRUSH_HTTPSERVER_DIR_BASE', 'youngj-httpserver-');
+
+/**
+ * Base URL for automatic download of supported version of httpserver.
+ */
+define('DRUSH_HTTPSERVER_BASE_URL', 'https://github.com/youngj/httpserver/tarball/');
+
+/**
+ * Implementation of hook_drush_help().
+ */
+function runserver_drush_help($section) {
+  switch ($section) {
+    case 'meta:runserver:title':
+      return dt("Runserver commands");
+    case 'drush:runserver':
+      return dt("Runs a lightweight built in http server for development.
+ - Don't use this for production, it is neither scalable nor secure for this use.
+ - If you run multiple servers simultaniously, you will need to assign each a unique port.
+ - Use Ctrl-C or equivalent to stop the server when complete.");
+  }
+}
+
+/**
+ * Implementation of hook_drush_command().
+ */
+function runserver_drush_command() {
+  $items = array();
+
+  $items['runserver'] = array(
+    'description' => 'Runs a lightweight built in http server for development.',
+    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_SITE,
+    'arguments' => array(
+      'addr:port' => 'Host IP address and port number to bind to (default 127.0.0.1:8888). The IP is optional, in which case just pass in the numeric port.',
+    ),
+    'options' => array(
+      'php-cgi' => 'Name of the php-cgi binary. If it is not on your current $PATH you should include the full path. You can include command line parameters to pass into php-cgi.',
+      'conf-inject' => 'Key-value array of variables to override in the $conf array for the running site. By default disables drupal_http_request_fails to avoid errors on Windows (which supports only one connection at a time). Note that as this is a key-value array, it can only be specified in a drushrc or alias file, and not on the command line.',
+    ),
+    'aliases' => array('rs'),
+  );
+  return $items;
+}
+
+/**
+ * Validate callback for runserver command.
+ */
+function drush_core_runserver_validate() {
+  if (version_compare(PHP_VERSION, '5.3.0') < 0) {
+    return drush_set_error('RUNSERVER_PHP_VERSION', dt('The runserver command requires php 5.3, which could not be found.'));
+  }
+  if (!drush_shell_exec('which ' . drush_get_option('php-cgi', 'php-cgi'))) {
+    return drush_set_error('RUNSERVER_PHP_CGI', dt('The runserver command requires the php-cgi binary, which could not be found.'));
+  }
+}
+
+/**
+ * Callback for runserver command.
+ */
+function drush_core_runserver($addrport = '8888') {
+  // Fetch httpserver to our /lib directory, if needed.
+  $lib = drush_get_option('lib', DRUSH_BASE_PATH . '/lib');
+  $httpserverfile = $lib . '/' . DRUSH_HTTPSERVER_DIR_BASE . substr(DRUSH_HTTPSERVER_VERSION, 0, 7) . '/httpserver.php';
+  if (!drush_file_not_empty($httpserverfile)) {
+    // Download and extract httpserver, and confirm success.
+    drush_lib_fetch(DRUSH_HTTPSERVER_BASE_URL . DRUSH_HTTPSERVER_VERSION);
+    if (!drush_file_not_empty($httpserverfile)) {
+      // Something went wrong - the library is still not present.
+      return drush_set_error('RUNSERVER_HTTPSERVER_LIB_NOT_FOUND', dt("The runserver command needs a copy of the httpserver library in order to function, and the attempt to download this file automatically failed. To continue you will need to download the package from !url, extract it into the !lib directory, such that httpserver.php exists at !httpserverfile.", array('!version' => DRUSH_HTTPSERVER_VERSION, '!url' => DRUSH_HTTPSERVER_BASE_URL . DRUSH_HTTPSERVER_VERSION, '!httpserverfile' => $httpserverfile, '!lib' => $lib)));
+    }
+  }
+
+  // Include the library and our class that extends it.
+  require_once $httpserverfile;
+  require_once 'runserver-drupal.inc';
+  
+  // Determine configuration.
+  if (is_numeric($addrport)) {
+    $addr = '127.0.0.1';
+    $port = $addrport;
+  }
+  else {
+    $addrport = explode(':', $addrport);
+    if (count($addrport) !== 2 && is_numeric($addrport[1])) {
+      return drush_set_error('RUNSERVER_INVALID_ADDRPORT', dt('Invalid address/port argument - should be either numeric (port only), or in the "host:port" format..'));
+    }
+    $addr = $addrport[0];
+    $port = $addrport[1];
+  }
+  
+  // We delete any registered files here, since they are not caught by Ctrl-C.
+  _drush_delete_registered_files();
+  
+  // Create a new server instance and start it running.
+  $server = new DrupalServer(array(
+    'addr' => $addr,
+    'port' => $port,
+    'serverid' => 'Drush runserver',
+    'php_cgi' => drush_get_option('php-cgi', 'php-cgi') . ' --define auto_prepend_file="' . DRUSH_BASE_PATH . '/commands/runserver/runserver-prepend.php"',
+  ));
+  $server->run_forever();
+}
diff --git a/includes/drush.inc b/includes/drush.inc
index a3ce1a3..ea175de 100644
--- a/includes/drush.inc
+++ b/includes/drush.inc
@@ -348,6 +348,7 @@ function drush_get_global_options($brief = FALSE) {
     $options['user']             = array('short-form' => 'u', 'description' => dt("Specify a Drupal user to login with. May be a name or a number."));
     $options['backend']          = array('short-form' => 'b', 'description' => dt("Hide all output and return structured data (internal use only)."));
     $options['choice']           = dt("Provide an answer to a multiple-choice prompt.");
+    $options['lib']              = dt("Location of directory where 3rd party libraries are available, or where Drush can downloaded them to if they are not found.");
     $options['no-label']         = dt("Remove the site label that drush includes in multi-site command output(e.g. `drush @site1,@site2 status`).");
     $options['nocolor']          = dt("Suppress color highlighting on log messages.");
     $options['show-passwords']   = dt("Show database passwords in commands that display connection information.");
@@ -703,21 +704,26 @@ function drush_op($function) {
 }
 
 /**
- * Download a file using wget or curl. Uses download cache.
+ * Download a file using wget, curl or file_get_contents, or via download cache.
  *
  * @param string $url
- *   The path to the file to download
- *
+ *   The url of the file to download.
+ * @param string $destination
+ *   The name of the file to be saved, which may include the full path.
+ *   Optional, if omitted the filename will be extracted from the url and the
+ *   file downloaded to the current working directory (Drupal root if
+ *   bootstrapped).
  * @param integer $cache_duration
  *   The acceptable age of a cached file. If cached file is too old, a fetch
- *   will occur and cache will be updated.
+ *   will occur and cache will be updated. Optional, if ommitted the file will
+ *   be fetched directly.
  *
  * @return string
- *   The path to the downloaded file, or FALSE
- *   if the file could not be downloaded.
+ *   The path to the downloaded file, or FALSE if the file could not be
+ *   downloaded.
  */
-function drush_download_file($url, $cache_duration) {
-  if (drush_get_option('cache') && $cache_dir = drush_directory_cache()) {
+function drush_download_file($url, $destination = FALSE, $cache_duration = 0) {
+  if (drush_get_option('cache') && $cache_duration !== 0 && $cache_dir = drush_directory_cache()) {
     drush_mkdir($cache_dir);
     $cache_name = str_replace(array(':', '/'), '-', $url);
     $cache_file = $cache_dir . "/" . $cache_name;
@@ -737,7 +743,7 @@ function drush_download_file($url, $cache_duration) {
       }
     }
   }
-  elseif ($return = _drush_download_file($url)) {
+  elseif ($return = _drush_download_file($url, $destination)) {
     drush_register_file_for_deletion($return);
     return $return;
   }
@@ -747,37 +753,104 @@ function drush_download_file($url, $cache_duration) {
 }
 
 /**
- * Download a file using wget or curl. Does not use download cache.
+ * Download a file using wget, curl or file_get_contents. Does not use download
+ * cache.
  *
  * @param string $url
- *   The path to the file to download
+ *   The url of the file to download.
+ * @param string $destination
+ *   The name of the file to be saved, which may include the full path.
+ *   Optional, if omitted the filename will be extracted from the url and the
+ *   file downloaded to the current working directory (Drupal root if
+ *   bootstrapped).
  *
  * @return string
- *   The path to the downloaded file, or FALSE
- *   if the file could not be downloaded. If omitted, downloads to
- *   current working directory (Drupal root if bootstrapped).
+ *   The path to the downloaded file, or FALSE if the file could not be
+ *   downloaded.
  */
-function _drush_download_file($url, $destination = NULL) {
+function _drush_download_file($url, $destination = FALSE) {
   if (!$destination) {
     $destination = getcwd() . '/' . basename($url);
   }
 
   $destination_tmp = drush_tempnam('download_file');
-  if (!drush_shell_exec("wget -O %s %s", $destination_tmp, $url)) {
-    // Wget failed - try curl.
-    if (!drush_shell_exec("curl -o %s %s", $destination, $url)) {
-      return FALSE;
-    }
+  drush_shell_exec("wget -q --timeout=30 -O %s %s", $destination_tmp, $url);
+  if (!drush_file_not_empty($destination_tmp)) {
+    drush_shell_exec("curl -s -L --connect-timeout 30 -o %s %s", $destination_tmp, $url);
   }
-  else {
-    // Wget succeeded. Move to final $destination.
-    drush_move_dir($destination_tmp, $destination);
+  if (!drush_file_not_empty($destination_tmp) && $file = @file_get_contents($url)) {
+    @file_put_contents($destination_tmp, $file);
+  }
+  if (!drush_file_not_empty($destination_tmp)) {
+    // Download failed.
+    return FALSE;
   }
 
+  drush_move_dir($destination_tmp, $destination);
   return $destination;
 }
 
 /**
+ * Extract a tarball.
+ *
+ * @param string $path
+ *   The name of the .tar.gz or .tgz file to be extracted.
+ * @param string $destination
+ *   The destination directory the tarball should be extracted into.
+ *   Optional, if ommitted the tarball directory will be used as destination.
+ *
+ * @return string
+ *   A file listing of the tarball if the extraction reported success,
+ *   otherwise FALSE.
+ */
+function drush_tarball_extract($path, $destination = FALSE) {
+  // Chdir to the download location.
+  $olddir = getcwd();
+  if (!$destination) {
+    $destination = dirname($path);
+  }
+  drush_op('chdir', $destination);
+  $tarpath = basename($path, '.tar.gz');
+  $tarpath = basename($tarpath, '.tgz');
+  $tarpath = $destination . '/' . $tarpath . '.tar';
+  // Ensure the intermediate file is deleted.
+  drush_register_file_for_deletion($tarpath);
+  // Decompress and untar in two steps as tar -xzf does not work on windows.
+  $result = FALSE;
+  if (drush_shell_exec("gzip --decompress --stdout %s > %s", $path, $tarpath) && drush_shell_exec("tar -xf %s", $tarpath)) {
+    // We use a separate tar -tf instead of -xvf above because
+    // the output is not the same in Mac.
+    drush_shell_exec("tar -tf %s", $tarpath);
+    $result = drush_shell_exec_output();
+  }
+  drush_op('chdir', $olddir);
+  return $result;
+}
+
+/**
+ * Extract a tarball to the lib directory.
+ * Checks for reported success, but callers should normally check for existence
+ * of specific expected file(s) in the library.
+ *
+ * @param string $url
+ *   The URL to of the .tar.gz or .tgz file to be extracted.
+ *
+ * @return string
+ *   TRUE is the download and extraction reported success, FALSE otherwise.
+ */
+function drush_lib_fetch($url) {
+  $lib = drush_get_option('lib', DRUSH_BASE_PATH . '/lib');
+  if (!is_writable($lib)) {
+    return drush_bootstrap_error('DRUSH_LIB_UNWRITABLE', dt("Drush needs to download a library from !url in order to function, and the attempt to download this file automatically failed because you do not have permission to write to the library directory !path. To continue you will need to manually download the package from !url, extract it, and copy the directory into your !path directory.", array('!path' => $lib, '!url' => $url)));
+  }
+
+  // We use an arbitary filename, since some sources (e.g. github) do not
+  // include a filename in the URL.
+  $path = $lib . '/drush-library-' . mt_rand() . '.tar.gz';
+  return drush_download_file($url, $path) && drush_tarball_extract($path);
+}
+
+/**
  * @defgroup commandprocessing Command processing functions.
  * @{
  *
diff --git a/includes/environment.inc b/includes/environment.inc
index ee25bbb..90d06a6 100644
--- a/includes/environment.inc
+++ b/includes/environment.inc
@@ -123,9 +123,9 @@ define('DRUSH_BOOTSTRAP_DRUPAL_LOGIN', 6);
 define('DRUSH_TABLE_VERSION', '1.1.3');
 
 /**
- * URL for automatic file download for supported version of Console Table.
+ * Base URL for automatic file download of PEAR packages.
  */
-define('DRUSH_TABLE_URL', 'http://svn.php.net/viewvc/pear/packages/Console_Table/trunk/Table.php?revision=267580&view=co');
+define('DRUSH_PEAR_BASE_URL', 'http://download.pear.php.net/package/');
 
 /**
  * Helper function listing phases.
@@ -504,7 +504,11 @@ function _drush_bootstrap_drush_validate() {
     return $return;
   }
 
-  if (drush_environment_table_inc() === FALSE) {
+  if (drush_environment_lib() === FALSE) {
+    return FALSE;
+  }
+
+  if (drush_environment_table_lib() === FALSE) {
     return FALSE;
   }
 
@@ -522,35 +526,38 @@ function drush_environment_check_os() {
   }
 }
 
-function drush_environment_table_inc() {
-  // try using the PEAR installed version of Console_Table
+/*
+ * Check for the existence of the specified lib directory, and create if needed.
+ */
+function drush_environment_lib() {
+  $lib = drush_get_option('lib', DRUSH_BASE_PATH . '/lib');
+  drush_mkdir($lib);
+  if (!is_dir($lib)) {
+    return FALSE;
+  }
+}
+
+function drush_environment_table_lib() {
+  // Try using the PEAR installed version of Console_Table.
   $tablefile = 'Console/Table.php';
   if (@file_get_contents($tablefile, FILE_USE_INCLUDE_PATH) === FALSE) {
-    $tablefile = DRUSH_BASE_PATH . '/includes/table.inc';
-
-    // Attempt to download Console Table, via various methods.
+    $lib = drush_get_option('lib', DRUSH_BASE_PATH . '/lib');
+    $tablefile = $lib . '/Console_Table-' . DRUSH_TABLE_VERSION . '/Table.php';
+    // If it is not already present, download Console Table.
     if (!drush_file_not_empty($tablefile)) {
-      $targetpath = dirname($tablefile);
-      // not point continuing if we can't write to the target path
-      if (!is_writable($targetpath)) {
-        return drush_bootstrap_error('DRUSH_TABLES_INC', dt("Drush needs a copy of the PEAR Console_Table library in order to function, and the attempt to download this file automatically failed because you do not have permission to write files in !path. To continue you will need to download the !version package from http://pear.php.net/package/Console_Table, extract it, and copy the Table.php file into Drush's directory as !tablefile.", array('!path' => $targetpath, '!version' => DRUSH_TABLE_VERSION ,'!tablefile' => $tablefile)));
-      }
-
-      if ($file = @file_get_contents(DRUSH_TABLE_URL)) {
-        @file_put_contents($tablefile, $file);
+      // Attempt to remove the old Console Table file, from the legacy location.
+      // TODO: Remove this (and associated .git.ignore) in Drush 6.x.
+      $tablefile_legacy = DRUSH_BASE_PATH . '/includes/table.inc';
+      if (drush_file_not_empty($tablefile_legacy)) {
+        drush_op('unlink', $tablefile_legacy);
       }
-      if (!file_exists($tablefile)) {
-        drush_shell_exec("wget -q --timeout=30 -O $tablefile " . DRUSH_TABLE_URL);
-        // wget creates an empty file on timeout. We remove it here.
-        if (file_exists($tablefile) && !drush_file_not_empty($tablefile)) {
-          unlink($tablefile);
-        }
-        if (!file_exists($tablefile)) {
-          drush_shell_exec("curl -s  --connect-timeout 30 -o $tablefile " . DRUSH_TABLE_URL);
-          if (!file_exists($tablefile)) {
-            return drush_bootstrap_error('DRUSH_TABLES_INC', dt("Drush needs a copy of the PEAR Console_Table library in order to function, and the attempt to download this file automatically failed. To continue you will need to download the !version package from http://pear.php.net/package/Console_Table, extract it, and copy the Table.php file into Drush's directory as !tablefile.", array('!version' => DRUSH_TABLE_VERSION ,'!tablefile' => $tablefile)));
-          }
-        }
+      
+      // Download and extract Console_Table, and confirm success.
+      drush_lib_fetch(DRUSH_PEAR_BASE_URL . 'Console_Table-' . DRUSH_TABLE_VERSION . '.tgz');
+      // Remove unneccessary package.xml file which ends up in /lib.
+      drush_op('unlink', $lib . '/package.xml');
+      if (!drush_file_not_empty($tablefile)) {
+        return drush_bootstrap_error('DRUSH_TABLES_LIB_NOT_FOUND', dt("Drush needs a copy of the PEAR Console_Table library in order to function, and the attempt to download this file automatically failed. To continue you will need to download the !version package from http://pear.php.net/package/Console_Table, extract it into !lib directory, such that Table.php exists at !tablefile.", array('!version' => DRUSH_TABLE_VERSION, '!tablefile' => $tablefile, '!lib' => $lib)));
       }
     }
   }
