diff --git a/.htaccess.sample b/.htaccess.sample
index c7b4df00f7d629ec99e800a4a6dd7c9e45432cbd..92a50e2df4b8ea244447b3cb47dd44e3af3a711a 100644
--- a/.htaccess.sample
+++ b/.htaccess.sample
@@ -62,6 +62,16 @@ DirectoryIndex index.php index.html index.htm
 <IfModule mod_rewrite.c>
   RewriteEngine on
 
+  # THIS SECTION IS AUTOMATICALY GENERATED.
+  # DO NOT EDIT!!!!
+  
+  RewriteRule .*/cron cron.php
+  RewriteRule .*/update.php update.php
+  
+  # %UNL_CREATION_TOOL_STUB%
+  
+  # END AUTOMATICALLY GENERATED AREA.
+  
   # Block access to "hidden" directories whose names begin with a period. This
   # includes directories used by version control systems such as Subversion or
   # Git to store control files. Files whose names begin with a period, as well
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 68c580e7738bf1217f4f4f594eefa713df9e340e..1c56966077d662ceea11d1ed8175222ad3d30620 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,6 @@
-// $Id: CHANGELOG.txt,v 1.371 2010/09/16 01:09:34 webchick Exp $
+// $Id: CHANGELOG.txt,v 1.373 2010/10/07 03:32:59 webchick Exp $
 
-Drupal 7.0 alpha 7, 2010-09-15
+Drupal 7.0 beta 1, 2010-10-06
 ----------------------
 - Database:
     * Fully rewritten database layer utilizing PHP 5's PDO abstraction layer.
diff --git a/INSTALL.txt b/INSTALL.txt
index 3630823ae21a7ffe9e23d52d51d60b05dd3eca6f..c8dc7ba1ab279116baf2c37cd138dff5c0d3206a 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -1,4 +1,4 @@
-// $Id: INSTALL.txt,v 1.82 2010/09/14 18:46:40 webchick Exp $
+// $Id: INSTALL.txt,v 1.83 2010/09/22 01:49:17 webchick Exp $
 
 CONTENTS OF THIS FILE
 ---------------------
@@ -72,12 +72,24 @@ INSTALLATION
 
      mv drupal-x.x/* drupal-x.x/.htaccess /var/www/html
 
-   If you would like to have the default English interface translated to a
-   different language, we have good news. You can install and use Drupal in
-   other languages from the start. Check whether a released package of the
-   language desired is available for this Drupal version at
-   http://drupal.org/project/translations and download the package. Extract
-   the contents to the same directory where you extracted Drupal into.
+   By default, Drupal is installed in English, and further languages may be
+   installed later. Follow these steps to translate Drupal into your language
+   during installation:
+
+   - Download a translation file for this Drupal version from the translation
+     server:
+     http://localize.drupal.org/download
+
+   - Rename the downloaded file to your language's ISO code (e.g., de.po or
+     fr.po) and place it into the directory /translations right below
+     the installation profile's directory that you want to use for your
+     installation (usually "standard"):
+
+       /profiles/standard/translations/
+
+   - Reload the language selection page after adding translations.
+
+   For detailed instructions, visit http://drupal.org/localize.
 
 2. IF NECESSARY, CREATE THE CONFIGURATION FILE AND GRANT WRITE PERMISSIONS
 
diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt
index d5088ae2bd614ffd634fcac70376da431d83ead0..69c63031521f7fcc3a0c448153e521f7a58bb0d4 100644
--- a/MAINTAINERS.txt
+++ b/MAINTAINERS.txt
@@ -1,4 +1,4 @@
-// $Id: MAINTAINERS.txt,v 1.46 2010/09/11 14:49:42 dries Exp $
+// $Id: MAINTAINERS.txt,v 1.48 2010/09/30 13:28:08 dries Exp $
 
 Drupal core is maintained by the community.  To participate, go to
 
@@ -32,6 +32,9 @@ Base system
 Batch system
 - Yves Chedemois 'yched' <http://drupal.org/user/39567>
 
+Cache system
+- Damien Tournoud 'DamZ' <http://drupal.org/user/22211>
+
 Cron system
 - Károly Négyesi 'chx' <http://drupal.org/user/9446>
 - Derek Wright 'dww' <http://drupal.org/user/46549>
@@ -277,12 +280,13 @@ Theme maintainers
 
 Bartik theme
 - Jen Simmons 'jensimmons' <http://drupal.org/user/140882>
+- Jeff Burns 'Jeff Burnz' <http://drupal.org/user/61393>
 
 Garland theme
 - ?
 
 Seven theme
-- ?
+- Jeff Burns 'Jeff Burnz' <http://drupal.org/user/61393>
 
 Stark theme
 - John Wilkins 'JohnAlbin' <http://drupal.org/user/32095>
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 97d76722271f0dedfe9b55cbdc4fafc032590397..55cf1b4637fb5922595eec62b2da0d6d9c12ad1a 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -1,4 +1,4 @@
-// $Id: UPGRADE.txt,v 1.24 2010/08/11 01:06:44 dries Exp $
+// $Id: UPGRADE.txt,v 1.25 2010/10/04 07:20:38 webchick Exp $
 
 UPGRADING
 ---------
@@ -12,6 +12,9 @@ Prior to upgrading, you should ensure that:
  * Custom and contributed themes have been checked for compatibility (#11).
  * You have read through this entire document.
 
+If you are upgrading from one major version to another (i.e., 6.x to 7.x),
+you must first upgrade to the latest version of your current release.
+
 Let's begin!
 
 1.  Back up your Drupal database and site root directory. Be especially sure
@@ -70,7 +73,7 @@ Let's begin!
 
     Note: if you are unable to access update.php do the following:
 
-      - Open your settings.php with a text editor.
+      - Open your settings.php file with a text editor.
 
       - There is a line that says $update_free_access = FALSE;
         Change it to $update_free_access = TRUE;
@@ -80,7 +83,7 @@ Let's begin!
 
 11. Ensure that the versions of all custom and contributed modules match the
     new Drupal version to which you have updated. For a major update, such as
-    from 5.x to 6.x, modules from previous versions will not be compatible
+    from 6.x to 7.x, modules from previous versions will not be compatible
     and updated versions will be required.
 
       - For contributed modules, check http://drupal.org/project/modules
@@ -107,5 +110,5 @@ Let's begin!
     screens at http://www.example.com/?q=admin/config/development/maintenance
     (replace www.example.com with your installation's domain name and path).
 
-For more information on upgrading visit
+For more information on upgrading, visit
 the Drupal handbook at http://drupal.org/upgrade
diff --git a/cron.php b/cron.php
index 91e6f9573aebd19d3d804ab0a38b231a5e700f5c..41b9d11d05c6eb61563a5d431047a1f2b3883836 100644
--- a/cron.php
+++ b/cron.php
@@ -11,7 +11,9 @@
  */
 define('DRUPAL_ROOT', getcwd());
 
+include_once DRUPAL_ROOT . '/includes/unl_bootstrap.inc';
 include_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+unl_bootstrap();
 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
 if (!isset($_GET['cron_key']) || variable_get('cron_key', 'drupal') != $_GET['cron_key']) {
diff --git a/includes/ajax.inc b/includes/ajax.inc
index 37b3d9c597b4624871970ca5ad7fed3ee27c8f20..6f7b937908609092f54e0bdef4ebeef78d53c1e1 100644
--- a/includes/ajax.inc
+++ b/includes/ajax.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: ajax.inc,v 1.32 2010/09/13 01:09:25 dries Exp $
+// $Id: ajax.inc,v 1.36 2010/10/06 23:03:39 webchick Exp $
 
 /**
  * @file
@@ -26,14 +26,34 @@
  * also return a richer set of @link ajax_commands AJAX framework commands @endlink.
  *
  * Standard form handling is as follows:
- *   - A form element has a #ajax member.
+ *   - A form element has a #ajax property that includes #ajax['callback'] and
+ *     omits #ajax['path']. See below about using #ajax['path'] to implement
+ *     advanced use-cases that require something other than standard form
+ *     handling.
  *   - On the specified element, AJAX processing is triggered by a change to
  *     that element.
- *   - The form is submitted and rebuilt.
- *   - The function named by #ajax['callback'] is called, which returns content
- *     or an array of AJAX framework commands.
- *   - The content returned by the callback replaces the div on the page
- *     referenced by #ajax['wrapper'].
+ *   - The browser submits an HTTP POST request to the 'system/ajax' Drupal
+ *     path.
+ *   - The menu page callback for 'system/ajax', ajax_form_callback(), calls
+ *     drupal_process_form() to process the form submission and rebuild the
+ *     form if necessary. The form is processed in much the same way as if it
+ *     were submitted without AJAX, with the same #process functions and
+ *     validation and submission handlers called in either case, making it easy
+ *     to create AJAX-enabled forms that degrade gracefully when JavaScript is
+ *     disabled.
+ *   - After form processing is complete, ajax_form_callback() calls the
+ *     function named by #ajax['callback'], which returns the form element that
+ *     has been updated and needs to be returned to the browser, or
+ *     alternatively, an array of custom AJAX commands.
+ *   - The page delivery callback for 'system/ajax', ajax_deliver(), renders the
+ *     element returned by #ajax['callback'], and returns the JSON string
+ *     created by ajax_render() to the browser.
+ *   - The browser unserializes the returned JSON string into an array of
+ *     command objects and executes each command, resulting in the old page
+ *     content within and including the HTML element specified by
+ *     #ajax['wrapper'] being replaced by the new content returned by
+ *     #ajax['callback'], using a JavaScript animation effect specified by
+ *     #ajax['effect'].
  *
  * A simple example of basic AJAX use from the
  * @link http://drupal.org/project/examples Examples module @endlink follows:
@@ -193,11 +213,76 @@
  *   functions.
  */
 function ajax_render($commands = array()) {
-  // Automatically extract any 'settings' added via drupal_add_js() and make
-  // them the first command.
-  $scripts = drupal_add_js(NULL, NULL);
+  // AJAX responses aren't rendered with html.tpl.php, so we have to call
+  // drupal_get_css() and drupal_get_js() here, in order to have new files added
+  // during this request to be loaded by the page. We only want to send back
+  // files that the page hasn't already loaded, so we implement simple diffing
+  // logic using array_diff_key().
+  foreach (array('css', 'js') as $type) {
+    // It is highly suspicious if $_POST['ajax_page_state'][$type] is empty,
+    // since the base page ought to have at least one JS file and one CSS file
+    // loaded. It probably indicates an error, and rather than making the page
+    // reload all of the files, instead we return no new files.
+    if (empty($_POST['ajax_page_state'][$type])) {
+      $items[$type] = array();
+    }
+    else {
+      $function = 'drupal_add_' . $type;
+      $items[$type] = $function();
+      drupal_alter($type, $items[$type]);
+      // @todo Inline CSS and JS items are indexed numerically. These can't be
+      //   reliably diffed with array_diff_key(), since the number can change
+      //   due to factors unrelated to the inline content, so for now, we strip
+      //   the inline items from AJAX responses, and can add support for them
+      //   when drupal_add_css() and drupal_add_js() are changed to using md5()
+      //   or some other hash of the inline content.
+      foreach ($items[$type] as $key => $item) {
+        if (is_numeric($key)) {
+          unset($items[$type][$key]);
+        }
+      }
+      // Ensure that the page doesn't reload what it already has.
+      $items[$type] = array_diff_key($items[$type], $_POST['ajax_page_state'][$type]);
+    }
+  }
+
+  // Settings are handled separately, later in this function, so that changes to
+  // the ajaxPageState setting that occur during drupal_get_css() and
+  // drupal_get_js() get included, and because the jQuery.extend() code produced
+  // by drupal_get_js() for adding settings isn't appropriate during an AJAX
+  // response, because it does not pass TRUE for the "deep" parameter, and
+  // therefore, can clobber existing settings on the page.
+  if (isset($items['js']['settings'])) {
+    unset($items['js']['settings']);
+  }
+
+  // Render the HTML to load these files, and add AJAX commands to insert this
+  // HTML in the page. We pass TRUE as the $skip_alter argument to prevent the
+  // data from being altered again, as we already altered it above.
+  $styles = drupal_get_css($items['css'], TRUE);
+  $scripts_footer = drupal_get_js('footer', $items['js'], TRUE);
+  $scripts_header = drupal_get_js('header', $items['js'], TRUE);
+
+  $extra_commands = array();
+  if (!empty($styles)) {
+    $extra_commands[] = ajax_command_prepend('head', $styles);
+  }
+  if (!empty($scripts_header)) {
+    $extra_commands[] = ajax_command_prepend('head', $scripts_header);
+  }
+  if (!empty($scripts_footer)) {
+    $extra_commands[] = ajax_command_append('body', $scripts_footer);
+  }
+  if (!empty($extra_commands)) {
+    $commands = array_merge($extra_commands, $commands);
+  }
+
+  $scripts = drupal_add_js();
   if (!empty($scripts['settings'])) {
-    array_unshift($commands, ajax_command_settings(call_user_func_array('array_merge_recursive', $scripts['settings']['data'])));
+    $settings = $scripts['settings'];
+    // Automatically extract any settings added via drupal_add_js() and make
+    // them the first command.
+    array_unshift($commands, ajax_command_settings(call_user_func_array('array_merge_recursive', $settings['data']), TRUE));
   }
 
   // Allow modules to alter any AJAX response.
@@ -286,6 +371,39 @@ function ajax_form_callback() {
   }
 }
 
+/**
+ * Theme callback for AJAX requests.
+ *
+ * Many different pages can invoke an AJAX request to system/ajax or another
+ * generic AJAX path. It is almost always desired for an AJAX response to be
+ * rendered using the same theme as the base page, because most themes are built
+ * with the assumption that they control the entire page, so if the CSS for two
+ * themes are both loaded for a given page, they may conflict with each other.
+ * For example, Bartik is Drupal's default theme, and Seven is Drupal's default
+ * administration theme. Depending on whether the "Use the administration theme
+ * when editing or creating content" checkbox is checked, the node edit form may
+ * be displayed in either theme, but the AJAX response to the Field module's
+ * "Add another item" button should be rendered using the same theme as the rest
+ * of the page. Therefore, system_menu() sets the 'theme callback' for
+ * 'system/ajax' to this function, and it is recommended that modules
+ * implementing other generic AJAX paths do the same.
+ */
+function ajax_base_page_theme() {
+  if (!empty($_POST['ajax_page_state']['theme']) && !empty($_POST['ajax_page_state']['theme_token'])) {
+    $theme = $_POST['ajax_page_state']['theme'];
+    $token = $_POST['ajax_page_state']['theme_token'];
+
+    // Prevent a request forgery from giving a person access to a theme they
+    // shouldn't be otherwise allowed to see. However, since everyone is allowed
+    // to see the default theme, token validation isn't required for that, and
+    // bypassing it allows most use-cases to work even when accessed from the
+    // page cache.
+    if ($theme === variable_get('theme_default', 'bartik') || drupal_valid_token($token, $theme)) {
+      return $theme;
+    }
+  }
+}
+
 /**
  * Package and send the result of a page callback to the browser as an AJAX response.
  *
@@ -457,7 +575,7 @@ function ajax_process_form($element, &$form_state) {
   // Attach JavaScript settings to the element.
   if (isset($element['#ajax']['event'])) {
     $element['#attached']['library'][] = array('system', 'form');
-    $element['#attached']['js']['misc/ajax.js'] = array('weight' => JS_LIBRARY + 2);
+    $element['#attached']['js']['misc/ajax.js'] = array('group' => JS_LIBRARY, 'weight' => 2);
 
     $settings = $element['#ajax'];
 
diff --git a/includes/batch.inc b/includes/batch.inc
index 4f062758cc997daa0364565973d84052400ef5ac..0f30bc4305ddb30ee98d0798d537c7782a02154a 100644
--- a/includes/batch.inc
+++ b/includes/batch.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: batch.inc,v 1.51 2010/09/13 01:09:25 dries Exp $
+// $Id: batch.inc,v 1.53 2010/10/04 07:34:26 webchick Exp $
 
 
 /**
@@ -285,7 +285,7 @@ function _batch_process() {
       );
       call_user_func_array($function, array_merge($args, array(&$batch_context)));
 
-      if ($finished == 1) {
+      if ($finished >= 1) {
         // Make sure this step is not counted twice when computing $current.
         $finished = 0;
         // Remove the processed operation and clear the sandbox.
@@ -343,7 +343,7 @@ function _batch_process() {
 
     $current    = $total - $remaining + $finished;
     $percentage = _batch_api_percentage($total, $current);
-    $elapsed    = $current_set['elapsed'];
+    $elapsed    = isset($current_set['elapsed']) ? $current_set['elapsed'] : 0;
     $values     = array(
       '@remaining'  => $remaining,
       '@total'      => $total,
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index e23ac2fbe4ca749fc16d9e8e93a2b040ed5bee03..39ba0e7a3ba05981a3ebe1e4e4de5ec0b8eea3d2 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: bootstrap.inc,v 1.418 2010/09/16 01:09:34 webchick Exp $
+// $Id: bootstrap.inc,v 1.422 2010/10/07 03:32:59 webchick Exp $
 
 /**
  * @file
@@ -9,7 +9,7 @@
 /**
  * The current system version.
  */
-define('VERSION', '7.0-alpha7');
+define('VERSION', '7.0-beta1');
 
 /**
  * Core API compatibility.
@@ -690,7 +690,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
     try {
       if (function_exists('db_query')) {
         $file = db_query("SELECT filename FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
-        if (file_exists($file)) {
+        if (file_exists(DRUPAL_ROOT . '/' . $file)) {
           $files[$type][$name] = $file;
         }
       }
@@ -2593,7 +2593,6 @@ function drupal_get_schema($table = NULL, $rebuild = FALSE) {
       // On some databases this function may be called before bootstrap has
       // been completed, so we force the functions we need to load just in case.
       if (function_exists('module_load_all_includes')) {
-
         // There is currently a bug in module_list() where it caches what it
         // was last called with, which is not always what you want.
         // module_load_all_includes() calls module_list(), but if this function
@@ -2601,7 +2600,7 @@ function drupal_get_schema($table = NULL, $rebuild = FALSE) {
         // uninitialized and therefore return no modules. Instead, we have to
         // "prime" module_list() here to to values we want, specifically
         // "yes rebuild the list and don't limit to bootstrap".
-        // TODO: Remove this call after http://drupal.org/node/222109 is fixed.
+        // @todo Remove this call after http://drupal.org/node/222109 is fixed.
         module_list(TRUE, FALSE);
         module_load_all_includes('install');
       }
@@ -2613,7 +2612,9 @@ function drupal_get_schema($table = NULL, $rebuild = FALSE) {
         // would cause array_merge() to set the $schema variable to NULL as well.
         // That would break modules which use $schema further down the line.
         $current = (array) module_invoke($module, 'schema');
-        _drupal_schema_initialize($module, $current);
+        // Set 'module' and 'name' keys for each table, and remove descriptions,
+        // as they needlessly slow down cache_get() for every single request.
+        _drupal_schema_initialize($current, $module);
         $schema = array_merge($schema, $current);
       }
 
diff --git a/includes/common.inc b/includes/common.inc
index 5316afad8d40e0ed2e097dfaa3581a3ee772b05f..51a352fdf42713bafc0e613fb28e274f5b30af92 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: common.inc,v 1.1220 2010/09/15 04:34:26 webchick Exp $
+// $Id: common.inc,v 1.1236 2010/10/07 00:28:19 webchick Exp $
 
 /**
  * @file
@@ -56,33 +56,33 @@ define('SAVED_UPDATED', 2);
 define('SAVED_DELETED', 3);
 
 /**
- * The default weight of system CSS files added to the page.
+ * The default group for system CSS files added to the page.
  */
 define('CSS_SYSTEM', -100);
 
 /**
- * The default weight of CSS files added to the page.
+ * The default group for module CSS files added to the page.
  */
 define('CSS_DEFAULT', 0);
 
 /**
- * The default weight of theme CSS files added to the page.
+ * The default group for theme CSS files added to the page.
  */
 define('CSS_THEME', 100);
 
 /**
- * The weight of JavaScript libraries, settings or jQuery plugins being
- * added to the page.
+ * The default group for JavaScript libraries, settings or jQuery plugins added
+ * to the page.
  */
 define('JS_LIBRARY', -100);
 
 /**
- * The default weight of JavaScript being added to the page.
+ * The default group for module JavaScript code added to the page.
  */
 define('JS_DEFAULT', 0);
 
 /**
- * The weight of theme JavaScript code being added to the page.
+ * The default group for theme JavaScript code added to the page.
  */
 define('JS_THEME', 100);
 
@@ -162,7 +162,7 @@ define('DRUPAL_CACHE_GLOBAL', 0x0008);
 function drupal_add_region_content($region = NULL, $data = NULL) {
   static $content = array();
 
-  if (!is_null($region) && !is_null($data)) {
+  if (isset($region) && isset($data)) {
     $content[$region][] = $data;
   }
   return $content;
@@ -230,7 +230,7 @@ function drupal_get_profile() {
 function drupal_set_breadcrumb($breadcrumb = NULL) {
   $stored_breadcrumb = &drupal_static(__FUNCTION__);
 
-  if (!is_null($breadcrumb)) {
+  if (isset($breadcrumb)) {
     $stored_breadcrumb = $breadcrumb;
   }
   return $stored_breadcrumb;
@@ -242,7 +242,7 @@ function drupal_set_breadcrumb($breadcrumb = NULL) {
 function drupal_get_breadcrumb() {
   $breadcrumb = drupal_set_breadcrumb();
 
-  if (is_null($breadcrumb)) {
+  if (!isset($breadcrumb)) {
     $breadcrumb = menu_get_active_breadcrumb();
   }
 
@@ -1616,7 +1616,7 @@ function format_rss_item($title, $link, $description, $args = array()) {
  * Format XML elements.
  *
  * @param $array
- *   An array where each item represent an element and is either a:
+ *   An array where each item represents an element and is either a:
  *   - (key => value) pair (<key>value</key>)
  *   - Associative array with fields:
  *     - 'key': element name
@@ -2270,9 +2270,9 @@ function l($text, $path, array $options = array()) {
 
   // Merge in defaults.
   $options += array(
-      'attributes' => array(),
-      'html' => FALSE,
-    );
+    'attributes' => array(),
+    'html' => FALSE,
+  );
 
   // Append active class.
   if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) &&
@@ -2434,7 +2434,7 @@ function drupal_deliver_html_page($page_callback_result) {
         // Print a 404 page.
         drupal_add_http_header('Status', '404 Not Found');
 
-        watchdog('page not found', 'page not found: %q.', array('%q' => $_GET['q']), WATCHDOG_WARNING);
+        watchdog('page not found', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);
 
         // Keep old path for reference, and to allow forms to redirect to it.
         if (!isset($_GET['destination'])) {
@@ -2463,7 +2463,7 @@ function drupal_deliver_html_page($page_callback_result) {
       case MENU_ACCESS_DENIED:
         // Print a 403 page.
         drupal_add_http_header('Status', '403 Forbidden');
-        watchdog('access denied', 'access denied: %q', array('%q' => $_GET['q']), WATCHDOG_WARNING);
+        watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);
 
         // Keep old path for reference, and to allow forms to redirect to it.
         if (!isset($_GET['destination'])) {
@@ -2737,19 +2737,50 @@ function drupal_add_html_head_link($attributes, $header = FALSE) {
  *     'modules/node/node.css' is 'node.css'. If the external library "node.js"
  *     ships with a 'node.css', then a different, unique basename would be
  *     'node.js.css'.
- *   - 'weight': The weight of the stylesheet specifies the order in which the
- *     CSS will appear when presented on the page. Available constants are:
+ *   - 'group': A number identifying the group in which to add the stylesheet.
+ *     Available constants are:
  *     - CSS_SYSTEM: Any system-layer CSS.
  *     - CSS_DEFAULT: Any module-layer CSS.
  *     - CSS_THEME: Any theme-layer CSS.
- *     If you need to embed a CSS file before any other module's stylesheets,
- *     for example, you would use CSS_DEFAULT - 1. Note that inline CSS is
- *     simply appended to the end of the specified scope (region), so they
- *     always come last.
+ *     The group number serves as a weight: the markup for loading a stylesheet
+ *     within a lower weight group is output to the page before the markup for
+ *     loading a stylesheet within a higher weight group, so CSS within higher
+ *     weight groups take precendence over CSS within lower weight groups.
+ *   - 'every_page': For optimal front-end performance when aggregation is
+ *     enabled, this should be set to TRUE if the stylesheet is present on every
+ *     page of the website for users for whom it is present at all. This
+ *     defaults to FALSE. It is set to TRUE for stylesheets added via module and
+ *     theme .info files. Modules that add stylesheets within hook_init()
+ *     implementations, or from other code that ensures that the stylesheet is
+ *     added to all website pages, should also set this flag to TRUE. All
+ *     stylesheets within the same group that have the 'every_page' flag set to
+ *     TRUE and do not have 'preprocess' set to FALSE are aggregated together
+ *     into a single aggregate file, and that aggregate file can be reused
+ *     across a user's entire site visit, leading to faster navigation between
+ *     pages. However, stylesheets that are only needed on pages less frequently
+ *     visited, can be added by code that only runs for those particular pages,
+ *     and that code should not set the 'every_page' flag. This minimizes the
+ *     size of the aggregate file that the user needs to download when first
+ *     visiting the website. Stylesheets without the 'every_page' flag are
+ *     aggregated into a separate aggregate file. This other aggregate file is
+ *     likely to change from page to page, and each new aggregate file needs to
+ *     be downloaded when first encountered, so it should be kept relatively
+ *     small by ensuring that most commonly needed stylesheets are added to
+ *     every page.
+ *   - 'weight': The weight of the stylesheet specifies the order in which the
+ *     CSS will appear relative to other stylesheets with the same group and
+ *     'every_page' flag. The exact ordering of stylesheets is as follows:
+ *     - First by group.
+ *     - Then by the 'every_page' flag, with TRUE coming before FALSE.
+ *     - Then by weight.
+ *     - Then by the order in which the CSS was added. For example, all else
+ *       being the same, a stylesheet added by a call to drupal_add_css() that
+ *       happened later in the page request gets added to the page after one for
+ *       which drupal_add_css() happened earlier in the page request.
  *   - 'media': The media type for the stylesheet, e.g., all, print, screen.
  *     Defaults to 'all'.
  *   - 'preprocess': If TRUE and CSS aggregation/compression is enabled, the
- *     styles will be aggregated and compressed. Defaults to FALSE.
+ *     styles will be aggregated and compressed. Defaults to TRUE.
  *   - 'browsers': An array containing information specifying which browsers
  *     should load the CSS item. See drupal_pre_render_conditional_comments()
  *     for details.
@@ -2775,9 +2806,11 @@ function drupal_add_css($data = NULL, $options = NULL) {
   if (isset($data)) {
     $options += array(
       'type' => 'file',
-      'weight' => CSS_DEFAULT,
+      'group' => CSS_DEFAULT,
+      'weight' => 0,
+      'every_page' => FALSE,
       'media' => 'all',
-      'preprocess' => FALSE,
+      'preprocess' => TRUE,
       'data' => $data,
       'browsers' => array(),
     );
@@ -2786,6 +2819,11 @@ function drupal_add_css($data = NULL, $options = NULL) {
       '!IE' => TRUE,
     );
 
+    // Files with a query string cannot be preprocessed.
+    if ($options['type'] === 'file' && $options['preprocess'] && strpos($options['data'], '?') !== FALSE) {
+      $options['preprocess'] = FALSE;
+    }
+
     // Always add a tiny value to the weight, to conserve the insertion order.
     $options['weight'] += count($css) / 1000;
 
@@ -2825,19 +2863,25 @@ function drupal_add_css($data = NULL, $options = NULL) {
  * @param $css
  *   (optional) An array of CSS files. If no array is provided, the default
  *   stylesheets array is used instead.
+ * @param $skip_alter
+ *   (optional) If set to TRUE, this function skips calling drupal_alter() on
+ *   $css, useful when the calling function passes a $css array that has already
+ *   been altered.
  * @return
  *   A string of XHTML CSS tags.
  */
-function drupal_get_css($css = NULL) {
+function drupal_get_css($css = NULL, $skip_alter = FALSE) {
   if (!isset($css)) {
     $css = drupal_add_css();
   }
 
   // Allow modules and themes to alter the CSS items.
-  drupal_alter('css', $css);
+  if (!$skip_alter) {
+    drupal_alter('css', $css);
+  }
 
-  // Sort CSS items according to their weights.
-  uasort($css, 'drupal_sort_weight');
+  // Sort CSS items, so that they appear in the correct order.
+  uasort($css, 'drupal_sort_css_js');
 
   // Remove the overridden CSS files. Later CSS files override former ones.
   $previous_item = array();
@@ -2858,9 +2902,55 @@ function drupal_get_css($css = NULL) {
     '#type' => 'styles',
     '#items' => $css,
   );
+
+  // Provide the page with information about the individual CSS files used,
+  // information not otherwise available when CSS aggregation is enabled.
+  $setting['ajaxPageState']['css'] = array_fill_keys(array_keys($css), 1);
+  $styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting);
+
   return drupal_render($styles);
 }
 
+/**
+ * Function used by uasort to sort the array structures returned by drupal_add_css() and drupal_add_js().
+ *
+ * This sort order helps optimize front-end performance while providing modules
+ * and themes with the necessary control for ordering the CSS and JavaScript
+ * appearing on a page.
+ */
+function drupal_sort_css_js($a, $b) {
+  // First order by group, so that, for example, all items in the CSS_SYSTEM
+  // group appear before items in the CSS_DEFAULT_GROUP, which appear before
+  // all items in the CSS_THEME group. Modules may create additional groups by
+  // defining their own constants.
+  if ($a['group'] < $b['group']) {
+    return -1;
+  }
+  elseif ($a['group'] > $b['group']) {
+    return 1;
+  }
+  // Within a group, order all infrequently needed, page-specific files after
+  // common files needed throughout the website. Separating this way allows for
+  // the aggregate file generated for all of the common files to be reused
+  // across a site visit without being cut by a page using a less common file.
+  elseif ($a['every_page'] && !$b['every_page']) {
+    return -1;
+  }
+  elseif (!$a['every_page'] && $b['every_page']) {
+    return 1;
+  }
+  // Finally, order by weight.
+  elseif ($a['weight'] < $b['weight']) {
+    return -1;
+  }
+  elseif ($a['weight'] > $b['weight']) {
+    return 1;
+  }
+  else {
+    return 0;
+  }
+}
+
 /**
  * Default callback to group CSS items.
  *
@@ -2924,7 +3014,10 @@ function drupal_group_css($css) {
     switch ($item['type']) {
       case 'file':
         // Group file items if their 'preprocess' flag is TRUE.
-        $group_keys = $item['preprocess'] ? array($item['type'], $item['media'], $item['browsers']) : FALSE;
+        // Help ensure maximum reuse of aggregate files by only grouping
+        // together items that share the same 'group' value and 'every_page'
+        // flag. See drupal_add_css() for details about that.
+        $group_keys = $item['preprocess'] ? array($item['type'], $item['group'], $item['every_page'], $item['media'], $item['browsers']) : FALSE;
         break;
       case 'inline':
         // Always group inline items.
@@ -3119,12 +3212,24 @@ function drupal_pre_render_styles($elements) {
         elseif ($group['preprocess']) {
           $import = array();
           foreach ($group['items'] as $item) {
-            // The dummy query string needs to be added to the URL to control
-            // browser-caching. IE7 does not support a media type on the @import
-            // statement, so we instead specify the media for the group on the
-            // STYLE tag.
-            $query_string_separator = (strpos($item['data'], '?') !== FALSE) ? '&' : '?';
-            $import[] = '@import url("' . check_plain(file_create_url($item['data']) . $query_string_separator . $query_string) . '");';
+            // A theme's .info file may have an entry for a file that doesn't
+            // exist as a way of overriding a module or base theme CSS file from
+            // being added to the page. Normally, file_exists() calls that need
+            // to run for every page request should be minimized, but this one
+            // is okay, because it only runs when CSS aggregation is disabled.
+            // On a server under heavy enough load that file_exists() calls need
+            // to be minimized, CSS aggregation should be enabled, in which case
+            // this code is not run. When aggregation is enabled,
+            // drupal_load_stylesheet() checks file_exists(), but only when
+            // building the aggregate file, which is then reused for many page
+            // requests.
+            if (file_exists($item['data'])) {
+              // The dummy query string needs to be added to the URL to control
+              // browser-caching. IE7 does not support a media type on the
+              // @import statement, so we instead specify the media for the
+              // group on the STYLE tag.
+              $import[] = '@import url("' . check_plain(file_create_url($item['data']) . '?' . $query_string) . '");';
+            }
           }
           // In addition to IE's limit of 31 total CSS inclusion tags, it also
           // has a limit of 31 @import statements per STYLE tag.
@@ -3143,6 +3248,14 @@ function drupal_pre_render_styles($elements) {
         else {
           foreach ($group['items'] as $item) {
             $element = $link_element_defaults;
+            // We do not check file_exists() here, because this code runs for
+            // files whose 'preprocess' is set to FALSE, and therefore, even
+            // when aggregation is enabled, and we want to avoid needlessly
+            // taxing a server that may be under heavy load. The file_exists()
+            // performed above for files whose 'preprocess' is TRUE is done for
+            // the benefit of theme .info files, but code that deals with files
+            // whose 'preprocess' is FALSE is responsible for ensuring the file
+            // exists.
             // The dummy query string needs to be added to the URL to control
             // browser-caching.
             $query_string_separator = (strpos($item['data'], '?') !== FALSE) ? '&' : '?';
@@ -3654,27 +3767,63 @@ function drupal_region_class($region) {
  *   - scope: The location in which you want to place the script. Possible
  *     values are 'header' or 'footer'. If your theme implements different
  *     regions, you can also use these. Defaults to 'header'.
- *   - weight: A number defining the order in which the JavaScript is added to
- *     the page. In some cases, the order in which the JavaScript is presented
- *     on the page is very important. jQuery, for example, must be added to
- *     the page before any jQuery code is run, so jquery.js uses a weight of
- *     JS_LIBRARY - 20, jquery.once.js (a library drupal.js depends on) uses
- *     a weight of JS_LIBRARY - 19, drupal.js uses a weight of JS_LIBRARY - 1,
- *     and all following scripts depending on jQuery and Drupal behaviors are
- *     simply added using the default weight of JS_DEFAULT. Available constants
- *     are:
+ *   - 'group': A number identifying the group in which to add the JavaScript.
+ *     Available constants are:
  *     - JS_LIBRARY: Any libraries, settings, or jQuery plugins.
  *     - JS_DEFAULT: Any module-layer JavaScript.
  *     - JS_THEME: Any theme-layer JavaScript.
- *     If you need to invoke a JavaScript file before any other module's
- *     JavaScript, for example, you would use JS_DEFAULT - 1.
+ *     The group number serves as a weight: JavaScript within a lower weight
+ *     group is presented on the page before JavaScript within a higher weight
+ *     group.
+ *  - 'every_page': For optimal front-end performance when aggregation is
+ *     enabled, this should be set to TRUE if the JavaScript is present on every
+ *     page of the website for users for whom it is present at all. This
+ *     defaults to FALSE. It is set to TRUE for JavaScript files that are added
+ *     via module and theme .info files. Modules that add JavaScript within
+ *     hook_init() implementations, or from other code that ensures that the
+ *     JavaScript is added to all website pages, should also set this flag to
+ *     TRUE. All JavaScript files within the same group and that have the
+ *     'every_page' flag set to TRUE and do not have 'preprocess' set to FALSE
+ *     are aggregated together into a single aggregate file, and that aggregate
+ *     file can be reused across a user's entire site visit, leading to faster
+ *     navigation between pages. However, JavaScript that is only needed on
+ *     pages less frequently visited, can be added by code that only runs for
+ *     those particular pages, and that code should not set the 'every_page'
+ *     flag. This minimizes the size of the aggregate file that the user needs
+ *     to download when first visiting the website. JavaScript without the
+ *     'every_page' flag is aggregated into a separate aggregate file. This
+ *     other aggregate file is likely to change from page to page, and each new
+ *     aggregate file needs to be downloaded when first encountered, so it
+ *     should be kept relatively small by ensuring that most commonly needed
+ *     JavaScript is added to every page.
+ *   - weight: A number defining the order in which the JavaScript is added to
+ *     the page relative to other JavaScript with the same 'scope', 'group',
+ *     and 'every_page' value. In some cases, the order in which the JavaScript
+ *     is presented on the page is very important. jQuery, for example, must be
+ *     added to the page before any jQuery code is run, so jquery.js uses the
+ *     JS_LIBRARY group and a weight of -20, jquery.once.js (a library drupal.js
+ *     depends on) uses the JS_LIBRARY group and a weight of -19, drupal.js uses
+ *     the JS_LIBRARY group and a weight of -1, other libraries use the
+ *     JS_LIBRARY group and a weight of 0 or higher, and all other scripts use
+ *     one of the other group constants. The exact ordering of JavaScript is as
+ *     follows:
+ *     - First by scope, with 'header' first, 'footer' last, and any other
+ *       scopes provided by a custom theme coming in between, as determined by
+ *       the theme.
+ *     - Then by group.
+ *     - Then by the 'every_page' flag, with TRUE coming before FALSE.
+ *     - Then by weight.
+ *     - Then by the order in which the JavaScript was added. For example, all
+ *       else being the same, JavaScript added by a call to drupal_add_js() that
+ *       happened later in the page request gets added to the page after one for
+ *       which drupal_add_js() happened earlier in the page request.
  *   - defer: If set to TRUE, the defer attribute is set on the &lt;script&gt;
  *     tag.  Defaults to FALSE.
  *   - cache: If set to FALSE, the JavaScript file is loaded anew on every page
  *     call; in other words, it is not cached. Used only when 'type' references
  *     a JavaScript file. Defaults to TRUE.
  *   - preprocess: If TRUE and JavaScript aggregation is enabled, the script
- *     file will be aggregated. Defaults to FALSE.
+ *     file will be aggregated. Defaults to TRUE.
  *
  * @return
  *   The current array of JavaScript files, settings, and in-line code,
@@ -3715,21 +3864,25 @@ function drupal_add_js($data = NULL, $options = NULL) {
           ),
           'type' => 'setting',
           'scope' => 'header',
-          'weight' => JS_LIBRARY,
+          'group' => JS_LIBRARY,
+          'every_page' => TRUE,
+          'weight' => 0,
         ),
         'misc/drupal.js' => array(
           'data' => 'misc/drupal.js',
           'type' => 'file',
           'scope' => 'header',
-          'weight' => JS_LIBRARY - 1,
+          'group' => JS_LIBRARY,
+          'every_page' => TRUE,
+          'weight' => -1,
+          'preprocess' => TRUE,
           'cache' => TRUE,
           'defer' => FALSE,
-          'preprocess' => TRUE,
         ),
       );
       // Register all required libraries.
-      drupal_add_library('system', 'jquery');
-      drupal_add_library('system', 'once');
+      drupal_add_library('system', 'jquery', TRUE);
+      drupal_add_library('system', 'once', TRUE);
     }
 
     switch ($options['type']) {
@@ -3763,11 +3916,13 @@ function drupal_add_js($data = NULL, $options = NULL) {
 function drupal_js_defaults($data = NULL) {
   return array(
     'type' => 'file',
-    'weight' => JS_DEFAULT,
+    'group' => JS_DEFAULT,
+    'every_page' => FALSE,
+    'weight' => 0,
     'scope' => 'header',
     'cache' => TRUE,
     'defer' => FALSE,
-    'preprocess' => FALSE,
+    'preprocess' => TRUE,
     'version' => NULL,
     'data' => $data,
   );
@@ -3794,13 +3949,17 @@ function drupal_js_defaults($data = NULL) {
  * @param $javascript
  *   (optional) An array with all JavaScript code. Defaults to the default
  *   JavaScript array for the given scope.
+ * @param $skip_alter
+ *   (optional) If set to TRUE, this function skips calling drupal_alter() on
+ *   $javascript, useful when the calling function passes a $javascript array
+ *   that has already been altered.
  * @return
  *   All JavaScript code segments and includes for the scope as HTML tags.
  * @see drupal_add_js()
  * @see locale_js_alter()
  * @see drupal_js_defaults()
  */
-function drupal_get_js($scope = 'header', $javascript = NULL) {
+function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALSE) {
   if (!isset($javascript)) {
     $javascript = drupal_add_js();
   }
@@ -3809,13 +3968,15 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
   }
 
   // Allow modules to alter the JavaScript.
-  drupal_alter('js', $javascript);
+  if (!$skip_alter) {
+    drupal_alter('js', $javascript);
+  }
 
   // Filter out elements of the given scope.
   $items = array();
-  foreach ($javascript as $item) {
+  foreach ($javascript as $key => $item) {
     if ($item['scope'] == $scope) {
-      $items[] = $item;
+      $items[$key] = $item;
     }
   }
 
@@ -3845,8 +4006,24 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
   // third-party code might require the use of a different query string.
   $js_version_string = variable_get('drupal_js_version_query_string', 'v=');
 
-  // Sort the JavaScript by weight so that it appears in the correct order.
-  uasort($items, 'drupal_sort_weight');
+  // Sort the JavaScript so that it appears in the correct order.
+  uasort($items, 'drupal_sort_css_js');
+
+  // Provide the page with information about the individual JavaScript files
+  // used, information not otherwise available when aggregation is enabled.
+  $setting['ajaxPageState']['js'] = array_fill_keys(array_keys($items), 1);
+  unset($setting['ajaxPageState']['js']['settings']);
+  drupal_add_js($setting, 'setting');
+
+  // If we're outputting the header scope, then this might be the final time
+  // that drupal_get_js() is running, so add the setting to this output as well
+  // as to the drupal_add_js() cache. If $items['settings'] doesn't exist, it's
+  // because drupal_get_js() was intentionally passed a $javascript argument
+  // stripped off settings, potentially in order to override how settings get
+  // output, so in this case, do not add the setting to this output.
+  if ($scope == 'header' && isset($items['settings'])) {
+    $items['settings']['data'][] = $setting;
+  }
 
   // Loop through the JavaScript to construct the rendered output.
   $element = array(
@@ -3891,8 +4068,13 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
         }
         else {
           // By increasing the index for each aggregated file, we maintain
-          // the relative ordering of JS by weight.
-          $key = 'aggregate' . $index;
+          // the relative ordering of JS by weight. We also set the key such
+          // that groups are split by items sharing the same 'group' value and
+          // 'every_page' flag. While this potentially results in more aggregate
+          // files, it helps make each one more reusable across a site visit,
+          // leading to better front-end performance of a website as a whole.
+          // See drupal_add_js() for details.
+          $key = 'aggregate_' . $item['group'] . '_' . $item['every_page'] . '_' . $index;
           $processed[$key] = '';
           $files[$key][$item['data']] = $item;
         }
@@ -3956,9 +4138,9 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
  *
  * @param $elements
  *   The structured array describing the data being rendered.
- * @param $weight
- *   The default weight of JavaScript and CSS being added. This is only applied
- *   to the stylesheets and JavaScript items that don't have an explicit weight
+ * @param $group
+ *   The default group of JavaScript and CSS being added. This is only applied
+ *   to the stylesheets and JavaScript items that don't have an explicit group
  *   assigned to them.
  * @param $dependency_check
  *   When TRUE, will exit if a given library's dependencies are missing. When
@@ -3974,7 +4156,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL) {
  * @see drupal_add_css()
  * @see drupal_render()
  */
-function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_check = FALSE) {
+function drupal_process_attached($elements, $group = JS_DEFAULT, $dependency_check = FALSE, $every_page = NULL) {
   // Add defaults to the special attached structures that should be processed differently.
   $elements['#attached'] += array(
     'library' => array(),
@@ -3985,7 +4167,7 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
   // Add the libraries first.
   $success = TRUE;
   foreach ($elements['#attached']['library'] as $library) {
-    if (drupal_add_library($library[0], $library[1]) === FALSE) {
+    if (drupal_add_library($library[0], $library[1], $every_page) === FALSE) {
       $success = FALSE;
       // Exit if the dependency is missing.
       if ($dependency_check) {
@@ -4012,9 +4194,13 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
         $data = $options['data'];
         unset($options['data']);
       }
-      // Apply the default weight if the weight isn't explicitly given.
-      if (!isset($options['weight'])) {
-        $options['weight'] = $weight;
+      // Apply the default group if it isn't explicitly given.
+      if (!isset($options['group'])) {
+        $options['group'] = $group;
+      }
+      // Set the every_page flag if one was passed.
+      if (isset($every_page)) {
+        $options['every_page'] = $every_page;
       }
       call_user_func('drupal_add_' . $type, $data, $options);
     }
@@ -4161,7 +4347,7 @@ function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_ch
  * @see form_example_states_form()
  */
 function drupal_process_states(&$elements) {
-  $elements['#attached']['js']['misc/states.js'] = array('weight' => JS_LIBRARY + 1);
+  $elements['#attached']['js']['misc/states.js'] = array('group' => JS_LIBRARY, 'weight' => 1);
   $elements['#attached']['js'][] = array(
     'type' => 'setting',
     'data' => array('states' => array('#' . $elements['#id'] => $elements['#states'])),
@@ -4190,7 +4376,7 @@ function drupal_process_states(&$elements) {
  * @see hook_library()
  * @see hook_library_alter()
  */
-function drupal_add_library($module, $name) {
+function drupal_add_library($module, $name, $every_page = NULL) {
   $added = &drupal_static(__FUNCTION__, array());
 
   // Only process the library if it exists and it was not added already.
@@ -4202,7 +4388,7 @@ function drupal_add_library($module, $name) {
         'js' => $library['js'],
         'css' => $library['css'],
       );
-      $added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE);
+      $added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE, $every_page);
     }
     else {
       // Requested library does not exist.
@@ -4383,8 +4569,8 @@ function drupal_add_tabledrag($table_id, $action, $relationship, $group, $subgro
     // Add the table drag JavaScript to the page before the module JavaScript
     // to ensure that table drag behaviors are registered before any module
     // uses it.
-    drupal_add_js('misc/jquery.cookie.js', array('weight' => JS_DEFAULT - 2));
-    drupal_add_js('misc/tabledrag.js', array('weight' => JS_DEFAULT - 1));
+    drupal_add_js('misc/jquery.cookie.js', array('weight' => -2));
+    drupal_add_js('misc/tabledrag.js', array('weight' => -1));
     $js_added = TRUE;
   }
 
@@ -5604,6 +5790,31 @@ function element_get_visible_children(array $elements) {
   return array_keys($visible_children);
 }
 
+/**
+ * Sets HTML attributes based on element properties.
+ *
+ * @param $element
+ *   The renderable element to process.
+ * @param $map
+ *   An associative array whose keys are element property names and whose values
+ *   are the HTML attribute names to set for corresponding the property; e.g.,
+ *   array('#propertyname' => 'attributename'). If both names are identical
+ *   except for the leading '#', then an attribute name value is sufficient and
+ *   no property name needs to be specified.
+ */
+function element_set_attributes(array &$element, array $map) {
+  foreach ($map as $property => $attribute) {
+    // If the key is numeric, the attribute name needs to be taken over.
+    if (is_int($property)) {
+      $property = '#' . $attribute;
+    }
+    // Do not overwrite already existing attributes.
+    if (isset($element[$property]) && !isset($element['#attributes'][$attribute])) {
+      $element['#attributes'][$attribute] = $element[$property];
+    }
+  }
+}
+
 /**
  * Sets a value in a nested array with variable depth.
  *
@@ -5821,7 +6032,7 @@ function drupal_common_theme() {
       // - http://dev.w3.org/html5/spec/Overview.html#alt
       // The title attribute is optional in all cases, so it is omitted by
       // default.
-      'variables' => array('path' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'getsize' => TRUE),
+      'variables' => array('path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array()),
     ),
     'breadcrumb' => array(
       'variables' => array('breadcrumb' => NULL),
@@ -5937,6 +6148,9 @@ function drupal_common_theme() {
     'date' => array(
       'render element' => 'element',
     ),
+    'exposed_filters' => array(
+      'render element' => 'form',
+    ),
     'checkbox' => array(
       'render element' => 'element',
     ),
@@ -6005,7 +6219,7 @@ function drupal_common_theme() {
  */
 function drupal_install_schema($module) {
   $schema = drupal_get_schema_unprocessed($module);
-  _drupal_schema_initialize($module, $schema);
+  _drupal_schema_initialize($schema, $module, FALSE);
 
   foreach ($schema as $name => $table) {
     db_create_table($name, $table);
@@ -6028,7 +6242,7 @@ function drupal_install_schema($module) {
  */
 function drupal_uninstall_schema($module) {
   $schema = drupal_get_schema_unprocessed($module);
-  _drupal_schema_initialize($module, $schema);
+  _drupal_schema_initialize($schema, $module, FALSE);
 
   foreach ($schema as $table) {
     if (db_table_exists($table['name'])) {
@@ -6066,7 +6280,7 @@ function drupal_get_schema_unprocessed($module, $table = NULL) {
   module_load_install($module);
   $schema = module_invoke($module, 'schema');
 
-  if (!is_null($table) && isset($schema[$table])) {
+  if (isset($table) && isset($schema[$table])) {
     return $schema[$table];
   }
   elseif (!empty($schema)) {
@@ -6078,20 +6292,30 @@ function drupal_get_schema_unprocessed($module, $table = NULL) {
 /**
  * Fill in required default values for table definitions returned by hook_schema().
  *
- * @param $module
- *   The module for which hook_schema() was invoked.
  * @param $schema
  *   The schema definition array as it was returned by the module's
  *   hook_schema().
+ * @param $module
+ *   The module for which hook_schema() was invoked.
+ * @param $remove_descriptions
+ *   (optional) Whether to additionally remove 'description' keys of all tables
+ *   and fields to improve performance of serialize() and unserialize().
+ *   Defaults to TRUE.
  */
-function _drupal_schema_initialize($module, &$schema) {
+function _drupal_schema_initialize(&$schema, $module, $remove_descriptions = TRUE) {
   // Set the name and module key for all tables.
-  foreach ($schema as $name => $table) {
+  foreach ($schema as $name => &$table) {
     if (empty($table['module'])) {
-      $schema[$name]['module'] = $module;
+      $table['module'] = $module;
     }
     if (!isset($table['name'])) {
-      $schema[$name]['name'] = $name;
+      $table['name'] = $name;
+    }
+    if ($remove_descriptions) {
+      unset($table['description']);
+      foreach ($table['fields'] as &$field) {
+        unset($field['description']);
+      }
     }
   }
 }
@@ -6180,7 +6404,7 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
     }
 
     if (!property_exists($object, $field)) {
-      // Skip fields that are not provided, default values are already known 
+      // Skip fields that are not provided, default values are already known
       // by the database.
       continue;
     }
@@ -6199,7 +6423,7 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
     // MySQL PDO silently casts e.g. FALSE and '' to 0 when inserting the value
     // into an integer column, but PostgreSQL PDO does not. Also type cast NULL
     // when the column does not allow this.
-    if (!is_null($object->$field) || !empty($info['not null'])) {
+    if (isset($object->$field) || !empty($info['not null'])) {
       if ($info['type'] == 'int' || $info['type'] == 'serial') {
         $fields[$field] = (int) $fields[$field];
       }
@@ -6506,8 +6730,13 @@ function drupal_flush_all_caches() {
   system_rebuild_theme_data();
   drupal_theme_rebuild();
 
-  menu_rebuild();
   node_types_rebuild();
+  // node_menu() defines menu items based on node types so it needs to come
+  // after node types are rebuilt.
+  menu_rebuild();
+
+  // Synchronize to catch any actions that were added or removed.
+  actions_synchronize();
 
   // Don't clear cache_form - in-progress form submissions may break.
   // Ordered so clearing the page cache will always be the last action.
@@ -6769,10 +6998,10 @@ function entity_create_stub_entity($entity_type, $ids) {
   $entity = new stdClass();
   $info = entity_get_info($entity_type);
   $entity->{$info['entity keys']['id']} = $ids[0];
-  if (!empty($info['entity keys']['revision']) && !is_null($ids[1])) {
+  if (!empty($info['entity keys']['revision']) && isset($ids[1])) {
     $entity->{$info['entity keys']['revision']} = $ids[1];
   }
-  if (!empty($info['entity keys']['bundle']) && !is_null($ids[2])) {
+  if (!empty($info['entity keys']['bundle']) && isset($ids[2])) {
     $entity->{$info['entity keys']['bundle']} = $ids[2];
   }
   return $entity;
@@ -6786,15 +7015,16 @@ function entity_create_stub_entity($entity_type, $ids) {
  * database access if loaded again during the same page request.
  *
  * The actual loading is done through a class that has to implement the
- * DrupalEntityController interface. By default, DrupalDefaultEntityController
- * is used. Entity types can specify that a different class should be used by
- * setting the 'controller class' key in hook_entity_info(). These classes can
- * either implement the DrupalEntityController interface, or, most commonly,
- * extend the DrupalDefaultEntityController class. See node_entity_info() and
- * the NodeController in node.module as an example.
+ * DrupalEntityControllerInterface interface. By default,
+ * DrupalDefaultEntityController is used. Entity types can specify that a
+ * different class should be used by setting the 'controller class' key in
+ * hook_entity_info(). These classes can either implement the
+ * DrupalEntityControllerInterface interface, or, most commonly, extend the
+ * DrupalDefaultEntityController class. See node_entity_info() and the
+ * NodeController in node.module as an example.
  *
  * @see hook_entity_info()
- * @see DrupalEntityController
+ * @see DrupalEntityControllerInterface
  * @see DrupalDefaultEntityController
  *
  * @param $entity_type
@@ -6809,7 +7039,7 @@ function entity_create_stub_entity($entity_type, $ids) {
  * @return
  *   An array of entity objects indexed by their ids.
  */
-function entity_load($entity_type, $ids = array(), $conditions = array(), $reset = FALSE) {
+function entity_load($entity_type, $ids = FALSE, $conditions = array(), $reset = FALSE) {
   if ($reset) {
     entity_get_controller($entity_type)->resetCache();
   }
diff --git a/includes/database/database.inc b/includes/database/database.inc
index 0b8b95d5bb4541f947cea3c6fe6ee138cee70da5..52e6e51fadd0809ce3d4aa98bfe2113e5adae9cc 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: database.inc,v 1.135 2010/09/11 21:14:31 webchick Exp $
+// $Id: database.inc,v 1.140 2010/10/03 01:29:40 dries Exp $
 
 /**
  * @file
@@ -41,7 +41,7 @@
  * @code
  * $result = db_query_range('SELECT n.nid, n.title, n.created
  *   FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
- * foreach($result as $record) {
+ * foreach ($result as $record) {
  *   // Perform operations on $node->title, etc. here.
  * }
  * @endcode
@@ -50,7 +50,8 @@
  * out into an argument passed to db_query() so that SQL injection attacks
  * from user input can be caught and nullified. The LIMIT syntax varies between
  * database servers, so that is abstracted into db_query_range() arguments.
- * Finally, note the PDO-based ability to foreach() over the result set.
+ * Finally, note the PDO-based ability to iterate over the result set using
+ * foreach ().
  *
  * All queries are passed as a prepared statement string. A
  * prepared statement is a "template" of a query that omits literal or variable
@@ -166,6 +167,8 @@
  *   }
  * }
  * @endcode
+ *
+ * @link http://drupal.org/developing/api/database
  */
 
 
@@ -815,6 +818,7 @@ abstract class DatabaseConnection extends PDO {
    * Force all alias names to be strictly alphanumeric-plus-underscore. In
    * contrast to DatabaseConnection::escapeField() /
    * DatabaseConnection::escapeTable(), this doesn't allow the period (".")
+   * because that is not allowed in aliases.
    *
    * @return
    *   The sanitized field name string.
@@ -1065,7 +1069,9 @@ abstract class DatabaseConnection extends PDO {
   /**
    * Returns the version of the database server.
    */
-  abstract public function version();
+  public function version() {
+    return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
+  }
 
   /**
    * Determines if this driver supports transactions.
@@ -2184,9 +2190,12 @@ function db_autoload($class) {
 /**
  * Executes an arbitrary query string against the active database.
  *
+ * Use this function for SELECT queries if it is just a simple query string.
+ * If the caller or other modules need to change the query, use db_select()
+ * instead.
+ *
  * Do not use this function for INSERT, UPDATE, or DELETE queries. Those should
- * be handled via the appropriate query builder factory. Use this function for
- * SELECT queries that do not require a query builder.
+ * be handled via db_insert(), db_update() and db_delete() respectively.
  *
  * @param $query
  *   The prepared statement query to run. Although it will accept both named and
diff --git a/includes/database/mysql/database.inc b/includes/database/mysql/database.inc
index f937378fe6a0d762a76203c2bbad8ca10004174f..127c8daf8cec9d312900ffd83c11b1695b3db51b 100644
--- a/includes/database/mysql/database.inc
+++ b/includes/database/mysql/database.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: database.inc,v 1.33 2010/08/11 02:17:39 dries Exp $
+// $Id: database.inc,v 1.34 2010/10/03 01:29:41 dries Exp $
 
 /**
  * @file
@@ -79,11 +79,6 @@ class DatabaseConnection_mysql extends DatabaseConnection {
     return 'mysql';
   }
 
-  public function version() {
-    $data = $this->query('SHOW variables LIKE :name', array(':name' => 'version'))->fetchAssoc();
-    return $data['value'];
-  }
-
   public function databaseType() {
     return 'mysql';
   }
diff --git a/includes/database/mysql/schema.inc b/includes/database/mysql/schema.inc
index 3a6815528d794606ca9d0eebde69601a3565a720..f042a217383f00654e5532158f1e718c1677b5ea 100644
--- a/includes/database/mysql/schema.inc
+++ b/includes/database/mysql/schema.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: schema.inc,v 1.41 2010/08/02 18:55:17 webchick Exp $
+// $Id: schema.inc,v 1.42 2010/09/25 01:41:26 dries Exp $
 
 /**
  * @file
@@ -156,7 +156,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       if (is_string($spec['default'])) {
         $spec['default'] = "'" . $spec['default'] . "'";
       }
-      elseif (is_null($spec['default'])) {
+      elseif (!isset($spec['default'])) {
         $spec['default'] = 'NULL';
       }
       $sql .= ' DEFAULT ' . $spec['default'];
@@ -351,7 +351,7 @@ class DatabaseSchema_mysql extends DatabaseSchema {
       throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
-    if (is_null($default)) {
+    if (!isset($default)) {
       $default = 'NULL';
     }
     else {
diff --git a/includes/database/pgsql/database.inc b/includes/database/pgsql/database.inc
index dbb32867148d2242c75303795e7663066dbbc833..57e77507c7b729c16f259f56c89fcb253bb85244 100644
--- a/includes/database/pgsql/database.inc
+++ b/includes/database/pgsql/database.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: database.inc,v 1.41 2010/08/11 02:17:39 dries Exp $
+// $Id: database.inc,v 1.43 2010/10/03 01:29:41 dries Exp $
 
 /**
  * @file
@@ -126,22 +126,23 @@ class DatabaseConnection_pgsql extends DatabaseConnection {
     return 'pgsql';
   }
 
-  public function version() {
-    return $this->query('SHOW SERVER_VERSION')->fetchField();
-  }
-
   public function databaseType() {
     return 'pgsql';
   }
 
   public function mapConditionOperator($operator) {
-    static $specials = array(
-      // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
-      // statements, we need to use ILIKE instead. Use backslash for escaping
-      // wildcard characters.
-      'LIKE' => array('operator' => 'ILIKE', 'postfix' => " ESCAPE '\\\\'"),
-      'NOT LIKE' => array('operator' => 'NOT ILIKE', 'postfix' => " ESCAPE '\\\\'"),
-    );
+    static $specials;
+
+    // Function calls not allowed in static declarations, thus this method.
+    if (!isset($specials)) {
+      $specials = array(
+        // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
+        // statements, we need to use ILIKE instead. Use backslash for escaping
+        // wildcard characters.
+        'LIKE' => array('operator' => 'ILIKE', 'postfix' => ' ESCAPE ' . $this->quote("\\")),
+        'NOT LIKE' => array('operator' => 'NOT ILIKE', 'postfix' => ' ESCAPE ' . $this->quote("\\")),
+      );
+    }
 
     return isset($specials[$operator]) ? $specials[$operator] : NULL;
   }
diff --git a/includes/database/pgsql/query.inc b/includes/database/pgsql/query.inc
index a1c6e0932e83efab79fab99ec14513a2e21c60a0..dcd753eea2887d04b2c9cc87f42634b45b122cae 100644
--- a/includes/database/pgsql/query.inc
+++ b/includes/database/pgsql/query.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: query.inc,v 1.22 2010/09/01 01:43:50 webchick Exp $
+// $Id: query.inc,v 1.23 2010/09/24 21:24:13 webchick Exp $
 
 /**
  * @ingroup database
@@ -217,4 +217,86 @@ class SelectQuery_pgsql extends SelectQuery {
     return $this;
   }
 
+  /**
+   * Overrides SelectQuery::orderBy().
+   *
+   * PostgreSQL adheres strictly to the SQL-92 standard and requires that when
+   * using DISTINCT or GROUP BY conditions, fields and expressions that are
+   * ordered on also need to be selected. This is a best effort implementation
+   * to handle the cases that can be automated by adding the field if it is not
+   * yet selected.
+   *
+   * @code
+   *   $query = db_select('node', 'n');
+   *   $query->join('node_revision', 'nr', 'n.vid = nr.vid');
+   *   $query
+   *     ->distinct()
+   *     ->fields('n')
+   *     ->orderBy('timestamp');
+   * @endcode
+   *
+   * In this query, it is not possible (without relying on the schema) to know
+   * whether timestamp belongs to node_revisions and needs to be added or
+   * belongs to node and is already selected. Queries like this will need to be
+   * corrected in the original query by adding an explicit call to
+   * SelectQuery::addField() or SelectQuery::fields().
+   *
+   * Since this has a small performance impact, both by the additional
+   * processing in this function and in the database that needs to return the
+   * additional fields, this is done as an override instead of implementing it
+   * directly in SelectQuery::orderBy().
+   */
+  public function orderBy($field, $direction = 'ASC') {
+    // Call parent function to order on this.
+    $return = parent::orderBy($field, $direction);
+
+    // If there is a table alias specified, split it up.
+    if (strpos($field, '.') !== FALSE) {
+      list($table, $table_field) = explode('.', $field);
+    }
+    // Figure out if the field has already been added.
+    foreach ($this->fields as $existing_field) {
+      if (!empty($table)) {
+        // If table alias is given, check if field and table exists.
+        if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) {
+          return $return;
+        }
+      }
+      else {
+        // If there is no table, simply check if the field exists as a field or
+        // an aliased field.
+        if ($existing_field['alias'] == $field) {
+          return $return;
+        }
+      }
+    }
+
+    // Also check expression aliases.
+    foreach ($this->expressions as $expression) {
+      if ($expression['alias'] == $field) {
+        return $return;
+      }
+    }
+
+    // If a table loads all fields, it can not be added again. It would
+    // result in an ambigious alias error because that field would be loaded
+    // twice: Once through table_alias.* and once directly. If the field
+    // actually belongs to a different table, it must be added manually.
+    foreach ($this->tables as $table) {
+      if (!empty($table['all_fields'])) {
+        return $return;
+      }
+    }
+
+    // If $field contains an characters which are not allowed in a field name
+    // it is considered an expression, these can't be handeld automatically
+    // either.
+    if ($this->connection->escapeField($field) != $field) {
+      return $return;
+    }
+
+    // This is a case that can be handled automatically, add the field.
+    $this->addField(NULL, $field);
+    return $return;
+  }
 }
diff --git a/includes/database/pgsql/schema.inc b/includes/database/pgsql/schema.inc
index ca923a50160c6169aed7923e5faa1b4a92493961..cb08207d98d28243be42699c4974b247d006cf39 100644
--- a/includes/database/pgsql/schema.inc
+++ b/includes/database/pgsql/schema.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: schema.inc,v 1.37 2010/09/01 01:28:41 webchick Exp $
+// $Id: schema.inc,v 1.38 2010/09/25 01:41:26 dries Exp $
 
 /**
  * @file
@@ -353,7 +353,7 @@ class DatabaseSchema_pgsql extends DatabaseSchema {
       throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot set default value of field %table.%field: field doesn't exist.", array('%table' => $table, '%field' => $field)));
     }
 
-    if (is_null($default)) {
+    if (!isset($default)) {
       $default = 'NULL';
     }
     else {
diff --git a/includes/database/query.inc b/includes/database/query.inc
index f87ff09f8c7d1786ab3f2926f44702f841d5fb10..5a00cf6009337e8975c8ea00644ad5536bf01e2d 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: query.inc,v 1.55 2010/08/05 08:26:35 webchick Exp $
+// $Id: query.inc,v 1.56 2010/09/24 02:05:55 dries Exp $
 
 /**
  * @ingroup database
@@ -570,332 +570,6 @@ class InsertQuery extends Query {
   }
 }
 
-/**
- * General class for an abstracted MERGE operation.
- */
-class MergeQuery extends Query {
-  /**
-   * Returned by execute() if an INSERT query has been executed.
-   */
-  const STATUS_INSERT = 1;
-
-  /**
-   * Returned by execute() if an UPDATE query has been executed.
-   */
-  const STATUS_UPDATE = 2;
-
-  /**
-   * The table on which to insert.
-   *
-   * @var string
-   */
-  protected $table;
-
-  /**
-   * An array of fields on which to insert.
-   *
-   * @var array
-   */
-  protected $insertFields = array();
-
-  /**
-   * An array of fields to update instead of the values specified in
-   * $insertFields;
-   *
-   * @var array
-   */
-  protected $updateFields = array();
-
-  /**
-   * An array of key fields for this query.
-   *
-   * @var array
-   */
-  protected $keyFields = array();
-
-  /**
-   * An array of fields to not update in case of a duplicate record.
-   *
-   * @var array
-   */
-  protected $excludeFields = array();
-
-  /**
-   * An array of fields to update to an expression in case of a duplicate record.
-   *
-   * This variable is a nested array in the following format:
-   * <some field> => array(
-   *  'condition' => <condition to execute, as a string>
-   *  'arguments' => <array of arguments for condition, or NULL for none>
-   * );
-   *
-   * @var array
-   */
-  protected $expressionFields = array();
-
-  public function __construct($connection, $table, array $options = array()) {
-    $options['return'] = Database::RETURN_AFFECTED;
-    parent::__construct($connection, $options);
-    $this->table = $table;
-  }
-
-  /**
-   * Set the field->value pairs to be merged into the table.
-   *
-   * This method should only be called once. It may be called either
-   * with a single associative array or two indexed arrays. If called
-   * with an associative array, the keys are taken to be the fields
-   * and the values are taken to be the corresponding values to set.
-   * If called with two arrays, the first array is taken as the fields
-   * and the second array is taken as the corresponding values.
-   *
-   * @param $fields
-   *   An array of fields to set.
-   * @param $values
-   *   An array of fields to set into the database. The values must be
-   *   specified in the same order as the $fields array.
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function fields(array $fields, array $values = array()) {
-    if (count($values) > 0) {
-      $fields = array_combine($fields, $values);
-    }
-    $this->insertFields = $fields;
-
-    return $this;
-  }
-
-  /**
-   * Set the key field(s) to be used to insert or update into the table.
-   *
-   * This method should only be called once. It may be called either
-   * with a single associative array or two indexed arrays. If called
-   * with an associative array, the keys are taken to be the fields
-   * and the values are taken to be the corresponding values to set.
-   * If called with two arrays, the first array is taken as the fields
-   * and the second array is taken as the corresponding values.
-   *
-   * These fields are the "pivot" fields of the query. Typically they
-   * will be the fields of the primary key. If the record does not
-   * yet exist, they will be inserted into the table along with the
-   * values set in the fields() method. If the record does exist,
-   * these fields will be used in the WHERE clause to select the
-   * record to update.
-   *
-   * @param $fields
-   *   An array of fields to set.
-   * @param $values
-   *   An array of fields to set into the database. The values must be
-   *   specified in the same order as the $fields array.
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function key(array $fields, array $values = array()) {
-    if ($values) {
-      $fields = array_combine($fields, $values);
-    }
-    $this->keyFields = $fields;
-
-    return $this;
-  }
-
-  /**
-   * Specify fields to update in case of a duplicate record.
-   *
-   * If a record with the values in keys() already exists, the fields and values
-   * specified here will be updated in that record. If this method is not called,
-   * it defaults to the same values as were passed to the fields() method.
-   *
-   * @param $fields
-   *   An array of fields to set.
-   * @param $values
-   *   An array of fields to set into the database. The values must be
-   *   specified in the same order as the $fields array.
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function update(array $fields, array $values = array()) {
-    if ($values) {
-      $fields = array_combine($fields, $values);
-    }
-    $this->updateFields = $fields;
-
-    return $this;
-  }
-
-  /**
-   * Specify fields that should not be updated in case of a duplicate record.
-   *
-   * If this method is called and a record with the values in keys() already
-   * exists, Drupal will instead update the record with the values passed
-   * in the fields() method except for the fields specified in this method. That
-   * is, calling this method is equivalent to calling update() with identical
-   * parameters as fields() minus the keys specified here.
-   *
-   * The update() method takes precedent over this method. If update() is called,
-   * this method has no effect.
-   *
-   * @param $exclude_fields
-   *   An array of fields in the query that should not be updated to match those
-   *   specified by the fields() method.
-   *   Alternatively, the fields may be specified as a variable number of string
-   *   parameters.
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function updateExcept($exclude_fields) {
-    if (!is_array($exclude_fields)) {
-      $exclude_fields = func_get_args();
-    }
-    $this->excludeFields = $exclude_fields;
-
-    return $this;
-  }
-
-  /**
-   * Specify fields to be updated as an expression.
-   *
-   * Expression fields are cases such as counter=counter+1. This method only
-   * applies if a duplicate key is detected. This method takes precedent over
-   * both update() and updateExcept().
-   *
-   * @param $field
-   *   The field to set.
-   * @param $expression
-   *   The field will be set to the value of this expression. This parameter
-   *   may include named placeholders.
-   * @param $arguments
-   *   If specified, this is an array of key/value pairs for named placeholders
-   *   corresponding to the expression.
-   * @return MergeQuery
-   *   The called object.
-   */
-  public function expression($field, $expression, array $arguments = NULL) {
-    $this->expressionFields[$field] = array(
-      'expression' => $expression,
-      'arguments' => $arguments,
-    );
-
-    return $this;
-  }
-
-  /**
-   * Generic preparation and validation for a MERGE query.
-   *
-   * @return
-   *   TRUE if the validation was successful, FALSE if not.
-   *
-   * @throws InvalidMergeQueryException
-   */
-  public function preExecute() {
-
-    // A merge query without any key field is invalid.
-    if (count($this->keyFields) == 0) {
-      throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query");
-    }
-
-    return TRUE;
-  }
-
-  /**
-   * Run the MERGE query against the database.
-   *
-   * @return
-   *   A status indicating the executed operation:
-   *   - MergeQuery::STATUS_INSERT for an INSERT operation.
-   *   - MergeQuery::STATUS_UPDATE for an UPDATE operation.
-   *
-   * @throws InvalidMergeQueryException
-   */
-  public function execute() {
-    // If validation fails, simply return NULL.
-    // Note that validation routines in preExecute() may throw exceptions instead.
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-
-    // In the degenerate case of this query type, we have to run multiple
-    // queries as there is no universal single-query mechanism that will work.
-
-    // Wrap multiple queries in a transaction, if the database supports it.
-    $transaction = $this->connection->startTransaction();
-
-    try {
-      // Manually check if the record already exists.
-      // We build a 'SELECT 1 FROM table WHERE conditions FOR UPDATE' query,
-      // that will lock the rows that matches our set of conditions as well as
-      // return the information that there are such rows.
-      $select = $this->connection->select($this->table);
-      $select->addExpression('1');
-      foreach ($this->keyFields as $field => $value) {
-        $select->condition($field, $value);
-      }
-
-      // Using SELECT FOR UPDATE syntax will lock the rows we want to attempt to update.
-      $sql = ((string) $select) . ' FOR UPDATE';
-      $arguments = $select->getArguments();
-
-      // If there are no existing records, run an insert query.
-      if (!$this->connection->query($sql, $arguments)->fetchField()) {
-        // If there is no existing record, run an insert query.
-        $insert_fields = $this->insertFields + $this->keyFields;
-        try {
-          $this->connection->insert($this->table, $this->queryOptions)->fields($insert_fields)->execute();
-          return MergeQuery::STATUS_INSERT;
-        }
-        catch (Exception $e) {
-          // The insert query failed, maybe it's because a racing insert query
-          // beat us in inserting the same row. Retry the select query, if it
-          // returns a row, ignore the error and continue with the update
-          // query below.
-          if (!$this->connection->query($sql, $arguments)->fetchField()) {
-            throw $e;
-          }
-        }
-      }
-
-      // Proceed with an update query if a row was found.
-      if ($this->updateFields) {
-        $update_fields = $this->updateFields;
-      }
-      else {
-        $update_fields = $this->insertFields;
-        // If there are no exclude fields, this is a no-op.
-        foreach ($this->excludeFields as $exclude_field) {
-          unset($update_fields[$exclude_field]);
-        }
-      }
-      if ($update_fields || $this->expressionFields) {
-        // Only run the update if there are fields or expressions to update.
-        $update = $this->connection->update($this->table, $this->queryOptions)->fields($update_fields);
-        foreach ($this->keyFields as $field => $value) {
-          $update->condition($field, $value);
-        }
-        foreach ($this->expressionFields as $field => $expression) {
-          $update->expression($field, $expression['expression'], $expression['arguments']);
-        }
-        $update->execute();
-        return MergeQuery::STATUS_UPDATE;
-      }
-    }
-    catch (Exception $e) {
-      // Something really wrong happened here, bubble up the exception to the
-      // caller.
-      $transaction->rollback();
-      throw $e;
-    }
-    // Transaction commits here where $transaction looses scope.
-  }
-
-  public function __toString() {
-    // In the degenerate case, there is no string-able query as this operation
-    // is potentially two queries.
-    return '';
-  }
-}
-
-
 /**
  * General class for an abstracted DELETE operation.
  */
@@ -1205,6 +879,386 @@ class UpdateQuery extends Query implements QueryConditionInterface {
 
 }
 
+/**
+ * General class for an abstracted MERGE operation.
+ *
+ * An ANSI SQL:2003 compatible database would run the following query:
+ *
+ * @code
+ * MERGE INTO table_name_1 USING table_name_2 ON (condition)
+ *   WHEN MATCHED THEN
+ *   UPDATE SET column1 = value1 [, column2 = value2 ...]
+ *   WHEN NOT MATCHED THEN
+ *   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
+ * @endcode
+ *
+ * Other databases (most notably MySQL, PostgreSQL and SQLite) will emulate
+ * this statement by running a SELECT and then INSERT or UPDATE.
+ *
+ * By default, the two table names are identical and they are passed into the
+ * the constructor. table_name_2 can be specified by the
+ * MergeQuery::conditionTable() method. It can be either a string or a
+ * subquery.
+ *
+ * The condition is built exactly like SelectQuery or UpdateQuery conditions,
+ * the UPDATE query part is built similarly like an UpdateQuery and finally the
+ * INSERT query part is built similarly like an InsertQuery. However, both
+ * UpdateQuery and InsertQuery has a fields method so
+ * MergeQuery::updateFields() and MergeQuery::insertFields() needs to be called
+ * instead. MergeQuery::fields() can also be called which calls both of these
+ * methods as the common case is to use the same column-value pairs for both
+ * INSERT and UPDATE. However, this is not mandatory. Another convinient
+ * wrapper is MergeQuery::key() which adds the same column-value pairs to all
+ * three parts: the condition, the INSERT query part and the UPDATE query part.
+ *
+ * Several methods (key(), fields(), insertFields()) can be called to set a
+ * key-value pair for the INSERT query part. Subsequent calls for the same
+ * fields override the earlier ones. The same is true for UPDATE and key(),
+ * fields() and updateFields().
+ */
+class MergeQuery extends Query implements QueryConditionInterface {
+  /**
+   * Returned by execute() if an INSERT query has been executed.
+   */
+  const STATUS_INSERT = 1;
+
+  /**
+   * Returned by execute() if an UPDATE query has been executed.
+   */
+  const STATUS_UPDATE = 2;
+
+  /**
+   * The table to be used for INSERT and UPDATE.
+   *
+   * @var string
+   */
+  protected $table;
+
+  /**
+   * The table or subquery to be used for the condition.
+   */
+  protected $conditionTable;
+
+  /**
+   * An array of fields on which to insert.
+   *
+   * @var array
+   */
+  protected $insertFields = array();
+
+  /**
+   * An array of fields which should be set to their database-defined defaults.
+   *
+   * Used on INSERT.
+   *
+   * @var array
+   */
+  protected $defaultFields = array();
+
+  /**
+   * An array of values to be inserted.
+   *
+   * @var string
+   */
+  protected $insertValues = array();
+
+  /**
+   * An array of fields that will be updated.
+   *
+   * @var array
+   */
+  protected $updateFields = array();
+
+  /**
+   * An array of fields to update to an expression in case of a duplicate record.
+   *
+   * This variable is a nested array in the following format:
+   * <some field> => array(
+   *  'condition' => <condition to execute, as a string>
+   *  'arguments' => <array of arguments for condition, or NULL for none>
+   * );
+   *
+   * @var array
+   */
+  protected $expressionFields = array();
+
+  /**
+   * Flag indicated whether an UPDATE is necessary.
+   *
+   * @var boolean
+   */
+  protected $needsUpdate = FALSE;
+
+  public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
+    $options['return'] = Database::RETURN_AFFECTED;
+    parent::__construct($connection, $options);
+    $this->table = $table;
+    $this->conditionTable = $table;
+    $this->condition = new DatabaseCondition('AND');
+  }
+
+  /**
+   * Set the table or subquery to be used for the condition.
+   *
+   * @param $table
+   *   The table name or the subquery to be used. Use a SelectQuery object to
+   *   pass in a subquery.
+   *
+   * @return MergeQuery
+   *   The called object.
+   */
+  protected function conditionTable($table) {
+    $this->conditionTable = $table;
+    return $this;
+  }
+
+  /**
+   * Adds a set of field->value pairs to be updated.
+   *
+   * @param $fields
+   *   An associative array of fields to write into the database. The array keys
+   *   are the field names while the values are the values to which to set them.
+   *
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function updateFields(array $fields) {
+    $this->updateFields = $fields;
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Specify fields to be updated as an expression.
+   *
+   * Expression fields are cases such as counter = counter + 1. This method
+   * takes precedence over MergeQuery::updateFields() and it's wrappers,
+   * MergeQuery::key() and MergeQuery::fields().
+   *
+   * @param $field
+   *   The field to set.
+   * @param $expression
+   *   The field will be set to the value of this expression. This parameter
+   *   may include named placeholders.
+   * @param $arguments
+   *   If specified, this is an array of key/value pairs for named placeholders
+   *   corresponding to the expression.
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function expression($field, $expression, array $arguments = NULL) {
+    $this->expressionFields[$field] = array(
+      'expression' => $expression,
+      'arguments' => $arguments,
+    );
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Adds a set of field->value pairs to be inserted.
+   *
+   * @param $fields
+   *   An array of fields on which to insert. This array may be indexed or
+   *   associative. If indexed, the array is taken to be the list of fields.
+   *   If associative, the keys of the array are taken to be the fields and
+   *   the values are taken to be corresponding values to insert. If a
+   *   $values argument is provided, $fields must be indexed.
+   * @param $values
+   *   An array of fields to insert into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function insertFields(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    $this->insertFields = $fields;
+    return $this;
+  }
+
+  /**
+   * Specifies fields for which the database-defaults should be used.
+   *
+   * If you want to force a given field to use the database-defined default,
+   * not NULL or undefined, use this method to instruct the database to use
+   * default values explicitly. In most cases this will not be necessary
+   * unless you are inserting a row that is all default values, as you cannot
+   * specify no values in an INSERT query.
+   *
+   * Specifying a field both in fields() and in useDefaults() is an error
+   * and will not execute.
+   *
+   * @param $fields
+   *   An array of values for which to use the default values
+   *   specified in the table definition.
+   *
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function useDefaults(array $fields) {
+    $this->defaultFields = $fields;
+    return $this;
+  }
+
+  /**
+   * Set common field-value pairs in the INSERT and UPDATE query parts.
+   *
+   * This method should only be called once. It may be called either
+   * with a single associative array or two indexed arrays. If called
+   * with an associative array, the keys are taken to be the fields
+   * and the values are taken to be the corresponding values to set.
+   * If called with two arrays, the first array is taken as the fields
+   * and the second array is taken as the corresponding values.
+   *
+   * @param $fields
+   *   An associative array of fields on which to insert. The keys of the
+   *   array are taken to be the fields and the values are taken to be
+   *   corresponding values to insert.
+   * @param $values
+   *   An array of fields to set into the database. The values must be
+   *   specified in the same order as the $fields array.
+   *
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function fields(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    foreach ($fields as $key => $value) {
+      $this->insertFields[$key] = $value;
+      $this->updateFields[$key] = $value;
+    }
+    $this->needsUpdate = TRUE;
+    return $this;
+  }
+
+  /**
+   * Set the key field(s) to be used everywhere.
+   *
+   * This method should only be called once. It may be called either
+   * with a single associative array or two indexed arrays. If called
+   * with an associative array, the keys are taken to be the fields
+   * and the values are taken to be the corresponding values to set.
+   * If called with two arrays, the first array is taken as the fields
+   * and the second array is taken as the corresponding values.
+   *
+   * The fields are copied to all three parts of the query: the condition,
+   * the UPDATE part and the INSERT part. If no other method is called, the
+   * UPDATE will become a no-op.
+   *
+   * @param $fields
+   *   An array of fields to set.
+   * @param $values
+   *   An array of fields to set into the database. The values must be
+   *   specified in the same order as the $fields array.
+   * @return MergeQuery
+   *   The called object.
+   */
+  public function key(array $fields, array $values = array()) {
+    if ($values) {
+      $fields = array_combine($fields, $values);
+    }
+    foreach ($fields as $key => $value) {
+      $this->insertFields[$key] = $value;
+      $this->updateFields[$key] = $value;
+      $this->condition($key, $value);
+    }
+    return $this;
+  }
+
+  public function condition($field, $value = NULL, $operator = NULL) {
+    $this->condition->condition($field, $value, $operator);
+    return $this;
+  }
+
+  public function isNull($field) {
+    $this->condition->isNull($field);
+    return $this;
+  }
+
+  public function isNotNull($field) {
+    $this->condition->isNotNull($field);
+    return $this;
+  }
+
+  public function &conditions() {
+    return $this->condition->conditions();
+  }
+
+  public function arguments() {
+    return $this->condition->arguments();
+  }
+
+  public function where($snippet, $args = array()) {
+    $this->condition->where($snippet, $args);
+    return $this;
+  }
+
+  public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder = NULL) {
+    return $this->condition->compile($connection, isset($queryPlaceholder) ? $queryPlaceholder : $this);
+  }
+
+  public function __toString() {
+  }
+
+  public function execute() {
+    // Wrap multiple queries in a transaction, if the database supports it.
+    $transaction = $this->connection->startTransaction();
+    try {
+      if (!count($this->condition)) {
+        throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
+      }
+      $select = $this->connection->select($this->conditionTable)
+        ->condition($this->condition)
+        ->forUpdate();
+      $select->addExpression('1');
+      if (!$select->execute()->fetchField()) {
+        try {
+          $insert = $this->connection->insert($this->table)->fields($this->insertFields);
+          if ($this->defaultFields) {
+            $insert->useDefaults($this->defaultFields);
+          }
+          $insert->execute();
+          return MergeQuery::STATUS_INSERT;
+        }
+        catch (Exception $e) {
+          echo $e->getMessage();
+          // The insert query failed, maybe it's because a racing insert query
+          // beat us in inserting the same row. Retry the select query, if it
+          // returns a row, ignore the error and continue with the update
+          // query below.
+          if (!$select->execute()->fetchField()) {
+            throw $e;
+          }
+        }
+      }
+      if ($this->needsUpdate) {
+        $update = $this->connection->update($this->table)
+          ->fields($this->updateFields)
+          ->condition($this->condition);
+        if ($this->expressionFields) {
+          foreach ($this->expressionFields as $field => $data) {
+            $update->expression($field, $data['expression'], $data['arguments']);
+          }
+        }
+        $update->execute();
+        return MergeQuery::STATUS_UPDATE;
+      }
+    }
+    catch (Exception $e) {
+      // Something really wrong happened here, bubble up the exception to the
+      // caller.
+      $transaction->rollback();
+      throw $e;
+    }
+    // Transaction commits here where $transaction looses scope.
+  }
+}
+
 /**
  * Generic class for a series of conditions in a query.
  */
diff --git a/includes/database/select.inc b/includes/database/select.inc
index 5a6021263dcb3fbe77d35ac18332ca8f93b3bc69..9947002aaeac63c6856b3a4192c5f20eda346a4e 100644
--- a/includes/database/select.inc
+++ b/includes/database/select.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: select.inc,v 1.48 2010/09/03 19:06:55 dries Exp $
+// $Id: select.inc,v 1.52 2010/10/05 01:42:24 dries Exp $
 
 /**
  * @ingroup database
@@ -366,6 +366,13 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn
    * If called multiple times, the query will order by each specified field in the
    * order this method is called.
    *
+   * If the query uses DISTINCT or GROUP BY conditions, fields or expressions
+   * that are used for the order must be selected to be compatible with some
+   * databases like PostgreSQL. The PostgreSQL driver can handle simple cases
+   * automatically but it is suggested to explicitly specify them. Additionally,
+   * when ordering on an alias, the alias must be added before orderBy() is
+   * called.
+   *
    * @param $field
    *   The field on which to order.
    * @param $direction
@@ -503,6 +510,22 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn
    * duplicate the connection itself.
    */
   public function __clone();
+
+  /**
+   * Add FOR UPDATE to the query.
+   *
+   * FOR UPDATE prevents the rows retrieved by the SELECT statement from being
+   * modified or deleted by other transactions until the current transaction
+   * ends. Other transactions that attempt UPDATE, DELETE, or SELECT FOR UPDATE
+   * of these rows will be blocked until the current transaction ends.
+   *
+   * @param $set
+   *   IF TRUE, FOR UPDATE will be added to the query, if FALSE then it won't.
+   *
+   * @return QueryConditionInterface
+   *   The called object.
+   */
+  public function forUpdate($set = TRUE);
 }
 
 /**
@@ -659,7 +682,7 @@ class SelectQueryExtender implements SelectQueryInterface {
 
   public function preExecute(SelectQueryInterface $query = NULL) {
     // If no query object is passed in, use $this.
-    if (is_null($query)) {
+    if (!isset($query)) {
       $query = $this;
     }
 
@@ -740,6 +763,11 @@ class SelectQueryExtender implements SelectQueryInterface {
     return $this;
   }
 
+  public function forUpdate($set = TRUE) {
+    $this->query->forUpdate($set);
+    return $this;
+  }
+
   public function countQuery() {
     // Create our new query object that we will mutate into a count query.
     $count = clone($this);
@@ -919,6 +947,11 @@ class SelectQuery extends Query implements SelectQueryInterface {
    */
   protected $prepared = FALSE;
 
+  /**
+   * The FOR UPDATE status
+   */
+  protected $forUpdate = FALSE;
+
   public function __construct($table, $alias = NULL, DatabaseConnection $connection, $options = array()) {
     $options['return'] = Database::RETURN_STATEMENT;
     parent::__construct($connection, $options);
@@ -1033,6 +1066,12 @@ class SelectQuery extends Query implements SelectQueryInterface {
     return $this;
   }
 
+  public function forUpdate($set = TRUE) {
+    if (isset($set)) {
+      $this->forUpdate = $set;
+    }
+    return $this;
+  }
 
   /* Alter accessors to expose the query data to alter hooks. */
 
@@ -1108,7 +1147,7 @@ class SelectQuery extends Query implements SelectQueryInterface {
    */
   public function preExecute(SelectQueryInterface $query = NULL) {
     // If no query object is passed in, use $this.
-    if (is_null($query)) {
+    if (!isset($query)) {
       $query = $this;
     }
 
@@ -1360,7 +1399,7 @@ class SelectQuery extends Query implements SelectQueryInterface {
       $count->distinct = FALSE;
     }
 
-    $query = db_select($count);
+    $query = $this->connection->select($count);
     $query->addExpression('COUNT(*)');
 
     return $query;
@@ -1387,10 +1426,10 @@ class SelectQuery extends Query implements SelectQueryInterface {
     foreach ($this->fields as $alias => $field) {
       // Always use the AS keyword for field aliases, as some
       // databases require it (e.g., PostgreSQL).
-      $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeField($field['alias']);
+      $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
     }
     foreach ($this->expressions as $alias => $expression) {
-      $fields[] = $expression['expression'] . ' AS ' . $expression['alias'];
+      $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
     }
     $query .= implode(', ', $fields);
 
@@ -1476,6 +1515,10 @@ class SelectQuery extends Query implements SelectQueryInterface {
       }
     }
 
+    if ($this->forUpdate) {
+      $query .= ' FOR UPDATE';
+    }
+
     return $query;
   }
 
diff --git a/includes/database/sqlite/database.inc b/includes/database/sqlite/database.inc
index e6f2408477366ee5c637b0d5a9a64ebd31827c2f..e03e34f0830bbe679e8bd3bb1a31581ff5e7fd66 100644
--- a/includes/database/sqlite/database.inc
+++ b/includes/database/sqlite/database.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: database.inc,v 1.37 2010/08/27 15:45:46 webchick Exp $
+// $Id: database.inc,v 1.39 2010/10/03 01:29:41 dries Exp $
 
 /**
  * @file
@@ -82,7 +82,7 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
   public function sqlFunctionGreatest() {
     $args = func_get_args();
     foreach ($args as $k => $v) {
-      if (is_null($v)) {
+      if (!isset($v)) {
         unset($args);
       }
     }
@@ -182,10 +182,6 @@ class DatabaseConnection_sqlite extends DatabaseConnection {
     return 'sqlite';
   }
 
-  public function version() {
-    return $this->query('SELECT sqlite_version()')->fetchField();
-  }
-
   public function databaseType() {
     return 'sqlite';
   }
diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc
index 2de07e0fd3b4e6e5a3c6e9c0f971c0f383067f59..fe33f44d5f07d9bc2b072f9844ddd52e5bb0f416 100644
--- a/includes/database/sqlite/query.inc
+++ b/includes/database/sqlite/query.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: query.inc,v 1.11 2010/07/03 20:45:45 webchick Exp $
+// $Id: query.inc,v 1.13 2010/09/25 01:41:26 dries Exp $
 
 /**
  * @file
@@ -11,6 +11,16 @@
  * @{
  */
 
+/**
+ * SQLite specific query builder for SELECT statements.
+ */
+class SelectQuery_sqlite extends SelectQuery {
+  public function forUpdate($set = TRUE) {
+    // SQLite does not support FOR UPDATE so nothing to do.
+    return $this;
+  }
+}
+
 /**
  * SQLite specific implementation of InsertQuery.
  *
@@ -100,7 +110,7 @@ class UpdateQuery_sqlite extends UpdateQuery {
         $condition->condition($field, $data['expression'], '<>');
         $condition->isNull($field);
       }
-      elseif (is_null($data)) {
+      elseif (!isset($data)) {
         // The field will be set to NULL.
         $condition->isNull($field);
       }
@@ -118,65 +128,6 @@ class UpdateQuery_sqlite extends UpdateQuery {
 
 }
 
-/**
- * SQLite specific implementation of MergeQuery.
- *
- * SQLite doesn't support row-level locking, but acquire locks on the whole
- * database file. We implement MergeQuery using a different strategy:
- *   - UPDATE xxx WHERE <key condition>
- *   - if the previous query hasn't matched, INSERT
- *
- * The first UPDATE query will acquire a RESERVED lock on the database.
- */
-class MergeQuery_sqlite extends MergeQuery {
-  public function execute() {
-    // If validation fails, simply return NULL.
-    // Note that validation routines in preExecute() may throw exceptions instead.
-    if (!$this->preExecute()) {
-      return NULL;
-    }
-
-    // Wrap multiple queries in a transaction.
-    $transaction = $this->connection->startTransaction();
-
-    if ($this->updateFields) {
-      $update_fields = $this->updateFields;
-    }
-    else {
-      $update_fields = $this->insertFields;
-      // If there are no exclude fields, this is a no-op.
-      foreach ($this->excludeFields as $exclude_field) {
-        unset($update_fields[$exclude_field]);
-      }
-    }
-
-    // The update fields are empty, fill them with dummy data.
-    if (!$update_fields && !$this->expressionFields) {
-      $update_fields = array_slice($this->keyFields, 0, 1);
-    }
-
-    // Start with an update query, this acquires a RESERVED lock on the database.
-    // Use the SQLite-specific 'sqlite_return_matched_rows' query option to
-    // return the number of rows matched by that query, not modified by it.
-    $update = $this->connection->update($this->table, array('sqlite_return_matched_rows' => TRUE) + $this->queryOptions)->fields($update_fields);
-
-    foreach ($this->keyFields as $field => $value) {
-      $update->condition($field, $value);
-    }
-    foreach ($this->expressionFields as $field => $expression) {
-      $update->expression($field, $expression['expression'], $expression['arguments']);
-    }
-    if ($update->execute()) {
-      return MergeQuery::STATUS_UPDATE;
-    }
-
-    // The UPDATE query failed to match rows, proceed with an INSERT.
-    $insert_fields = $this->insertFields + $this->keyFields;
-    $this->connection->insert($this->table, $this->queryOptions)->fields($insert_fields)->execute();
-    return MergeQuery::STATUS_INSERT;
-  }
-}
-
 /**
  * SQLite specific implementation of DeleteQuery.
  *
diff --git a/includes/entity.inc b/includes/entity.inc
index d182a0656fd7b45713154ec70d2a3c1be7e84ed8..0d7510dd452e1eb7dd6d42ce09691e779f01cbf4 100644
--- a/includes/entity.inc
+++ b/includes/entity.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: entity.inc,v 1.14 2010/09/15 04:34:26 webchick Exp $
+// $Id: entity.inc,v 1.15 2010/10/06 13:57:47 dries Exp $
 
 /**
  * Interface for entity controller classes.
@@ -446,31 +446,11 @@ class EntityFieldQuery {
   public $propertyConditions = array();
 
   /**
-   * List of order clauses for entity-generic metadata.
+   * List of order clauses.
    *
    * @var array
-   *
-   * @see EntityFieldQuery::entityOrderBy()
-   */
-  public $entityOrder = array();
-
-  /**
-   * List of order clauses for fields.
-   *
-   * @var array
-   *
-   * @see EntityFieldQuery::fieldOrderBy()
-   */
-  public $fieldOrder = array();
-
-  /**
-   * List of order clauses for entities.
-   *
-   * @var array
-   *
-   * @see EntityFieldQuery::entityOrderBy()
    */
-  public $propertyOrder = array();
+  public $order = array();
 
   /**
    * The query range.
@@ -709,7 +689,11 @@ class EntityFieldQuery {
    *   The called object.
    */
   public function entityOrderBy($name, $direction) {
-    $this->entityOrder[$name] = $direction;
+    $this->order[] = array(
+      'type' => 'entity',
+      'specifier' => $name,
+      'direction' => $direction,
+    );
     return $this;
   }
 
@@ -734,12 +718,16 @@ class EntityFieldQuery {
     if (is_scalar($field)) {
       $field = field_info_field($field);
     }
-    // Ensure the same index is used for fieldOrder as for fields.
+    // Save the index used for the new field, for later use in field storage.
     $index = count($this->fields);
     $this->fields[$index] = $field;
-    $this->fieldOrder[$index] = array(
-      'field' => $field,
-      'column' => $column,
+    $this->order[] = array(
+      'type' => 'field',
+      'specifier' => array(
+        'field' => $field,
+        'index' => $index,
+        'column' => $column,
+      ),
       'direction' => $direction,
     );
     return $this;
@@ -764,8 +752,9 @@ class EntityFieldQuery {
    *   The called object.
    */
   public function propertyOrderBy($column, $direction) {
-    $this->propertyOrder[] = array(
-      'column' => $column,
+    $this->order[] = array(
+      'type' => 'property',
+      'specifier' => $column,
       'direction' => $direction,
     );
     return $this;
@@ -919,13 +908,6 @@ class EntityFieldQuery {
     // Execute the query using the correct callback.
     $result = call_user_func($this->queryCallback(), $this);
 
-    // Sanity checks.
-    if (!empty($this->propertyConditions)) {
-      throw new EntityFieldQueryException(t('Property query conditions were not handled in !function.', array('!function' => $function)));
-    }
-    if (!empty($this->propertyOrderBy)) {
-      throw new EntityFieldQueryException(t('Property query order by was not handled in !function.', array('!function' => $function)));
-    }
     return $result;
   }
 
@@ -985,6 +967,10 @@ class EntityFieldQuery {
     $base_table = $entity_info['base table'];
     $select_query = db_select($base_table);
     $select_query->addExpression(':entity_type', 'entity_type', array(':entity_type' => $entity_type));
+    // Process the property conditions.
+    foreach ($this->propertyConditions as $property_condition) {
+      $this->addCondition($select_query, "$base_table." . $property_condition['column'], $property_condition);
+    }
     // Process the four possible entity condition.
     // The id field is always present in entity keys.
     $sql_field = $entity_info['entity keys']['id'];
@@ -1024,15 +1010,20 @@ class EntityFieldQuery {
       $this->addCondition($select_query, $sql_field, $this->entityConditions['bundle'], $having);
     }
 
-    foreach ($this->entityOrder as $key => $direction) {
-      if (isset($id_map[$key])) {
-        $select_query->orderBy($id_map[$key], $direction);
+    // Order the query.
+    foreach ($this->order as $order) {
+      if ($order['type'] == 'entity') {
+        $key = $order['specifier'];
+        if (!isset($id_map[$key])) {
+          throw new EntityFieldQueryException(t('Do not know how to order on @key for @entity_type', array('@key' => $key, '@entity_type' => $entity_type)));
+        }
+        $select_query->orderBy($id_map[$key], $order['direction']);
       }
-      else {
-        throw new EntityFieldQueryException(t('Do not know how to order on @key for @entity_type', array('@key' => $key, '@entity_type' => $entity_type)));
+      elseif ($order['type'] == 'property') {
+        $select_query->orderBy("$base_table." . $order['specifier'], $order['direction']);
       }
     }
-    $this->processProperty($select_query, $base_table);
+
     return $this->finishQuery($select_query);
   }
 
@@ -1073,27 +1064,6 @@ class EntityFieldQuery {
     return $return;
   }
 
-  /**
-   * Processes the property condition and orders.
-   *
-   * This is a helper for hook_entity_query() and hook_field_storage_query().
-   *
-   * @param SelectQuery $select_query
-   *   A SelectQuery object.
-   * @param $entity_base_table
-   *   The name of the entity base table. This already should be in
-   *   $select_query.
-   */
-  public function processProperty(SelectQuery $select_query, $entity_base_table) {
-    foreach ($this->propertyConditions as $entity_condition) {
-      $this->addCondition($select_query, "$entity_base_table." . $entity_condition['column'], $entity_condition);
-    }
-    foreach ($this->propertyOrder as $order) {
-      $select_query->orderBy("$entity_base_table." . $order['column'], $order['direction']);
-    }
-    unset($this->propertyConditions, $this->propertyOrder);
-  }
-
   /**
    * Adds a condition to an already built SelectQuery (internal function).
    *
diff --git a/includes/file.inc b/includes/file.inc
index 6a18aee6f8d9d481cf1c7135068147cb21d3af13..d46c4b15f140d4ba7572b7be799c7a89f4e0c09d 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.inc,v 1.229 2010/09/11 21:14:31 webchick Exp $
+// $Id: file.inc,v 1.235 2010/10/05 06:23:18 webchick Exp $
 
 /**
  * @file
@@ -523,8 +523,7 @@ function file_load($fid) {
 /**
  * Save a file object to the database.
  *
- * If the $file->fid is not set a new record will be added. Re-saving an
- * existing file will not change its status.
+ * If the $file->fid is not set a new record will be added.
  *
  * @param $file
  *   A file object returned by file_load().
@@ -662,7 +661,7 @@ function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $c
   $result = $query->execute();
 
   // If the row has more than the specified count decrement it by that number.
-  if (!$result) {
+  if (!$result && $count > 0) {
     $query = db_update('file_usage')
       ->condition('module', $module)
       ->condition('fid', $file->fid);
@@ -671,9 +670,7 @@ function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $c
         ->condition('type', $type)
         ->condition('id', $id);
     }
-    if ($count) {
-      $query->expression('count', 'count - :count', array(':count' => $count));
-    }
+    $query->expression('count', 'count - :count', array(':count' => $count));
     $query->execute();
   }
 }
@@ -856,7 +853,6 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
   file_ensure_htaccess();
   // Perform the copy operation.
   if (!@copy($source, $destination)) {
-    drupal_set_message(t('The specified file %file could not be copied.', array('%file' => $source)), 'error');
     watchdog('file', 'The specified file %file could not be copied to %destination.', array('%file' => $source, '%destination' => drupal_realpath($destination)), WATCHDOG_ERROR);
     return FALSE;
   }
@@ -1296,7 +1292,7 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
   $query = db_select('file_managed', 'f');
   $query->condition('f.status', $status);
   $query->addExpression('SUM(f.filesize)', 'filesize');
-  if (!is_null($uid)) {
+  if (isset($uid)) {
     $query->condition('f.uid', $uid);
   }
   return $query->execute()->fetchField();
@@ -2194,11 +2190,11 @@ function drupal_dirname($uri) {
  * @ingroup php_wrappers
  */
 function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
-  if (is_null($mode)) {
+  if (!isset($mode)) {
     $mode = variable_get('file_chmod_directory', 0775);
   }
 
-  if (is_null($context)) {
+  if (!isset($context)) {
     return mkdir($uri, $mode, $recursive);
   }
   else {
@@ -2281,9 +2277,9 @@ function drupal_tempnam($directory, $prefix) {
  * Get the path of system-appropriate temporary directory.
  */
 function file_directory_temp() {
-  $temporary_directory = variable_get('file_directory_temp', NULL);
+  $temporary_directory = variable_get('file_temporary_path', NULL);
 
-  if (is_null($temporary_directory)) {
+  if (empty($temporary_directory)) {
     $directories = array();
 
     // Has PHP been set with an upload_tmp_dir?
@@ -2320,7 +2316,7 @@ function file_directory_temp() {
       $temporary_directory = variable_get('file_public_path', conf_path() . '/files') . $path_delimiter . 'tmp';
     }
     // Save the path of the discovered directory.
-    variable_set('file_directory_temp', $temporary_directory);
+    variable_set('file_temporary_path', $temporary_directory);
   }
 
   return $temporary_directory;
diff --git a/includes/filetransfer/ftp.inc b/includes/filetransfer/ftp.inc
index 6c069d26dd96aae6d581511d4d78658bce16c680..6258f768dc0f8a7b94ce53fad4a599b0147fc1c0 100644
--- a/includes/filetransfer/ftp.inc
+++ b/includes/filetransfer/ftp.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: ftp.inc,v 1.13 2010/08/17 22:05:22 dries Exp $
+// $Id: ftp.inc,v 1.14 2010/10/05 02:08:53 dries Exp $
 
 /**
  * Base class for FTP implementations.
@@ -21,8 +21,7 @@ abstract class FileTransferFTP extends FileTransfer {
    * @param array $settings
    * @return FileTransferFTP
    *   The appropriate FileTransferFTP subclass based on the available
-   *   options.  If the FTP PHP extension is available, use it.  Otherwise, we
-   *   try to use the FTP file stream support.
+   *   options. If the FTP PHP extension is available, use it.
    */
   static function factory($jail, $settings) {
     $settings['hostname'] = empty($settings['hostname']) ? 'localhost' : $settings['hostname'];
@@ -31,9 +30,6 @@ abstract class FileTransferFTP extends FileTransfer {
     if (function_exists('ftp_connect')) {
       $class = 'FileTransferFTPExtension';
     }
-    elseif (ini_get('allow_url_fopen')) {
-      $class = 'FileTransferFTPWrapper';
-    }
     else {
       throw new FileTransferException('No FTP backend available.');
     }
@@ -42,70 +38,6 @@ abstract class FileTransferFTP extends FileTransfer {
   }
 }
 
-/**
- * Connection class using the FTP URL wrapper.
- */
-class FileTransferFTPWrapper extends FileTransferFTP {
-
-  function connect() {
-    $this->connection = 'ftp://' . urlencode($this->username) . ':' . urlencode($this->password) . '@' . $this->hostname . ':' . $this->port . '/';
-    if (!is_dir($this->connection)) {
-      throw new FileTransferException('FTP Connection failed.');
-    }
-  }
-
-  function createDirectoryJailed($directory) {
-    if (!@drupal_mkdir($this->connection . $directory)) {
-      $exception = new FileTransferException('Cannot create directory @directory.', NULL, array('@directory' => $directory));
-      throw $exception;
-    }
-  }
-
-  function removeDirectoryJailed($directory) {
-    if (is_dir($this->connection . $directory)) {
-      $dh = opendir($this->connection . $directory);
-      while (($resource = readdir($dh)) !== FALSE) {
-        if ($resource == '.' || $resource == '..') {
-          continue;
-        }
-        $full_path = $directory . DIRECTORY_SEPARATOR . $resource;
-        if (is_file($this->connection . $full_path)) {
-          $this->removeFile($full_path);
-        }
-        elseif (is_dir($this->connection . $full_path)) {
-          $this->removeDirectory($full_path . '/');
-        }
-      }
-      closedir($dh);
-      if (!drupal_rmdir($this->connection . $directory)) {
-        $exception = new FileTransferException('Cannot remove @directory.', NULL, array('@directory' => $directory));
-        throw $exception;
-      }
-    }
-  }
-
-  function copyFileJailed($source, $destination) {
-    if (!@copy($source, $this->connection . '/' . $destination)) {
-      throw new FileTransferException('Cannot copy @source_file to @destination_file.', NULL, array('@source' => $source, '@destination' => $destination));
-    }
-  }
-
-  function removeFileJailed($destination) {
-    if (!@drupal_unlink($this->connection . '/' .$destination)) {
-      throw new FileTransferException('Cannot remove @destination', NULL, array('@destination' => $destination));
-    }
-  }
-
-  function isDirectory($path) {
-    return is_dir($this->connection . '/' . $path);
-  }
-
-  public function isFile($path) {
-    // This is stupid, but is_file and file_exists don't work! always return true.
-    return @fopen($this->connection . '/' . $path,'r');
-  }
-}
-
 class FileTransferFTPExtension extends FileTransferFTP implements FileTransferChmodInterface {
 
   public function connect() {
diff --git a/includes/form.inc b/includes/form.inc
index 88a05544c38efde7fc1ff3980ce489a6f48c4492..17ffe6b702079c672ed830fa5b3f030a36738803 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: form.inc,v 1.492 2010/09/14 21:42:05 dries Exp $
+// $Id: form.inc,v 1.501 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @defgroup forms Form builder functions
@@ -219,11 +219,13 @@ function drupal_get_form($form_id) {
  *     request (so a browser refresh does not re-submit the form). However, if
  *     'rebuild' has been set to TRUE, then a new copy of the form is
  *     immediately built and sent to the browser; instead of a redirect. This is
- *     used for multi-step forms, such as wizards and confirmation forms. Also,
- *     if a form validation handler has set 'rebuild' to TRUE and a validation
- *     error occurred, then the form is rebuilt prior to being returned,
- *     enabling form elements to be altered, as appropriate to the particular
- *     validation error.
+ *     used for multi-step forms, such as wizards and confirmation forms.
+ *     Normally, $form_state['rebuild'] is set by a submit handler, since it is
+ *     usually logic within a submit handler that determines whether a form is
+ *     done or requires another step. However, a validation handler may already
+ *     set $form_state['rebuild'] to cause the form processing to bypass submit
+ *     handlers and rebuild the form instead, even if there are no validation
+ *     errors.
  *   - input: An array of input that corresponds to $_POST or $_GET, depending
  *     on the 'method' chosen (see below).
  *   - method: The HTTP form method to use for finding the input for this form.
@@ -362,6 +364,7 @@ function form_state_defaults() {
     'build_info' => array('args' => array()),
     'temporary' => array(),
     'submitted' => FALSE,
+    'executed' => FALSE,
     'programmed' => FALSE,
     'cache'=> FALSE,
     'method' => 'post',
@@ -526,6 +529,7 @@ function form_state_keys_no_cache() {
     'method',
     'submit_handlers',
     'submitted',
+    'executed',
     'validate_handlers',
     'values',
   );
@@ -804,23 +808,39 @@ function drupal_process_form($form_id, &$form, &$form_state) {
     if (!empty($form_state['programmed'])) {
       return;
     }
-  }
 
-  // If $form_state['rebuild'] has been set and input has been processed without
-  // validation errors, we're in a multi-step workflow that is not yet complete.
-  // We need to construct a new $form based on the changes made to $form_state
-  // during this request.
-  if ($form_state['rebuild'] && $form_state['process_input'] && !form_get_errors()) {
-    $form = drupal_rebuild_form($form_id, $form_state, $form);
+    // If $form_state['rebuild'] has been set and input has been processed
+    // without validation errors, we are in a multi-step workflow that is not
+    // yet complete. A new $form needs to be constructed based on the changes
+    // made to $form_state during this request. Normally, a submit handler sets
+    // $form_state['rebuild'] if a fully executed form requires another step.
+    // However, for forms that have not been fully executed (e.g., AJAX
+    // submissions triggered by non-buttons), there is no submit handler to set
+    // $form_state['rebuild']. It would not make sense to redisplay the
+    // identical form without an error for the user to correct, so we also
+    // rebuild error-free non-executed forms, regardless of
+    // $form_state['rebuild'].
+    // @todo D8: Simplify this logic; considering AJAX and non-HTML front-ends,
+    //   along with element-level #submit properties, it makes no sense to have
+    //   divergent form execution based on whether the triggering element has
+    //   #executes_submit_callback set to TRUE.
+    if (($form_state['rebuild'] || !$form_state['executed']) && !form_get_errors()) {
+      // Form building functions (e.g., _form_builder_handle_input_element())
+      // may use $form_state['rebuild'] to determine if they are running in the
+      // context of a rebuild, so ensure it is set.
+      $form_state['rebuild'] = TRUE;
+      $form = drupal_rebuild_form($form_id, $form_state, $form);
+    }
   }
+
   // After processing the form, the form builder or a #process callback may
   // have set $form_state['cache'] to indicate that the form and form state
   // shall be cached. But the form may only be cached if the 'no_cache' property
   // is not set to TRUE. Only cache $form as it was prior to form_builder(),
   // because form_builder() must run for each request to accomodate new user
-  // input. We do not cache here for forms that have been rebuilt, because
-  // drupal_rebuild_form() takes care of that.
-  elseif ($form_state['cache'] && empty($form_state['no_cache'])) {
+  // input. Rebuilt forms are not cached here, because drupal_rebuild_form()
+  // already takes care of that.
+  if (!$form_state['rebuild'] && $form_state['cache'] && empty($form_state['no_cache'])) {
     form_set_cache($form['#build_id'], $unprocessed_form, $form_state);
   }
 }
@@ -1142,6 +1162,19 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
             }
           }
         }
+        // Non-multiple select fields always have a value in HTML. If the user
+        // does not change the form, it will be the value of the first option.
+        // Because of this, form validation for the field will almost always
+        // pass, even if the user did not select anything. To work around this
+        // browser behavior, required select fields without a #default_value get
+        // an additional, first empty option. In case the submitted value is
+        // identical to the empty option's value, we reset the element's value
+        // to NULL to trigger the regular #required handling below.
+        // @see form_process_select()
+        elseif ($elements['#type'] == 'select' && !$elements['#multiple'] && $elements['#required'] && !isset($elements['#default_value']) && $elements['#value'] === $elements['#empty_value']) {
+          $elements['#value'] = NULL;
+          form_set_value($elements, NULL, $form_state);
+        }
         elseif (!isset($options[$elements['#value']])) {
           form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
           watchdog('form', 'Illegal choice %choice in %name element.', array('%choice' => $elements['#value'], '%name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
@@ -1183,13 +1216,27 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
     }
 
     // Make sure a value is passed when the field is required.
-    // A simple call to empty() will not cut it here as some fields, like
-    // checkboxes, can return a valid value of '0'. Instead, check the
-    // length if it's a string, and the item count if it's an array.
-    // An unchecked checkbox has a #value of integer 0, different than string
-    // '0', which could be a valid value.
-    if (isset($elements['#needs_validation']) && $elements['#required'] && (!count($elements['#value']) || (is_string($elements['#value']) && strlen(trim($elements['#value'])) == 0) || $elements['#value'] === 0)) {
-      form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+    if (isset($elements['#needs_validation']) && $elements['#required']) {
+      // A simple call to empty() will not cut it here as some fields, like
+      // checkboxes, can return a valid value of '0'. Instead, check the
+      // length if it's a string, and the item count if it's an array.
+      // An unchecked checkbox has a #value of integer 0, different than string
+      // '0', which could be a valid value.
+      $is_empty_multiple = (!count($elements['#value']));
+      $is_empty_string = (is_string($elements['#value']) && drupal_strlen(trim($elements['#value'])) == 0);
+      $is_empty_value = ($elements['#value'] === 0);
+      if ($is_empty_multiple || $is_empty_string || $is_empty_value) {
+        // Although discouraged, a #title is not mandatory for form elements. In
+        // case there is no #title, we cannot set a form error message.
+        // Instead of setting no #title, form constructors are encouraged to set
+        // #title_display to 'invisible' to improve accessibility.
+        if (isset($elements['#title'])) {
+          form_error($elements, $t('!name field is required.', array('!name' => $elements['#title'])));
+        }
+        else {
+          form_error($elements);
+        }
+      }
     }
 
     // Call user-defined form level validators.
@@ -1414,17 +1461,20 @@ function form_get_errors() {
 }
 
 /**
- * Return the error message filed against the form with the specified name.
+ * Returns the error message filed against the given form element.
+ *
+ * Form errors higher up in the form structure override deeper errors as well as
+ * errors on the element itself.
  */
 function form_get_error($element) {
   $form = form_set_error();
-  $key = $element['#parents'][0];
-  if (isset($form[$key])) {
-    return $form[$key];
-  }
-  $key = implode('][', $element['#parents']);
-  if (isset($form[$key])) {
-    return $form[$key];
+  $parents = array();
+  foreach ($element['#parents'] as $parent) {
+    $parents[] = $parent;
+    $key = implode('][', $parents);
+    if (isset($form[$key])) {
+      return $form[$key];
+    }
   }
 }
 
@@ -2059,7 +2109,7 @@ function form_type_checkboxes_value($element, $input = FALSE) {
     // checkboxes to the server at all). This will not affect non-programmatic
     // form submissions, since a checkbox can never legitimately be NULL.
     foreach ($input as $key => $value) {
-      if (is_null($value)) {
+      if (!isset($value)) {
         unset($input[$key]);
       }
     }
@@ -2115,6 +2165,15 @@ function form_type_select_value($element, $input = FALSE) {
         return (isset($element['#default_value']) && is_array($element['#default_value'])) ? $element['#default_value'] : array();
       }
     }
+    // Non-multiple select elements may have an empty option preprended to them
+    // (see form_process_select()). When this occurs, usually #empty_value is
+    // an empty string, but some forms set #empty_value to integer 0 or some
+    // other non-string constant. PHP receives all submitted form input as
+    // strings, but if the empty option is selected, set the value to match the
+    // empty value exactly.
+    elseif (isset($element['#empty_value']) && $input === (string) $element['#empty_value']) {
+      return $element['#empty_value'];
+    }
     else {
       return $input;
     }
@@ -2234,6 +2293,72 @@ function _form_options_flatten($array) {
   return $return;
 }
 
+/**
+ * Processes a select list form element.
+ *
+ * This process callback is mandatory for select fields, since all user agents
+ * automatically preselect the first available option of single (non-multiple)
+ * select lists.
+ *
+ * @param $element
+ *   The form element to process. Properties used:
+ *   - #multiple: (optional) Indicates whether one or more options can be
+ *     selected. Defaults to FALSE.
+ *   - #default_value: Must be NULL or not set in case there is no value for the
+ *     element yet, in which case a first default option is inserted by default.
+ *     Whether this first option is a valid option depends on whether the field
+ *     is #required or not.
+ *   - #required: (optional) Whether the user needs to select an option (TRUE)
+ *     or not (FALSE). Defaults to FALSE.
+ *   - #empty_option: (optional) The label to show for the first default option.
+ *     By default, the label is automatically set to "- Please select -" for a
+ *     required field and "- None -" for an optional field.
+ *   - #empty_value: (optional) The value for the first default option, which is
+ *     used to determine whether the user submitted a value or not.
+ *     - If #required is TRUE, this defaults to '' (an empty string).
+ *     - If #required is not TRUE and this value isn't set, then no extra option
+ *       is added to the select control, leaving the control in a slightly
+ *       illogical state, because there's no way for the user to select nothing,
+ *       since all user agents automatically preselect the first available
+ *       option. But people are used to this being the behavior of select
+ *       controls.
+ *       @todo Address the above issue in Drupal 8.
+ *     - If #required is not TRUE and this value is set (most commonly to an
+ *       empty string), then an extra option (see #empty_option above)
+ *       representing a "non-selection" is added with this as its value.
+ *
+ * @see _form_validate()
+ */
+function form_process_select($element) {
+  // #multiple select fields need a special #name.
+  if ($element['#multiple']) {
+    $element['#attributes']['multiple'] = 'multiple';
+    $element['#attributes']['name'] = $element['#name'] . '[]';
+  }
+  // A non-#multiple select needs special handling to prevent user agents from
+  // preselecting the first option without intention. #multiple select lists do
+  // not get an empty option, as it would not make sense, user interface-wise.
+  else {
+    $required = $element['#required'];
+    // If the element is required and there is no #default_value, then add an
+    // empty option that will fail validation, so that the user is required to
+    // make a choice. Also, if there's a value for #empty_value or
+    // #empty_option, then add an option that represents emptiness.
+    if (($required && !isset($element['#default_value'])) || isset($element['#empty_value']) || isset($element['#empty_option'])) {
+      $element += array(
+        '#empty_value' => '',
+        '#empty_option' => $required ? t('- Select - ') : t('- None -'),
+      );
+      // The empty option is prepended to #options and purposively not merged
+      // to prevent another option in #options mistakenly using the same value
+      // as #empty_value.
+      $empty_option = array($element['#empty_value'] => $element['#empty_option']);
+      $element['#options'] = $empty_option + $element['#options'];
+    }
+  }
+  return $element;
+}
+
 /**
  * Returns HTML for a select form element.
  *
@@ -2251,10 +2376,10 @@ function _form_options_flatten($array) {
  */
 function theme_select($variables) {
   $element = $variables['element'];
-  $size = $element['#size'] ? ' size="' . $element['#size'] . '"' : '';
+  element_set_attributes($element, array('id', 'name', 'size'));
   _form_set_class($element, array('form-select'));
-  $multiple = $element['#multiple'];
-  return '<select name="' . $element['#name'] . '' . ($multiple ? '[]' : '') . '"' . ($multiple ? ' multiple="multiple" ' : '') . drupal_attributes($element['#attributes']) . ' id="' . $element['#id'] . '" ' . $size . '>' . form_select_options($element) . '</select>';
+
+  return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>';
 }
 
 /**
@@ -2276,7 +2401,7 @@ function form_select_options($element, $choices = NULL) {
   // array_key_exists() accommodates the rare event where $element['#value'] is NULL.
   // isset() fails in this situation.
   $value_valid = isset($element['#value']) || array_key_exists('#value', $element);
-  $value_is_array = is_array($element['#value']);
+  $value_is_array = $value_valid && is_array($element['#value']);
   $options = '';
   foreach ($choices as $key => $choice) {
     if (is_array($choice)) {
@@ -2364,6 +2489,8 @@ function form_get_options($element, $key) {
  */
 function theme_fieldset($variables) {
   $element = $variables['element'];
+  element_set_attributes($element, array('id'));
+  _form_set_class($element, array('form-wrapper'));
 
   $output = '<fieldset' . drupal_attributes($element['#attributes']) . '>';
   if (!empty($element['#title'])) {
@@ -2397,10 +2524,9 @@ function theme_fieldset($variables) {
 function theme_radio($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'radio';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#return_value'];
-  if (check_plain($element['#value']) == $element['#return_value']) {
+  element_set_attributes($element, array('id', 'name', '#return_value' => 'value'));
+
+  if (isset($element['#return_value']) && check_plain($element['#value']) == $element['#return_value']) {
     $element['#attributes']['checked'] = 'checked';
   }
   _form_set_class($element, array('form-radio'));
@@ -2422,7 +2548,7 @@ function theme_radio($variables) {
 function theme_radios($variables) {
   $element = $variables['element'];
   $attributes = array();
-  if (!empty($element['#id'])) {
+  if (isset($element['#id'])) {
     $attributes['id'] = $element['#id'];
   }
   $attributes['class'] = 'form-radios';
@@ -2507,9 +2633,11 @@ function theme_date($variables) {
 function form_process_date($element) {
   // Default to current date
   if (empty($element['#value'])) {
-    $element['#value'] = array('day' => format_date(REQUEST_TIME, 'custom', 'j'),
-                            'month' => format_date(REQUEST_TIME, 'custom', 'n'),
-                            'year' => format_date(REQUEST_TIME, 'custom', 'Y'));
+    $element['#value'] = array(
+      'day' => format_date(REQUEST_TIME, 'custom', 'j'),
+      'month' => format_date(REQUEST_TIME, 'custom', 'n'),
+      'year' => format_date(REQUEST_TIME, 'custom', 'Y'),
+    );
   }
 
   $element['#tree'] = TRUE;
@@ -2529,9 +2657,11 @@ function form_process_date($element) {
       case 'day':
         $options = drupal_map_assoc(range(1, 31));
         break;
+
       case 'month':
         $options = drupal_map_assoc(range(1, 12), 'map_month');
         break;
+
       case 'year':
         $options = drupal_map_assoc(range(1900, 2050));
         break;
@@ -2632,11 +2762,10 @@ function theme_checkbox($variables) {
   $element = $variables['element'];
   $t = get_t();
   $element['#attributes']['type'] = 'checkbox';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#return_value'];
+  element_set_attributes($element, array('id', 'name', '#return_value' => 'value'));
+
   // Unchecked checkbox has #value of integer 0.
-  if ($element['#value'] !== 0 && $element['#value'] == $element['#return_value']) {
+  if (isset($element['#return_value']) && isset($element['#value']) && $element['#value'] !== 0 && $element['#value'] == $element['#return_value']) {
     $element['#attributes']['checked'] = 'checked';
   }
   _form_set_class($element, array('form-checkbox'));
@@ -2657,12 +2786,12 @@ function theme_checkbox($variables) {
 function theme_checkboxes($variables) {
   $element = $variables['element'];
   $attributes = array();
-  if (!empty($element['#id'])) {
+  if (isset($element['#id'])) {
     $attributes['id'] = $element['#id'];
   }
-  $attributes['class'] = 'form-checkboxes';
+  $attributes['class'][] = 'form-checkboxes';
   if (!empty($element['#attributes']['class'])) {
-    $attributes['class'] .= ' ' . implode(' ', $element['#attributes']['class']);
+    $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']);
   }
   return '<div' . drupal_attributes($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
 }
@@ -2823,12 +2952,13 @@ function theme_tableselect($variables) {
     // Add an empty header or a "Select all" checkbox to provide room for the
     // checkboxes/radios in the first table column.
     if ($element['#js_select']) {
-      // Add a "Select all" checkbox when checkboxes are displayed.
+      // Add a "Select all" checkbox.
       drupal_add_js('misc/tableselect.js');
       array_unshift($header, array('class' => array('select-all')));
     }
     else {
-      // Add an empty header when radio buttons are displayed.
+      // Add an empty header when radio buttons are displayed or a "Select all"
+      // checkbox is not desired.
       array_unshift($header, '');
     }
   }
@@ -2931,14 +3061,13 @@ function form_process_fieldset(&$element, &$form_state) {
   }
 
   // Contains form element summary functionalities.
-  $element['#attached']['js']['misc/form.js'] = array('weight' => JS_LIBRARY + 1);
+  $element['#attached']['js']['misc/form.js'] = array('group' => JS_LIBRARY, 'weight' => 1);
 
   // The .form-wrapper class is required for #states to treat fieldsets like
   // containers.
   if (!isset($element['#attributes']['class'])) {
     $element['#attributes']['class'] = array();
   }
-  $element['#attributes']['class'][] = 'form-wrapper';
 
   // Collapsible fieldsets
   if (!empty($element['#collapsible'])) {
@@ -2948,7 +3077,6 @@ function form_process_fieldset(&$element, &$form_state) {
       $element['#attributes']['class'][] = 'collapsed';
     }
   }
-  $element['#attributes']['id'] = $element['#id'];
 
   return $element;
 }
@@ -2964,6 +3092,10 @@ function form_process_fieldset(&$element, &$form_state) {
  *   The modified element with all group members.
  */
 function form_pre_render_fieldset($element) {
+  // Fieldsets may be rendered outside of a Form API context.
+  if (!isset($element['#parents']) || !isset($element['#groups'])) {
+    return $element;
+  }
   // Inject group member elements belonging to this group.
   $parents = implode('][', $element['#parents']);
   $children = element_children($element['#groups'][$parents]);
@@ -3073,8 +3205,7 @@ function theme_vertical_tabs($variables) {
  * @ingroup themeable
  */
 function theme_submit($variables) {
-  $element = $variables['element'];
-  return theme('button', $element);
+  return theme('button', $variables['element']);
 }
 
 /**
@@ -3090,11 +3221,8 @@ function theme_submit($variables) {
 function theme_button($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'submit';
-  if (!empty($element['#name'])) {
-    $element['#attributes']['name'] = $element['#name'];
-  }
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#value'];
+  element_set_attributes($element, array('id', 'name', 'value'));
+
   $element['#attributes']['class'][] = 'form-' . $element['#button_type'];
   if (!empty($element['#attributes']['disabled'])) {
     $element['#attributes']['class'][] = 'form-button-disabled';
@@ -3116,11 +3244,8 @@ function theme_button($variables) {
 function theme_image_button($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'image';
-  $element['#attributes']['name'] = $element['#name'];
-  if (!empty($element['#value'])) {
-    $element['#attributes']['value'] = $element['#value'];
-  }
-  $element['#attributes']['id'] = $element['#id'];
+  element_set_attributes($element, array('id', 'name', 'value'));
+
   $element['#attributes']['src'] = file_create_url($element['#src']);
   if (!empty($element['#title'])) {
     $element['#attributes']['alt'] = $element['#title'];
@@ -3148,9 +3273,7 @@ function theme_image_button($variables) {
 function theme_hidden($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'hidden';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#value'];
+  element_set_attributes($element, array('name', 'value'));
   return '<input' . drupal_attributes($element['#attributes']) . " />\n";
 }
 
@@ -3168,15 +3291,7 @@ function theme_hidden($variables) {
 function theme_textfield($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'text';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#value'];
-  if (!empty($element['#size'])) {
-    $element['#attributes']['size'] = $element['#size'];
-  }
-  if (!empty($element['#maxlength'])) {
-    $element['#attributes']['maxlength'] = $element['#maxlength'];
-  }
+  element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
   _form_set_class($element, array('form-text'));
 
   $extra = '';
@@ -3186,7 +3301,7 @@ function theme_textfield($variables) {
 
     $attributes = array();
     $attributes['type'] = 'hidden';
-    $attributes['id'] = $element['#id'] . '-autocomplete';
+    $attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
     $attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE));
     $attributes['disabled'] = 'disabled';
     $attributes['class'][] = 'autocomplete';
@@ -3210,14 +3325,13 @@ function theme_textfield($variables) {
  */
 function theme_form($variables) {
   $element = $variables['element'];
-  if (!empty($element['#action'])) {
+  if (isset($element['#action'])) {
     $element['#attributes']['action'] = drupal_strip_dangerous_protocols($element['#action']);
   }
-  $element['#attributes']['method'] = $element['#method'];
+  element_set_attributes($element, array('method', 'id'));
   if (empty($element['#attributes']['accept-charset'])) {
     $element['#attributes']['accept-charset'] = "UTF-8";
   }
-  $element['#attributes']['id'] = $element['#id'];
   // Anonymous DIV to satisfy XHTML compliance.
   return '<form' . drupal_attributes($element['#attributes']) . '><div>' . $element['#children'] . '</div></form>';
 }
@@ -3235,10 +3349,7 @@ function theme_form($variables) {
  */
 function theme_textarea($variables) {
   $element = $variables['element'];
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['cols'] = $element['#cols'];
-  $element['#attributes']['rows'] = $element['#rows'];
+  element_set_attributes($element, array('id', 'name', 'cols', 'rows'));
   _form_set_class($element, array('form-textarea'));
 
   $wrapper_attributes = array(
@@ -3271,15 +3382,7 @@ function theme_textarea($variables) {
 function theme_password($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'password';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  $element['#attributes']['value'] = $element['#value'];
-  if (!empty($element['#size'])) {
-    $element['#attributes']['size'] = $element['#size'];
-  }
-  if (!empty($element['#maxlength'])) {
-    $element['#attributes']['maxlength'] = $element['#maxlength'];
-  }
+  element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
   _form_set_class($element, array('form-text'));
 
   return '<input' . drupal_attributes($element['#attributes']) . ' />';
@@ -3316,11 +3419,7 @@ function form_process_weight($element) {
 function theme_file($variables) {
   $element = $variables['element'];
   $element['#attributes']['type'] = 'file';
-  $element['#attributes']['name'] = $element['#name'];
-  $element['#attributes']['id'] = $element['#id'];
-  if (!empty($element['#size'])) {
-    $element['#attributes']['size'] = $element['#size'];
-  }
+  element_set_attributes($element, array('id', 'name', 'size'));
   _form_set_class($element, array('form-file'));
 
   return '<input' . drupal_attributes($element['#attributes']) . ' />';
@@ -3373,10 +3472,16 @@ function theme_file($variables) {
  * @ingroup themeable
  */
 function theme_form_element($variables) {
-  $element = $variables['element'];
+  $element = &$variables['element'];
   // This is also used in the installer, pre-database setup.
   $t = get_t();
 
+  // This function is invoked as theme wrapper, but the rendered form element
+  // may not necessarily have been processed by form_builder().
+  $element += array(
+    '#title_display' => 'before',
+  );
+
   // Add element #id for #type 'item'.
   if (isset($element['#markup']) && !empty($element['#id'])) {
     $attributes['id'] = $element['#id'];
@@ -3404,11 +3509,11 @@ function theme_form_element($variables) {
 
   switch ($element['#title_display']) {
     case 'before':
+    case 'invisible':
       $output .= ' ' . theme('form_element_label', $variables);
       $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
       break;
 
-    case 'invisible':
     case 'after':
       $output .= ' ' . $prefix . $element['#children'] . $suffix;
       $output .= ' ' . theme('form_element_label', $variables) . "\n";
@@ -3422,7 +3527,7 @@ function theme_form_element($variables) {
   }
 
   if (!empty($element['#description'])) {
-    $output .= ' <div class="description">' . $element['#description'] . "</div>\n";
+    $output .= '<div class="description">' . $element['#description'] . "</div>\n";
   }
 
   $output .= "</div>\n";
@@ -3521,10 +3626,13 @@ function _form_set_class(&$element, $class = array()) {
     }
     $element['#attributes']['class'] = array_merge($element['#attributes']['class'], $class);
   }
-  if ($element['#required']) {
+  // This function is invoked from form element theme functions, but the
+  // rendered form element may not necessarily have been processed by
+  // form_builder().
+  if (!empty($element['#required'])) {
     $element['#attributes']['class'][] = 'required';
   }
-  if (form_get_error($element)) {
+  if (isset($element['#parents']) && form_get_error($element)) {
     $element['#attributes']['class'][] = 'error';
   }
 }
@@ -3897,7 +4005,7 @@ function _batch_queue($batch_set) {
 
   // The class autoloader is not available when running update.php, so make
   // sure the files are manually included.
-  if (is_null($queues)) {
+  if (!isset($queues)) {
     $queues = array();
     require_once DRUPAL_ROOT . '/modules/system/system.queue.inc';
     require_once DRUPAL_ROOT . '/includes/batch.queue.inc';
diff --git a/includes/install.core.inc b/includes/install.core.inc
index fed7784b5dcbf9d810e825fd21b46a1779bb7d8b..fea10913d4ae2cc0eb5578686ce81adfc9845a11 100644
--- a/includes/install.core.inc
+++ b/includes/install.core.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: install.core.inc,v 1.30 2010/09/14 21:42:05 dries Exp $
+// $Id: install.core.inc,v 1.38 2010/10/07 03:26:41 webchick Exp $
 
 /**
  * @file
@@ -1198,21 +1198,36 @@ function install_select_locale(&$install_state) {
   }
 
   if (empty($install_state['parameters']['locale'])) {
-    // If only the built-in (English) language is available, and we are using
-    // the default profile and performing an interactive installation, inform
-    // the user that the installer can be localized. Otherwise we assume the
-    // user knows what he is doing.
+    // If only the built-in (English) language is available, and we are
+    // performing an interactive installation, inform the user that the
+    // installer can be localized. Otherwise we assume the user knows what he
+    // is doing.
     if (count($locales) == 1) {
-      if ($profilename == 'standard' && $install_state['interactive']) {
+      if ($install_state['interactive']) {
         drupal_set_title(st('Choose language'));
         if (!empty($install_state['parameters']['localize'])) {
-          $output = '<p>' . st('With the addition of an appropriate translation package, this installer is capable of proceeding in another language of your choice. To install and use Drupal in a language other than English:') . '</p>';
-          $output .= '<ul><li>' . st('Determine if <a href="@translations" target="_blank">a translation of this Drupal version</a> is available in your language of choice. A translation is provided via a translation package; each translation package enables the display of a specific version of Drupal in a specific language. Not all languages are available for every version of Drupal.', array('@translations' => 'http://drupal.org/project/translations')) . '</li>';
-          $output .= '<li>' . st('If an alternative translation package of your choice is available, download and extract its contents to your Drupal root directory.') . '</li>';
-          $output .= '<li>' . st('Return to choose language using the second link below and select your desired language from the displayed list. Reloading the page allows the list to automatically adjust to the presence of new translation packages.') . '</li>';
-          $output .= '</ul><p>' . st('Alternatively, to install and use Drupal in English, or to defer the selection of an alternative language until after installation, select the first link below.') . '</p>';
-          $output .= '<p>' . st('How should the installation continue?') . '</p>';
-          $output .= '<ul><li><a href="install.php?profile=' . $profilename . '&amp;locale=en">' . st('Continue installation in English') . '</a></li><li><a href="install.php?profile=' . $profilename . '">' . st('Return to choose a language') . '</a></li></ul>';
+          $output = '<p>Follow these steps to translate Drupal into your language:</p>';
+          $output .= '<ol>';
+          $output .= '<li>Download a translation from the <a href="http://localize.drupal.org/download" target="_blank">translation server</a>.</li>';
+          $output .= '<li>Rename the downloaded file retaining only the language code at the end of the file name and its extension. For example, if the file name is
+<pre>
+drupal-7.0.pt-br.po
+</pre>
+rename it to
+<pre>
+pt-br.po
+</pre></li>';
+          $output .= '<li>Place it into the following directory:
+<pre>
+/profiles/' . $profilename . '/translations/
+</pre></li>';
+          $output .= '</ol>';
+          $output .= '<p>For more information on installing Drupal in different languages, visit the <a href="http://drupal.org/localize" target="_blank">drupal.org handbook page</a>.</p>';
+          $output .= '<p>How should the installation continue?</p>';
+          $output .= '<ul>';
+          $output .= '<li><a href="install.php?profile=' . $profilename . '">Reload the language selection page after adding translations</a></li>';
+          $output .= '<li><a href="install.php?profile=' . $profilename . '&amp;locale=en">Continue installation in English</a></li>';
+          $output .= '</ul>';
         }
         else {
           include_once DRUPAL_ROOT . '/includes/form.inc';
@@ -1221,8 +1236,8 @@ function install_select_locale(&$install_state) {
         }
         return $output;
       }
-      // One language, but not the default profile or not an interactive
-      // installation. Assume the user knows what he is doing.
+      // One language, but not an interactive installation. Assume the user
+      // knows what he is doing.
       $locale = current($locales);
       $install_state['parameters']['locale'] = $locale->name;
       return;
@@ -1263,7 +1278,7 @@ function install_select_locale(&$install_state) {
 /**
  * Form API array definition for language selection.
  */
-function install_select_locale_form($form, &$form_state, $locales, $profilename = 'standard') {
+function install_select_locale_form($form, &$form_state, $locales, $profilename) {
   include_once DRUPAL_ROOT . '/includes/iso.inc';
   $languages = _locale_get_predefined_list();
   foreach ($locales as $locale) {
@@ -1280,7 +1295,7 @@ function install_select_locale_form($form, &$form_state, $locales, $profilename
       '#parents' => array('locale')
     );
   }
-  if ($profilename == 'standard') {
+  if (count($locales) == 1) {
     $form['help'] = array(
       '#markup' => '<p><a href="install.php?profile=' . $profilename . '&amp;localize=true">' . st('Learn how to install Drupal in other languages') . '</a></p>',
     );
@@ -1388,6 +1403,7 @@ function install_profile_modules(&$install_state) {
     'operations' => $operations,
     'title' => st('Installing @drupal', array('@drupal' => drupal_install_profile_distribution_name())),
     'error_message' => st('The installation has encountered an error.'),
+    'finished' => '_install_profile_modules_finished',
   );
   return $batch;
 }
@@ -1512,9 +1528,6 @@ function install_finished(&$install_state) {
   // registered by the install profile are registered correctly.
   drupal_flush_all_caches();
 
-  // Register actions declared by any modules.
-  actions_synchronize();
-
   // Remember the profile which was used.
   variable_set('install_profile', drupal_get_profile());
 
@@ -1549,6 +1562,15 @@ function _install_module_batch($module, $module_name, &$context) {
   $context['message'] = st('Installed %module module.', array('%module' => $module_name));
 }
 
+/**
+ * 'Finished' callback for module installation batch.
+ */
+function _install_profile_modules_finished($success, $results, $operations) {
+  // Flush all caches to complete the module installation process. Subsequent
+  // installation tasks will now have full access to the profile's modules.
+  drupal_flush_all_caches();
+}
+
 /**
  * Checks installation requirements and reports any errors.
  */
@@ -1615,7 +1637,18 @@ function install_check_requirements($install_state) {
         // therefore must delete the file we just created and force the
         // administrator to log on to the server and create it manually.
         else {
-          drupal_unlink($settings_file);
+          $deleted = @drupal_unlink($settings_file);
+          // We expect deleting the file to be successful (since we just
+          // created it ourselves above), but if it fails somehow, we set a
+          // variable so we can display a one-time error message to the
+          // administrator at the bottom of the requirements list. We also try
+          // to make the file writable, to eliminate any conflicting error
+          // messages in the requirements list.
+          $exists = !$deleted;
+          if ($exists) {
+            $settings_file_ownership_error = TRUE;
+            $writable = drupal_verify_install_file($settings_file, FILE_READABLE|FILE_WRITABLE);
+          }
         }
       }
     }
@@ -1646,7 +1679,15 @@ function install_check_requirements($install_state) {
       else {
         $requirements['settings file'] = array(
           'title'       => st('Settings file'),
-          'value'       => st('Settings file is writable.'),
+          'value'       => st('The settings file is writable.'),
+        );
+      }
+      if (!empty($settings_file_ownership_error)) {
+        $requirements['settings file ownership'] = array(
+          'title'       => st('Settings file'),
+          'value'       => st('The settings file is owned by the web server.'),
+          'severity'    => REQUIREMENT_ERROR,
+          'description' => st('The @drupal installer failed to create a settings file with proper file ownership. Log on to your web server, remove the existing %file file, and create a new one by copying the %default_file file to %file. More details about installing Drupal are available in <a href="@install_txt">INSTALL.txt</a>. If you have problems with the file permissions on your server, consult the <a href="@handbook_url">online handbook</a>.', array('@drupal' => drupal_install_profile_distribution_name(), '%file' => $file, '%default_file' => $default_settings_file, '@install_txt' => base_path() . 'INSTALL.txt', '@handbook_url' => 'http://drupal.org/server-permissions')),
         );
       }
     }
@@ -1715,11 +1756,11 @@ function _install_configure_form($form, &$form_state, &$install_state) {
   );
 
   $countries = country_get_list();
-  $countries = array_merge(array('' => st('No default country')), $countries);
   $form['server_settings']['site_default_country'] = array(
     '#type' => 'select',
     '#title' => t('Default country'),
-    '#default_value' => variable_get('site_default_country', ''),
+    '#empty_value' => '',
+    '#default_value' => variable_get('site_default_country', NULL),
     '#options' => $countries,
     '#description' => st('Select the default country for the site.'),
     '#weight' => 0,
@@ -1738,7 +1779,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
   $form['server_settings']['clean_url'] = array(
     '#type' => 'hidden',
     '#default_value' => 0,
-    '#attributes' => array('class' => array('install')),
+    '#attributes' => array('id' => 'edit-clean-url', 'class' => array('install')),
   );
 
   $form['update_notifications'] = array(
diff --git a/includes/locale.inc b/includes/locale.inc
index 8662afd8f3c197b02f9a4b476db642782a3f1993..42cdbf273e952a88b7424b1617f784cee163a765 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -1,11 +1,37 @@
 <?php
-// $Id: locale.inc,v 1.258 2010/07/30 02:47:27 dries Exp $
+// $Id: locale.inc,v 1.260 2010/10/06 13:38:39 dries Exp $
 
 /**
  * @file
  * Administration functions for locale.module.
  */
 
+/**
+ * The language is determined using a URL language indicator:
+ * path prefix or domain according to the configuration.
+ */
+define('LOCALE_LANGUAGE_NEGOTIATION_URL', 'locale-url');
+
+/**
+ * The language is set based on the browser language settings.
+ */
+define('LOCALE_LANGUAGE_NEGOTIATION_BROWSER', 'locale-browser');
+
+/**
+ * The language is determined using the current interface language.
+ */
+define('LOCALE_LANGUAGE_NEGOTIATION_INTERFACE', 'locale-interface');
+
+/**
+ * The language is set based on the user language settings.
+ */
+define('LOCALE_LANGUAGE_NEGOTIATION_USER', 'locale-user');
+
+/**
+ * The language is set based on the request/session parameters.
+ */
+define('LOCALE_LANGUAGE_NEGOTIATION_SESSION', 'locale-session');
+
 /**
  * Regular expression pattern used to localize JavaScript strings.
  */
@@ -156,6 +182,10 @@ function locale_language_from_session($languages) {
 function locale_language_from_url($languages) {
   $language_url = FALSE;
 
+  if (!language_negotiation_get_any(LOCALE_LANGUAGE_NEGOTIATION_URL)) {
+    return $language_url;
+  }
+
   switch (variable_get('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX)) {
     case LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX:
       // $_GET['q'] might not be available at this time, because
@@ -1585,7 +1615,7 @@ function _locale_translate_seek() {
   }
 
   $output .= theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No strings available.')));
-  $output .= theme('pager', array('tags' => NULL));
+  $output .= theme('pager');
 
   return $output;
 }
diff --git a/includes/menu.inc b/includes/menu.inc
index 0c698962670b118730f3ee76c819e530ac74d73c..f7217c62936d6bb5e9903bf3439c0189f2c48429 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.inc,v 1.408 2010/09/01 02:59:04 dries Exp $
+// $Id: menu.inc,v 1.413 2010/10/03 23:29:09 dries Exp $
 
 /**
  * @file
@@ -141,9 +141,9 @@ define('MENU_NORMAL_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB);
  * Menu type -- A hidden, internal callback, typically used for API calls.
  *
  * Callbacks simply register a path so that the correct function is fired
- * when the URL is accessed. They are not shown in the menu.
+ * when the URL is accessed. They do not appear in menus or breadcrumbs.
  */
-define('MENU_CALLBACK', MENU_VISIBLE_IN_BREADCRUMB);
+define('MENU_CALLBACK', 0x0000);
 
 /**
  * Menu type -- A normal menu item, hidden until enabled by an administrator.
@@ -728,12 +728,26 @@ function _menu_translate(&$router_item, $map, $to_arg = FALSE) {
 
   // Generate the link path for the page request or local tasks.
   $link_map = explode('/', $router_item['path']);
+  if (isset($router_item['tab_root'])) {
+    $tab_root_map = explode('/', $router_item['tab_root']);
+  }
+  if (isset($router_item['tab_parent'])) {
+    $tab_parent_map = explode('/', $router_item['tab_parent']);
+  }
   for ($i = 0; $i < $router_item['number_parts']; $i++) {
     if ($link_map[$i] == '%') {
       $link_map[$i] = $path_map[$i];
     }
+    if (isset($tab_root_map[$i]) && $tab_root_map[$i] == '%') {
+      $tab_root_map[$i] = $path_map[$i];
+    }
+    if (isset($tab_parent_map[$i]) && $tab_parent_map[$i] == '%') {
+      $tab_parent_map[$i] = $path_map[$i];
+    }
   }
   $router_item['href'] = implode('/', $link_map);
+  $router_item['tab_root_href'] = implode('/', $tab_root_map);
+  $router_item['tab_parent_href'] = implode('/', $tab_parent_map);
   $router_item['options'] = array();
   _menu_check_access($router_item, $map);
 
@@ -778,7 +792,11 @@ function menu_tail_to_arg($arg, $map, $index) {
  * preparation such as always calling to_arg functions
  *
  * @param $item
- *   A menu link
+ *   A menu link.
+ * @param $translate
+ *   (optional) Whether to try to translate a link containing dynamic path
+ *   argument placeholders (%) based on the menu router item of the current
+ *   path. Defaults to FALSE. Internally used for breadcrumbs.
  *
  * @return
  *   Returns the map of path arguments with objects loaded as defined in the
@@ -789,8 +807,10 @@ function menu_tail_to_arg($arg, $map, $index) {
  *   $item['options'] is unserialized; it is also changed within the call here
  *   to $item['localized_options'] by _menu_item_localize().
  */
-function _menu_link_translate(&$item) {
-  $item['options'] = unserialize($item['options']);
+function _menu_link_translate(&$item, $translate = FALSE) {
+  if (!is_array($item['options'])) {
+    $item['options'] = unserialize($item['options']);
+  }
   if ($item['external']) {
     $item['access'] = 1;
     $map = array();
@@ -799,13 +819,40 @@ function _menu_link_translate(&$item) {
     $item['localized_options'] = $item['options'];
   }
   else {
+    // Complete the path of the menu link with elements from the current path,
+    // if it contains dynamic placeholders (%).
     $map = explode('/', $item['link_path']);
-    if (!empty($item['to_arg_functions'])) {
-      _menu_link_map_translate($map, $item['to_arg_functions']);
+    if (strpos($item['link_path'], '%') !== FALSE) {
+      // Invoke registered to_arg callbacks.
+      if (!empty($item['to_arg_functions'])) {
+        _menu_link_map_translate($map, $item['to_arg_functions']);
+      }
+      // Or try to derive the path argument map from the current router item,
+      // if this $item's path is within the router item's path. This means
+      // that if we are on the current path 'foo/%/bar/%/baz', then
+      // menu_get_item() will have translated the menu router item for the
+      // current path, and we can take over the argument map for a link like
+      // 'foo/%/bar'. This inheritance is only valid for breadcrumb links.
+      // @see _menu_tree_check_access()
+      // @see menu_get_active_breadcrumb()
+      elseif ($translate && ($current_router_item = menu_get_item())) {
+        // If $translate is TRUE, then this link is in the active trail.
+        // Only translate paths within the current path.
+        if (strpos($current_router_item['path'], $item['link_path']) === 0) {
+          $count = count($map);
+          $map = array_slice($current_router_item['original_map'], 0, $count);
+          $item['original_map'] = $map;
+          if (isset($current_router_item['map'])) {
+            $item['map'] = array_slice($current_router_item['map'], 0, $count);
+          }
+          // Reset access to check it (for the first time).
+          unset($item['access']);
+        }
+      }
     }
     $item['href'] = implode('/', $map);
 
-    // Note - skip callbacks without real values for their arguments.
+    // Skip links containing untranslated arguments.
     if (strpos($item['href'], '%') !== FALSE) {
       $item['access'] = FALSE;
       return FALSE;
@@ -913,11 +960,12 @@ function menu_tree_output($tree) {
   // Pull out just the menu links we are going to render so that we
   // get an accurate count for the first/last classes.
   foreach ($tree as $data) {
-    if (!$data['link']['hidden']) {
+    if ($data['link']['access'] && !$data['link']['hidden']) {
       $items[] = $data;
     }
   }
 
+  $router_item = menu_get_item();
   $num_items = count($items);
   foreach ($items as $i => $data) {
     $class = array();
@@ -942,7 +990,14 @@ function menu_tree_output($tree) {
     // Set a class if the link is in the active trail.
     if ($data['link']['in_active_trail']) {
       $class[] = 'active-trail';
-      $data['localized_options']['attributes']['class'][] = 'active-trail';
+      $data['link']['localized_options']['attributes']['class'][] = 'active-trail';
+    }
+    // Normally, l() compares the href of every link with $_GET['q'] and sets
+    // the active class accordingly. But local tasks do not appear in menu
+    // trees, so if the current path is a local task, and this link is its
+    // tab root, then we have to set the class manually.
+    if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) {
+      $data['link']['localized_options']['attributes']['class'][] = 'active';
     }
 
     // Allow menu-specific theme overrides.
@@ -993,7 +1048,7 @@ function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
   // Use $mlid as a flag for whether the data being loaded is for the whole tree.
   $mlid = isset($link['mlid']) ? $link['mlid'] : 0;
   // Generate a cache ID (cid) specific for this $menu_name, $link, $language, and depth.
-  $cid = 'links:' . $menu_name . ':all-cid:' . $mlid . ':' . $GLOBALS['language']->language . ':' . (int) $max_depth;
+  $cid = 'links:' . $menu_name . ':all:' . $mlid . ':' . $GLOBALS['language']->language . ':' . (int) $max_depth;
 
   if (!isset($tree[$cid])) {
     // If the static variable doesn't have the data, check {cache_menu}.
@@ -1042,9 +1097,13 @@ function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
  * field, see http://drupal.org/node/141866 for more.
  *
  * @param $menu_name
- *   The named menu links to return
+ *   The named menu links to return.
  * @param $max_depth
- *   Optional maximum depth of links to retrieve.
+ *   (optional) The maximum depth of links to retrieve.
+ * @param $only_active_trail
+ *   (optional) Whether to only return the links in the active trail (TRUE)
+ *   instead of all links on every level of the menu link tree (FALSE). Defaults
+ *   to FALSE. Internally used for breadcrumbs only.
  *
  * @return
  *   An array of menu links, in the order they should be rendered. The array
@@ -1053,7 +1112,7 @@ function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
  *   submenu below the link if there is one, and it is a subtree that has the
  *   same structure described for the top-level array.
  */
-function menu_tree_page_data($menu_name, $max_depth = NULL) {
+function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = FALSE) {
   $tree = &drupal_static(__FUNCTION__, array());
 
   // Load the menu item corresponding to the current page.
@@ -1062,7 +1121,18 @@ function menu_tree_page_data($menu_name, $max_depth = NULL) {
       $max_depth = min($max_depth, MENU_MAX_DEPTH);
     }
     // Generate a cache ID (cid) specific for this page.
-    $cid = 'links:' . $menu_name . ':page-cid:' . $item['href'] . ':' . $GLOBALS['language']->language . ':' . (int) $item['access'] . ':' . (int) $max_depth;
+    $cid = 'links:' . $menu_name . ':page:' . $item['href'] . ':' . $GLOBALS['language']->language . ':' . (int) $item['access'] . ':' . (int) $max_depth;
+    // If we are asked for the active trail only, and $menu_name has not been
+    // built and cached for this page yet, then this likely means that it
+    // won't be built anymore, as this function is invoked from
+    // template_process_page(). So in order to not build a giant menu tree
+    // that needs to be checked for access on all levels, we simply check
+    // whether we have the menu already in cache, or otherwise, build a minimum
+    // tree containing the breadcrumb/active trail only.
+    // @see menu_set_active_trail()
+    if (!isset($tree[$cid]) && $only_active_trail) {
+      $cid .= ':trail';
+    }
 
     if (!isset($tree[$cid])) {
       // If the static variable doesn't have the data, check {cache_menu}.
@@ -1078,57 +1148,39 @@ function menu_tree_page_data($menu_name, $max_depth = NULL) {
           'min_depth' => 1,
           'max_depth' => $max_depth,
         );
+        // Parent mlids; used both as key and value to ensure uniqueness.
+        // We always want all the top-level links with plid == 0.
+        $active_trail = array(0 => 0);
+
         // If the item for the current page is accessible, build the tree
         // parameters accordingly.
         if ($item['access']) {
-          // Check whether a menu link exists that corresponds to the current path.
-          $args[] = $item['href'];
-          if (drupal_is_front_page()) {
-            $args[] = '<front>';
-          }
-          $active_link = db_select('menu_links')
-            ->fields('menu_links', array(
-              'p1',
-              'p2',
-              'p3',
-              'p4',
-              'p5',
-              'p6',
-              'p7',
-              'p8',
-            ))
-            ->condition('menu_name', $menu_name)
-            ->condition('link_path', $args, 'IN')
-            ->execute()->fetchAssoc();
-
-          if (empty($active_link)) {
-            // If no link exists, we may be on a local task that's not in the links.
-            // TODO: Handle the case like a local task on a specific node in the menu.
-            $active_link = db_select('menu_links')
-              ->fields('menu_links', array(
-                'p1',
-                'p2',
-                'p3',
-                'p4',
-                'p5',
-                'p6',
-                'p7',
-                'p8',
-              ))
-              ->condition('menu_name', $menu_name)
-              ->condition('link_path', $item['tab_root'])
-              ->execute()->fetchAssoc();
+          // Find a menu link corresponding to the current path.
+          if ($active_link = menu_link_get_preferred()) {
+            // The active link may only be taken into account to build the
+            // active trail, if it resides in the requested menu. Otherwise,
+            // we'd needlessly re-run _menu_build_tree() queries for every menu
+            // on every page.
+            if ($active_link['menu_name'] == $menu_name) {
+              // Use all the coordinates, except the last one because there
+              // can be no child beyond the last column.
+              for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
+                if ($active_link['p' . $i]) {
+                  $active_trail[$active_link['p' . $i]] = $active_link['p' . $i];
+                }
+              }
+              // If we are asked to build links for the active trail only, skip
+              // the entire 'expanded' handling.
+              if ($only_active_trail) {
+                $tree_parameters['only_active_trail'] = TRUE;
+              }
+            }
           }
-
-          // We always want all the top-level links with plid == 0.
-          $active_link[] = '0';
-
-          // Use array_values() so that the indices are numeric.
-          $parents = $active_link = array_unique(array_values($active_link));
+          $parents = $active_trail;
 
           $expanded = variable_get('menu_expanded', array());
           // Check whether the current menu has any links set to be expanded.
-          if (in_array($menu_name, $expanded)) {
+          if (!$only_active_trail && in_array($menu_name, $expanded)) {
             // Collect all the links set to be expanded, and then add all of
             // their children to the list as well.
             do {
@@ -1142,19 +1194,19 @@ function menu_tree_page_data($menu_name, $max_depth = NULL) {
                 ->execute();
               $num_rows = FALSE;
               foreach ($result as $item) {
-                $parents[] = $item['mlid'];
+                $parents[$item['mlid']] = $item['mlid'];
                 $num_rows = TRUE;
               }
             } while ($num_rows);
           }
           $tree_parameters['expanded'] = $parents;
-          $tree_parameters['active_trail'] = $active_link;
+          $tree_parameters['active_trail'] = $active_trail;
         }
-        // Otherwise, only show the top-level menu items when access is denied.
+        // If access is denied, we only show top-level links in menus.
         else {
-          $tree_parameters['expanded'] = array(0);
+          $tree_parameters['expanded'] = $active_trail;
+          $tree_parameters['active_trail'] = $active_trail;
         }
-
         // Cache the tree building parameters using the page-specific cid.
         cache_set($cid, $tree_parameters, 'cache_menu');
       }
@@ -1178,9 +1230,12 @@ function menu_tree_page_data($menu_name, $max_depth = NULL) {
  *   (optional) An associative array of build parameters. Possible keys:
  *   - expanded: An array of parent link ids to return only menu links that are
  *     children of one of the plids in this list. If empty, the whole menu tree
- *     is built.
+ *     is built, unless 'only_active_trail' is TRUE.
  *   - active_trail: An array of mlids, representing the coordinates of the
  *     currently active menu link.
+ *   - only_active_trail: Whether to only return links that are in the active
+ *     trail. This option is ignored, if 'expanded' is non-empty. Internally
+ *     used for breadcrumbs.
  *   - min_depth: The minimum depth of menu links in the resulting tree.
  *     Defaults to 1, which is the default to build a whole tree for a menu, i.e.
  *     excluding menu container itself.
@@ -1241,6 +1296,8 @@ function _menu_build_tree($menu_name, array $parameters = array()) {
       'page_callback',
       'page_arguments',
       'delivery_callback',
+      'tab_parent',
+      'tab_root',
       'title',
       'title_callback',
       'title_arguments',
@@ -1256,6 +1313,9 @@ function _menu_build_tree($menu_name, array $parameters = array()) {
     if (!empty($parameters['expanded'])) {
       $query->condition('ml.plid', $parameters['expanded'], 'IN');
     }
+    elseif (!empty($parameters['only_active_trail'])) {
+      $query->condition('ml.mlid', $parameters['active_trail'], 'IN');
+    }
     $min_depth = (isset($parameters['min_depth']) ? $parameters['min_depth'] : 1);
     if ($min_depth != 1) {
       $query->condition('ml.depth', $min_depth, '>=');
@@ -1269,8 +1329,8 @@ function _menu_build_tree($menu_name, array $parameters = array()) {
     foreach ($query->execute() as $item) {
       $links[] = $item;
     }
-    $active_link = (isset($parameters['active_trail']) ? $parameters['active_trail'] : array());
-    $data['tree'] = menu_tree_data($links, $active_link, $min_depth);
+    $active_trail = (isset($parameters['active_trail']) ? $parameters['active_trail'] : array());
+    $data['tree'] = menu_tree_data($links, $active_trail, $min_depth);
     $data['node_links'] = array();
     menu_tree_collect_node_links($data['tree'], $data['node_links']);
 
@@ -1315,7 +1375,6 @@ function menu_tree_collect_node_links(&$tree, &$node_links) {
  *   menu_tree_collect_node_links().
  */
 function menu_tree_check_access(&$tree, $node_links = array()) {
-
   if ($node_links) {
     $nids = array_keys($node_links);
     $select = db_select('node', 'n');
@@ -1331,7 +1390,6 @@ function menu_tree_check_access(&$tree, $node_links = array()) {
     }
   }
   _menu_tree_check_access($tree);
-  return;
 }
 
 /**
@@ -1342,7 +1400,7 @@ function _menu_tree_check_access(&$tree) {
   foreach ($tree as $key => $v) {
     $item = &$tree[$key]['link'];
     _menu_link_translate($item);
-    if ($item['access']) {
+    if ($item['access'] || ($item['in_active_trail'] && strpos($item['href'], '%') !== FALSE)) {
       if ($tree[$key]['below']) {
         _menu_tree_check_access($tree[$key]['below']);
       }
@@ -1534,7 +1592,6 @@ function menu_get_active_help() {
   }
 
   $arg = drupal_help_arg(arg(NULL));
-  $empty_arg = drupal_help_arg();
 
   foreach (module_implements('help') as $module) {
     $function = $module . '_help';
@@ -1675,6 +1732,7 @@ function menu_navigation_links($menu_name, $level = 0) {
   }
 
   // Create a single level of links.
+  $router_item = menu_get_item();
   $links = array();
   foreach ($tree as $item) {
     if (!$item['link']['hidden']) {
@@ -1684,6 +1742,14 @@ function menu_navigation_links($menu_name, $level = 0) {
       $l['title'] = $item['link']['title'];
       if ($item['link']['in_active_trail']) {
         $class = ' active-trail';
+        $l['attributes']['class'][] = 'active-trail';
+      }
+      // Normally, l() compares the href of every link with $_GET['q'] and sets
+      // the active class accordingly. But local tasks do not appear in menu
+      // trees, so if the current path is a local task, and this link is its
+      // tab root, then we have to set the class manually.
+      if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != $_GET['q']) {
+        $l['attributes']['class'][] = 'active';
       }
       // Keyed with the unique mlid to generate classes in theme_links().
       $links['menu-' . $item['link']['mlid'] . $class] = $l;
@@ -1729,7 +1795,7 @@ function menu_local_tasks($level = 0) {
     // If this router item points to its parent, start from the parents to
     // compute tabs and actions.
     if ($router_item && ($router_item['type'] & MENU_LINKS_TO_PARENT)) {
-      $router_item = menu_get_item($router_item['tab_parent']);
+      $router_item = menu_get_item($router_item['tab_parent_href']);
     }
 
     // If we failed to fetch a router item or the current user doesn't have
@@ -1790,6 +1856,16 @@ function menu_local_tasks($level = 0) {
             for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
             // Use the path of the parent instead.
             $link['href'] = $tasks[$p]['href'];
+            // Mark the link as active, if the current path happens to be the
+            // path of the default local task itself (i.e., instead of its
+            // tab_parent_href or tab_root_href). Normally, links for default
+            // local tasks link to their parent, but the path of default local
+            // tasks can still be accessed directly, in which case this link
+            // would not be marked as active, since l() only compares the href
+            // with $_GET['q'].
+            if ($link['href'] != $_GET['q']) {
+              $link['localized_options']['attributes']['class'][] = 'active';
+            }
             $tabs_current[] = array(
               '#theme' => 'menu_local_task',
               '#link' => $link,
@@ -1859,6 +1935,13 @@ function menu_local_tasks($level = 0) {
           }
           // We check for the active tab.
           if ($item['path'] == $path) {
+            // Mark the link as active, if the current path is a (second-level)
+            // local task of a default local task. Since this default local task
+            // links to its parent, l() will not mark it as active, as it only
+            // compares the link's href to $_GET['q'].
+            if ($link['href'] != $_GET['q']) {
+              $link['localized_options']['attributes']['class'][] = 'active';
+            }
             $tabs_current[] = array(
               '#theme' => 'menu_local_task',
               '#link' => $link,
@@ -2053,12 +2136,12 @@ function theme_menu_local_tasks() {
   $output = array();
 
   if ($primary = menu_primary_local_tasks()) {
-    $primary['#prefix'] = '<ul class="tabs primary">';
+    $primary['#prefix'] = '<h2 class="element-invisible">' . t('Primary tabs') . '</h2><ul class="tabs primary">';
     $primary['#suffix'] = '</ul>';
     $output[] = $primary;
   }
   if ($secondary = menu_secondary_local_tasks()) {
-    $secondary['#prefix'] = '<ul class="tabs secondary">';
+    $secondary['#prefix'] = '<h2 class="element-invisible">' . t('Secondary tabs') . '</h2><ul class="tabs secondary">';
     $secondary['#suffix'] = '</ul>';
     $output[] = $secondary;
   }
@@ -2103,7 +2186,7 @@ function menu_set_active_item($path) {
 }
 
 /**
- * Sets or gets the active trail (path to root menu root) of the current page.
+ * Sets or gets the active trail (path to menu tree root) of the current page.
  *
  * @param $new_trail
  *   Menu trail to set, or NULL to use previously-set or calculated trail. If
@@ -2132,76 +2215,150 @@ function menu_set_active_trail($new_trail = NULL) {
   }
   elseif (!isset($trail)) {
     $trail = array();
-    $trail[] = array('title' => t('Home'), 'href' => '<front>', 'localized_options' => array(), 'type' => 0);
-    $item = menu_get_item();
-
-    // Check whether the current item is a local task (displayed as a tab).
-    if ($item['tab_parent']) {
-      // The title of a local task is used for the tab, never the page title.
-      // Thus, replace it with the item corresponding to the root path to get
-      // the relevant href and title. For example, the menu item corresponding
-      // to 'admin' is used when on the 'By module' tab at 'admin/by-module'.
-      $parts = explode('/', $item['tab_root']);
-      $args = arg();
-      // Replace wildcards in the root path using the current path.
-      foreach ($parts as $index => $part) {
-        if ($part == '%') {
-          $parts[$index] = $args[$index];
-        }
-      }
-      // Retrieve the menu item using the root path after wildcard replacement.
-      $root_item = menu_get_item(implode('/', $parts));
-      if ($root_item && $root_item['access']) {
-        $item = $root_item;
-      }
+    $trail[] = array(
+      'title' => t('Home'),
+      'href' => '<front>',
+      'link_path' => '',
+      'localized_options' => array(),
+      'type' => 0,
+    );
+
+    // Try to retrieve a menu link corresponding to the current path. If more
+    // than one exists, the link from the most preferred menu is returned.
+    $preferred_link = menu_link_get_preferred();
+    $current_item = menu_get_item();
+
+    // There is a link for the current path.
+    if ($preferred_link) {
+      // Pass TRUE for $only_active_trail to make menu_tree_page_data() build
+      // a stripped down menu tree containing the active trail only, in case
+      // the given menu has not been built in this request yet.
+      $tree = menu_tree_page_data($preferred_link['menu_name'], NULL, TRUE);
+      list($key, $curr) = each($tree);
     }
-    $menu_names = menu_get_active_menu_names();
-    $curr = FALSE;
-    // Determine if the current page is a link in any of the active menus.
-    if ($menu_names) {
-      $query = db_select('menu_links', 'ml');
-      $query->fields('ml', array('menu_name'));
-      $query->condition('ml.link_path', $item['href']);
-      $query->condition('ml.menu_name', $menu_names, 'IN');
-      $result = $query->execute();
-      $found = array();
-      foreach ($result as $menu) {
-        $found[] = $menu->menu_name;
-      }
-      // The $menu_names array is ordered, so take the first one that matches.
-      $found_menu_names = array_intersect($menu_names, $found);
-      $name = current($found_menu_names);
-      if ($name !== FALSE) {
-        $tree = menu_tree_page_data($name);
-        list($key, $curr) = each($tree);
-      }
+    // There is no link for the current path.
+    else {
+      $preferred_link = $current_item;
+      $curr = FALSE;
     }
 
     while ($curr) {
-      // Terminate the loop when we find the current path in the active trail.
-      if ($curr['link']['href'] == $item['href']) {
-        $trail[] = $curr['link'];
-        $curr = FALSE;
-      }
-      else {
-        // Add the link if it's in the active trail, then move to the link below.
-        if ($curr['link']['in_active_trail']) {
-          $trail[] = $curr['link'];
-          $tree = $curr['below'] ? $curr['below'] : array();
+      $link = $curr['link'];
+      if ($link['in_active_trail']) {
+        // Add the link to the trail, unless it links to its parent.
+        if (!($link['type'] & MENU_LINKS_TO_PARENT)) {
+          // The menu tree for the active trail may contain additional links
+          // that have not been translated yet, since they contain dynamic
+          // argument placeholders (%). Such links are not contained in regular
+          // menu trees, and have only been loaded for the additional
+          // translation that happens here, so as to be able to display them in
+          // the breadcumb for the current page.
+          // @see _menu_tree_check_access()
+          // @see _menu_link_translate()
+          if (strpos($link['href'], '%') !== FALSE) {
+            _menu_link_translate($link, TRUE);
+          }
+          if ($link['access']) {
+            $trail[] = $link;
+          }
         }
-        list($key, $curr) = each($tree);
+        $tree = $curr['below'] ? $curr['below'] : array();
       }
+      list($key, $curr) = each($tree);
     }
     // Make sure the current page is in the trail (needed for the page title),
-    // but exclude tabs and the front page.
-    $last = count($trail) - 1;
-    if ($trail[$last]['href'] != $item['href'] && !(bool) ($item['type'] & MENU_IS_LOCAL_TASK) && !drupal_is_front_page()) {
-      $trail[] = $item;
+    // if the link's type allows it to be shown in the breadcrumb. Also exclude
+    // it if we are on the front page.
+    $last = end($trail);
+    if ($last['href'] != $preferred_link['href'] && ($preferred_link['type'] & MENU_VISIBLE_IN_BREADCRUMB) == MENU_VISIBLE_IN_BREADCRUMB && !drupal_is_front_page()) {
+      $trail[] = $preferred_link;
     }
   }
   return $trail;
 }
 
+/**
+ * Lookup the preferred menu link for a given system path.
+ *
+ * @param $path
+ *   The path, for example 'node/5'. The function will find the corresponding
+ *   menu link ('node/5' if it exists, or fallback to 'node/%').
+ *
+ * @return
+ *   A fully translated menu link, or NULL if not matching menu link was
+ *   found. The most specific menu link ('node/5' preferred over 'node/%') in
+ *   the most preferred menu (as defined by menu_get_active_menu_names()) is
+ *   returned.
+ */
+function menu_link_get_preferred($path = NULL) {
+  $preferred_links = &drupal_static(__FUNCTION__);
+
+  if (!isset($path)) {
+    $path = $_GET['q'];
+  }
+
+  if (!isset($preferred_links[$path])) {
+    $preferred_links[$path] = FALSE;
+
+    // Look for the correct menu link by building a list of candidate paths,
+    // which are ordered by priority (translated hrefs are preferred over
+    // untranslated paths). Afterwards, the most relevant path is picked from
+    // the menus, ordered by menu preference.
+    $item = menu_get_item($path);
+    $path_candidates = array();
+    // 1. The current item href.
+    $path_candidates[$item['href']] = $item['href'];
+    // 2. The tab root href of the current item (if any).
+    if ($item['tab_parent'] && ($tab_root = menu_get_item($item['tab_root_href']))) {
+      $path_candidates[$tab_root['href']] = $tab_root['href'];
+    }
+    // 3. The current item path (with wildcards).
+    $path_candidates[$item['path']] = $item['path'];
+    // 4. The tab root path of the current item (if any).
+    if (!empty($tab_root)) {
+      $path_candidates[$tab_root['path']] = $tab_root['path'];
+    }
+
+    // Retrieve a list of menu names, ordered by preference.
+    $menu_names = menu_get_active_menu_names();
+
+    $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
+    $query->leftJoin('menu_router', 'm', 'm.path = ml.router_path');
+    $query->fields('ml');
+    // Weight must be taken from {menu_links}, not {menu_router}.
+    $query->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), array('weight')));
+    $query->condition('ml.menu_name', $menu_names, 'IN');
+    $query->condition('ml.link_path', $path_candidates, 'IN');
+
+    // Sort candidates by link path and menu name.
+    $candidates = array();
+    foreach ($query->execute() as $candidate) {
+      $candidates[$candidate['link_path']][$candidate['menu_name']] = $candidate;
+    }
+
+    // Pick the most specific link, in the most preferred menu.
+    foreach ($path_candidates as $link_path) {
+      if (!isset($candidates[$link_path])) {
+        continue;
+      }
+      foreach ($menu_names as $menu_name) {
+        if (!isset($candidates[$link_path][$menu_name])) {
+          continue;
+        }
+        $candidate_item = $candidates[$link_path][$menu_name];
+        $map = explode('/', $path);
+        _menu_translate($candidate_item, $map);
+        if ($candidate_item['access']) {
+          $preferred_links[$path] = $candidate_item;
+        }
+        break 2;
+      }
+    }
+  }
+
+  return $preferred_links[$path];
+}
+
 /**
  * Gets the active trail (path to root menu root) of the current page.
  *
@@ -2213,6 +2370,8 @@ function menu_get_active_trail() {
 
 /**
  * Get the breadcrumb for the current page, as determined by the active trail.
+ *
+ * @see menu_set_active_trail()
  */
 function menu_get_active_breadcrumb() {
   $breadcrumb = array();
@@ -2223,17 +2382,38 @@ function menu_get_active_breadcrumb() {
   }
 
   $item = menu_get_item();
-  if ($item && $item['access']) {
+  if (!empty($item['access'])) {
     $active_trail = menu_get_active_trail();
 
-    foreach ($active_trail as $parent) {
-      $breadcrumb[] = l($parent['title'], $parent['href'], $parent['localized_options']);
-    }
-    $end = end($active_trail);
+    // Allow modules to alter the breadcrumb, if possible, as that is much
+    // faster than rebuilding an entirely new active trail.
+    drupal_alter('menu_breadcrumb', $active_trail, $item);
 
     // Don't show a link to the current page in the breadcrumb trail.
-    if ($item['href'] == $end['href'] || (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT && $end['href'] != '<front>')) {
-      array_pop($breadcrumb);
+    $end = end($active_trail);
+    if ($item['href'] == $end['href']) {
+      array_pop($active_trail);
+    }
+
+    // Remove the tab root (parent) if the current path links to its parent.
+    // Normally, the tab root link is included in the breadcrumb, as soon as we
+    // are on a local task or any other child link. However, if we are on a
+    // default local task (e.g., node/%/view), then we do not want the tab root
+    // link (e.g., node/%) to appear, as it would be identical to the current
+    // page. Since this behavior also needs to work recursively (i.e., on
+    // default local tasks of default local tasks), and since the last non-task
+    // link in the trail is used as page title (see menu_get_active_title()),
+    // this condition cannot be cleanly integrated into menu_get_active_trail().
+    // menu_get_active_trail() already skips all links that link to their parent
+    // (commonly MENU_DEFAULT_LOCAL_TASK). In order to also hide the parent link
+    // itself, we always remove the last link in the trail, if the current
+    // router item links to its parent.
+    if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
+      array_pop($active_trail);
+    }
+
+    foreach ($active_trail as $parent) {
+      $breadcrumb[] = l($parent['title'], $parent['href'], $parent['localized_options']);
     }
   }
   return $breadcrumb;
@@ -2319,6 +2499,7 @@ function menu_reset_static_cache() {
   drupal_static_reset('menu_tree_all_data');
   drupal_static_reset('menu_tree_page_data');
   drupal_static_reset('menu_load_all');
+  drupal_static_reset('menu_link_get_preferred');
 }
 
 /**
@@ -3167,6 +3348,7 @@ function _menu_router_build($callbacks) {
       'title' => '',
       'weight' => 0,
       'type' => MENU_NORMAL_ITEM,
+      'module' => '',
       '_number_parts' => $number_parts,
       '_parts' => $parts,
       '_fit' => $fit,
@@ -3296,7 +3478,6 @@ function _menu_router_build($callbacks) {
       'file' => '',
       'file path' => '',
       'include file' => '',
-      'module' => '',
     );
 
     // Calculate out the file to be included for each callback, if any.
diff --git a/includes/module.inc b/includes/module.inc
index 25059bfba38f4879c901f785715a46e5bdc33db5..e75fdc7d6617c19a34d8bd98ef820c0b4fc006b3 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: module.inc,v 1.198 2010/09/03 19:49:55 dries Exp $
+// $Id: module.inc,v 1.202 2010/10/03 02:04:55 dries Exp $
 
 /**
  * @file
@@ -65,9 +65,11 @@ function module_list($refresh = FALSE, $bootstrap = FALSE, $sort = FALSE, $fixed
       }
     }
     else {
-      // As this is the $refresh case, make sure that system_list() returns
-      // fresh data.
-      drupal_static_reset('system_list');
+      if ($refresh) {
+        // For the $refresh case, make sure that system_list() returns fresh
+        // data.
+        drupal_static_reset('system_list');
+      }
       if ($bootstrap) {
         $list = system_list('bootstrap');
       }
@@ -405,8 +407,19 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
       // Now install the module if necessary.
       if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) {
         drupal_install_schema($module);
+
+        // Set the schema version to the number of the last update provided
+        // by the module.
         $versions = drupal_get_schema_versions($module);
-        drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED);
+        $version = $versions ? max($versions) : SCHEMA_INSTALLED;
+
+        // If the module has no current updates, but has some that were
+        // previously removed, set the version to the value of
+        // hook_update_last_removed().
+        if ($last_removed = module_invoke($module, 'update_last_removed')) {
+          $version = max($version, $last_removed);
+        }
+        drupal_set_installed_schema_version($module, $version);
         // Allow the module to perform install tasks.
         module_invoke($module, 'install');
         // Record the fact that it was installed.
@@ -819,7 +832,7 @@ function drupal_required_modules() {
  * @endcode
  *
  * @param $type
- *   A string describing the data type of the alterable $data. 'form', 'links',
+ *   A string describing the type of the alterable $data. 'form', 'links',
  *   'node_content', and so on are several examples. Alternatively can be an
  *   array, in which case hook_TYPE_alter() is invoked for each value in the
  *   array, ordered first by module, and then for each module, in the order of
@@ -827,13 +840,16 @@ function drupal_required_modules() {
  *   execute both hook_form_alter() and hook_form_FORM_ID_alter()
  *   implementations, it passes array('form', 'form_' . $form_id) for $type.
  * @param &$data
- *   The primary data to be altered.
+ *   The variable that will be passed to hook_TYPE_alter() implementations to be
+ *   altered. The type of this variable depends on the value of the $type
+ *   argument. For example, when altering a 'form', $data will be a structured
+ *   array. When altering a 'profile', $data will be an object.
  * @param &$context1
  *   (optional) An additional variable that is passed by reference.
  * @param &$context2
  *   (optional) An additional variable that is passed by reference. If more
  *   context needs to be provided to implementations, then this should be an
- *   keyed array as described above.
+ *   associative array as described above.
  */
 function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) {
   // Use the advanced drupal_static() pattern, since this is called very often.
diff --git a/includes/pager.inc b/includes/pager.inc
index 4934cc1ea5e30bd4d58f1a79ea79e189757e456a..8ca44a07ac54b3bd178e3484ba011ef1404479c1 100644
--- a/includes/pager.inc
+++ b/includes/pager.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: pager.inc,v 1.82 2010/09/09 23:18:30 webchick Exp $
+// $Id: pager.inc,v 1.84 2010/10/06 13:38:39 dries Exp $
 
 /**
  * @file
@@ -117,7 +117,7 @@ class PagerDefault extends SelectQueryExtender {
    * @return SelectQueryInterface
    *   A count query object.
    */
-  protected function getCountQuery() {
+  public function getCountQuery() {
     if ($this->customCountQuery) {
       return $this->customCountQuery;
     }
@@ -420,7 +420,10 @@ function theme_pager($variables) {
         'data' => $li_last,
       );
     }
-    return '<h2 class="element-invisible">' . t('Pages') . '</h2>' . theme('item_list', array('items' => $items, 'title' => NULL, 'type' => 'ul', 'attributes' => array('class' => array('pager'))));
+    return '<h2 class="element-invisible">' . t('Pages') . '</h2>' . theme('item_list', array(
+      'items' => $items,
+      'attributes' => array('class' => array('pager')),
+    ));
   }
 }
 
diff --git a/includes/registry.inc b/includes/registry.inc
index 9b9a2414f5603987a1d79013b6815b6ae53786e4..b0faf2590d463bf5275510d6e20228ba2bb19b4b 100644
--- a/includes/registry.inc
+++ b/includes/registry.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: registry.inc,v 1.33 2010/07/10 01:57:32 dries Exp $
+// $Id: registry.inc,v 1.34 2010/09/17 14:45:46 dries Exp $
 
 /**
  * @file
@@ -165,7 +165,7 @@ function _registry_parse_files($files) {
  *   (optional) Weight of the module.
  */
 function _registry_parse_file($filename, $contents, $module = '', $weight = 0) {
-  if (preg_match_all('/^\s*(?:abstract)?\s*(class|interface)\s+([a-zA-Z0-9_]+)/m', $contents, $matches)) {
+  if (preg_match_all('/^\s*(?:abstract|final)?\s*(class|interface)\s+([a-zA-Z0-9_]+)/m', $contents, $matches)) {
     $query = db_insert('registry')->fields(array('name', 'type', 'filename', 'module', 'weight'));
     foreach ($matches[2] as $key => $name) {
       $query->values(array(
diff --git a/includes/session.inc b/includes/session.inc
index f4dd1a8f9803c407daccfbfc465337a66a80c6de..2a11b090fa26ceb05354b562fa7f968ceebe16ec 100644
--- a/includes/session.inc
+++ b/includes/session.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: session.inc,v 1.88 2010/07/16 02:53:02 dries Exp $
+// $Id: session.inc,v 1.89 2010/09/17 14:56:27 dries Exp $
 
 /**
  * @file
@@ -311,8 +311,9 @@ function drupal_session_regenerate() {
     }
     $params = session_get_cookie_params();
     $session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
-    // If the session cookie lifetime is set, the session will expire $params['lifetime'] seconds from the current request.
-    // If it is not set, it will expire when the browser is closed.
+    // If a session cookie lifetime is set, the session will expire
+    // $params['lifetime'] seconds from the current request. If it is not set,
+    // it will expire when the browser is closed.
     $expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0;
     setcookie($insecure_session_name, $session_id, $expire, $params['path'], $params['domain'], FALSE, $params['httponly']);
     $_COOKIE[$insecure_session_name] = $session_id;
diff --git a/includes/theme.inc b/includes/theme.inc
index 658128c1099491f6293fcd48a12223e3ca9972b9..de781acfda25ea414a662a52749272d3f61eed19 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: theme.inc,v 1.611 2010/09/14 21:42:05 dries Exp $
+// $Id: theme.inc,v 1.618 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @file
@@ -102,6 +102,15 @@ function drupal_theme_initialize() {
 
   // Themes can have alter functions, so reset the drupal_alter() cache.
   drupal_static_reset('drupal_alter');
+
+  // Provide the page with information about the theme that's used, so that a
+  // later AJAX request can be rendered using the same theme.
+  // @see ajax_base_page_theme()
+  $setting['ajaxPageState'] = array(
+    'theme' => $theme_key,
+    'themeToken' => drupal_get_token($theme_key),
+  );
+  drupal_add_js($setting, 'setting');
 }
 
 /**
@@ -164,7 +173,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
   // And now add the stylesheets properly
   foreach ($final_stylesheets as $media => $stylesheets) {
     foreach ($stylesheets as $stylesheet) {
-      drupal_add_css($stylesheet, array('weight' => CSS_THEME, 'media' => $media, 'preprocess' => TRUE));
+      drupal_add_css($stylesheet, array('group' => CSS_THEME, 'every_page' => TRUE, 'media' => $media));
     }
   }
 
@@ -189,7 +198,7 @@ function _drupal_theme_initialize($theme, $base_theme = array(), $registry_callb
 
   // Add scripts used by this theme.
   foreach ($final_scripts as $script) {
-    drupal_add_js($script, array('weight' => JS_THEME, 'preprocess' => TRUE));
+    drupal_add_js($script, array('group' => JS_THEME, 'every_page' => TRUE));
   }
 
   $theme_engine = NULL;
@@ -581,11 +590,7 @@ function list_themes($refresh = FALSE) {
     // Also check that the site is not in the middle of an install or update.
     if (!defined('MAINTENANCE_MODE')) {
       try {
-        foreach (system_list('theme') as $theme) {
-          if (file_exists($theme->filename)) {
-            $themes[] = $theme;
-          }
-        }
+        $themes = system_list('theme');
       }
       catch (Exception $e) {
         // If the database is not available, rebuild the theme data.
@@ -870,6 +875,7 @@ function theme($hook, $variables = array()) {
   }
 
   // Generate the output using either a function or a template.
+  $output = '';
   if (isset($info['function'])) {
     if (function_exists($info['function'])) {
       $output = $info['function']($variables);
@@ -1118,7 +1124,7 @@ function theme_get_setting($setting_name, $theme = NULL) {
   $cache = &drupal_static(__FUNCTION__, array());
 
   // If no key is given, use the current theme if we can determine it.
-  if (is_null($theme)) {
+  if (!isset($theme)) {
     $theme = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : '';
   }
 
@@ -1479,6 +1485,8 @@ function theme_links($variables) {
  *   An associative array containing:
  *   - path: Either the path of the image file (relative to base_path()) or a
  *     full URL.
+ *   - width: The width of the image (if known).
+ *   - height: The height of the image (if known).
  *   - alt: The alternative text for text-based browsers. HTML 4 and XHTML 1.0
  *     always require an alt attribute. The HTML 5 draft allows the alt
  *     attribute to be omitted in some cases. Therefore, this variable defaults
@@ -1492,38 +1500,19 @@ function theme_links($variables) {
  *   - title: The title text is displayed when the image is hovered in some
  *     popular browsers.
  *   - attributes: Associative array of attributes to be placed in the img tag.
- *   - getsize: If set to TRUE, the image's dimension are fetched and added as
- *     width/height attributes.
  */
 function theme_image($variables) {
-  $path = $variables['path'];
-  $alt = $variables['alt'];
-  $title = $variables['title'];
   $attributes = $variables['attributes'];
-  $getsize = $variables['getsize'];
+  $attributes['src'] = file_create_url($variables['path']);
 
-  if (!$getsize || (is_file($path) && (list($width, $height) = @getimagesize($path)))) {
-    // The src attribute can be omitted, by passing NULL for $path and FALSE for
-    // $getsize.
-    if (isset($path)) {
-      $attributes['src'] = file_create_url($path);
-    }
-    // The alt attribute defaults to an empty string. By passing NULL as value,
-    // it can be omitted.
-    if (isset($alt)) {
-      $attributes['alt'] = $alt;
-    }
-    if (isset($title)) {
-      $attributes['title'] = $title;
-    }
-    if (!isset($attributes['width']) && !empty($width)) {
-      $attributes['width'] = $width;
-    }
-    if (!isset($attributes['height']) && !empty($height)) {
-      $attributes['height'] = $height;
+  foreach (array('width', 'height', 'alt', 'title') as $key) {
+
+    if (isset($variables[$key])) {
+      $attributes[$key] = $variables[$key];
     }
-    return '<img' . drupal_attributes($attributes) . ' />';
   }
+
+  return '<img' . drupal_attributes($attributes) . ' />';
 }
 
 /**
@@ -2257,7 +2246,6 @@ function template_preprocess_page(&$variables) {
 
   $variables['base_path']         = base_path();
   $variables['front_page']        = url();
-  $variables['breadcrumb']        = theme('breadcrumb', array('breadcrumb' => drupal_get_breadcrumb()));
   $variables['feed_icons']        = drupal_get_feeds();
   $variables['language']          = $GLOBALS['language'];
   $variables['language']->dir     = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
@@ -2269,7 +2257,6 @@ function template_preprocess_page(&$variables) {
   $variables['site_name']         = (theme_get_setting('toggle_name') ? filter_xss_admin(variable_get('site_name', 'Drupal')) : '');
   $variables['site_slogan']       = (theme_get_setting('toggle_slogan') ? filter_xss_admin(variable_get('site_slogan', '')) : '');
   $variables['tabs']              = theme('menu_local_tasks');
-  $variables['title']             = drupal_get_title();
 
   if ($node = menu_get_object()) {
     $variables['node'] = $node;
@@ -2281,6 +2268,28 @@ function template_preprocess_page(&$variables) {
   }
 }
 
+/**
+ * Process variables for page.tpl.php
+ *
+ * Perform final addition of variables before passing them into the template.
+ * To customize these variables, simply set them in an earlier step.
+ *
+ * @see template_preprocess_page()
+ * @see page.tpl.php
+ */
+function template_process_page(&$variables) {
+  if (!isset($variables['breadcrumb'])) {
+    // Build the breadcrumb last, so as to increase the chance of being able to
+    // re-use the cache of an already rendered menu containing the active link
+    // for the current page.
+    // @see menu_tree_page_data()
+    $variables['breadcrumb'] = theme('breadcrumb', array('breadcrumb' => drupal_get_breadcrumb()));
+  }
+  if (!isset($variables['title'])) {
+    $variables['title'] = drupal_get_title();
+  }
+}
+
 /**
  * Process variables for html.tpl.php
  *
diff --git a/includes/theme.maintenance.inc b/includes/theme.maintenance.inc
index 815e314e8ca7950b996a765b2d79b1afbba00294..56d8b5487ae377aaed949a006ce4b4886410fff3 100644
--- a/includes/theme.maintenance.inc
+++ b/includes/theme.maintenance.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: theme.maintenance.inc,v 1.66 2010/09/09 15:47:03 webchick Exp $
+// $Id: theme.maintenance.inc,v 1.67 2010/09/19 18:10:41 dries Exp $
 
 /**
  * @file
@@ -77,12 +77,13 @@ function _drupal_maintenance_theme() {
 
   // These are usually added from system_init() -except maintenance.css.
   // When the database is inactive it's not called so we add it here.
-  drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
-  drupal_add_css(drupal_get_path('module', 'system') . '/system-behavior.css');
-  drupal_add_css(drupal_get_path('module', 'system') . '/system-menus.css');
-  drupal_add_css(drupal_get_path('module', 'system') . '/system-messages.css');
-  drupal_add_css(drupal_get_path('module', 'system') . '/maintenance.css');
-  drupal_add_css(drupal_get_path('module', 'system') . '/admin.css');
+  $path = drupal_get_path('module', 'system');
+  drupal_add_css($path . '/system.base.css');
+  drupal_add_css($path . '/system.admin.css');
+  drupal_add_css($path . '/system.menus.css');
+  drupal_add_css($path . '/system.messages.css');
+  drupal_add_css($path . '/system.theme.css');
+  drupal_add_css($path . '/system.maintenance.css');
 }
 
 /**
diff --git a/includes/unl_bootstrap.inc b/includes/unl_bootstrap.inc
new file mode 100644
index 0000000000000000000000000000000000000000..41949dd9f6821709afe4914c5f1baa9ab1d8fe8f
--- /dev/null
+++ b/includes/unl_bootstrap.inc
@@ -0,0 +1,39 @@
+<?php
+
+function unl_bootstrap() {
+  $original_script_name = $_SERVER['SCRIPT_NAME'];
+  $php_file = basename($original_script_name);
+  
+  $request_uri = parse_url($_SERVER['REQUEST_URI']);
+  $path_parts = explode('/', $request_uri['path']);
+  foreach ($path_parts as $path_index => $path_part) {
+    if (!$path_part) {
+      unset($path_parts[$path_index]);
+    }
+  }
+  
+  $previous_conf_path = '';
+  $previous_script_name = '';
+  for ($i = count($path_parts); $i >= 0; $i--) {
+    if ($i == 0) {
+      $_SERVER['SCRIPT_NAME'] = '/' . $php_file;
+    }
+    else {
+      $_SERVER['SCRIPT_NAME'] = '/' . implode('/', array_slice($path_parts, 0, $i)) . '/' . $php_file;
+    }
+    $conf_path = conf_path(TRUE, TRUE);
+    
+    if ($previous_conf_path && ($conf_path != $previous_conf_path)) {
+      $_SERVER['SCRIPT_NAME'] = $previous_script_name;
+      break;
+    }
+    
+    if ($_SERVER['SCRIPT_NAME'] == $original_script_name) {
+      break;
+    }
+    $previous_conf_path = $conf_path;
+    $previous_script_name = $_SERVER['SCRIPT_NAME'];
+  }
+  
+  conf_path(TRUE, TRUE);
+}
diff --git a/includes/update.inc b/includes/update.inc
index 3fe43e1d308458564257c895b5d8029197550582..f68f0c5f3799855af9b480fecdbad7af2b0aad8a 100644
--- a/includes/update.inc
+++ b/includes/update.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.inc,v 1.67 2010/09/13 05:50:08 webchick Exp $
+// $Id: update.inc,v 1.76 2010/10/06 21:51:10 webchick Exp $
 
 /**
  * @file
@@ -9,6 +9,16 @@
  * installation. It is included and used extensively by update.php.
  */
 
+/**
+ * Minimum schema version of Drupal 6 required for upgrade to Drupal 7.
+ *
+ * Upgrades from Drupal 6 to Drupal 7 require that Drupal 6 be running
+ * the most recent version, or the upgrade could fail. We can't easily
+ * check the Drupal 6 version once the update process has begun, so instead
+ * we check the schema version of system.module in the system table.
+ */
+define('REQUIRED_D6_SCHEMA_VERSION', '6055');
+
 /**
  * Disable any items in the {system} table that are not core compatible.
  */
@@ -120,6 +130,24 @@ function update_prepare_d7_bootstrap() {
   // created yet.
   drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
 
+  // If the site has not updated to Drupal 7 yet, check to make sure that it is
+  // running an up-to-date version of Drupal 6 before proceeding. Note this has
+  // to happen AFTER the database bootstraps because of
+  // drupal_get_installed_schema_version().
+  $system_schema = drupal_get_installed_schema_version('system');
+  if ($system_schema < 7000) {
+    $has_required_schema = $system_schema >= REQUIRED_D6_SCHEMA_VERSION;
+    $requirements = array(
+      'drupal 6 version' => array(
+        'title' => 'Drupal 6 version',
+        'value' => $has_required_schema ? 'You are running a current version of Drupal 6.' : 'You are not running a current version of Drupal 6',
+        'severity' => $has_required_schema ? REQUIREMENT_OK : REQUIREMENT_ERROR,
+        'description' => $has_required_schema ? '' : 'Please update your Drupal 6 installation to the most recent version before attempting to upgrade to Drupal 7',
+      ),
+    );
+    update_extra_requirements($requirements);
+  }
+
   // Create the registry tables.
   if (!db_table_exists('registry')) {
     $schema['registry'] = array(
@@ -148,6 +176,43 @@ function update_prepare_d7_bootstrap() {
     db_create_table('registry_file', $schema['registry_file']);
   }
 
+  // Older versions of Drupal 6 do not include the semaphore table, which is 
+  // required to bootstrap, so we add it now so that we can bootstrap and
+  // provide a reasonable error message.
+  if (!db_table_exists('semaphore')) {
+    $semaphore = array(
+      'description' => 'Table for holding semaphores, locks, flags, etc. that cannot be stored as Drupal variables since they must not be cached.',
+      'fields' => array(
+        'name' => array(
+          'description' => 'Primary Key: Unique name.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => ''
+        ),
+        'value' => array(
+          'description' => 'A value for the semaphore.',
+          'type' => 'varchar',
+          'length' => 255,
+          'not null' => TRUE,
+          'default' => ''
+        ),
+        'expire' => array(
+          'description' => 'A Unix timestamp with microseconds indicating when the semaphore should expire.',
+          'type' => 'float',
+          'size' => 'big',
+          'not null' => TRUE
+        ),
+      ),
+      'indexes' => array(
+        'value' => array('value'),
+        'expire' => array('expire'),
+      ),
+      'primary key' => array('name'),
+    );
+    db_create_table('semaphore', $semaphore);
+  }
+
   // The new cache_bootstrap bin is required to bootstrap to
   // DRUPAL_BOOTSTRAP_SESSION, so create it here rather than in
   // update_fix_d7_requirements().
@@ -295,6 +360,7 @@ function update_fix_d7_block_deltas(&$sandbox, $renamed_deltas, $moved_deltas) {
   $result = db_select('users', 'u')
     ->fields('u', array('uid', 'data'))
     ->condition('uid', $sandbox['last_user_processed'], '>')
+    ->orderBy('uid', 'ASC')
     ->where('data IS NOT NULL')
     ->range(0, $limit)
     ->execute();
@@ -436,7 +502,7 @@ function update_fix_d7_requirements() {
     db_create_table('role_permission', $schema['role_permission']);
 
     // Drops and recreates semaphore value index.
-    db_drop_index('semaphore', 'expire');
+    db_drop_index('semaphore', 'value');
     db_add_index('semaphore', 'value', array('value'));
 
     $schema['date_format_type'] = array(
@@ -637,6 +703,9 @@ function update_fix_d7_requirements() {
       db_change_field('languages', 'javascript', 'javascript', array('type' => 'varchar', 'length' => 64, 'not null' => TRUE, 'default' => ''));
     }
 
+    // Rename action description to label.
+    db_change_field('actions', 'description', 'label', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '0'));
+
     variable_set('update_d7_requirements', TRUE);
   }
 
@@ -672,7 +741,6 @@ function update_fix_d7_install_profile() {
     // Merge in defaults.
     $info = $info + array(
       'dependencies' => array(),
-      'dependents' => array(),
       'description' => '',
       'package' => 'Other',
       'version' => NULL,
@@ -790,16 +858,9 @@ function update_do_one($module, $number, $dependency_map, &$context) {
     return;
   }
 
-  if (!isset($context['log'])) {
-    $context['log'] = variable_get('update_log_queries', 0);
-  }
-
   $ret = array();
   if (function_exists($function)) {
     try {
-      if ($context['log']) {
-        Database::startLog($function);
-      }
       $ret['results']['query'] = $function($context['sandbox']);
       $ret['results']['success'] = TRUE;
     }
@@ -813,10 +874,6 @@ function update_do_one($module, $number, $dependency_map, &$context) {
       $variables = _drupal_decode_exception($e);
       $ret['#abort'] = array('success' => FALSE, 'query' => t('%type: %message in %function (line %line of %file).', $variables));
     }
-
-    if ($context['log']) {
-      $ret['queries'] = Database::getLog($function);
-    }
   }
 
   if (isset($context['sandbox']['#finished'])) {
diff --git a/includes/xmlrpcs.inc b/includes/xmlrpcs.inc
index 0976e1054737f098365661eb3a80aac598eac108..b1b2f9f26732e9de347cd43d28e56327cbf1cbf4 100644
--- a/includes/xmlrpcs.inc
+++ b/includes/xmlrpcs.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: xmlrpcs.inc,v 1.41 2010/07/31 04:17:34 dries Exp $
+// $Id: xmlrpcs.inc,v 1.42 2010/10/02 01:22:41 dries Exp $
 
 /**
  * @file
@@ -45,7 +45,9 @@ function xmlrpc_server($callbacks) {
   // We build an array of all method names by combining the built-ins
   // with those defined by modules implementing the _xmlrpc hook.
   // Built-in methods are overridable.
-  foreach (array_merge($defaults, (array) $callbacks) as $key => $callback) {
+  $callbacks = array_merge($defaults, (array) $callbacks);
+  drupal_alter('xmlrpc', $callbacks);
+  foreach ($callbacks as $key => $callback) {
     // we could check for is_array($callback)
     if (is_int($key)) {
       $method = $callback[0];
diff --git a/index.php b/index.php
index c7d323b49714b52a4cdb6217ff659f712d640a7a..ea72099b49f7e8b6e23d91e10ff9cda9b98984f7 100644
--- a/index.php
+++ b/index.php
@@ -17,6 +17,8 @@
  */
 define('DRUPAL_ROOT', getcwd());
 
+require_once DRUPAL_ROOT . '/includes/unl_bootstrap.inc';
 require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
+unl_bootstrap();
 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 menu_execute_active_handler();
diff --git a/misc/ajax.js b/misc/ajax.js
index 553d2ccf5d7161252b6e1caf4dd8a1ce978dd815..01a90ef116dc4f284f197d54fda5588ed07b6d6c 100644
--- a/misc/ajax.js
+++ b/misc/ajax.js
@@ -1,4 +1,4 @@
-// $Id: ajax.js,v 1.18 2010/06/25 20:34:07 dries Exp $
+// $Id: ajax.js,v 1.23 2010/10/06 18:27:09 webchick Exp $
 (function ($) {
 
 /**
@@ -55,7 +55,13 @@ Drupal.behaviors.AJAX = {
       // AJAX submits specified in this manner automatically submit to the
       // normal form action.
       element_settings.url = $(this.form).attr('action');
-      element_settings.set_click = TRUE;
+      // Form submit button clicks need to tell the form what was clicked so
+      // it gets passed in the POST request.
+      element_settings.setClick = true;
+      // Form buttons use the 'click' event rather than mousedown.
+      element_settings.event = 'click';
+      // Clicked form buttons look better with the throbber than the progress bar.
+      element_settings.progress = { 'type': 'throbber' };
 
       var base = $(this).attr('id');
       Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings);
@@ -98,7 +104,9 @@ Drupal.ajax = function (base, element, element_settings) {
       type: 'bar',
       message: 'Please wait...'
     },
-    submit: {}
+    submit: {
+      'js': true
+    }
   };
 
   $.extend(this, defaults, element_settings);
@@ -119,13 +127,14 @@ Drupal.ajax = function (base, element, element_settings) {
   // Set the options for the ajaxSubmit function.
   // The 'this' variable will not persist inside of the options object.
   var ajax = this;
-  var options = {
+  ajax.options = {
     url: ajax.url,
     data: ajax.submit,
     beforeSerialize: function (element_settings, options) {
       return ajax.beforeSerialize(element_settings, options);
     },
     beforeSubmit: function (form_values, element_settings, options) {
+      ajax.ajaxing = true;
       return ajax.beforeSubmit(form_values, element_settings, options);
     },
     success: function (response, status) {
@@ -137,6 +146,7 @@ Drupal.ajax = function (base, element, element_settings) {
       return ajax.success(response, status);
     },
     complete: function (response, status) {
+      ajax.ajaxing = false;
       if (status == 'error' || status == 'parsererror') {
         return ajax.error(response, ajax.url);
       }
@@ -147,21 +157,30 @@ Drupal.ajax = function (base, element, element_settings) {
 
   // Bind the ajaxSubmit function to the element event.
   $(this.element).bind(element_settings.event, function () {
-    if (ajax.form) {
-      // If setClick is set, we must set this to ensure that the button's
-      // value is passed.
-      if (ajax.setClick) {
-        // Mark the clicked button. 'form.clk' is a special variable for
-        // ajaxSubmit that tells the system which element got clicked to
-        // trigger the submit. Without it there would be no 'op' or
-        // equivalent.
-        ajax.form.clk = this.element;
-      }
+    if (ajax.ajaxing) {
+      return false;
+    }
 
-      ajax.form.ajaxSubmit(options);
+    try {
+      if (ajax.form) {
+        // If setClick is set, we must set this to ensure that the button's
+        // value is passed.
+        if (ajax.setClick) {
+          // Mark the clicked button. 'form.clk' is a special variable for
+          // ajaxSubmit that tells the system which element got clicked to
+          // trigger the submit. Without it there would be no 'op' or
+          // equivalent.
+          this.form.clk = this;
+        }
+
+        ajax.form.ajaxSubmit(ajax.options);
+      }
+      else {
+        $.ajax(ajax.options);
+      }
     }
-    else {
-      $.ajax(options);
+    catch (e) {
+      alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message);
     }
 
     return false;
@@ -212,6 +231,17 @@ Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) {
     form_values.push({ name: 'ajax_html_ids[]', value: this.id });
   });
 
+  // Allow Drupal to return new JavaScript and CSS files to load without
+  // returning the ones already loaded.
+  form_values.push({ name: 'ajax_page_state[theme]', value: Drupal.settings.ajaxPageState.theme });
+  form_values.push({ name: 'ajax_page_state[theme_token]', value: Drupal.settings.ajaxPageState.themeToken });
+  for (var key in Drupal.settings.ajaxPageState.css) {
+    form_values.push({ name: 'ajax_page_state[css][' + key + ']', value: 1 });
+  }
+  for (var key in Drupal.settings.ajaxPageState.js) {
+    form_values.push({ name: 'ajax_page_state[js][' + key + ']', value: 1 });
+  }
+
   // Insert progressbar or throbber.
   if (this.progress.type == 'bar') {
     var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.id, eval(this.progress.update_callback), this.progress.method, eval(this.progress.error_callback));
@@ -335,9 +365,27 @@ Drupal.ajax.prototype.commands = {
     var method = response.method || ajax.method;
     var effect = ajax.getEffect(response);
 
-    // Manually insert HTML into the jQuery object, using $() directly crashes
-    // Safari with long string lengths. http://dev.jquery.com/ticket/3178
-    var new_content = $('<div></div>').html(response.data);
+    // We don't know what response.data contains: it might be a string of text
+    // without HTML, so don't rely on jQuery correctly iterpreting
+    // $(response.data) as new HTML rather than a CSS selector. Also, if
+    // response.data contains top-level text nodes, they get lost with either
+    // $(response.data) or $('<div></div>').replaceWith(response.data).
+    var new_content_wrapped = $('<div></div>').html(response.data);
+    var new_content = new_content_wrapped.contents();
+
+    // For legacy reasons, the effects processing code assumes that new_content
+    // consists of a single top-level element. Also, it has not been
+    // sufficiently tested whether attachBehaviors() can be successfully called
+    // with a context object that includes top-level text nodes. However, to
+    // give developers full control of the HTML appearing in the page, and to
+    // enable AJAX content to be inserted in places where DIV elements are not
+    // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new
+    // content satisfies the requirement of a single top-level element, and
+    // only use the container DIV created above when it doesn't. For more
+    // information, please see http://drupal.org/node/736066.
+    if (new_content.length != 1 || new_content.get(0).nodeType != 1) {
+      new_content = new_content_wrapped;
+    }
 
     // If removing content from the wrapper, detach behaviors first.
     switch (method) {
diff --git a/modules/aggregator/aggregator.info b/modules/aggregator/aggregator.info
index 8a960a82dde0328584da3ad2c1827ae5a9efa374..6134004950aed4d1c05a4575d6be7a16970cfb5a 100644
--- a/modules/aggregator/aggregator.info
+++ b/modules/aggregator/aggregator.info
@@ -15,8 +15,8 @@ files[] = aggregator.test
 configure = admin/config/services/aggregator/settings
 stylesheets[all][] = aggregator.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module
index 0ebbc0a3f0840573c5b6b7c24a50da33a10508e1..21b21f87cf4c3e45c5c3bbbc8b6385ee00ac5dc0 100644
--- a/modules/aggregator/aggregator.module
+++ b/modules/aggregator/aggregator.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: aggregator.module,v 1.443 2010/09/05 02:21:38 dries Exp $
+// $Id: aggregator.module,v 1.444 2010/09/24 00:37:41 dries Exp $
 
 /**
  * @file
@@ -134,7 +134,6 @@ function aggregator_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_admin_remove_feed', 5),
     'access arguments' => array('administer news feeds'),
-    'type' => MENU_CALLBACK,
     'file' => 'aggregator.admin.inc',
   );
   $items['admin/config/services/aggregator/update/%aggregator_feed'] = array(
@@ -142,7 +141,6 @@ function aggregator_menu() {
     'page callback' => 'aggregator_admin_refresh_feed',
     'page arguments' => array(5),
     'access arguments' => array('administer news feeds'),
-    'type' => MENU_CALLBACK,
     'file' => 'aggregator.admin.inc',
   );
   $items['admin/config/services/aggregator/list'] = array(
@@ -227,7 +225,6 @@ function aggregator_menu() {
     'page callback' => 'aggregator_page_source',
     'page arguments' => array(2),
     'access arguments' => array('access news feeds'),
-    'type' => MENU_CALLBACK,
     'file' => 'aggregator.pages.inc',
   );
   $items['aggregator/sources/%aggregator_feed/view'] = array(
@@ -257,7 +254,6 @@ function aggregator_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_form_feed', 6),
     'access arguments' => array('administer news feeds'),
-    'type' => MENU_CALLBACK,
     'file' => 'aggregator.admin.inc',
   );
   $items['admin/config/services/aggregator/edit/category/%aggregator_category'] = array(
@@ -265,7 +261,6 @@ function aggregator_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_form_category', 6),
     'access arguments' => array('administer news feeds'),
-    'type' => MENU_CALLBACK,
     'file' => 'aggregator.admin.inc',
   );
 
diff --git a/modules/aggregator/aggregator.pages.inc b/modules/aggregator/aggregator.pages.inc
index 9e355fc25e6d561181ee0b2102a24fd2a50b6972..0f5e850c2609f25651b3e5ac04a934b090205dbf 100644
--- a/modules/aggregator/aggregator.pages.inc
+++ b/modules/aggregator/aggregator.pages.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: aggregator.pages.inc,v 1.43 2010/08/03 02:02:01 dries Exp $
+// $Id: aggregator.pages.inc,v 1.44 2010/10/06 13:38:39 dries Exp $
 
 /**
  * @file
@@ -268,7 +268,7 @@ function theme_aggregator_categorize_items($variables) {
  * @see aggregator-wrapper.tpl.php
  */
 function template_preprocess_aggregator_wrapper(&$variables) {
-  $variables['pager'] = theme('pager', array('tags' => NULL));
+  $variables['pager'] = theme('pager');
 }
 
 /**
diff --git a/modules/aggregator/aggregator.processor.inc b/modules/aggregator/aggregator.processor.inc
index 8d32ef02cb607d95a7f2f6da1982e14ee4e91f2e..fec66e244db035f84e3dc7aed7f3be571a2a2d18 100644
--- a/modules/aggregator/aggregator.processor.inc
+++ b/modules/aggregator/aggregator.processor.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: aggregator.processor.inc,v 1.12 2009/12/04 16:49:45 dries Exp $
+// $Id: aggregator.processor.inc,v 1.14 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -70,7 +70,7 @@ function aggregator_aggregator_remove($feed) {
 function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
   if (in_array('aggregator', variable_get('aggregator_processors', array('aggregator')))) {
     $info = module_invoke('aggregator', 'aggregator_process', 'info');
-    $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
+    $items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
     $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
     $period[AGGREGATOR_CLEAR_NEVER] = t('Never');
 
@@ -90,8 +90,9 @@ function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
 
     $form['modules']['aggregator']['aggregator_summary_items'] = array(
       '#type' => 'select',
-      '#title' => t('Number of items shown in listing pages') ,
+      '#title' => t('Number of items shown in listing pages'),
       '#default_value' => variable_get('aggregator_summary_items', 3),
+      '#empty_value' => 0,
       '#options' => $items,
     );
 
diff --git a/modules/aggregator/tests/aggregator_test.info b/modules/aggregator/tests/aggregator_test.info
index 419bf4f1f00120a082818febb3263ebd336e2bdc..065cebd48d310ac459db1ee10f7f5b7d3d6152bf 100644
--- a/modules/aggregator/tests/aggregator_test.info
+++ b/modules/aggregator/tests/aggregator_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = aggregator_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/block/block.admin.inc b/modules/block/block.admin.inc
index c2923305881a4cbff982d4880ebcb8c6eadda012..4a51eaee014a5498c15dad38e98b93c8617d9603 100644
--- a/modules/block/block.admin.inc
+++ b/modules/block/block.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: block.admin.inc,v 1.86 2010/08/30 00:22:03 webchick Exp $
+// $Id: block.admin.inc,v 1.89 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -85,9 +85,6 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r
     $block_regions = system_region_list($theme, REGIONS_VISIBLE);
   }
 
-  // We always add a region for disabled blocks.
-  $block_regions += array(BLOCK_REGION_NONE => '<' . t('none') . '>');
-
   // Weights range from -delta to +delta, so delta should be at least half
   // of the amount of blocks present. This makes sure all blocks in the same
   // region get an unique weight.
@@ -100,7 +97,8 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r
   );
   $form['block_regions'] = array(
     '#type' => 'value',
-    '#value' => $block_regions,
+    // Add a last region for disabled blocks.
+    '#value' => $block_regions + array(BLOCK_REGION_NONE => BLOCK_REGION_NONE),
   );
   $form['blocks'] = array();
   $form['#tree'] = TRUE;
@@ -127,11 +125,14 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r
       '#default_value' => $block['weight'],
       '#delta' => $weight_delta,
       '#title_display' => 'invisible',
-      '#title' => t('Weight for @row', array('@row' => $block['info'])),
+      '#title' => t('Weight for @block block', array('@block' => $block['info'])),
     );
     $form['blocks'][$key]['region'] = array(
       '#type' => 'select',
-      '#default_value' => $block['region'],
+      '#default_value' => $block['region'] != BLOCK_REGION_NONE ? $block['region'] : NULL,
+      '#empty_value' => BLOCK_REGION_NONE,
+      '#title_display' => 'invisible',
+      '#title' => t('Region for @block block', array('@block' => $block['info'])),
       '#options' => $block_regions,
     );
     $form['blocks'][$key]['configure'] = array(
@@ -148,7 +149,7 @@ function block_admin_display_form($form, &$form_state, $blocks, $theme, $block_r
     }
   }
   // Do not allow disabling the main system content block.
-  unset($form['blocks']['system_main']['region']['#options'][BLOCK_REGION_NONE]);
+  $form['blocks']['system_main']['region']['#required'] = TRUE;
 
   $form['actions'] = array(
     '#tree' => FALSE,
@@ -300,9 +301,9 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
       $form['regions'][$key] = array(
         '#type' => 'select',
         '#title' => $theme->info['name'],
-        '#default_value' => (!empty($region) ? $region : BLOCK_REGION_NONE),
-        '#options' => array(BLOCK_REGION_NONE => t('<none>')) + system_region_list($key, REGIONS_VISIBLE),
-        '#expandable' => ($key !== $theme_default),
+        '#default_value' => !empty($region) && $region != -1 ? $region : NULL,
+        '#empty_value' => BLOCK_REGION_NONE,
+        '#options' => system_region_list($key, REGIONS_VISIBLE),
         '#weight' => ($key == $theme_default ? 9 : 10),
       );
     }
@@ -655,7 +656,7 @@ function template_preprocess_block_admin_display_form(&$variables) {
     $block = &$variables['form']['blocks'][$i];
 
     // Fetch the region for the current block.
-    $region = $block['region']['#default_value'];
+    $region = (isset($block['region']['#default_value']) ? $block['region']['#default_value'] : BLOCK_REGION_NONE);
 
     // Set special classes needed for table drag and drop.
     $block['region']['#attributes']['class'] = array('block-region-select', 'block-region-' . $region);
diff --git a/modules/block/block.info b/modules/block/block.info
index 14fd45ac3361c79a98a7b1771b3b4aba9b022813..5077c9f1149c092fae7c0aaf474134e9f19f1357 100644
--- a/modules/block/block.info
+++ b/modules/block/block.info
@@ -10,8 +10,8 @@ files[] = block.install
 files[] = block.test
 configure = admin/structure/block
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/block/block.install b/modules/block/block.install
index 2328748248c70dd3718be034726d05da95b2e0f6..a21e8d2b16ed7161f7fea1621cbaa32ca8d63b5d 100644
--- a/modules/block/block.install
+++ b/modules/block/block.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: block.install,v 1.45 2010/07/28 01:40:39 dries Exp $
+// $Id: block.install,v 1.46 2010/09/28 03:30:37 webchick Exp $
 
 /**
  * @file
@@ -156,9 +156,8 @@ function block_schema() {
       ),
       'format' => array(
         'type' => 'int',
-        'size' => 'small',
-        'not null' => TRUE,
-        'default' => 0,
+        'unsigned' => TRUE,
+        'not null' => FALSE,
         'description' => 'The {filter_format}.format of the block body.',
       ),
     ),
@@ -188,6 +187,19 @@ function block_install() {
     ->execute();
 }
 
+/**
+ * Implements hook_update_dependencies().
+ */
+function block_update_dependencies() {
+  // Block update 7005 needs to query the list of existing text formats and
+  // therefore must run after filter_update_7000().
+  $dependencies['block'][7005] = array(
+    'filter' => 7000,
+  );
+
+  return $dependencies;
+}
+
 /**
  * @defgroup updates-6.x-to-7.x Block updates from 6.x to 7.x
  * @{
@@ -397,13 +409,25 @@ function block_update_7004() {
  * Update the {block_custom}.format column.
  */
 function block_update_7005() {
-  // It was previously possible for a value of "0" to be stored in database
-  // tables to indicate that a particular piece of text should be filtered
-  // using the default text format.
+  // For an explanation of these updates, see the code comments in
+  // user_update_7010().
+  db_change_field('block_custom', 'format', 'format', array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => FALSE,
+    'description' => 'The {filter_format}.format of the block body.',
+  ));
+  db_update('block_custom')
+    ->fields(array('format' => NULL))
+    ->condition('body', '')
+    ->condition('format', 0)
+    ->execute();
+  $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
   $default_format = variable_get('filter_default_format', 1);
   db_update('block_custom')
     ->fields(array('format' => $default_format))
-    ->condition('format', 0)
+    ->isNotNull('format')
+    ->condition('format', $existing_formats, 'NOT IN')
     ->execute();
 }
 
diff --git a/modules/block/block.module b/modules/block/block.module
index 5c053342d815ac93f1775d697b5af51044c31301..27e31bc02f73274096d2d82f73afc746f16cce38 100644
--- a/modules/block/block.module
+++ b/modules/block/block.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: block.module,v 1.428 2010/09/12 00:20:36 dries Exp $
+// $Id: block.module,v 1.431 2010/09/28 03:30:37 webchick Exp $
 
 /**
  * @file
@@ -113,11 +113,6 @@ function block_menu() {
     'access arguments' => array('administer blocks'),
     'file' => 'block.admin.inc',
   );
-  $items['admin/structure/block/list'] = array(
-    'title' => 'List',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => -10,
-  );
   $items['admin/structure/block/manage/%/%'] = array(
     'title' => 'Configure block',
     'page callback' => 'drupal_get_form',
@@ -224,10 +219,12 @@ function block_block_info() {
  * Implements hook_block_configure().
  */
 function block_block_configure($delta = 0) {
-  $custom_block = array('format' => filter_default_format());
   if ($delta) {
     $custom_block = block_custom_block_get($delta);
   }
+  else {
+    $custom_block = array();
+  }
   return block_custom_block_form($custom_block);
 }
 
@@ -297,7 +294,7 @@ function block_page_build(&$page) {
       $page['page_top']['backlink'] = array(
         '#type' => 'link',
         '#title' => t('Exit block region demonstration'),
-        '#href' => 'admin/structure/block/list' . (variable_get('theme_default', 'garland') == $theme ? '' : '/' . $theme),
+        '#href' => 'admin/structure/block' . (variable_get('theme_default', 'bartik') == $theme ? '' : '/list/' . $theme),
         // Add the "overlay-restore" class to indicate this link should restore
         // the context in which the region demonstration page was opened.
         '#options' => array('attributes' => array('class' => array('block-demo-backlink', 'overlay-restore'))),
@@ -954,16 +951,6 @@ function block_user_role_delete($role) {
     ->execute();
 }
 
-/**
- * Implements hook_filter_format_delete().
- */
-function block_filter_format_delete($format, $fallback) {
-  db_update('block_custom')
-    ->fields(array('format' => $fallback->format))
-    ->condition('format', $format->format)
-    ->execute();
-}
-
 /**
  * Implements hook_menu_delete().
  */
diff --git a/modules/block/tests/block_test.info b/modules/block/tests/block_test.info
index 58590722a7bea70b4056be65c1789134c7ffea3b..a941f84a2a860963d56d49851893b3332dd95be9 100644
--- a/modules/block/tests/block_test.info
+++ b/modules/block/tests/block_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = block_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/blog/blog.info b/modules/blog/blog.info
index a23228ad353201b1a1c0078f6f9517647471518e..491fe0bf30a5e153227e754c82e1bfe15524f0b2 100644
--- a/modules/blog/blog.info
+++ b/modules/blog/blog.info
@@ -9,8 +9,8 @@ files[] = blog.module
 files[] = blog.pages.inc
 files[] = blog.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/book/book.admin.inc b/modules/book/book.admin.inc
index d41da65cab502f757a10ac46604360207089ca3e..b589f7d11ed0495eda391eedde8a4b9d1dc086f8 100644
--- a/modules/book/book.admin.inc
+++ b/modules/book/book.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: book.admin.inc,v 1.36 2010/06/26 21:32:20 dries Exp $
+// $Id: book.admin.inc,v 1.37 2010/09/27 00:53:56 dries Exp $
 
 /**
  * @file
@@ -91,7 +91,6 @@ function book_admin_edit($form, $form_state, $node) {
 function book_admin_edit_validate($form, &$form_state) {
   if ($form_state['values']['tree_hash'] != $form_state['values']['tree_current_hash']) {
     form_set_error('', t('This book has been modified by another user, the changes could not be saved.'));
-    $form_state['rebuild'] = TRUE;
   }
 }
 
diff --git a/modules/book/book.info b/modules/book/book.info
index 7222f470fbdf8d5efa7079ab6615312fd481c12e..c0a360b0050dd039db7f3a52aa08a88b69ca9699 100644
--- a/modules/book/book.info
+++ b/modules/book/book.info
@@ -12,8 +12,8 @@ files[] = book.test
 configure = admin/content/book/settings
 stylesheets[all][] = book.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/book/book.module b/modules/book/book.module
index 1a53dcc4158da98f00594917f09649f0ed02c656..5baa788872994095acc79796f96bc107e0279b22 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: book.module,v 1.552 2010/09/09 23:01:48 dries Exp $
+// $Id: book.module,v 1.553 2010/09/24 00:37:42 dries Exp $
 
 /**
  * @file
@@ -182,7 +182,6 @@ function book_menu() {
     'access callback' => '_book_outline_remove_access',
     'access arguments' => array(1),
     'theme callback' => '_node_custom_theme',
-    'type' => MENU_CALLBACK,
     'file' => 'book.pages.inc',
   );
 
diff --git a/modules/color/color.info b/modules/color/color.info
index 65d8ac8e43dc2f66777f33a7f356b9ebdea59e20..f67f4d1a9ac80d41ab92b35d8274c7848ff9f639 100644
--- a/modules/color/color.info
+++ b/modules/color/color.info
@@ -9,8 +9,8 @@ files[] = color.module
 files[] = color.install
 files[] = color.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/color/color.module b/modules/color/color.module
index 2a22a1481ea751df9607ba803346af97fc99c5d5..aa1007c13814a7b5d1121c3c5aac965a66f2ee83 100644
--- a/modules/color/color.module
+++ b/modules/color/color.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: color.module,v 1.90 2010/08/17 22:05:22 dries Exp $
+// $Id: color.module,v 1.92 2010/10/05 19:59:10 dries Exp $
 
 /**
  * Implements hook_help().
@@ -63,7 +63,7 @@ function _color_theme_select_form_alter(&$form, &$form_state) {
   foreach (element_children($form) as $theme) {
     if ($screenshot = variable_get('color_' . $theme . '_screenshot')) {
       if (isset($form[$theme]['screenshot'])) {
-        $form[$theme]['screenshot']['#markup'] = theme('image', array('path' => $screenshot, 'alt' => '', 'title' => '', 'attributes' => array('class' => array('screenshot')), 'getsize' => FALSE));
+        $form[$theme]['screenshot']['#markup'] = theme('image', array('path' => $screenshot, 'title' => '', 'attributes' => array('class' => array('screenshot'))));
       }
     }
   }
@@ -247,7 +247,7 @@ function theme_color_scheme_form($variables) {
   
   $preview_js_path = isset($info['preview_js']) ? $path . $info['preview_js'] : drupal_get_path('module', 'color') . '/' . 'preview.js';
   // Add the JS at a weight below color.js.
-  drupal_add_js($preview_js_path, array('weight' => JS_DEFAULT - 1));
+  drupal_add_js($preview_js_path, array('weight' => -1));
     
   $output  = '';
   $output .= '<div class="color-form clearfix">';
diff --git a/modules/comment/comment.api.php b/modules/comment/comment.api.php
index e1f34ecb7f91a4a54f63b4761e9debdbf3b50451..a36ea1771b46267a432aed0c70381b8802b0dfa2 100644
--- a/modules/comment/comment.api.php
+++ b/modules/comment/comment.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment.api.php,v 1.16 2010/02/09 22:30:30 dries Exp $
+// $Id: comment.api.php,v 1.17 2010/10/03 01:15:33 dries Exp $
 
 /**
  * @file
@@ -64,10 +64,12 @@ function hook_comment_load($comments) {
  *
  * @param $comment
  *   Passes in the comment the action is being performed on.
- * @return
- *   Nothing.
+ * @param $view_mode
+ *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   The language code used for rendering.
  */
-function hook_comment_view($comment) {
+function hook_comment_view($comment, $view_mode, $langcode) {
   // how old is the comment
   $comment->time_ago = time() - $comment->changed;
 }
diff --git a/modules/comment/comment.info b/modules/comment/comment.info
index 8fe14f2f1a7e4a3605cd84c80230127b01f1fa1c..545726f1493982fdf78262cd24d62f7d701ce4dd 100644
--- a/modules/comment/comment.info
+++ b/modules/comment/comment.info
@@ -14,8 +14,8 @@ files[] = comment.tokens.inc
 configure = admin/content/comment
 stylesheets[all][] = comment.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/comment/comment.install b/modules/comment/comment.install
index 358eec788d31d4d3b9b08a7c6175b2c96980ca48..8d25520cf906e2e31556a2a28aa41e4b819cf84e 100644
--- a/modules/comment/comment.install
+++ b/modules/comment/comment.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment.install,v 1.72 2010/09/13 05:50:09 webchick Exp $
+// $Id: comment.install,v 1.73 2010/09/28 03:30:37 webchick Exp $
 
 /**
  * @file
@@ -87,6 +87,12 @@ function comment_update_dependencies() {
     'system' => 7021,
   );
 
+  // Comment update 7006 needs to query the list of existing text formats and
+  // therefore must run after filter_update_7000().
+  $dependencies['comment'][7006] = array(
+    'filter' => 7000,
+  );
+
   return $dependencies;
 }
 
@@ -300,24 +306,31 @@ function comment_update_7006(&$sandbox) {
     $query->addField('c', 'comment', 'comment_body_value');
     $query->addField('c', 'format', 'comment_body_format');
 
-    $comment_body_table = 'field_data_comment_body';
-
-    db_insert($comment_body_table)
+    db_insert('field_data_comment_body')
       ->from($query)
       ->execute();
-    // Update the comment body format in a similar manner as is done for other
-    // modules in filter_update_7005(), but we do this one here since we are
-    // already migrating the data.
-    db_update($comment_body_table)
-      ->fields(array('comment_body_format' => variable_get('filter_default_format', 1)))
-      ->condition('comment_body_format', 0)
-      ->execute();
 
     $sandbox['#finished'] = 1 - count($sandbox['types']) / $sandbox['total'];
   }
 
   // On the last pass of the update, $sandbox['types'] will be empty.
   if (empty($sandbox['types'])) {
+    // Update the comment body text formats. For an explanation of these
+    // updates, see the code comments in user_update_7010().
+    db_update('field_data_comment_body')
+      ->fields(array('comment_body_format' => NULL))
+      ->condition('comment_body_value', '')
+      ->condition('comment_body_format', 0)
+      ->execute();
+    $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
+    $default_format = variable_get('filter_default_format', 1);
+    db_update('field_data_comment_body')
+      ->fields(array('comment_body_format' => $default_format))
+      ->isNotNull('comment_body_format')
+      ->condition('comment_body_format', $existing_formats, 'NOT IN')
+      ->execute();
+
+    // Finally, remove the old comment data.
     db_drop_field('comment', 'comment');
     db_drop_field('comment', 'format');
   }
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 8b8eef6e57a8dd48cd6bc8d20fdc05e1b6f8f3fe..8f8e3a18b41ba4b0561e23a5d5b5ac8fa3021efa 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment.module,v 1.898 2010/09/13 05:52:18 webchick Exp $
+// $Id: comment.module,v 1.904 2010/10/05 06:17:28 webchick Exp $
 
 /**
  * @file
@@ -82,8 +82,8 @@ function comment_help($path, $arg) {
       $output .= '<dl>';
       $output .= '<dt>' . t('Default and custom settings') . '</dt>';
       $output .= '<dd>' . t("Each <a href='@content-type'>content type</a> can have its own default comment settings configured as: <em>Open</em> to allow new comments, <em>Hidden</em> to hide existing comments and prevent new comments, or <em>Closed</em> to view existing comments, but prevent new comments. These defaults will apply to all new content created (changes to the settings on existing content must be done manually). Other comment settings can also be customized per content type, and can be overridden for any given item of content. When a comment has no replies, it remains editable by its author, as long as the author has a user account and is logged in.", array('@content-type' => url('admin/structure/types'))) . '</dd>';
-      $output .= '<dt>' . t('Comment moderation') . '</dt>';
-      $output .= '<dd>' . t("Comments from users who do not have the <em>Post comments without approval</em> permission are placed in the <a href='@comment-approval'>Unapproved comments</a> queue, until a user who has permission to <em>Administer comments</em> moderates them as either published or deleted. Published comments can be bulk managed on the <a href='@admin-comment'>Published comments</a> administration page.", array('@comment-approval' => url('admin/content/comment/approval'), '@admin-comment' => url('admin/content/comment'))) . '</dd>';
+      $output .= '<dt>' . t('Comment approval') . '</dt>';
+      $output .= '<dd>' . t("Comments from users who have the <em>Skip comment approval</em> permission are published immediately. All other comments are placed in the <a href='@comment-approval'>Unapproved comments</a> queue, until a user who has permission to <em>Administer comments</em> publishes or deletes them. Published comments can be bulk managed on the <a href='@admin-comment'>Published comments</a> administration page.", array('@comment-approval' => url('admin/content/comment/approval'), '@admin-comment' => url('admin/content/comment'))) . '</dd>';
       $output .= '</dl>';
       return $output;
   }
@@ -220,7 +220,7 @@ function comment_menu() {
     'description' => 'List and edit site comments and the comment approval queue.',
     'page callback' => 'comment_admin',
     'access arguments' => array('administer comments'),
-    'type' => MENU_LOCAL_TASK,
+    'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
     'file' => 'comment.admin.inc',
   );
   // Tabs begin here.
@@ -241,7 +241,6 @@ function comment_menu() {
     'page callback' => 'comment_permalink',
     'page arguments' => array(1),
     'access arguments' => array('access comments'),
-    'type' => MENU_CALLBACK,
   );
   $items['comment/%/view'] = array(
     'title' => 'View comment',
@@ -264,7 +263,6 @@ function comment_menu() {
     'page callback' => 'comment_approve',
     'page arguments' => array(1),
     'access arguments' => array('administer comments'),
-    'type' => MENU_CALLBACK,
     'file' => 'comment.pages.inc',
     'weight' => 1,
   );
@@ -283,7 +281,6 @@ function comment_menu() {
     'page arguments' => array(2),
     'access callback' => 'node_access',
     'access arguments' => array('view', 2),
-    'type' => MENU_CALLBACK,
     'file' => 'comment.pages.inc',
   );
 
@@ -295,7 +292,7 @@ function comment_menu() {
  */
 function comment_menu_alter(&$items) {
   // Add comments to the description for admin/content.
-  $items['admin/content']['description'] = "Administer content and comments";
+  $items['admin/content']['description'] = 'Administer content and comments.';
 
   // Adjust the Field UI tabs on admin/structure/types/manage/[node-type].
   // See comment_entity_info().
@@ -389,10 +386,10 @@ function comment_permission() {
       'title' => t('View comments'),
     ),
     'post comments' => array(
-      'title' => t('Post comments with approval'),
+      'title' => t('Post comments'),
     ),
-    'post comments without approval' => array(
-      'title' => t('Post comments without approval'),
+    'skip comment approval' => array(
+      'title' => t('Skip comment approval'),
     ),
     'edit own comments' => array(
       'title' => t('Edit own comments'),
@@ -890,13 +887,20 @@ function comment_prepare_thread(&$comments) {
  *   The node the comment is attached to.
  * @param $view_mode
  *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  *
  * @return
  *   An array as expected by drupal_render().
  */
-function comment_view($comment, $node, $view_mode = 'full') {
+function comment_view($comment, $node, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Populate $comment->content with a render() array.
-  comment_build_content($comment, $node, $view_mode);
+  comment_build_content($comment, $node, $view_mode, $langcode);
 
   $build = $comment->content;
   // We don't need duplicate rendering info in comment->content.
@@ -907,6 +911,7 @@ function comment_view($comment, $node, $view_mode = 'full') {
     '#comment' => $comment,
     '#node' => $node,
     '#view_mode' => $view_mode,
+    '#language' => $langcode,
   );
 
   if (empty($comment->in_preview)) {
@@ -951,15 +956,22 @@ function comment_view($comment, $node, $view_mode = 'full') {
  *   The node the comment is attached to.
  * @param $view_mode
  *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  */
-function comment_build_content($comment, $node, $view_mode = 'full') {
+function comment_build_content($comment, $node, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Remove previously built content, if exists.
   $comment->content = array();
 
   // Build fields content.
   field_attach_prepare_view('comment', array($comment->cid => $comment), $view_mode);
   entity_prepare_view('comment', array($comment->cid => $comment));
-  $comment->content += field_attach_view('comment', $comment, $view_mode);
+  $comment->content += field_attach_view('comment', $comment, $view_mode, $langcode);
 
   if (empty($comment->in_preview)) {
     $comment->content['links']['comment'] = array(
@@ -970,7 +982,7 @@ function comment_build_content($comment, $node, $view_mode = 'full') {
   }
 
   // Allow modules to make their own additions to the comment.
-  module_invoke_all('comment_view', $comment, $view_mode);
+  module_invoke_all('comment_view', $comment, $view_mode, $langcode);
 }
 
 /**
@@ -1046,10 +1058,14 @@ function comment_links($comment, $node) {
  *   View mode, e.g. 'full', 'teaser'...
  * @param $weight
  *   An integer representing the weight of the first comment in the list.
+ * @param $langcode
+ *   A string indicating the language field values are to be shown in. If no
+ *   language is provided the current content language is used.
+ *
  * @return
  *   An array in the format expected by drupal_render().
  */
-function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0) {
+function comment_view_multiple($comments, $node, $view_mode = 'full', $weight = 0, $langcode = NULL) {
   field_attach_prepare_view('comment', $comments, $view_mode);
   entity_prepare_view('comment', $comments);
 
@@ -1057,7 +1073,7 @@ function comment_view_multiple($comments, $node, $view_mode = 'full', $weight =
     '#sorted' => TRUE,
   );
   foreach ($comments as $comment) {
-    $build[$comment->cid] = comment_view($comment, $node, $view_mode);
+    $build[$comment->cid] = comment_view($comment, $node, $view_mode, $langcode);
     $build[$comment->cid]['#weight'] = $weight;
     $weight++;
   }
@@ -1405,7 +1421,7 @@ function comment_save($comment) {
       'mail' => '',
       'homepage' => '',
       'name' => '',
-      'status' => user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED,
+      'status' => user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED,
     );
     foreach ($defaults as $key => $default) {
       if (!isset($comment->$key)) {
@@ -1851,7 +1867,7 @@ function comment_form($form, &$form_state, $comment) {
     else {
       $author = ($comment->name ? $comment->name : variable_get('anonymous', t('Anonymous')));
     }
-    $status = (user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED);
+    $status = (user_access('skip comment approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED);
     $date = '';
   }
 
@@ -2204,8 +2220,10 @@ function template_preprocess_comment(&$variables) {
   $variables['signature'] = $comment->signature;
 
   $uri = entity_uri('comment', $comment);
+  $uri['options'] += array('attributes' => array('class' => 'permalink', 'rel' => 'bookmark'));
+
   $variables['title']     = l($comment->subject, $uri['path'], $uri['options']);
-  $variables['permalink'] = l('#', $uri['path'], $uri['options']);
+  $variables['permalink'] = l(t('Permalink'), $uri['path'], $uri['options']);
 
   // Preprocess fields.
   field_attach_preprocess('comment', $comment, $variables['elements'], $variables);
@@ -2264,7 +2282,7 @@ function theme_comment_post_forbidden($variables) {
     if (!isset($authenticated_post_comments)) {
       // We only output a link if we are certain that users will get permission
       // to post comments by logging in.
-      $authenticated_post_comments = array_key_exists(DRUPAL_AUTHENTICATED_RID, user_roles(TRUE, 'post comments') + user_roles(TRUE, 'post comments without approval'));
+      $authenticated_post_comments = array_key_exists(DRUPAL_AUTHENTICATED_RID, user_roles(TRUE, 'post comments') + user_roles(TRUE, 'skip comment approval'));
     }
 
     if ($authenticated_post_comments) {
diff --git a/modules/comment/comment.test b/modules/comment/comment.test
index 5060436abbbc44c869774175a0aa25db62d0a297..0f423ec45dee1f8551e6cd17492b15e686a99eb3 100644
--- a/modules/comment/comment.test
+++ b/modules/comment/comment.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment.test,v 1.89 2010/08/30 00:22:03 webchick Exp $
+// $Id: comment.test,v 1.90 2010/10/05 06:17:28 webchick Exp $
 
 class CommentHelperCase extends DrupalWebTestCase {
   protected $admin_user;
@@ -440,7 +440,7 @@ class CommentPreviewTest extends CommentHelperCase {
    */
   function testCommentEditPreview() {
     $langcode = LANGUAGE_NONE;
-    $web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'post comments without approval'));
+    $web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'skip comment approval'));
     $this->drupalLogin($this->admin_user);
     $this->setCommentPreview(DRUPAL_OPTIONAL);
     $this->setCommentForm(TRUE);
@@ -495,7 +495,7 @@ class CommentAnonymous extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
       'post comments' => TRUE,
-      'post comments without approval' => TRUE,
+      'skip comment approval' => TRUE,
     ));
     $this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
     $this->drupalLogout();
@@ -579,7 +579,7 @@ class CommentAnonymous extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => FALSE,
       'post comments' => FALSE,
-      'post comments without approval' => FALSE,
+      'skip comment approval' => FALSE,
     ));
 
     // Attempt to view comments while disallowed.
@@ -598,7 +598,7 @@ class CommentAnonymous extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
       'post comments' => FALSE,
-      'post comments without approval' => FALSE,
+      'skip comment approval' => FALSE,
     ));
     $this->drupalGet('node/' . $this->node->nid);
     $this->assertPattern('/<div ([^>]*?)id="comments"([^>]*?)>/', t('Comments were displayed.'));
@@ -890,7 +890,7 @@ class CommentApprovalTest extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
       'post comments' => TRUE,
-      'post comments without approval' => FALSE,
+      'skip comment approval' => FALSE,
     ));
     $this->drupalLogin($this->admin_user);
     $this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
@@ -959,7 +959,7 @@ class CommentApprovalTest extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
       'post comments' => TRUE,
-      'post comments without approval' => FALSE,
+      'skip comment approval' => FALSE,
     ));
     $this->drupalLogin($this->admin_user);
     $this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
diff --git a/modules/contact/contact.info b/modules/contact/contact.info
index cce79871d523309bb014a3c282948f1ee7d72e88..40b742091b352d15a200a59892ca925f63061b4f 100644
--- a/modules/contact/contact.info
+++ b/modules/contact/contact.info
@@ -11,8 +11,8 @@ files[] = contact.install
 files[] = contact.test
 configure = admin/structure/contact
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/contact/contact.module b/modules/contact/contact.module
index 5beceaf3420dcce48c7854cdcff43353bdfe6789..b424d95e60099984829eb245473b0cd7bcf8754d 100644
--- a/modules/contact/contact.module
+++ b/modules/contact/contact.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: contact.module,v 1.147 2010/04/13 15:13:41 dries Exp $
+// $Id: contact.module,v 1.148 2010/09/24 00:37:42 dries Exp $
 
 /**
  * @file
@@ -77,7 +77,6 @@ function contact_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('contact_category_edit_form', 4),
     'access arguments' => array('administer contact forms'),
-    'type' => MENU_CALLBACK,
     'file' => 'contact.admin.inc',
   );
   $items['admin/structure/contact/delete/%contact'] = array(
@@ -85,7 +84,6 @@ function contact_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('contact_category_delete_form', 4),
     'access arguments' => array('administer contact forms'),
-    'type' => MENU_CALLBACK,
     'file' => 'contact.admin.inc',
   );
   $items['contact'] = array(
diff --git a/modules/contextual/contextual.info b/modules/contextual/contextual.info
index f5e346860d134629a792c7bacf89c52c018dfc76..9ee3e44bddd19e31db5f2257684195fd975bd0b6 100644
--- a/modules/contextual/contextual.info
+++ b/modules/contextual/contextual.info
@@ -6,8 +6,8 @@ version = VERSION
 core = 7.x
 files[] = contextual.module
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/dashboard/dashboard.info b/modules/dashboard/dashboard.info
index 19c1d2ed53a3d675678a4bbf40a879f87ec64dff..343075f3faba6c6a6755a88490baa3eeb0f0412e 100644
--- a/modules/dashboard/dashboard.info
+++ b/modules/dashboard/dashboard.info
@@ -9,8 +9,8 @@ files[] = dashboard.test
 dependencies[] = block
 configure = admin/dashboard/customize
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/dashboard/dashboard.module b/modules/dashboard/dashboard.module
index fad6a9e57115407aeaf01e2e096b3f0498ea84eb..b6350853f0dd1152ac918bad89607634f87a2226 100644
--- a/modules/dashboard/dashboard.module
+++ b/modules/dashboard/dashboard.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: dashboard.module,v 1.35 2010/09/14 21:51:01 webchick Exp $
+// $Id: dashboard.module,v 1.39 2010/10/03 00:14:57 dries Exp $
 
 /**
  * Implements hook_help().
@@ -33,27 +33,26 @@ function dashboard_help($path, $arg) {
 function dashboard_menu() {
   $items['admin/structure/dashboard'] = array(
     'title' => 'Dashboard',
-    'description' => "Configure which blocks can be shown on the dashboard.",
+    'description' => 'Configure which blocks can be shown on the dashboard.',
     'page callback' => 'dashboard_admin_blocks',
     'access arguments' => array('administer blocks'),
   );
   $items['admin/dashboard'] = array(
     'title' => 'Dashboard',
-    'description' => 'View and customize your dashboard',
+    'description' => 'View and customize your dashboard.',
     'page callback' => 'dashboard_admin',
     'access arguments' => array('access dashboard'),
-    'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
     // Make this appear first, so for example, in admin menus, it shows up on
-    // the top corner of the window as a convinient "home link".
+    // the top corner of the window as a convenient "home link".
     'weight' => -15,
   );
   $items['admin/dashboard/customize'] = array(
-    'title' => 'Dashboard',
-    'description' => 'View and customize your dashboard',
+    'title' => 'Customize dashboard',
+    'description' => 'Customize your dashboard.',
     'page callback' => 'dashboard_admin',
     'page arguments' => array(TRUE),
     'access arguments' => array('access dashboard'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
   );
   $items['admin/dashboard/drawer'] = array(
     'page callback' => 'dashboard_show_disabled',
@@ -236,14 +235,6 @@ function dashboard_forms() {
  *   Whether to launch in customization mode right away. TRUE or FALSE.
  */
 function dashboard_admin($launch_customize = FALSE) {
-  // Only continue if provided arguments are expected. This function serves
-  // as the callback for the top-level admin/ page, so any unexpected arguments
-  // are likely the result of someone typing in the URL of an administrative
-  // page that doesn't actually exist; for example, admin/some/random/page.
-  if (!is_bool($launch_customize)) {
-    return MENU_NOT_FOUND;
-  }
-
   $js_settings = array(
     'dashboard' => array(
       'drawer' => url('admin/dashboard/drawer'),
@@ -335,9 +326,6 @@ function dashboard_form_block_admin_display_form_alter(&$form, &$form_state, $fo
  * Implements hook_form_FORM_ID_alter().
  */
 function dashboard_form_dashboard_admin_display_form_alter(&$form, &$form_state) {
-  // Inherit the submit handler from the main block administration form.
-  $form['#submit'][] = 'block_admin_display_form_submit';
-
   // Redirect the 'configure' and 'delete' links on each block back to the
   // dashboard blocks administration page.
   foreach ($form['blocks'] as &$block) {
@@ -559,7 +547,7 @@ function dashboard_update() {
 function theme_dashboard($variables) {
   extract($variables);
   drupal_add_css(drupal_get_path('module', 'dashboard') . '/dashboard.css');
-  return '<div id="dashboard">' . $element['#children'] . '</div>';
+  return '<div id="dashboard" class="clearfix">' . $element['#children'] . '</div>';
 }
 
 /**
diff --git a/modules/dblog/dblog.info b/modules/dblog/dblog.info
index bdf82cddd88c83989395c0ba96f4998fe65be24d..2acabdc4a1e643a7a56dabe4b32bc3a0392cfb98 100644
--- a/modules/dblog/dblog.info
+++ b/modules/dblog/dblog.info
@@ -9,8 +9,8 @@ files[] = dblog.admin.inc
 files[] = dblog.install
 files[] = dblog.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/dblog/dblog.module b/modules/dblog/dblog.module
index 252c4011457e8d279e1390c49ac5b74d0d322347..d0e0c40ba4926bb9bd98f061cbe28d7da2a4b7c5 100644
--- a/modules/dblog/dblog.module
+++ b/modules/dblog/dblog.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: dblog.module,v 1.55 2010/09/01 03:03:05 dries Exp $
+// $Id: dblog.module,v 1.57 2010/10/03 02:14:23 dries Exp $
 
 /**
  * @file
@@ -67,7 +67,6 @@ function dblog_menu() {
     'page callback' => 'dblog_event',
     'page arguments' => array(3),
     'access arguments' => array('access site reports'),
-    'type' => MENU_CALLBACK,
     'file' => 'dblog.admin.inc',
   );
 
@@ -101,12 +100,25 @@ function dblog_init() {
  * Remove expired log messages and flood control events.
  */
 function dblog_cron() {
-  // Cleanup the watchdog table
-  if (variable_get('dblog_row_limit', 1000) > 0) {
-    $max = Database::getConnection('default', 'default')->query('SELECT MAX(wid) FROM {watchdog}')->fetchField();
-    Database::getConnection('default', 'default')->delete('watchdog')
-      ->condition('wid', $max - variable_get('dblog_row_limit', 1000), '<=')
-      ->execute();
+  // Cleanup the watchdog table.
+  $row_limit = variable_get('dblog_row_limit', 1000);
+
+  // For row limit n, get the wid of the nth row in descending wid order.
+  // Counting the most recent n rows avoids issues with wid number sequences,
+  // e.g. auto_increment value > 1 or rows deleted directly from the table.
+  if ($row_limit > 0) {
+    $min_row = db_select('watchdog', 'w')
+      ->fields('w', array('wid'))
+      ->orderBy('wid', 'DESC')
+      ->range($row_limit - 1, 1)
+      ->execute()->fetchField();
+
+    // Delete all table entries older than the nth row, if nth row was found.
+    if ($min_row) {
+      db_delete('watchdog')
+        ->condition('wid', $min_row, '<')
+        ->execute();
+    }
   }
 }
 
diff --git a/modules/field/field.api.php b/modules/field/field.api.php
index 07ff6e77c4f7992623dd61a653382ecaf9597dff..35243dcb95110604b2a64b34026764b4b2174ad3 100644
--- a/modules/field/field.api.php
+++ b/modules/field/field.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: field.api.php,v 1.90 2010/09/11 00:03:41 webchick Exp $
+// $Id: field.api.php,v 1.91 2010/10/03 01:15:33 dries Exp $
 
 /**
  * @ingroup field_fieldable_type
@@ -1236,6 +1236,7 @@ function hook_field_attach_purge($entity_type, $entity, $field, $instance) {
  *   - entity_type: The type of $entity; for example, 'node' or 'user'.
  *   - entity: The entity with fields to render.
  *   - view_mode: View mode, for example, 'full' or 'teaser'.
+ *   - language: The language code used for rendering.
  */
 function hook_field_attach_view_alter(&$output, $context) {
   // Append RDF term mappings on displayed taxonomy links.
diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc
index c51dfe0035715e7c17e3be43d5c995f2877e59b7..5a496e741bc755c0294067109ef8106020290e73 100644
--- a/modules/field/field.attach.inc
+++ b/modules/field/field.attach.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field.attach.inc,v 1.95 2010/08/01 19:49:35 dries Exp $
+// $Id: field.attach.inc,v 1.96 2010/10/03 01:15:33 dries Exp $
 
 /**
  * @file
@@ -1146,6 +1146,7 @@ function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL)
     'entity_type' => $entity_type,
     'entity' => $entity,
     'view_mode' => $view_mode,
+    'language' => $langcode,
   );
   drupal_alter('field_attach_view', $output, $context);
 
diff --git a/modules/field/field.crud.inc b/modules/field/field.crud.inc
index e2ec08b29f3670219a9b6a10bff774ad5e8797cf..400399e3dc43aaf8e40319c10e7002e26f7bc1e2 100644
--- a/modules/field/field.crud.inc
+++ b/modules/field/field.crud.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field.crud.inc,v 1.69 2010/09/11 00:03:42 webchick Exp $
+// $Id: field.crud.inc,v 1.71 2010/09/29 01:37:02 dries Exp $
 
 /**
  * @file
@@ -79,6 +79,11 @@
  *     'columns' setting are allowed. Note that field types can specify
  *     default indexes, which can be modified or added to when
  *     creating a field.
+ * - foreign keys: (optional) An associative array of relations, using the same
+ *   structure as the 'foreign keys' definition of hook_schema(). Note, however,
+ *   that the field data is not necessarily stored in SQL. Also, the possible
+ *   usage is limited, as you cannot specify another field as related, only
+ *   existing SQL tables, such as filter formats.
  * - settings (array)
  *     A sub-array of key/value pairs of field-type-specific settings. Each
  *     field type module defines and documents its own field settings.
@@ -319,9 +324,11 @@ function field_create_field($field) {
   // Collect storage information.
   module_load_install($field['module']);
   $schema = (array) module_invoke($field['module'], 'field_schema', $field);
-  $schema += array('columns' => array(), 'indexes' => array());
+  $schema += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
   // 'columns' are hardcoded in the field type.
   $field['columns'] = $schema['columns'];
+  // 'foreign keys' are hardcoded in the field type.
+  $field['foreign keys'] = $schema['foreign keys'];
   // 'indexes' can be both hardcoded in the field type, and specified in the
   // incoming $field definition.
   $field += array(
@@ -762,7 +769,7 @@ function _field_write_instance($instance, $update = FALSE) {
   // If no weight specified, make sure the field sinks at the bottom.
   if (!isset($instance['widget']['weight'])) {
     $max_weight = field_info_max_weight($instance['entity_type'], $instance['bundle'], 'form');
-    $instance['widget']['weight'] = !is_null($max_weight) ? $max_weight + 1 : 0;
+    $instance['widget']['weight'] = isset($max_weight) ? $max_weight + 1 : 0;
   }
   // Check widget module.
   $widget_type = field_info_widget_types($instance['widget']['type']);
@@ -788,7 +795,7 @@ function _field_write_instance($instance, $update = FALSE) {
     // If no weight specified, make sure the field sinks at the bottom.
     if (!isset($display['weight'])) {
       $max_weight = field_info_max_weight($instance['entity_type'], $instance['bundle'], $view_mode);
-      $display['weight'] = !is_null($max_weight) ? $max_weight + 1 : 0;
+      $display['weight'] = isset($max_weight) ? $max_weight + 1 : 0;
     }
     $instance['display'][$view_mode] = $display;
   }
diff --git a/modules/field/field.info b/modules/field/field.info
index 7985e9955c13d06b756ba38786ec9dffffbc3b57..a5b76addf8b01425b822aa661cde9d903e1f37ea 100644
--- a/modules/field/field.info
+++ b/modules/field/field.info
@@ -17,8 +17,8 @@ dependencies[] = field_sql_storage
 required = TRUE
 stylesheets[all][] = theme/field.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/field.install b/modules/field/field.install
index d638f69382ab845e5f500eb1db436bc9732c4129..4a54c7b6190c1c81f657e83cac565e14f7057853 100644
--- a/modules/field/field.install
+++ b/modules/field/field.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: field.install,v 1.20 2010/09/13 05:50:09 webchick Exp $
+// $Id: field.install,v 1.22 2010/09/29 19:46:40 dries Exp $
 
 /**
  * @file
@@ -171,7 +171,8 @@ function field_schema() {
 /**
  * Utility function: create a field by writing directly to the database.
  *
- * This function is valid for a database schema version 7000.
+ * This function can be used for databases whose schema is at field module
+ * version 7000 or higher.
  *
  * @ingroup update-api-6.x-to-7.x
  */
@@ -240,12 +241,106 @@ function _update_7000_field_create_field(&$field) {
 }
 
 /**
- * Utility function: create a field instance directly to the database.
+ * Utility function: delete a field stored in SQL storage directly from the database.
+ *
+ * To protect user data, this function can only be used to delete fields once
+ * all information it stored is gone. Delete all data from the
+ * field_data_$field_name table before calling by either manually issuing
+ * delete queries against it or using _update_7000_field_delete_instance().
+ *
+ * This function can be used for databases whose schema is at field module
+ * version 7000 or higher.
+ *
+ * @param $field_name
+ *   The field name to delete.
+ *
+ * @ingroup update-api-6.x-to-7.x
+ */
+function _update_7000_field_delete_field($field_name) {
+  $table_name = 'field_data_' . $field_name;
+  if (db_select($table_name)->range(0, 1)->countQuery()->execute()->fetchField()) {
+    $t = get_t();
+    throw new Exception($t('This function can only be used to delete fields without data'));
+  }
+  // Delete all instances.
+  db_delete('field_config_instance')
+    ->condition('field_name', $field_name)
+    ->execute();
+
+  // Nuke field data and revision tables.
+  db_drop_table($table_name);
+  db_drop_table('field_revision_' . $field_name);
+
+  // Delete the field.
+  db_delete('field_config')
+    ->condition('field_name', $field_name)
+    ->execute();
+}
+
+
+/**
+ * Utility function: delete an instance and all its data of a field stored in SQL Storage.
+ *
+ * BEWARE: this function deletes user data from the field storage tables.
  *
  * This function is valid for a database schema version 7000.
  *
  * @ingroup update-api-6.x-to-7.x
  */
+function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) {
+  // Delete field instance configuration data.
+  db_delete('field_config_instance')
+    ->condition('field_name', $field_name)
+    ->condition('entity_type', $entity_type)
+    ->condition('bundle', $bundle)
+    ->execute();
+
+  // Nuke data.
+  $etid = _field_sql_storage_etid($entity_type);
+  db_delete('field_data_' . $field_name)
+    ->condition('etid', $etid)
+    ->condition('bundle', $bundle)
+    ->execute();
+  db_delete('field_revision_' . $field_name)
+    ->condition('etid', $etid)
+    ->condition('bundle', $bundle)
+    ->execute();
+}
+
+/**
+ * Utility function: fetch all the field definitions from the database.
+ */
+function _update_7000_field_read_fields() {
+  $fields = array();
+  $results = db_query('SELECT * FROM {field_config} WHERE deleted = 0', array(), array('fetch' => PDO::FETCH_ASSOC));
+  foreach ($results as $record) {
+    $field = unserialize($record['data']);
+    $field['id'] = $record['id'];
+    $field['field_name'] = $record['field_name'];
+    $field['type'] = $record['type'];
+    $field['module'] = $record['module'];
+    $field['active'] = $record['active'];
+    $field['storage']['type'] = $record['storage_type'];
+    $field['storage']['module'] = $record['storage_module'];
+    $field['storage']['active'] = $record['storage_active'];
+    $field['locked'] = $record['locked'];
+    $field['cardinality'] = $record['cardinality'];
+    $field['translatable'] = $record['translatable'];
+    $field['deleted'] = $record['deleted'];
+
+    $fields[$field['field_name']] = $field;
+  }
+  return $fields;
+}
+
+/**
+ * Utility function: write a field instance directly to the database.
+ *
+ * This function can be used for databases whose schema is at field module
+ * version 7000 or higher.
+ *
+ * @ingroup update-api-6.x-to-7.x
+ */
 function _update_7000_field_create_instance($field, &$instance) {
   // Merge in defaults.
   $instance += array(
@@ -282,10 +377,12 @@ function _update_7000_field_create_instance($field, &$instance) {
  * Field update version placeholder.
  */
 function field_update_7000() {
-  // _update_7000_field_create_field() is supposed to create fields according
-  // to the structure of fields after running field_update_7000(). So this
-  // function needs to exist but as field is a new module in Drupal 7, it
-  // does not need to do anything.
+  // Some update helper functions (such as _update_7000_field_create_field())
+  // modify the database directly. They can be used safely only if the database
+  // schema matches the field module schema established for Drupal 7.0 (i.e.
+  // version 7000). This function exists solely to set the schema version to
+  // 7000, so that update functions calling those helpers can do so safely
+  // by declaring a dependency on field_update_7000().
 }
 
 /**
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.info b/modules/field/modules/field_sql_storage/field_sql_storage.info
index 0c5c0ed1300bc5c21163ba1288322a88055caa30..b93c651a3808e0e13e53bb878442ae8f750bbda1 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.info
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.info
@@ -10,8 +10,8 @@ files[] = field_sql_storage.install
 files[] = field_sql_storage.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.install b/modules/field/modules/field_sql_storage/field_sql_storage.install
index 783c293fb2fb078d1f1fe269a2a946b19ce7d6f9..554660ea8a22b489649847f09fe8ea9e82757c29 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.install
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_sql_storage.install,v 1.9 2010/02/15 18:43:00 dries Exp $
+// $Id: field_sql_storage.install,v 1.10 2010/09/29 19:46:40 dries Exp $
 
 /**
  * @file
@@ -44,3 +44,83 @@ function field_sql_storage_schema() {
   }
   return $schema;
 }
+
+/**
+ * Utility function: write field data directly to SQL storage.
+ *
+ * This function can be used for databases whose schema is at field module
+ * version 7000 or higher.
+ *
+ * @ingroup update-api-6.x-to-7.x
+ */
+function _update_7000_field_sql_storage_write($entity_type, $bundle, $entity_id, $revision_id, $field_name, $data) {
+  $etid = _field_sql_storage_etid($entity_type);
+  $table_name = "field_data_{$field_name}";
+  $revision_name = "field_revision_{$field_name}";
+
+  db_delete($table_name)
+    ->condition('etid', $etid)
+    ->condition('entity_id', $entity_id)
+    ->execute();
+  db_delete($revision_name)
+    ->condition('etid', $etid)
+    ->condition('entity_id', $entity_id)
+    ->condition('revision_id', $revision_id)
+    ->execute();
+
+  $columns = array();
+  foreach ($data as $langcode => $items) {
+    foreach ($items as $delta => $item) {
+      $record = array(
+        'etid' => $etid,
+        'entity_id' => $entity_id,
+        'revision_id' => $revision_id,
+        'bundle' => $bundle,
+        'delta' => $delta,
+        'language' => $langcode,
+      );
+      foreach ($item as $column => $value) {
+        $record[_field_sql_storage_columnname($field_name, $column)] = $value;
+      }
+
+      $records[] = $record;
+      // Record the columns used.
+      $columns += $record;
+    }
+  }
+
+  if ($columns) {
+    $query = db_insert($table_name)->fields(array_keys($columns));
+    $revision_query = db_insert($revision_name)->fields(array_keys($columns));
+    foreach ($records as $record) {
+      $query->values($record);
+      if ($revision_id) {
+        $revision_query->values($record);
+      }
+    }
+    $query->execute();
+    $revision_query->execute();
+  }
+}
+
+/**
+ * @defgroup field-sql-storage-updates-6.x-to-7.x Field SQL storage updates from 6.x to 7.x
+ * @{
+ */
+
+/**
+ * Field SQL storage update version placeholder.
+ */
+function field_sql_storage_update_7000() {
+  // Some update helper functions (such as
+  // _update_7000_field_sql_storage_write()) modify the database directly. They
+  // can be used safely only if the database schema matches the field module
+  // schema established for Drupal 7.0 (i.e. version 7000). This function exists
+  // solely to set the schema version to 7000, so that update functions calling
+  // those helpers can do so safely by declaring a dependency on
+  // field_sql_storage_update_7000().
+}
+
+/**
+ * @} End of "defgroup field-updates-6.x-to-7.x"
+ */
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.module b/modules/field/modules/field_sql_storage/field_sql_storage.module
index 1971ef2897b2925b44387e5c5354a65969d2e79b..f2e64301beb232e355870d3d18e5ff1ddec2fa0a 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.module
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_sql_storage.module,v 1.52 2010/09/05 20:00:45 dries Exp $
+// $Id: field_sql_storage.module,v 1.56 2010/10/06 13:57:47 dries Exp $
 
 /**
  * @file
@@ -106,7 +106,7 @@ function _field_sql_storage_indexname($name, $index) {
  */
 function _field_sql_storage_etid($entity_type) {
   $etid = variable_get('field_sql_storage_' . $entity_type . '_etid', NULL);
-  if (is_null($etid)) {
+  if (!isset($etid)) {
     $etid = db_insert('field_config_entity_type')->fields(array('type' => $entity_type))->execute();
     variable_set('field_sql_storage_' . $entity_type . '_etid', $etid);
   }
@@ -188,27 +188,39 @@ function _field_sql_storage_schema($field) {
     ),
   );
 
+  $field += array('columns' => array(), 'indexes' => array(), 'foreign keys' => array());
   // Add field columns.
-  foreach ((array) $field['columns'] as $column_name => $attributes) {
+  foreach ($field['columns'] as $column_name => $attributes) {
     $real_name = _field_sql_storage_columnname($field['field_name'], $column_name);
     $current['fields'][$real_name] = $attributes;
   }
 
   // Add indexes.
-  foreach ((array) $field['indexes'] as $index_name => $columns) {
+  foreach ($field['indexes'] as $index_name => $columns) {
     $real_name = _field_sql_storage_indexname($field['field_name'], $index_name);
     foreach ($columns as $column_name) {
       $current['indexes'][$real_name][] = _field_sql_storage_columnname($field['field_name'], $column_name);
     }
   }
 
+  // Add foreign keys.
+  foreach ($field['foreign keys'] as $specifier => $specification) {
+    $real_name = _field_sql_storage_indexname($field['field_name'], $specifier);
+    $current['foreign keys'][$real_name]['table'] = $specification['table'];
+    foreach ($specification['columns'] as $column => $referenced) {
+      $sql_storage_column = _field_sql_storage_columnname($field['field_name'], $column_name);
+      $current['foreign keys'][$real_name]['columns'][$sql_storage_column] = $referenced;
+    }
+  }
+
   // Construct the revision table. The primary key includes
   // revision_id but not entity_id so that multiple revision loads can
   // use the IN operator.
   $revision = $current;
   $revision['description'] = "Revision archive storage for {$deleted}field {$field['id']} ({$field['field_name']})";
-  $revision['revision_id']['description'] = 'The entity revision id this data is attached to';
   $revision['primary key'] = array('etid', 'revision_id', 'deleted', 'delta', 'language');
+  $revision['fields']['revision_id']['not null'] = TRUE;
+  $revision['fields']['revision_id']['description'] = 'The entity revision id this data is attached to';
 
   return array(
     _field_sql_storage_tablename($field) => $current,
@@ -538,35 +550,53 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) {
     }
   }
 
-  // Add field orders.
-  foreach ($query->fieldOrder as $key => $order) {
-    $table_alias = $table_aliases[$key];
-    $field = $order['field'];
-    $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $order['column']);
-    $select_query->orderBy($sql_field, $order['direction']);
-  }
-
   if (isset($query->deleted)) {
     $select_query->condition("$field_base_table.deleted", (int) $query->deleted);
   }
 
-  if ($query->propertyConditions || $query->propertyOrder) {
+  // Is there a need to sort the query by property?
+  $has_property_order = FALSE;
+  foreach ($query->order as $order) {
+    if ($order['type'] == 'property') {
+      $has_property_order = TRUE;
+    }
+  }
+
+  if ($query->propertyConditions || $has_property_order) {
     if (empty($query->entityConditions['entity_type']['value'])) {
       throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.');
     }
     $entity_type = $query->entityConditions['entity_type']['value'];
     $entity_base_table = _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table);
     $query->entityConditions['entity_type']['operator'] = '=';
-    $query->processProperty($select_query, $entity_base_table);
+    foreach ($query->propertyConditions as $property_condition) {
+      $query->addCondition($select_query, "$entity_base_table." . $property_condition['column'], $property_condition);
+    }
   }
   foreach ($query->entityConditions as $key => $condition) {
     $sql_field = $key == 'entity_type' ? 'fcet.type' : "$field_base_table.$key";
     $query->addCondition($select_query, $sql_field, $condition);
   }
-  foreach ($query->entityOrder as $key => $direction) {
-    $sql_field = $key == 'entity_type' ? 'fcet.type' : "$field_base_table.$key";
-    $select_query->orderBy($sql_field, $direction);
+
+  // Order the query.
+  foreach ($query->order as $order) {
+    if ($order['type'] == 'entity') {
+      $key = $order['specifier'];
+      $sql_field = $key == 'entity_type' ? 'fcet.type' : "$field_base_table.$key";
+      $select_query->orderBy($sql_field, $order['direction']);
+    }
+    elseif ($order['type'] == 'field') {
+      $specifier = $order['specifier'];
+      $field = $specifier['field'];
+      $table_alias = $table_aliases[$specifier['index']];
+      $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $specifier['column']);
+      $select_query->orderBy($sql_field, $order['direction']);
+    }
+    elseif ($order['type'] == 'property') {
+      $select_query->orderBy("$entity_base_table." . $order['specifier'], $order['direction']);
+    }
   }
+
   return $query->finishQuery($select_query, $id_key);
 }
 
diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.test b/modules/field/modules/field_sql_storage/field_sql_storage.test
index 783dc1b574055d6e7946b5b63c41ee4b37e7ac96..bbef5cc8f3300d9d695b2e8b1677d85e34de0574 100644
--- a/modules/field/modules/field_sql_storage/field_sql_storage.test
+++ b/modules/field/modules/field_sql_storage/field_sql_storage.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_sql_storage.test,v 1.21 2010/08/05 23:53:37 webchick Exp $
+// $Id: field_sql_storage.test,v 1.22 2010/09/29 01:37:02 dries Exp $
 
 /**
  * @file
@@ -392,4 +392,26 @@ class FieldSqlStorageTestCase extends DrupalWebTestCase {
       $this->assertEqual($details[FIELD_LOAD_REVISION][$revision][$column_name], $storage_column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => $revision)));
     }
   }
+
+  /**
+   * Test foreign key support.
+   */
+  function testFieldSqlStorageForeignKeys() {
+    // Create a decimal field.
+    $field_name = 'testfield';
+    $field = array('field_name' => $field_name, 'type' => 'text');
+    $field = field_create_field($field);
+    // Retrieve the field and instance with field_info and verify the foreign
+    // keys are in place.
+    $field = field_info_field($field_name);
+    $this->assertEqual($field['foreign keys']['format']['table'], 'filter_format', t('Foreign key table name preserved through CRUD'));
+    $this->assertEqual($field['foreign keys']['format']['columns']['format'], 'format', t('Foreign key column name preserved through CRUD'));
+    // Now grab the SQL schema and verify that too.
+    $schema = drupal_get_schema(_field_sql_storage_tablename($field));
+    $this->assertEqual(count($schema['foreign keys']), 1, t("There is 1 foreign key in the schema"));
+    $foreign_key = reset($schema['foreign keys']);
+    $filter_column = _field_sql_storage_columnname($field['field_name'], 'format');
+    $this->assertEqual($foreign_key['table'], 'filter_format', t('Foreign key table name preserved in the schema'));
+    $this->assertEqual($foreign_key['columns'][$filter_column], 'format', t('Foreign key column name preserved in the schema'));
+  }
 }
diff --git a/modules/field/modules/list/list.info b/modules/field/modules/list/list.info
index 37f2ff56484d682e9911b881dbdcc38283bd5916..23d0904227800394cb6c372f459d62ef09859a09 100644
--- a/modules/field/modules/list/list.info
+++ b/modules/field/modules/list/list.info
@@ -9,8 +9,8 @@ files[] = list.module
 files[] = tests/list.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/list/tests/list_test.info b/modules/field/modules/list/tests/list_test.info
index c3740709ee8fa78b0ac5bb91590047fa1a9d0063..2e356d89221b63995d2d372af9c10ec6f30e09f2 100644
--- a/modules/field/modules/list/tests/list_test.info
+++ b/modules/field/modules/list/tests/list_test.info
@@ -7,8 +7,8 @@ files[] = list_test.module
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/number/number.info b/modules/field/modules/number/number.info
index f6396b074d3debc66e09989a36fb405cdcb1b712..4a90975d5d541ffb9c7db44bb272e3f93e186f8a 100644
--- a/modules/field/modules/number/number.info
+++ b/modules/field/modules/number/number.info
@@ -8,8 +8,8 @@ dependencies[] = field
 files[] = number.module
 required = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/options/options.info b/modules/field/modules/options/options.info
index cb67005697aef1b7887af3c931facbe1272d6b89..596dff99abeb73b2dbd1cb8e63524ca8b5d4125d 100644
--- a/modules/field/modules/options/options.info
+++ b/modules/field/modules/options/options.info
@@ -9,8 +9,8 @@ files[] = options.module
 files[] = options.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/options/options.test b/modules/field/modules/options/options.test
index 3dfd9d910a83fcca412f5bdc7a87bb4310090ca1..729a1e172544a492c161114a78656879d1d37e82 100644
--- a/modules/field/modules/options/options.test
+++ b/modules/field/modules/options/options.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: options.test,v 1.16 2010/08/17 21:48:39 dries Exp $
+// $Id: options.test,v 1.17 2010/09/24 00:37:42 dries Exp $
 
 class OptionsWidgetsTestCase extends FieldTestCase {
   public static function getInfo() {
@@ -77,7 +77,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_test_entity_save($entity);
 
     // With no field data, no buttons are checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoFieldChecked("edit-card-1-$langcode-0");
     $this->assertNoFieldChecked("edit-card-1-$langcode-1");
     $this->assertNoFieldChecked("edit-card-1-$langcode-2");
@@ -89,7 +89,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Check that the selected button is checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-card-1-$langcode-0");
     $this->assertNoFieldChecked("edit-card-1-$langcode-1");
     $this->assertNoFieldChecked("edit-card-1-$langcode-2");
@@ -104,7 +104,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_update_field($this->card_1);
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-card-1-$langcode-99");
   }
 
@@ -134,7 +134,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_test_entity_save($entity);
 
     // Display form: with no field data, nothing is checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertNoFieldChecked("edit-card-2-$langcode-2");
@@ -150,7 +150,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertFieldChecked("edit-card-2-$langcode-2");
@@ -165,7 +165,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertNoFieldChecked("edit-card-2-$langcode-2");
@@ -194,7 +194,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_update_field($this->card_2);
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-99");
   }
 
@@ -222,7 +222,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_test_entity_save($entity);
 
     // Display form.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     // A required field without any value has a "none" option.
     $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- Select a value -'))), t('A required select list has a "Select a value" choice.'));
 
@@ -244,7 +244,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     // A required field with a value has no 'none' option.
     $this->assertFalse($this->xpath('//select[@id=:id]//option[@value="_none"]', array(':id' => 'edit-card-1-' . $langcode)), t('A required select list with an actual value has no "none" choice.'));
     $this->assertOptionSelected("edit-card-1-$langcode", 0);
@@ -256,12 +256,12 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_update_instance($instance);
 
     // Display form.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     // A non-required field has a 'none' option.
     $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1-' . $langcode, ':label' => t('- None -'))), t('A non-required select list has a "None" choice.'));
     // Submit form: Unselect the option.
     $edit = array("card_1[$langcode]" => '_none');
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
 
     // Test optgroups.
@@ -271,7 +271,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_update_field($this->card_1);
 
     // Display form: with no field data, nothing is selected
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
@@ -284,14 +284,14 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
 
     // Submit form: Unselect the option.
     $edit = array("card_1[$langcode]" => '_none');
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
   }
 
@@ -318,7 +318,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_test_entity_save($entity);
 
     // Display form: with no field data, nothing is selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -330,7 +330,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertOptionSelected("edit-card-2-$langcode", 2);
@@ -341,7 +341,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -361,18 +361,18 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     // Check that the 'none' option has no efect if actual options are selected
     // as well.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none', 0 => 0));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Check that selecting the 'none' option empties the field.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none'));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
 
     // A required select list does not have an empty key.
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2-' . $langcode)), t('A required select list does not have an empty key.'));
 
     // We do not have to test that a required select list with one option is
@@ -388,7 +388,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_update_instance($instance);
 
     // Display form: with no field data, nothing is selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -401,14 +401,14 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
 
     // Submit form: Unselect the option.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none'));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid . '/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
   }
 
@@ -435,7 +435,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     field_test_entity_save($entity);
 
     // Display form: with no field data, option is unchecked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoFieldChecked("edit-bool-$langcode");
     $this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', t('Option text was properly filtered.'));
 
@@ -445,7 +445,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'bool', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertFieldChecked("edit-bool-$langcode");
 
     // Submit form: uncheck the option.
@@ -454,7 +454,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, 'bool', $langcode, array(1));
 
     // Display form: with 'off' value, option is unchecked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid . '/edit');
     $this->assertNoFieldChecked("edit-bool-$langcode");
   }
 }
diff --git a/modules/field/modules/text/text.info b/modules/field/modules/text/text.info
index 0fc2b1c362ee7e4c5b072799c28e9707df4588f0..15ce9c09f542d88ac02f2fab180f4d9cac0fa9ee 100644
--- a/modules/field/modules/text/text.info
+++ b/modules/field/modules/text/text.info
@@ -9,8 +9,8 @@ files[] = text.module
 files[] = text.test
 required = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/modules/text/text.install b/modules/field/modules/text/text.install
index 4c41e80a7b92930c2c7ce6654e51dd4df0d8bae4..ce0178ceaa7440b9d4f663a687f09803ca28d084 100644
--- a/modules/field/modules/text/text.install
+++ b/modules/field/modules/text/text.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: text.install,v 1.1 2010/09/04 15:40:51 dries Exp $
+// $Id: text.install,v 1.2 2010/09/29 01:37:02 dries Exp $
 
 /**
  * @file
@@ -20,6 +20,7 @@ function text_field_schema($field) {
         ),
       );
       break;
+
     case 'text_long':
       $columns = array(
         'value' => array(
@@ -29,6 +30,7 @@ function text_field_schema($field) {
         ),
       );
       break;
+
     case 'text_with_summary':
       $columns = array(
         'value' => array(
@@ -56,5 +58,11 @@ function text_field_schema($field) {
     'indexes' => array(
       'format' => array('format'),
     ),
+    'foreign keys' => array(
+      'format' => array(
+        'table' => 'filter_format',
+        'columns' => array('format' => 'format'),
+      ),
+    ),
   );
 }
diff --git a/modules/field/modules/text/text.module b/modules/field/modules/text/text.module
index 4bbabccbf9556d57f35a626615506d5eded90c3a..5dae9c8b7dffb3b62300a97baac0ff9ded761550 100644
--- a/modules/field/modules/text/text.module
+++ b/modules/field/modules/text/text.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: text.module,v 1.64 2010/09/11 04:19:15 webchick Exp $
+// $Id: text.module,v 1.65 2010/09/18 02:18:35 dries Exp $
 
 /**
  * @file
@@ -600,16 +600,13 @@ function text_field_prepare_translation($entity_type, $entity, $field, $instance
 /**
  * Implements hook_filter_format_update().
  */
-function text_filter_format_update() {
+function text_filter_format_update($format) {
   field_cache_clear();
 }
 
 /**
- * Implements hook_filter_format_delete().
- *
- * @todo D8: Properly update filter format references in all fields. See
- *   http://drupal.org/node/556022 for details.
+ * Implements hook_filter_format_disable().
  */
-function text_filter_format_delete() {
+function text_filter_format_disable($format) {
   field_cache_clear();
 }
diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test
index 1843f36b6b80caa0cba73d165fa2cd87038041e5..eaab367c71b4796814747b0f8be4d04e469c34ce 100644
--- a/modules/field/modules/text/text.test
+++ b/modules/field/modules/text/text.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: text.test,v 1.27 2010/08/17 18:25:31 dries Exp $
+// $Id: text.test,v 1.29 2010/09/24 00:37:42 dries Exp $
 
 class TextFieldTestCase extends DrupalWebTestCase {
   protected $instance;
@@ -115,7 +115,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
       "{$this->field_name}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
@@ -163,11 +163,11 @@ class TextFieldTestCase extends DrupalWebTestCase {
     field_create_instance($this->instance);
     $langcode = LANGUAGE_NONE;
 
-    // Delete all text formats besides the plain text fallback format.
+    // Disable all text formats besides the plain text fallback format.
     $this->drupalLogin($this->admin_user);
     foreach (filter_formats() as $format) {
       if ($format->format != filter_fallback_format()) {
-        $this->drupalPost('admin/config/content/formats/' . $format->format . '/delete', array(), t('Delete'));
+        $this->drupalPost('admin/config/content/formats/' . $format->format . '/disable', array(), t('Disable'));
       }
     }
     $this->drupalLogin($this->web_user);
@@ -184,7 +184,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
       "{$this->field_name}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
@@ -210,7 +210,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
 
     // Display edition form.
     // We should now have a 'text format' selector.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
     $this->assertFieldByName("{$this->field_name}[$langcode][0][format]", '', t('Format selector is displayed'));
 
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index 41fecdbf6f89778af8cbe22ee4377f9d2e5586da..155ee5784b0f807e2772018f423196064c70add9 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: field.test,v 1.40 2010/09/11 06:03:11 webchick Exp $
+// $Id: field.test,v 1.42 2010/09/28 02:30:31 dries Exp $
 
 /**
  * @file
@@ -1259,14 +1259,14 @@ class FieldFormTestCase extends FieldTestCase {
     $value = mt_rand(1, 127);
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
     $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was saved');
 
     // Display edit form.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", $value, 'Widget is displayed with the correct default value');
     $this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
 
@@ -1281,7 +1281,7 @@ class FieldFormTestCase extends FieldTestCase {
     // Empty the field.
     $value = '';
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
     $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
     $entity = field_test_entity_test_load($id);
     $this->assertIdentical($entity->{$this->field_name}, array(), 'Field was emptied');
@@ -1306,7 +1306,7 @@ class FieldFormTestCase extends FieldTestCase {
     $value = mt_rand(1, 127);
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
@@ -1315,7 +1315,7 @@ class FieldFormTestCase extends FieldTestCase {
     // Edit with missing required value.
     $value = '';
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
     $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
   }
 
@@ -1384,7 +1384,7 @@ class FieldFormTestCase extends FieldTestCase {
 
     // Submit the form and create the entity.
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
@@ -1474,7 +1474,7 @@ class FieldFormTestCase extends FieldTestCase {
     // Create entity with three values.
     $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3');
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
 
     // Check that the values were saved.
@@ -1482,7 +1482,7 @@ class FieldFormTestCase extends FieldTestCase {
     $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
 
     // Display the form, check that the values are correctly filled in.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode]", '1, 2, 3', t('Widget is displayed.'));
 
     // Submit the form with more values than the field accepts.
@@ -1529,7 +1529,7 @@ class FieldFormTestCase extends FieldTestCase {
     // Create entity.
     $edit = array("{$field_name}[$langcode][0][value]" => 1);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
 
     // Check that the default value was saved.
@@ -1539,7 +1539,7 @@ class FieldFormTestCase extends FieldTestCase {
 
     // Create a new revision.
     $edit = array("{$field_name}[$langcode][0][value]" => 2, 'revision' => TRUE);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
 
     // Check that the new revision has the expected values.
     $entity = field_test_entity_test_load($id);
@@ -1616,7 +1616,7 @@ class FieldDisplayAPITestCase extends FieldTestCase {
     $settings = field_info_formatter_settings('field_test_default');
     $setting = $settings['test_formatter_setting'];
     $this->assertText($this->label, t('Label was displayed.'));
-    foreach($this->values as $delta => $value) {
+    foreach ($this->values as $delta => $value) {
       $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
     }
 
@@ -1633,7 +1633,7 @@ class FieldDisplayAPITestCase extends FieldTestCase {
     $setting = $display['settings']['test_formatter_setting_multiple'];
     $this->assertNoText($this->label, t('Label was not displayed.'));
     $array = array();
-    foreach($this->values as $delta => $value) {
+    foreach ($this->values as $delta => $value) {
       $array[] = $delta . ':' . $value['value'];
     }
     $this->assertText($setting . '|' . implode('|', $array), t('Values were displayed with expected setting.'));
@@ -1661,7 +1661,7 @@ class FieldDisplayAPITestCase extends FieldTestCase {
     $this->drupalSetContent(drupal_render($output));
     $setting = $this->instance['display']['teaser']['settings']['test_formatter_setting'];
     $this->assertText($this->label, t('Label was displayed.'));
-    foreach($this->values as $delta => $value) {
+    foreach ($this->values as $delta => $value) {
       $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
     }
 
@@ -1671,7 +1671,7 @@ class FieldDisplayAPITestCase extends FieldTestCase {
     $this->drupalSetContent(drupal_render($output));
     $setting = $this->instance['display']['default']['settings']['test_formatter_setting'];
     $this->assertText($this->label, t('Label was displayed.'));
-    foreach($this->values as $delta => $value) {
+    foreach ($this->values as $delta => $value) {
       $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
     }
   }
@@ -2721,7 +2721,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
     // Create a new revision.
     $langcode = field_valid_language(NULL);
     $edit = array("{$field_name}[$langcode][0][value]" => $entity->{$field_name}[$langcode][0]['value'], 'revision' => TRUE);
-    $this->drupalPost('test-entity/' . $eid . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $eid . '/edit', $edit, t('Save'));
 
     // Check translation revisions.
     $this->checkTranslationRevisions($eid, $eid, $available_languages);
diff --git a/modules/field/tests/field_test.entity.inc b/modules/field/tests/field_test.entity.inc
index 0ed6b4ffbbdc572057e46c63b9e394989258700b..39f2a69b2ec46747761ef501a57237be4f7d6702 100644
--- a/modules/field/tests/field_test.entity.inc
+++ b/modules/field/tests/field_test.entity.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_test.entity.inc,v 1.13 2010/09/11 06:03:11 webchick Exp $
+// $Id: field_test.entity.inc,v 1.14 2010/09/24 00:37:42 dries Exp $
 
 /**
  * @file
@@ -392,7 +392,7 @@ function field_test_entity_form_submit($form, &$form_state) {
   drupal_set_message($message);
 
   if ($entity->ftid) {
-    $form_state['redirect'] = 'test-entity/' . $entity->ftid . '/edit';
+    $form_state['redirect'] = 'test-entity/manage/' . $entity->ftid . '/edit';
   }
   else {
     // Error on save.
diff --git a/modules/field/tests/field_test.field.inc b/modules/field/tests/field_test.field.inc
index b7236192be47e6cf036456fde3cd8773ce878fd0..b75882fa768ad6f0b4c71bad66ed5fba25ca9ad5 100644
--- a/modules/field/tests/field_test.field.inc
+++ b/modules/field/tests/field_test.field.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_test.field.inc,v 1.12 2010/09/04 15:40:51 dries Exp $
+// $Id: field_test.field.inc,v 1.13 2010/09/28 02:30:31 dries Exp $
 
 /**
  * @file
@@ -184,7 +184,7 @@ function field_test_field_widget_form(&$form, &$form_state, $field, $instance, $
 function field_test_widget_multiple_validate($element, &$form_state) {
   $values = array_map('trim', explode(',', $element['#value']));
   $items = array();
-  foreach($values as $value) {
+  foreach ($values as $value) {
     $items[] = array('value' => $value);
   }
   form_set_value($element, $items, $form_state);
diff --git a/modules/field/tests/field_test.info b/modules/field/tests/field_test.info
index 7ecaabca357c87d8e869fd0f60775559c5c39847..9baafffc0d5733ee222a27177a7ee417eb2cfeb0 100644
--- a/modules/field/tests/field_test.info
+++ b/modules/field/tests/field_test.info
@@ -11,8 +11,8 @@ files[] = field_test.install
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field/tests/field_test.module b/modules/field/tests/field_test.module
index e031a4838fb0073308e09a5ad18eda02f35aa47e..baaef3f38b26799f82dca19a22322e66064c44dc 100644
--- a/modules/field/tests/field_test.module
+++ b/modules/field/tests/field_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_test.module,v 1.10 2010/09/11 06:03:11 webchick Exp $
+// $Id: field_test.module,v 1.12 2010/09/26 23:31:35 dries Exp $
 
 /**
  * @file
@@ -52,10 +52,10 @@ function field_test_menu() {
       'type' => MENU_NORMAL_ITEM,
     );
   }
-  $items['test-entity/%field_test_entity_test/edit'] = array(
+  $items['test-entity/manage/%field_test_entity_test/edit'] = array(
     'title' => 'Edit test entity',
     'page callback' => 'field_test_entity_edit',
-    'page arguments' => array(1),
+    'page arguments' => array(2),
     'access arguments' => array('administer field_test content'),
     'type' => MENU_NORMAL_ITEM,
   );
@@ -152,7 +152,7 @@ function field_test_field_language_alter(&$display_language, $context) {
 function field_test_memorize($key = NULL, $value = NULL) {
   $memorize = &drupal_static(__FUNCTION__, NULL);
 
-  if (is_null($key)) {
+  if (!isset($key)) {
     $return = $memorize;
     $memorize = array();
     return $return;
diff --git a/modules/field/tests/field_test.storage.inc b/modules/field/tests/field_test.storage.inc
index 7ef92101965d42bdae9ace3d86013afcc3b28d66..3a7a59a13111cade65c9b4252715f61fae595246 100644
--- a/modules/field/tests/field_test.storage.inc
+++ b/modules/field/tests/field_test.storage.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_test.storage.inc,v 1.6 2010/03/27 05:52:49 webchick Exp $
+// $Id: field_test.storage.inc,v 1.7 2010/09/26 23:31:35 dries Exp $
 
 /**
  * @file
@@ -70,7 +70,7 @@ function field_test_field_storage_details_alter(&$details, $field) {
  * Helper function: stores or retrieves data from the 'storage backend'.
  */
 function _field_test_storage_data($data = NULL) {
-  if (is_null($data)) {
+  if (!isset($data)) {
     return variable_get('field_test_storage_data', array());
   }
   else {
@@ -318,7 +318,7 @@ function field_test_field_storage_query($field_id, $conditions, $count, &$cursor
       }
 
       if ($match) {
-        if (is_null($skip) || $skipped >= $skip) {
+        if (!isset($skip) || $skipped >= $skip) {
           $cursor++;
           // If querying all revisions and the entity type has revisions, we need
           // to key the results by revision_ids.
diff --git a/modules/field_ui/field_ui.admin.inc b/modules/field_ui/field_ui.admin.inc
index a4fab1dadd4037675d4374bd02510fa4fd91c7c0..fb336d5627428906dd64b4ad2cba8db12c2f8b67 100644
--- a/modules/field_ui/field_ui.admin.inc
+++ b/modules/field_ui/field_ui.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_ui.admin.inc,v 1.65 2010/09/11 00:03:42 webchick Exp $
+// $Id: field_ui.admin.inc,v 1.71 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -68,7 +68,7 @@ function field_ui_inactive_message($entity_type, $bundle) {
  * This is intended as a callback for array_reduce().
  */
 function _field_ui_reduce_order($array, $a) {
-  $array = is_null($array) ? array() : $array;
+  $array = !isset($array) ? array() : $array;
   if ($a['name']) {
     $array[] = $a['name'];
   }
@@ -304,7 +304,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       t('Widget'),
       array('data' => t('Operations'), 'colspan' => 2),
     ),
-    '#parent_options' => array('' => t('<none>')),
+    '#parent_options' => array(),
     '#regions' => array(
       'main' => array(),
       'add_new' => array('title' => '&nbsp;'),
@@ -432,8 +432,6 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
   $field_type_options = field_ui_field_type_options();
   $widget_type_options = field_ui_widget_type_options(NULL, TRUE);
   if ($field_type_options && $widget_type_options) {
-    array_unshift($field_type_options, t('- Select a field type -'));
-    array_unshift($widget_type_options, t('- Select a widget -'));
     $name = '_add_new_field';
     $table[$name] = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
@@ -482,6 +480,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       'type' => array(
         '#type' => 'select',
         '#options' => $field_type_options,
+        '#empty_option' => t('- Select a field type -'),
         '#description' => t('Type of data to store.'),
         '#attributes' => array('class' => array('field-type-select')),
         '#prefix' => '<div class="add-new-placeholder">&nbsp;</div>',
@@ -489,6 +488,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       'widget_type' => array(
         '#type' => 'select',
         '#options' => $widget_type_options,
+        '#empty_option' => t('- Select a widget -'),
         '#description' => t('Form element to edit the data.'),
         '#attributes' => array('class' => array('widget-type-select')),
         '#cell_attributes' => array('colspan' => 3),
@@ -500,7 +500,6 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
   // Additional row: add existing field.
   $existing_field_options = field_ui_existing_field_options($entity_type, $bundle);
   if ($existing_field_options && $widget_type_options) {
-    array_unshift($existing_field_options, t('- Select an existing field -'));
     $name = '_add_existing_field';
     $table[$name] = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf', 'add-new')),
@@ -540,6 +539,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       'field_name' => array(
         '#type' => 'select',
         '#options' => $existing_field_options,
+        '#empty_option' => t('- Select an existing field -'),
         '#description' => t('Field to share'),
         '#attributes' => array('class' => array('field-select')),
         '#cell_attributes' => array('colspan' => 2),
@@ -548,6 +548,7 @@ function field_ui_field_overview_form($form, &$form_state, $entity_type, $bundle
       'widget_type' => array(
         '#type' => 'select',
         '#options' => $widget_type_options,
+        '#empty_option' => t('- Select a widget -'),
         '#description' => t('Form element to edit the data.'),
         '#attributes' => array('class' => array('widget-type-select')),
         '#cell_attributes' => array('colspan' => 3),
@@ -747,7 +748,7 @@ function field_ui_field_overview_form_submit($form, &$form_state) {
       field_create_instance($instance);
 
       $destinations[] = $admin_path . '/fields/' . $field['field_name'] . '/field-settings';
-      $destinations[] = $admin_path . '/fields/' . $field['field_name'] . '/edit';
+      $destinations[] = $admin_path . '/fields/' . $field['field_name'];
 
       // Store new field information for any additional submit handlers.
       $form_state['fields_added']['_add_new_field'] = $field['field_name'];
@@ -844,7 +845,7 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
       'visible' => array('message' => t('No field is displayed.')),
       'hidden' => array('title' => t('Hidden'), 'message' => t('No field is hidden.')),
     ),
-    '#parent_options' => array('' => t('<none>')),
+    '#parent_options' => array(),
     '#attributes' => array(
       'class' => array('field-ui-overview'),
       'id' => 'field-display-overview',
@@ -889,7 +890,6 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
         'parent' => array(
           '#type' => 'select',
           '#options' => $table['#parent_options'],
-          '#default_value' => '',
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
         ),
@@ -1043,7 +1043,6 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
         'parent' => array(
           '#type' => 'select',
           '#options' => $table['#parent_options'],
-          '#default_value' => '',
           '#attributes' => array('class' => array('field-parent')),
           '#parents' => array('fields', $name, 'parent'),
         ),
@@ -1114,7 +1113,7 @@ function field_ui_display_overview_form($form, &$form_state, $entity_type, $bund
     '#op' => 'refresh_table',
     // Do not check errors, but make sure we get the values of the
     // 'refresh_rows' input.
-    '#limit_validation_errors' => array('refresh_rows'),
+    '#limit_validation_errors' => array(array('refresh_rows')),
     '#submit' => array('field_ui_display_overview_multistep_submit'),
     '#ajax' => array(
       'callback' => 'field_ui_display_overview_multistep_js',
@@ -1648,13 +1647,22 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
   $bundles = field_info_bundles();
 
   // Create a form structure for the instance values.
-  $form['instance'] = array(
+  // @todo Fieldset element info needs to be merged in order to not skip the
+  //   default element definition for #pre_render. While the current default
+  //   value could simply be hard-coded, we'd possibly forget this location
+  //   when system_element_info() is updated. See also form_builder(). This
+  //   particular #pre_render, field_ui_field_edit_instance_pre_render(), might
+  //   as well be entirely needless though.
+  $form['instance'] = array_merge(element_info('fieldset'), array(
     '#tree' => TRUE,
     '#type' => 'fieldset',
     '#title' => t('%type settings', array('%type' => $bundles[$entity_type][$bundle]['label'])),
-    '#description' => t('These settings apply only to the %field field when used in the %type type.', array('%field' => $instance['label'], '%type' => $bundles[$entity_type][$bundle]['label'])),
+    '#description' => t('These settings apply only to the %field field when used in the %type type.', array(
+      '%field' => $instance['label'],
+      '%type' => $bundles[$entity_type][$bundle]['label'],
+    )),
     '#pre_render' => array('field_ui_field_edit_instance_pre_render'),
-  );
+  ));
 
   // Build the non-configurable instance values.
   $form['instance']['field_name'] = array(
@@ -1695,7 +1703,6 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
     '#default_value' => !empty($instance['description']) ? $instance['description'] : '',
     '#rows' => 5,
     '#description' => t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())),
-    '#required' => FALSE,
     '#weight' => 0,
   );
 
diff --git a/modules/field_ui/field_ui.info b/modules/field_ui/field_ui.info
index deefc225d69e0944f2336bafc94376a8864cfa5c..43640fc05909aafa661bf7c8280c2d35a618f114 100644
--- a/modules/field_ui/field_ui.info
+++ b/modules/field_ui/field_ui.info
@@ -9,8 +9,8 @@ files[] = field_ui.module
 files[] = field_ui.admin.inc
 files[] = field_ui.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/field_ui/field_ui.js b/modules/field_ui/field_ui.js
index e02d035d8bed82c1947452a1e399c2d4f3c68f46..2aa77310070ef286c3181a18fe6ae9e9cdbe7c26 100644
--- a/modules/field_ui/field_ui.js
+++ b/modules/field_ui/field_ui.js
@@ -1,4 +1,4 @@
-// $Id: field_ui.js,v 1.5 2010/09/11 00:03:42 webchick Exp $
+// $Id: field_ui.js,v 1.6 2010/10/06 13:09:11 dries Exp $
 
 (function($) {
 
@@ -203,7 +203,7 @@ Drupal.fieldUIOverview = {
   },
 
   /**
-   * Triigers AJAX refresh of selected rows.
+   * Triggers AJAX refresh of selected rows.
    *
    * The 'format type' selects can trigger a series of changes in child rows.
    * The #ajax behavior is therefore not attached directly to the selects, but
@@ -297,7 +297,6 @@ Drupal.fieldUIDisplayOverview.field.prototype = {
    *   Drupal.displayOverview.AJAXRefreshRows().
    */
   regionChange: function (region) {
-    $.debug(this.region + ' --> ' + region, this.name);
 
     // When triggered by a row drag, the 'format' select needs to be adjusted
     // to the new region.
diff --git a/modules/field_ui/field_ui.module b/modules/field_ui/field_ui.module
index 48690a5c83e79e35c94d2a654875ee28144341f6..21ce45033c7122485c699ce4937cca0c679588c9 100644
--- a/modules/field_ui/field_ui.module
+++ b/modules/field_ui/field_ui.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: field_ui.module,v 1.32 2010/09/11 00:03:42 webchick Exp $
+// $Id: field_ui.module,v 1.33 2010/09/24 00:37:42 dries Exp $
 
 /**
  * @file
@@ -114,7 +114,6 @@ function field_ui_menu() {
             'title arguments' => array($field_position),
             'page callback' => 'drupal_get_form',
             'page arguments' => array('field_ui_field_edit_form', $field_position),
-            'type' => MENU_LOCAL_TASK,
             'file' => 'field_ui.admin.inc',
           ) + $access;
           $items["$path/fields/%field_ui_menu/edit"] = array(
diff --git a/modules/file/file.field.inc b/modules/file/file.field.inc
index b7372c412bd95be291cd1f265056742996aa986a..61c37b1e345596e34cf6341136f948fec2f0d649 100644
--- a/modules/file/file.field.inc
+++ b/modules/file/file.field.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.field.inc,v 1.34 2010/09/09 23:28:16 webchick Exp $
+// $Id: file.field.inc,v 1.35 2010/10/01 01:32:59 webchick Exp $
 
 /**
  * @file
@@ -441,7 +441,6 @@ function file_field_widget_settings_form($field, $instance) {
  * Implements hook_field_widget_form().
  */
 function file_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $form['#attributes'] = array('enctype' => 'multipart/form-data');
 
   $defaults = array(
     'fid' => 0,
diff --git a/modules/file/file.info b/modules/file/file.info
index e0dd7d9be193d475f43b27a2438f508b0e6280c7..7c1c7d96ae7bf6059b5529d582ae6ad6e7179b2b 100644
--- a/modules/file/file.info
+++ b/modules/file/file.info
@@ -10,8 +10,8 @@ files[] = file.field.inc
 files[] = file.install
 files[] = tests/file.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/file/file.install b/modules/file/file.install
index 5a44efdc40f28d1a2d1526072f7df00536b55ba4..995c332c93af0bd118e47a983dbb27b13cfb090d 100644
--- a/modules/file/file.install
+++ b/modules/file/file.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.install,v 1.3 2010/09/04 15:40:51 dries Exp $
+// $Id: file.install,v 1.4 2010/09/29 01:37:03 dries Exp $
 
 /**
  * @file
@@ -35,6 +35,12 @@ function file_field_schema($field) {
     'indexes' => array(
       'fid' => array('fid'),
     ),
+    'foreign keys' => array(
+      'fid' => array(
+        'table' => 'file',
+        'columns' => array('fid' => 'fid'),
+      ),
+    ),
   );
 }
 
diff --git a/modules/file/file.js b/modules/file/file.js
index e6661cc76e1b6dfdcac387417285ec3351c0416d..774e525072e84d44d88922c9e0592e26feed79f0 100644
--- a/modules/file/file.js
+++ b/modules/file/file.js
@@ -1,4 +1,4 @@
-// $Id: file.js,v 1.4 2010/07/10 00:03:37 webchick Exp $
+// $Id: file.js,v 1.5 2010/09/28 02:31:52 dries Exp $
 
 /**
  * @file
@@ -65,7 +65,7 @@ Drupal.file = Drupal.file || {
     if (accept.length > 1 && this.value.length > 0) {
       var acceptableMatch = new RegExp('\\.(' + accept + ')$', 'gi');
       if (!acceptableMatch.test(this.value)) {
-        var error = Drupal.t("The selected file %filename cannot not be uploaded. Only files with the following extensions are allowed: %extensions.", {
+        var error = Drupal.t("The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.", {
           '%filename': this.value,
           '%extensions': accept.replace(/\|/g, ', ')
         });
diff --git a/modules/file/file.module b/modules/file/file.module
index fcda65bc9096c5f3cc1fd2f78bc52c28d3c5f4bc..73d54930dca6f3d45d5c865962dd6a6a4a9fefd7 100644
--- a/modules/file/file.module
+++ b/modules/file/file.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.module,v 1.40 2010/09/13 01:09:25 dries Exp $
+// $Id: file.module,v 1.42 2010/10/04 17:46:01 dries Exp $
 
 /**
  * @file
@@ -41,12 +41,14 @@ function file_menu() {
     'page callback' => 'file_ajax_upload',
     'delivery callback' => 'ajax_deliver',
     'access arguments' => array('access content'),
+    'theme callback' => 'ajax_base_page_theme',
     'type' => MENU_CALLBACK,
   );
   $items['file/progress'] = array(
     'page callback' => 'file_ajax_progress',
     'delivery callback' => 'ajax_deliver',
     'access arguments' => array('access content'),
+    'theme callback' => 'ajax_base_page_theme',
     'type' => MENU_CALLBACK,
   );
 
@@ -390,7 +392,6 @@ function file_managed_file_process($element, &$form_state, $form) {
     '#value' => t('Upload'),
     '#validate' => array(),
     '#submit' => array('file_managed_file_submit'),
-    '#limit_validation_errors' => array($element['#parents']),
     '#ajax' => $ajax_settings,
     '#weight' => -5,
   );
@@ -404,11 +405,16 @@ function file_managed_file_process($element, &$form_state, $form) {
     '#value' => t('Remove'),
     '#validate' => array(),
     '#submit' => array('file_managed_file_submit'),
-    '#limit_validation_errors' => array($element['#parents']),
     '#ajax' => $ajax_settings,
     '#weight' => -5,
   );
 
+  // Limit validation errors to the file field only. The entire field is needed later
+  // by file_field_widget_form(), so the last element is sliced off the #parents array
+  // to avoid removing too much from $form_state['values'].
+  $element['upload_button']['#limit_validation_errors'] = array(array_slice($element['#parents'], 0, -1));
+  $element['remove_button']['#limit_validation_errors'] = array(array_slice($element['#parents'], 0, -1));
+
   $element['fid'] = array(
     '#type' => 'hidden',
     '#value' => $fid,
diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test
index 7e1457e69e9685c5c880dbb0a3166277ce593fcf..177aaa1efc64176b6e979155b7480cd5b983784c 100644
--- a/modules/file/tests/file.test
+++ b/modules/file/tests/file.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.test,v 1.25 2010/09/11 21:14:31 webchick Exp $
+// $Id: file.test,v 1.26 2010/10/01 01:32:59 webchick Exp $
 
 /**
  * @file
@@ -114,8 +114,8 @@ class FileFieldTestCase extends DrupalWebTestCase {
     );
 
     if (is_numeric($nid_or_type)) {
-      $node = node_load($nid_or_type);
-      $delta = isset($node->$field_name) ? count($node->$field_name) : 0;
+      $node = node_load($nid_or_type, NULL, TRUE);
+      $delta = isset($node->{$field_name}[LANGUAGE_NONE]) ? count($node->{$field_name}[LANGUAGE_NONE]) : 0;
       $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']'] = drupal_realpath($file->uri);
       $this->drupalPost('node/' . $nid_or_type . '/edit', $edit, t('Save'));
     }
@@ -280,6 +280,17 @@ class FileFieldWidgetTestCase extends FileFieldTestCase {
       $this->assertTrue(empty($node->{$field_name}[LANGUAGE_NONE][0]['fid']), t('File was successfully removed from the node.'));
     }
 
+    // Test partial form submissions using the Upload button on a multivalue field.
+    field_delete_field($field_name);
+    $this->createFileField($field_name, $type_name, array('cardinality' => 3));
+
+    $this->drupalGet("node/add/$type_name");
+    for ($delta = 0; $delta < 3; $delta++) {
+      $edit = array('files[' . $field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']' => drupal_realpath($test_file->uri));
+      $this->drupalPost(NULL, $edit, t('Upload'));
+    }
+    $this->assertNoFieldByXpath('//input[@type="submit"]', t('Upload'), t('After uploading 3 files, the "Upload" button is no longer displayed.'));
+
     // Test private download method.
     $edit = array('field[settings][uri_scheme]' => 'private');
     $this->drupalPost("admin/structure/types/manage/$type_name/fields/$field_name", $edit, t('Save settings'));
diff --git a/modules/file/tests/file_module_test.info b/modules/file/tests/file_module_test.info
index 4c4bf6e574af987badf3e5fff214023cff7937ab..08bb0079dc64cc5eef2236d1d778935e003793ec 100644
--- a/modules/file/tests/file_module_test.info
+++ b/modules/file/tests/file_module_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = file_module_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/filter/filter.admin.inc b/modules/filter/filter.admin.inc
index e793b69d0ba2cbc0ba41c9e6010e540a38ada5c4..a1c841733e40ceb67a086049d1ed5b4a97f63a5f 100644
--- a/modules/filter/filter.admin.inc
+++ b/modules/filter/filter.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.admin.inc,v 1.64 2010/08/17 13:50:52 dries Exp $
+// $Id: filter.admin.inc,v 1.66 2010/09/29 19:52:12 dries Exp $
 
 /**
  * @file
@@ -20,7 +20,7 @@ function filter_admin_overview($form) {
   $form['#tree'] = TRUE;
   foreach ($formats as $id => $format) {
     // Check whether this is the fallback text format. This format is available
-    // to all roles and cannot be deleted via the admin interface.
+    // to all roles and cannot be disabled via the admin interface.
     $form['formats'][$id]['#is_fallback'] = ($id == $fallback_format);
     if ($form['formats'][$id]['#is_fallback']) {
       $form['formats'][$id]['name'] = array('#markup' => drupal_placeholder($format->name));
@@ -33,7 +33,7 @@ function filter_admin_overview($form) {
     }
     $form['formats'][$id]['roles'] = array('#markup' => $roles_markup);
     $form['formats'][$id]['configure'] = array('#type' => 'link', '#title' => t('configure'), '#href' => 'admin/config/content/formats/' . $id);
-    $form['formats'][$id]['delete'] = array('#type' => 'link', '#title' => t('delete'), '#href' => 'admin/config/content/formats/' . $id . '/delete', '#access' => !$form['formats'][$id]['#is_fallback']);
+    $form['formats'][$id]['disable'] = array('#type' => 'link', '#title' => t('disable'), '#href' => 'admin/config/content/formats/' . $id . '/disable', '#access' => !$form['formats'][$id]['#is_fallback']);
     $form['formats'][$id]['weight'] = array('#type' => 'weight', '#default_value' => $format->weight);
   }
   $form['actions'] = array('#type' => 'actions');
@@ -76,7 +76,7 @@ function theme_filter_admin_overview($variables) {
         drupal_render($form['formats'][$id]['roles']),
         drupal_render($form['formats'][$id]['weight']),
         drupal_render($form['formats'][$id]['configure']),
-        drupal_render($form['formats'][$id]['delete']),
+        drupal_render($form['formats'][$id]['disable']),
       ),
       'class' => array('draggable'),
     );
@@ -317,40 +317,26 @@ function filter_admin_format_form_submit($form, &$form_state) {
  * Menu callback; confirm deletion of a format.
  *
  * @ingroup forms
- * @see filter_admin_delete_submit()
+ * @see filter_admin_disable_submit()
  */
-function filter_admin_delete($form, &$form_state, $format) {
+function filter_admin_disable($form, &$form_state, $format) {
   $form['#format'] = $format;
 
-  $fallback_options = array();
-  foreach (filter_formats() as $id => $fallback_format) {
-    if ($id != $format->format) {
-      $fallback_options[$id] = $fallback_format->name;
-    }
-  }
-  $form['fallback'] = array(
-    '#type' => 'select',
-    '#title' => t('Replacement text format'),
-    '#options' => $fallback_options,
-    '#default_value' => filter_fallback_format(),
-    '#description' => t('Content assigned to the deleted text format will be reassigned to the chosen one.'),
-  );
-
   return confirm_form($form,
-    t('Are you sure you want to delete the text format %format?', array('%format' => $format->name)),
+    t('Are you sure you want to disable the text format %format?', array('%format' => $format->name)),
     'admin/config/content/formats',
-    NULL,
-    t('Delete')
+    t('Disabled text formats are completely removed from the administrative interface, and any content stored with that format will not be displayed. This action cannot be undone.'),
+    t('Disable')
   );
 }
 
 /**
- * Process filter delete form submission.
+ * Process filter disable form submission.
  */
-function filter_admin_delete_submit($form, &$form_state) {
+function filter_admin_disable_submit($form, &$form_state) {
   $format = $form['#format'];
-  filter_format_delete($format, $form_state['values']['fallback']);
-  drupal_set_message(t('Deleted text format %format.', array('%format' => $format->name)));
+  filter_format_disable($format);
+  drupal_set_message(t('Disabled text format %format.', array('%format' => $format->name)));
 
   $form_state['redirect'] = 'admin/config/content/formats';
 }
diff --git a/modules/filter/filter.api.php b/modules/filter/filter.api.php
index 95d79ef70bf5bdcbac7696048ac5a27aaa037abc..4d59a26f9698778f2007b920f908aca79abd2da8 100644
--- a/modules/filter/filter.api.php
+++ b/modules/filter/filter.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.api.php,v 1.20 2010/06/26 01:55:29 dries Exp $
+// $Id: filter.api.php,v 1.21 2010/09/18 02:18:35 dries Exp $
 
 /**
  * @file
@@ -209,7 +209,7 @@ function hook_filter_info_alter(&$info) {
  *   The format object of the format being updated.
  *
  * @see hook_filter_format_update()
- * @see hook_filter_format_delete()
+ * @see hook_filter_format_disable()
  */
 function hook_filter_format_insert($format) {
   mymodule_cache_rebuild();
@@ -226,34 +226,23 @@ function hook_filter_format_insert($format) {
  *   The format object of the format being updated.
  *
  * @see hook_filter_format_insert()
- * @see hook_filter_format_delete()
+ * @see hook_filter_format_disable()
  */
 function hook_filter_format_update($format) {
   mymodule_cache_rebuild();
 }
 
 /**
- * Perform actions when a text format has been deleted.
- *
- * All modules storing references to text formats have to implement this hook.
- *
- * When a text format is deleted, all content that previously had that format
- * assigned needs to be switched to the passed fallback format.
+ * Perform actions when a text format has been disabled.
  *
  * @param $format
- *   The format object of the format being deleted.
- * @param $fallback
- *   The format object of the format to use as replacement.
+ *   The format object of the format being disabled.
  *
  * @see hook_filter_format_insert()
  * @see hook_filter_format_update()
  */
-function hook_filter_format_delete($format, $fallback) {
-  // Replace the deleted format with the fallback format.
-  db_update('my_module_table')
-    ->fields(array('format' => $fallback->format))
-    ->condition('format', $format->format)
-    ->execute();
+function hook_filter_format_disable($format) {
+  mymodule_cache_rebuild();
 }
 
 /**
diff --git a/modules/filter/filter.css b/modules/filter/filter.css
index d8cc5a725d1ac90aba12b8141657712f43fbfc3f..4fe4af994e128e332bc05ff09c6cd9d4a1dba1ee 100644
--- a/modules/filter/filter.css
+++ b/modules/filter/filter.css
@@ -1,4 +1,4 @@
-/* $Id: filter.css,v 1.5 2010/07/20 10:11:54 dries Exp $ */
+/* $Id: filter.css,v 1.6 2010/09/19 18:10:41 dries Exp $ */
 
 .text-format-wrapper .form-item {
   margin-bottom: 0;
@@ -44,3 +44,11 @@
 input#edit-filters-filter-html-settings-allowed-html {
   width: 100%;
 }
+
+.tips {
+  margin-top: 0;
+  margin-bottom: 0;
+  padding-top: 0;
+  padding-bottom: 0;
+  font-size: 0.9em;
+}
diff --git a/modules/filter/filter.info b/modules/filter/filter.info
index 14a168ee6a1f2c6ca9e3d36bc86dab6a72f6956b..d233b76704808ea45cbda30feddbd0cb73134125 100644
--- a/modules/filter/filter.info
+++ b/modules/filter/filter.info
@@ -12,8 +12,8 @@ files[] = filter.test
 required = TRUE
 configure = admin/config/content/formats
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/filter/filter.install b/modules/filter/filter.install
index 1297c0bfe76a98e59b9f99434444342dadfe4fcf..fd82ae19499ecb2ede03efa44c012a080435b737 100644
--- a/modules/filter/filter.install
+++ b/modules/filter/filter.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.install,v 1.44 2010/09/13 05:50:09 webchick Exp $
+// $Id: filter.install,v 1.46 2010/09/28 03:30:37 webchick Exp $
 
 /**
  * @file
@@ -81,19 +81,27 @@ function filter_schema() {
         'size' => 'tiny',
         'description' => 'Flag to indicate whether format is cacheable. (1 = cacheable, 0 = not cacheable)',
       ),
+      'status' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 1,
+        'size' => 'tiny',
+        'description' => 'The status of the text format. (1 = enabled, 0 = disabled)',
+      ),
       'weight' => array(
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
         'description' => 'Weight of text format to use when listing.',
-      )
+      ),
     ),
     'primary key' => array('format'),
     'unique keys' => array(
       'name' => array('name'),
     ),
     'indexes' => array(
-      'weight' => array('weight'),
+      'status_weight' => array('status', 'weight'),
     ),
   );
 
@@ -162,7 +170,15 @@ function filter_update_dependencies() {
 function filter_update_7000() {
   db_rename_table('filter_formats', 'filter_format');
 
-  // Add a new filter_format.weight column.
+  // Add the new {filter_format}.status and {filter_format}.weight column.
+  db_add_field('filter_format', 'status', array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+    'default' => 1,
+    'size' => 'tiny',
+    'description' => 'The status of the text format. (1 = enabled, 0 = disabled)',
+  ));
   db_add_field('filter_format', 'weight', array(
     'type' => 'int',
     'not null' => TRUE,
@@ -170,7 +186,7 @@ function filter_update_7000() {
     'description' => 'Weight of text format to use when listing.',
   ), array(
     'indexes' => array(
-      'weight' => array('weight'),
+      'status_weight' => array('status', 'weight'),
     ),
   ));
 }
@@ -367,6 +383,7 @@ function filter_update_7005() {
       'name' => $format_name,
       'cache' => 1,
       'weight' => 1,
+      'status' => 1,
     ))
     ->execute();
 
@@ -418,7 +435,7 @@ function filter_update_7005() {
     ->execute();
 
   // We do not delete the 'filter_default_format' variable, since other modules
-  // may need it in their update functions.
+  // need it in their update functions; for an example, see user_update_7010().
   // @todo This variable can be deleted in Drupal 8.
 }
 
diff --git a/modules/filter/filter.module b/modules/filter/filter.module
index d36253dab442735bd4505c9391648fc2e403f82c..aed3c218988ec279265617b45ab7de8e8a7244c7 100644
--- a/modules/filter/filter.module
+++ b/modules/filter/filter.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.module,v 1.343 2010/09/11 03:30:03 dries Exp $
+// $Id: filter.module,v 1.351 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -114,7 +114,6 @@ function filter_menu() {
     'file' => 'filter.admin.inc',
   );
   $items['admin/config/content/formats/%filter_format'] = array(
-    'type' => MENU_CALLBACK,
     'title callback' => 'filter_admin_format_title',
     'title arguments' => array(4),
     'page callback' => 'filter_admin_format_page',
@@ -122,13 +121,12 @@ function filter_menu() {
     'access arguments' => array('administer filters'),
     'file' => 'filter.admin.inc',
   );
-  $items['admin/config/content/formats/%filter_format/delete'] = array(
-    'title' => 'Delete text format',
+  $items['admin/config/content/formats/%filter_format/disable'] = array(
+    'title' => 'Disable text format',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('filter_admin_delete', 4),
-    'access callback' => '_filter_delete_format_access',
+    'page arguments' => array('filter_admin_disable', 4),
+    'access callback' => '_filter_disable_format_access',
     'access arguments' => array(4),
-    'type' => MENU_CALLBACK,
     'file' => 'filter.admin.inc',
   );
   return $items;
@@ -140,11 +138,11 @@ function filter_menu() {
  * @param $format
  *   A text format object.
  * @return
- *   TRUE if the text format can be deleted by the current user, FALSE
+ *   TRUE if the text format can be disabled by the current user, FALSE
  *   otherwise.
  */
-function _filter_delete_format_access($format) {
-  // The fallback format can never be deleted.
+function _filter_disable_format_access($format) {
+  // The fallback format can never be disabled.
   return user_access('administer filters') && ($format->format != filter_fallback_format());
 }
 
@@ -187,6 +185,7 @@ function filter_format_load($format_id) {
 function filter_format_save(&$format) {
   $format->name = trim($format->name);
   $format->cache = _filter_format_is_cacheable($format);
+  $format->status = 1;
   // Programmatic saves may not contain any filters.
   if (!isset($format->filters)) {
     $format->filters = array();
@@ -256,31 +255,26 @@ function filter_format_save(&$format) {
 }
 
 /**
- * Delete a text format.
+ * Disable a text format.
+ *
+ * There is no core facility to re-enable a disabled format. It is not deleted
+ * to keep information for contrib and to make sure the format auto increment
+ * id is never reused. As there might be content using the disabled format,
+ * this would lead to data corruption.
  *
  * @param $format
- *   The text format object to be deleted.
- * @param $fallback_id
- *   (optional) The ID of the text format to use to reassign content that is
- *   currently using $format. If omitted, the currently stored
- *   filter_fallback_format() is used.
+ *   The text format object to be disabled.
  */
-function filter_format_delete($format, $fallback_id = NULL) {
-  db_delete('filter_format')
-    ->condition('format', $format->format)
-    ->execute();
-  db_delete('filter')
+function filter_format_disable($format) {
+  db_update('filter_format')
+    ->fields(array('status' => 0))
     ->condition('format', $format->format)
     ->execute();
 
   // Allow modules to react on text format deletion.
-  if (empty($fallback_id)) {
-    $fallback_id = filter_fallback_format();
-  }
-  $fallback = filter_format_load($fallback_id);
-  module_invoke_all('filter_format_delete', $format, $fallback);
+  module_invoke_all('filter_format_disable', $format);
 
-  // Clear the filter cache whenever a text format is deleted.
+  // Clear the filter cache whenever a text format is disabled.
   filter_formats_reset();
   cache_clear_all($format->format . ':', 'cache_filter', TRUE);
 }
@@ -381,6 +375,7 @@ function filter_formats($account = NULL) {
     $formats['all'] = db_select('filter_format', 'ff')
       ->addTag('translatable')
       ->fields('ff')
+      ->condition('status', 1)
       ->orderBy('weight')
       ->execute()
       ->fetchAllAssoc('format');
@@ -488,7 +483,7 @@ function filter_default_format($account = NULL) {
  *
  * The fallback text format is a regular text format in every respect, except
  * it does not participate in the filter permission system and cannot be
- * deleted. It needs to exist because any user who has permission to create
+ * disabled. It needs to exist because any user who has permission to create
  * formatted content must always have at least one text format they can use.
  *
  * Because the fallback format is available to all users, it should always be
@@ -503,15 +498,19 @@ function filter_default_format($account = NULL) {
  * the fallback format's weight determines its placement with respect to the
  * user's other formats.
  *
- * @see hook_filter_format_delete()
+ * Any modules implementing a format deletion functionality must not delete
+ * this format.
+ *
+ * @see hook_filter_format_disable()
  * @see filter_default_format()
  */
 function filter_fallback_format() {
   // This variable is automatically set in the database for all installations
-  // of Drupal. In the event that it gets deleted somehow, there is no safe
-  // default to return, since we do not want to risk making an existing (and
-  // potentially unsafe) text format on the site automatically available to all
-  // users. Returning NULL at least guarantees that this cannot happen.
+  // of Drupal. In the event that it gets disabled or deleted somehow, there
+  // is no safe default to return, since we do not want to risk making an 
+  // existing (and potentially unsafe) text format on the site automatically
+  // available to all users. Returning NULL at least guarantees that this
+  // cannot happen.
   return variable_get('filter_fallback_format');
 }
 
@@ -679,7 +678,7 @@ function filter_list_format($format_id) {
  * @ingroup sanitization
  */
 function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE) {
-  if (empty($format_id)) {
+  if (!isset($format_id)) {
     $format_id = filter_fallback_format();
   }
   // If the requested text format does not exist, the text cannot be filtered.
@@ -752,8 +751,8 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE)
  *   The form element to process. Properties used:
  *   - #base_type: The form element #type to use for the 'value' element.
  *     'textarea' by default.
- *   - #format: (optional) The text format id to preselect. If 0, NULL, or not
- *     set, the default format for the current user will be used.
+ *   - #format: (optional) The text format id to preselect. If NULL or not set,
+ *     the default format for the current user will be used.
  *
  * @return
  *   The expanded element.
@@ -821,9 +820,10 @@ function filter_process_format($element) {
   }
 
   // Use the default format for this user if none was selected.
-  if (empty($element['#format'])) {
+  if (!isset($element['#format'])) {
     $element['#format'] = filter_default_format($user);
   }
+
   $element['format']['format'] = array(
     '#type' => 'select',
     '#title' => t('Text format'),
@@ -842,20 +842,31 @@ function filter_process_format($element) {
     '#weight' => 0,
   );
 
-  // Lastly, disallow editing of this field if the user is not allowed to use
-  // the stored and preselected text format. But only, if that format actually
-  // exists.
   $all_formats = filter_formats();
-  if (!isset($formats[$element['#format']]) && isset($all_formats[$element['#format']])) {
+  $format_exists = isset($all_formats[$element['#format']]);
+  $user_has_access = isset($formats[$element['#format']]);
+  $user_is_admin = user_access('administer filters');
+
+  // If the stored format does not exist, administrators have to assign a new
+  // format.
+  if (!$format_exists && $user_is_admin) {
+    $element['format']['format']['#required'] = TRUE;
+    $element['format']['format']['#default_value'] = NULL;
+    // Force access to the format selector (it may have been denied above if
+    // the user only has access to a single format).
+    $element['format']['format']['#access'] = TRUE;
+  }
+  // Disable this widget, if the user is not allowed to use the stored format,
+  // or if the stored format does not exist. The 'administer filters' permission
+  // only grants access to the filter administration, not to all formats.
+  elseif (!$user_has_access || !$format_exists) {
     // Overload default values into #value to make them unalterable.
     $element['value']['#value'] = $element['value']['#default_value'];
     $element['format']['format']['#value'] = $element['format']['format']['#default_value'];
 
     // Prepend #pre_render callback to replace field value with user notice
     // prior to rendering.
-    if (!isset($element['value']['#pre_render'])) {
-      $element['value']['#pre_render'] = array();
-    }
+    $element['value'] += array('#pre_render' => array());
     array_unshift($element['value']['#pre_render'], 'filter_form_access_denied');
 
     // Cosmetic adjustments.
@@ -1014,11 +1025,11 @@ function filter_dom_serialize($dom_document) {
   $body_node = $dom_document->getElementsByTagName('body')->item(0);
   $body_content = '';
 
-  foreach($body_node->getElementsByTagName('script') as $node) {
+  foreach ($body_node->getElementsByTagName('script') as $node) {
     filter_dom_serialize_escape_cdata_element($dom_document, $node);
   }
 
-  foreach($body_node->getElementsByTagName('style') as $node) {
+  foreach ($body_node->getElementsByTagName('style') as $node) {
     filter_dom_serialize_escape_cdata_element($dom_document, $node, '/*', '*/');
   }
 
@@ -1174,7 +1185,7 @@ function _filter_html($text, $filter) {
   if ($filter->settings['filter_html_nofollow']) {
     $html_dom = filter_dom_load($text);
     $links = $html_dom->getElementsByTagName('a');
-    foreach($links as $link) {
+    foreach ($links as $link) {
       $link->setAttribute('rel', 'nofollow');
     }
     $text = filter_dom_serialize($html_dom);
diff --git a/modules/filter/filter.pages.inc b/modules/filter/filter.pages.inc
index 76ad21d0a5d21b5a778d3be4a4b65f8fb5ba38a9..af32fbf3f9c60aa352831bc9b3f58a8f31e817b9 100644
--- a/modules/filter/filter.pages.inc
+++ b/modules/filter/filter.pages.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.pages.inc,v 1.10 2010/04/13 15:23:03 dries Exp $
+// $Id: filter.pages.inc,v 1.11 2010/09/16 18:00:43 dries Exp $
 
 /**
  * @file
@@ -55,17 +55,17 @@ function theme_filter_tips($variables) {
 
   $multiple = count($tips) > 1;
   if ($multiple) {
-    $output = t('Text formats') . ':';
+    $output = '<h2>' . t('Text Formats') . '</h2>';
   }
 
   if (count($tips)) {
     if ($multiple) {
-      $output .= '<ul>';
+      $output .= '<div class="compose-tips">';
     }
     foreach ($tips as $name => $tiplist) {
       if ($multiple) {
-        $output .= '<li>';
-        $output .= '<strong>' . $name . '</strong>:<br />';
+        $output .= '<div class="filter-type filter-' . drupal_html_class($name) . '">';
+        $output .= '<h3>' . $name . '</h3>';
       }
 
       if (count($tiplist) > 0) {
@@ -77,11 +77,11 @@ function theme_filter_tips($variables) {
       }
 
       if ($multiple) {
-        $output .= '</li>';
+        $output .= '</div>';
       }
     }
     if ($multiple) {
-      $output .= '</ul>';
+      $output .= '</div>';
     }
   }
 
diff --git a/modules/filter/filter.test b/modules/filter/filter.test
index 4a737d9f6878500e63cf2b805ea85c0c1e48b136..54145a62f6ca7a20948546f329957639201d6c0e 100644
--- a/modules/filter/filter.test
+++ b/modules/filter/filter.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter.test,v 1.75 2010/09/04 17:55:43 dries Exp $
+// $Id: filter.test,v 1.77 2010/09/28 03:30:37 webchick Exp $
 
 /**
  * Tests for text format and filter CRUD operations.
@@ -57,14 +57,13 @@ class FilterCRUDTestCase extends DrupalWebTestCase {
     $this->verifyTextFormat($format);
     $this->verifyFilters($format);
 
-    // Delete the text format.
-    filter_format_delete($format);
+    // Disable the text format.
+    filter_format_disable($format);
+
     $db_format = db_query("SELECT * FROM {filter_format} WHERE format = :format", array(':format' => $format->format))->fetchObject();
-    $this->assertFalse($db_format, t('Database: Deleted text format no longer exists.'));
-    $db_filters = db_query("SELECT * FROM {filter} WHERE format = :format", array(':format' => $format->format))->fetchObject();
-    $this->assertFalse($db_filters, t('Database: Filters for deleted text format no longer exist.'));
+    $this->assertFalse($db_format->status, t('Database: Disabled text format is marked as disabled.'));
     $formats = filter_formats();
-    $this->assertTrue(!isset($formats[$format->format]), t('filter_formats: Deleted text format no longer exists.'));
+    $this->assertTrue(!isset($formats[$format->format]), t('filter_formats: Disabled text format no longer exists.'));
   }
 
   /**
@@ -196,15 +195,15 @@ class FilterAdminTestCase extends DrupalWebTestCase {
     $this->drupalGet('admin/config/content/formats/' . $format->format);
     $this->drupalPost(NULL, array(), t('Save configuration'));
 
-    // Delete text format.
+    // Disable text format.
     $this->drupalGet('admin/config/content/formats');
-    $this->assertRaw('admin/config/content/formats/' . $format->format . '/delete');
-    $this->drupalGet('admin/config/content/formats/' . $format->format . '/delete');
-    $this->drupalPost(NULL, array(), t('Delete'));
+    $this->assertRaw('admin/config/content/formats/' . $format->format . '/disable');
+    $this->drupalGet('admin/config/content/formats/' . $format->format . '/disable');
+    $this->drupalPost(NULL, array(), t('Disable'));
 
-    // Verify that deleted text format no longer exists.
+    // Verify that disabled text format no longer exists.
     $this->drupalGet('admin/config/content/formats/' . $format->format);
-    $this->assertResponse(404, t('Deleted text format no longer exists.'));
+    $this->assertResponse(404, t('Disabled text format no longer exists.'));
   }
 
   /**
@@ -218,12 +217,12 @@ class FilterAdminTestCase extends DrupalWebTestCase {
 
     list($filtered, $full, $plain) = $this->checkFilterFormats();
 
-    // Check that the fallback format exists and cannot be deleted.
+    // Check that the fallback format exists and cannot be disabled.
     $this->assertTrue(!empty($plain) && $plain == filter_fallback_format(), t('The fallback format is set to plain text.'));
     $this->drupalGet('admin/config/content/formats');
-    $this->assertNoRaw('admin/config/content/formats/' . $plain . '/delete', t('Delete link for the fallback format not found.'));
-    $this->drupalGet('admin/config/content/formats/' . $plain . '/delete');
-    $this->assertResponse(403, t('The fallback format cannot be deleted.'));
+    $this->assertNoRaw('admin/config/content/formats/' . $plain . '/disable', t('Disable link for the fallback format not found.'));
+    $this->drupalGet('admin/config/content/formats/' . $plain . '/disable');
+    $this->assertResponse(403, t('The fallback format cannot be disabled.'));
 
     // Verify access permissions to Full HTML format.
     $this->assertTrue(filter_access(filter_format_load($full), $this->admin_user), t('Admin user may use Full HTML.'));
@@ -283,9 +282,9 @@ class FilterAdminTestCase extends DrupalWebTestCase {
     $this->assertFieldByName('filters[' . $second_filter . '][status]', '', t('Line break filter found.'));
     $this->assertFieldByName('filters[' . $first_filter . '][status]', '', t('Url filter found.'));
 
-    // Delete new filter.
-    $this->drupalPost('admin/config/content/formats/' . $format->format . '/delete', array(), t('Delete'));
-    $this->assertRaw(t('Deleted text format %format.', array('%format' => $edit['name'])), t('Format successfully deleted.'));
+    // Disable new filter.
+    $this->drupalPost('admin/config/content/formats/' . $format->format . '/disable', array(), t('Disable'));
+    $this->assertRaw(t('Disabled text format %format.', array('%format' => $edit['name'])), t('Format successfully disabled.'));
 
     // Allow authenticated users on full HTML.
     $format = filter_format_load($full);
@@ -397,6 +396,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
 
 class FilterFormatAccessTestCase extends DrupalWebTestCase {
   protected $admin_user;
+  protected $filter_admin_user;
   protected $web_user;
   protected $allowed_format;
   protected $disallowed_format;
@@ -412,16 +412,16 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
   function setUp() {
     parent::setUp();
 
-    $this->full_html_format = db_query_range('SELECT * FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'Full HTML'))->fetchObject();
-
-    // Create two text formats and grant a regular user access to one of them.
-    $this->admin_user = $this->drupalCreateUser(array(
+    // Create a user who can administer text formats, but does not have
+    // specific permission to use any of them.
+    $this->filter_admin_user = $this->drupalCreateUser(array(
       'administer filters',
       'create page content',
       'edit any page content',
-      filter_permission_name($this->full_html_format),
     ));
-    $this->drupalLogin($this->admin_user);
+
+    // Create two text formats.
+    $this->drupalLogin($this->filter_admin_user);
     $formats = array();
     for ($i = 0; $i < 2; $i++) {
       $edit = array('name' => $this->randomName());
@@ -431,11 +431,23 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
       $formats[] = filter_format_load($format_id);
     }
     list($this->allowed_format, $this->disallowed_format) = $formats;
+    $this->drupalLogout();
 
+    // Create a regular user with access to one of the formats.
     $this->web_user = $this->drupalCreateUser(array(
       'create page content',
+      'edit any page content',
       filter_permission_name($this->allowed_format),
     ));
+
+    // Create an administrative user who has access to use both formats.
+    $this->admin_user = $this->drupalCreateUser(array(
+      'administer filters',
+      'create page content',
+      'edit any page content',
+      filter_permission_name($this->allowed_format),
+      filter_permission_name($this->disallowed_format),
+    ));
   }
 
   function testFormatPermissions() {
@@ -488,8 +500,11 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
   /**
    * Test editing a page using a disallowed text format.
    *
-   * Verifies that a regular user is able to edit a page, but is not allowed to
-   * change the fields which use an inaccessible text format.
+   * Verifies that regular users and administrators are able to edit a page,
+   * but not allowed to change the fields which use an inaccessible text
+   * format. Also verifies that fields which use a text format that does not
+   * exist can be edited by administrators only, but that the administrator is
+   * forced to choose a new format before saving the page.
    */
   function testFormatWidgetPermissions() {
     $langcode = LANGUAGE_NONE;
@@ -502,16 +517,12 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
     $edit = array();
     $edit['title'] = $this->randomName(8);
     $edit[$body_value_key] = $this->randomName(16);
-    $edit[$body_format_key] = $this->full_html_format->format;
+    $edit[$body_format_key] = $this->disallowed_format->format;
     $this->drupalPost('node/add/page', $edit, t('Save'));
     $node = $this->drupalGetNodeByTitle($edit['title']);
 
     // Try to edit with a less privileged user.
-    $this->moderator = $this->drupalCreateUser(array(
-      'edit any page content',
-      'create page content',
-    ));
-    $this->drupalLogin($this->moderator);
+    $this->drupalLogin($this->web_user);
     $this->drupalGet('node/' . $node->nid);
     $this->clickLink(t('Edit'));
 
@@ -530,14 +541,82 @@ class FilterFormatAccessTestCase extends DrupalWebTestCase {
     $this->assertText($new_edit['title'], t('New title found.'));
     $this->assertText($edit[$body_value_key], t('Old body found.'));
 
-    // Delete the Full HTML text format.
-    filter_format_delete($this->full_html_format);
+    // Check that even an administrator with "administer filters" permission
+    // cannot edit the body field if they do not have specific permission to
+    // use its stored format. (This must be disallowed so that the
+    // administrator is never forced to switch the text format to something
+    // else.)
+    $this->drupalLogin($this->filter_admin_user);
+    $this->drupalGet('node/' . $node->nid . '/edit');
+    $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
+
+    // Disable the text format used above.
+    filter_format_disable($this->disallowed_format);
     $this->resetFilterCaches();
 
-    // Verify that body field can be edited and a new format can be selected.
+    // Log back in as the less privileged user and verify that the body field
+    // is still disabled, since the less privileged user should not be able to
+    // edit content that does not have an assigned format.
+    $this->drupalLogin($this->web_user);
+    $this->drupalGet('node/' . $node->nid . '/edit');
+    $this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
+
+    // Log back in as the filter administrator and verify that the body field
+    // can be edited.
+    $this->drupalLogin($this->filter_admin_user);
     $this->drupalGet('node/' . $node->nid . '/edit');
     $this->assertNoFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", NULL, t('Text format access denied message not found.'));
     $this->assertFieldByXPath("//select[@name='$body_format_key']", NULL, t('Text format selector found.'));
+
+    // Verify that trying to save the node without selecting a new text format
+    // produces an error message, and does not result in the node being saved.
+    $old_title = $new_edit['title'];
+    $new_title = $this->randomName(8);
+    $edit = array('title' => $new_title);
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->assertText(t('!name field is required.', array('!name' => t('Text format'))), t('Error message is displayed.'));
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertText($old_title, t('Old title found.'));
+    $this->assertNoText($new_title, t('New title not found.'));
+
+    // Now select a new text format and make sure the node can be saved.
+    $edit[$body_format_key] = filter_fallback_format();
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->assertUrl('node/' . $node->nid);
+    $this->assertText($new_title, t('New title found.'));
+    $this->assertNoText($old_title, t('Old title not found.'));
+
+    // Switch the text format to a new one, then disable that format and all
+    // other formats on the site (leaving only the fallback format).
+    $this->drupalLogin($this->admin_user);
+    $edit = array($body_format_key => $this->allowed_format->format);
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->assertUrl('node/' . $node->nid);
+    foreach (filter_formats() as $format) {
+      if ($format->format != filter_fallback_format()) {
+        filter_format_disable($format);
+      }
+    }
+
+    // Since there is now only one available text format, the widget for
+    // selecting a text format would normally not display when the content is
+    // edited. However, we need to verify that the filter administrator still
+    // is forced to make a conscious choice to reassign the text to a different
+    // format.
+    $this->drupalLogin($this->filter_admin_user);
+    $old_title = $new_title;
+    $new_title = $this->randomName(8);
+    $edit = array('title' => $new_title);
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->assertText(t('!name field is required.', array('!name' => t('Text format'))), t('Error message is displayed.'));
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertText($old_title, t('Old title found.'));
+    $this->assertNoText($new_title, t('New title not found.'));
+    $edit[$body_format_key] = filter_fallback_format();
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->assertUrl('node/' . $node->nid);
+    $this->assertText($new_title, t('New title found.'));
+    $this->assertNoText($old_title, t('Old title not found.'));
   }
 
   /**
@@ -679,8 +758,8 @@ class FilterSecurityTestCase extends DrupalWebTestCase {
     $this->assertNoText($body_raw, t('Node body not found.'));
     $this->assertText('Filter: Testing filter', t('Testing filter output found.'));
 
-    // Delete the text format entirely.
-    $this->drupalPost('admin/config/content/formats/' . $format_id . '/delete', array(), t('Delete'));
+    // Disable the text format entirely.
+    $this->drupalPost('admin/config/content/formats/' . $format_id . '/disable', array(), t('Disable'));
 
     // Verify that the content is empty, because the text format does not exist.
     $this->drupalGet('node/' . $node->nid);
@@ -1587,7 +1666,7 @@ class FilterHooksTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
       'name' => 'Filter format hooks',
-      'description' => 'Test hooks for text formats insert/update/delete.',
+      'description' => 'Test hooks for text formats insert/update/disable.',
       'group' => 'Filter',
     );
   }
@@ -1634,18 +1713,10 @@ class FilterHooksTestCase extends DrupalWebTestCase {
     $bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
     $this->assertNotNull($bid, t('New block found in database'));
 
-    // Delete the text format.
-    $this->drupalPost('admin/config/content/formats/' . $format_id . '/delete', array(), t('Delete'));
-    $this->assertRaw(t('Deleted text format %format.', array('%format' => $name)), t('Format successfully deleted.'));
-    $this->assertText('hook_filter_format_delete invoked.', t('hook_filter_format_delete() was invoked.'));
-
-    // Verify that the deleted format was replaced with the fallback format.
-    $current_format = db_select('block_custom', 'b')
-      ->fields('b', array('format'))
-      ->condition('bid', $bid)
-      ->execute()
-      ->fetchField();
-    $this->assertEqual($current_format, filter_fallback_format(), t('Deleted text format replaced with the fallback format.'));
+    // Disable the text format.
+    $this->drupalPost('admin/config/content/formats/' . $format_id . '/disable', array(), t('Disable'));
+    $this->assertRaw(t('Disabled text format %format.', array('%format' => $name)), t('Format successfully disabled.'));
+    $this->assertText('hook_filter_format_disable invoked.', t('hook_filter_format_disable() was invoked.'));
   }
 }
 
diff --git a/modules/forum/forum-icon.tpl.php b/modules/forum/forum-icon.tpl.php
index 249979918960b92d5b4aebf66c91e39f5f4701bf..a191b5137ac513380fa119bbca3ff451612d9602 100644
--- a/modules/forum/forum-icon.tpl.php
+++ b/modules/forum/forum-icon.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: forum-icon.tpl.php,v 1.6 2009/10/09 00:59:59 dries Exp $
+// $Id: forum-icon.tpl.php,v 1.7 2010/10/03 00:41:14 dries Exp $
 
 /**
  * @file
@@ -14,12 +14,14 @@
  * @see theme_forum_icon()
  */
 ?>
+<div class="topic-status-<?php print $icon_class ?>" title="<?php print $icon_title ?>">
 <?php if ($new_posts): ?>
   <a id="new">
 <?php endif; ?>
 
-<?php print theme('image', array('path' => "misc/forum-$icon.png")) ?>
+  <span class="element-invisible"><?php print $icon_title ?></span>
 
 <?php if ($new_posts): ?>
   </a>
 <?php endif; ?>
+</div>
diff --git a/modules/forum/forum.css b/modules/forum/forum.css
index 19d75ea5812689ee99a5f0b12fea670b649289e7..eb2544e81ecd675c82ba2550f8dad76c8c60f10c 100644
--- a/modules/forum/forum.css
+++ b/modules/forum/forum.css
@@ -1,4 +1,4 @@
-/* $Id: forum.css,v 1.8 2010/04/28 20:08:38 dries Exp $ */
+/* $Id: forum.css,v 1.9 2010/10/03 00:41:14 dries Exp $ */
 
 #forum .description {
   font-size: 0.9em;
@@ -24,4 +24,24 @@
 #forum div.indent {
   margin-left: 20px;
 }
-
+#forum .icon div {
+  background-image: url(../../misc/forum-icons.png);
+  background-repeat: no-repeat;
+  width: 24px;
+  height: 24px;
+}
+#forum .icon .topic-status-new {
+  background-position: -24px 0;
+}
+#forum .icon .topic-status-hot {
+  background-position: -48px 0;
+}
+#forum .icon .topic-status-hot-new {
+  background-position: -72px 0;
+}
+#forum .icon .topic-status-sticky {
+  background-position: -96px 0;
+}
+#forum .icon .topic-status-closed {
+  background-position: -120px 0;
+}
diff --git a/modules/forum/forum.info b/modules/forum/forum.info
index c54a2c0704797a76c781f9d3a29b8e54bca3bbae..3b5cca783bb3565f88e59fd3cd73951efa250870 100644
--- a/modules/forum/forum.info
+++ b/modules/forum/forum.info
@@ -14,8 +14,8 @@ files[] = forum.test
 configure = admin/structure/forum
 stylesheets[all][] = forum.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/forum/forum.install b/modules/forum/forum.install
index 4a4dd32cb4c5dcc4a86e8bd352d5f2917121b262..f719708797f301268abe0c4bc6e381af48faf36f 100644
--- a/modules/forum/forum.install
+++ b/modules/forum/forum.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: forum.install,v 1.50 2010/08/22 13:55:53 dries Exp $
+// $Id: forum.install,v 1.52 2010/10/07 00:28:19 webchick Exp $
 
 /**
  * @file
@@ -52,7 +52,7 @@ function forum_enable() {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => $vocabulary->vid,
+            'vocabulary' => $vocabulary->machine_name,
             'parent' => 0,
           ),
         ),
@@ -71,30 +71,30 @@ function forum_enable() {
     );
     $term = (object) $edit;
     taxonomy_term_save($term);
-  }
 
-  // Create the instance on the bundle.
-  $instance = array(
-    'field_name' => 'taxonomy_' . $vocabulary->machine_name,
-    'entity_type' => 'node',
-    'label' => $vocabulary->name,
-    'bundle' => 'forum',
-    'required' => TRUE,
-    'widget' => array(
-      'type' => 'options_select',
-    ),
-    'display' => array(
-      'default' => array(
-        'type' => 'taxonomy_term_reference_link',
-        'weight' => 10,
+    // Create the instance on the bundle.
+    $instance = array(
+      'field_name' => 'taxonomy_' . $vocabulary->machine_name,
+      'entity_type' => 'node',
+      'label' => $vocabulary->name,
+      'bundle' => 'forum',
+      'required' => TRUE,
+      'widget' => array(
+        'type' => 'options_select',
       ),
-      'teaser' => array(
-        'type' => 'taxonomy_term_reference_link',
-        'weight' => 10,
+      'display' => array(
+        'default' => array(
+          'type' => 'taxonomy_term_reference_link',
+         'weight' => 10,
+        ),
+        'teaser' => array(
+          'type' => 'taxonomy_term_reference_link',
+         'weight' => 10,
+        ),
       ),
-    ),
-  );
-  field_create_instance($instance);
+    );
+    field_create_instance($instance);
+  }
 
   // Ensure the forum node type is available.
   node_types_rebuild();
diff --git a/modules/forum/forum.module b/modules/forum/forum.module
index 4f5ca81df1af9e2a5d4c61f99bd83f8808b51ecf..86ddb1bd6930a0b2cdec79167580c45cc89de69d 100644
--- a/modules/forum/forum.module
+++ b/modules/forum/forum.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: forum.module,v 1.575 2010/09/07 23:39:08 dries Exp $
+// $Id: forum.module,v 1.579 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -147,7 +147,6 @@ function forum_menu() {
     'page callback' => 'forum_form_main',
     'page arguments' => array('container', 5),
     'access arguments' => array('administer forums'),
-    'type' => MENU_CALLBACK,
     'file' => 'forum.admin.inc',
   );
   $items['admin/structure/forum/edit/forum/%taxonomy_term'] = array(
@@ -155,7 +154,6 @@ function forum_menu() {
     'page callback' => 'forum_form_main',
     'page arguments' => array('forum', 5),
     'access arguments' => array('administer forums'),
-    'type' => MENU_CALLBACK,
     'file' => 'forum.admin.inc',
   );
   return $items;
@@ -167,9 +165,9 @@ function forum_menu() {
 function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) {
   global $user;
 
-  // Add action link to 'node/add/forum' on 'forum' page.
-  if ($root_path == 'forum') {
-    $tid = (isset($router_item['page_arguments'][0]) ? $router_item['page_arguments'][0] : 0);
+  // Add action link to 'node/add/forum' on 'forum' sub-pages.
+  if ($root_path == 'forum' || $root_path == 'forum/%') {
+    $tid = (isset($router_item['page_arguments'][0]) ? $router_item['page_arguments'][0]->tid : 0);
     $forum_term = forum_forum_load($tid);
     if ($forum_term) {
       $vid = variable_get('forum_nav_vocabulary', 0);
@@ -603,7 +601,7 @@ function forum_form_alter(&$form, $form_state, $form_id) {
       $form['advanced']['parent']['#access'] = FALSE;
     }
   }
-  if ($form_id == 'forum_node_form') {
+  if (!empty($form['#node_edit_form']) && isset($form['taxonomy_forums'])) {
     $langcode = $form['taxonomy_forums']['#language'];
     // Make the vocabulary required for 'real' forum-nodes.
     $form['taxonomy_forums'][$langcode]['#required'] = TRUE;
@@ -1119,7 +1117,7 @@ function template_preprocess_forum_topic_list(&$variables) {
   $variables['topic_id'] = $variables['tid'];
   unset($variables['tid']);
 
-  $variables['pager'] = theme('pager', array('tags' => NULL));
+  $variables['pager'] = theme('pager');
 }
 
 /**
@@ -1137,18 +1135,22 @@ function template_preprocess_forum_topic_list(&$variables) {
 function template_preprocess_forum_icon(&$variables) {
   $variables['hot_threshold'] = variable_get('forum_hot_topic', 15);
   if ($variables['num_posts'] > $variables['hot_threshold']) {
-    $variables['icon'] = $variables['new_posts'] ? 'hot-new' : 'hot';
+    $variables['icon_class'] = $variables['new_posts'] ? 'hot-new' : 'hot';
+    $variables['icon_title'] = $variables['new_posts'] ? t('Hot topic, new comments') : t('Hot topic');
   }
   else {
-    $variables['icon'] = $variables['new_posts'] ? 'new' : 'default';
+    $variables['icon_class'] = $variables['new_posts'] ? 'new' : 'default';
+    $variables['icon_title'] = $variables['new_posts'] ? t('New comments') : t('Normal topic');
   }
 
   if ($variables['comment_mode'] == COMMENT_NODE_CLOSED || $variables['comment_mode'] == COMMENT_NODE_HIDDEN) {
-    $variables['icon'] = 'closed';
+    $variables['icon_class'] = 'closed';
+    $variables['icon_title'] = t('Closed topic');
   }
 
   if ($variables['sticky'] == 1) {
-    $variables['icon'] = 'sticky';
+    $variables['icon_class'] = 'sticky';
+    $variables['icon_title'] = t('Sticky topic');
   }
 }
 
diff --git a/modules/forum/forum.test b/modules/forum/forum.test
index 267dec7dee5791275ecb67b092f390977436572e..119a7ab90c2ce9dd73277a0b47b23ba218ee5a7d 100644
--- a/modules/forum/forum.test
+++ b/modules/forum/forum.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: forum.test,v 1.62 2010/08/30 00:22:03 webchick Exp $
+// $Id: forum.test,v 1.65 2010/09/28 02:30:31 dries Exp $
 
 class ForumTestCase extends DrupalWebTestCase {
   protected $admin_user;
@@ -25,9 +25,25 @@ class ForumTestCase extends DrupalWebTestCase {
   function setUp() {
     parent::setUp('taxonomy', 'comment', 'forum');
     // Create users.
-    $this->admin_user = $this->drupalCreateUser(array('administer blocks', 'administer forums', 'administer menu', 'administer taxonomy', 'create forum content')); // 'access administration pages'));
-    $this->edit_any_topics_user = $this->drupalCreateUser(array('create forum content', 'edit any forum content', 'delete any forum content', 'access administration pages'));
-    $this->edit_own_topics_user = $this->drupalCreateUser(array('create forum content', 'edit own forum content', 'delete own forum content'));
+    $this->admin_user = $this->drupalCreateUser(array(
+      'access administration pages',
+      'administer blocks',
+      'administer forums',
+      'administer menu',
+      'administer taxonomy',
+      'create forum content',
+    ));
+    $this->edit_any_topics_user = $this->drupalCreateUser(array(
+      'access administration pages',
+      'create forum content',
+      'edit any forum content',
+      'delete any forum content',
+    ));
+    $this->edit_own_topics_user = $this->drupalCreateUser(array(
+      'create forum content',
+      'edit own forum content',
+      'delete own forum content',
+    ));
     $this->web_user = $this->drupalCreateUser(array());
   }
 
@@ -48,6 +64,10 @@ class ForumTestCase extends DrupalWebTestCase {
     // Login an unprivileged user to view the forum topics and generate an
     // active forum topics list.
     $this->drupalLogin($this->web_user);
+    // Verify that this user is shown a message that they may not post content.
+    $this->drupalGet('forum/' . $this->forum['tid']);
+    $this->assertText(t('You are not allowed to post new content in the forum'), "Authenticated user without permission to post forum content is shown message in local tasks to that effect.");
+
     $this->viewForumTopics($this->nids);
 
     // Log in, and do basic tests for a user with permission to edit any forum
@@ -64,6 +84,12 @@ class ForumTestCase extends DrupalWebTestCase {
     // Verify that this user cannot edit forum content authored by another user.
     $this->verifyForums($this->edit_any_topics_user, $any_topics_user_node, FALSE, 403);
 
+    // Verify that this user is shown a local task to add new forum content.
+    $this->drupalGet('forum');
+    $this->assertLink(t('Add new Forum topic'));
+    $this->drupalGet('forum/' . $this->forum['tid']);
+    $this->assertLink(t('Add new Forum topic'));
+
     // Login a user with permission to edit any forum content.
     $this->drupalLogin($this->edit_any_topics_user);
     // Verify that this user can edit forum content authored by another user.
@@ -119,7 +145,7 @@ class ForumTestCase extends DrupalWebTestCase {
     // Must remove forum topics to test creating orphan topics.
     $vid = variable_get('forum_nav_vocabulary');
     $tree = taxonomy_get_tree($vid);
-    foreach($tree as $term) {
+    foreach ($tree as $term) {
       taxonomy_term_delete($term->tid);
     }
 
diff --git a/modules/help/help.admin.inc b/modules/help/help.admin.inc
index 697eb8ed22c94e0df97f5a4f061bde268554424a..4b783ac91a203b9266feba2aea07153eaf028274 100644
--- a/modules/help/help.admin.inc
+++ b/modules/help/help.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: help.admin.inc,v 1.12 2010/07/30 02:47:28 dries Exp $
+// $Id: help.admin.inc,v 1.13 2010/10/01 15:24:18 webchick Exp $
 
 /**
  * @file
@@ -22,12 +22,12 @@ function help_main() {
 function help_page($name) {
   $output = '';
   if (module_hook($name, 'help')) {
-    $module = drupal_parse_info_file(drupal_get_path('module', $name) . '/' . $name . '.info');
-    drupal_set_title($module['name']);
+    $info = system_get_info('module');
+    drupal_set_title($info[$name]['name']);
 
     $temp = module_invoke($name, 'help', "admin/help#$name", drupal_help_arg());
     if (empty($temp)) {
-      $output .= t("No help is available for module %module.", array('%module' => $module['name']));
+      $output .= t("No help is available for module %module.", array('%module' => $info[$name]['name']));
     }
     else {
       $output .= $temp;
@@ -35,12 +35,14 @@ function help_page($name) {
 
     // Only print list of administration pages if the module in question has
     // any such pages associated to it.
-    $admin_tasks = system_get_module_admin_tasks($name);
+    $admin_tasks = system_get_module_admin_tasks($name, $info[$name]);
     if (!empty($admin_tasks)) {
-      ksort($admin_tasks);
-      $output .= theme('item_list', array('items' => $admin_tasks, 'title' => t('@module administration pages', array('@module' => $module['name']))));
+      $links = array();
+      foreach ($admin_tasks as $task) {
+        $links[] = l($task['title'], $task['link_path'], $task['localized_options']);
+      }
+      $output .= theme('item_list', array('items' => $links, 'title' => t('@module administration pages', array('@module' => $info[$name]['name']))));
     }
-
   }
   return $output;
 }
diff --git a/modules/help/help.api.php b/modules/help/help.api.php
index 7229285309967d1e597489bc1e423bee71b8dfa7..36d425a06dd6c2dd9a3eea405357580c40f503b5 100644
--- a/modules/help/help.api.php
+++ b/modules/help/help.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: help.api.php,v 1.10 2010/08/11 01:06:44 dries Exp $
+// $Id: help.api.php,v 1.11 2010/10/06 03:43:01 webchick Exp $
 
 /**
  * @file
@@ -14,30 +14,30 @@
 /**
  * Provide online user help.
  *
- * By implementing hook_help(), a module can make documentation
- * available to the user for the module as a whole, or for specific paths.
- * Help for developers should usually be provided via function
- * header comments in the code, or in special API example files.
+ * By implementing hook_help(), a module can make documentation available to
+ * the user for the module as a whole, or for specific paths.  Help for
+ * developers should usually be provided via function header comments in the
+ * code, or in special API example files.
  *
  * For a detailed usage example, see page_example.module.
  *
  * @param $path
- *   The router menu path, as defined in hook_menu(), for the help that
- *   is being requested; e.g., 'admin/node' or 'user/edit'. If the router path
- *   includes a % wildcard, then this will appear in $path; for example,
- *   node pages would have $path equal to 'node/%' or 'node/%/view'. Your hook
- *   implementation may also be called with special descriptors after a
- *   "#" sign. Some examples:
- *   - admin/help#modulename
- *     The main module help text, displayed on the admin/help/modulename
- *     page and linked to from the admin/help page.
- *   - user/help#modulename
- *     The help for a distributed authorization module (if applicable).
+ *   The router menu path, as defined in hook_menu(), for the help that is
+ *   being requested; e.g., 'admin/people' or 'user/register'.  If the router
+ *   path includes a wildcard, then this will appear in $path as %, even if it
+ *   is a named %autoloader wildcard in the hook_menu() implementation; for
+ *   example, node pages would have $path equal to 'node/%' or 'node/%/view'.
+ *   To provide a help page for a whole module with a listing on admin/help,
+ *   your hook implementation should match a path with a special descriptor
+ *   after a "#" sign:
+ *     'admin/help#modulename'
+ *       The main module help text, displayed on the admin/help/modulename
+ *       page and linked to from the admin/help page.
  * @param $arg
  *   An array that corresponds to the return value of the arg() function, for
  *   modules that want to provide help that is specific to certain values
  *   of wildcards in $path. For example, you could provide help for the path
- *   'user/1' by looking for the path 'user/%' and $arg[1] == '1'. This
+ *   'user/1' by looking for the path 'user/%' and $arg[1] == '1'. This given
  *   array should always be used rather than directly invoking arg(), because
  *   your hook implementation may be called for other purposes besides building
  *   the current page's help. Note that depending on which module is invoking
diff --git a/modules/help/help.info b/modules/help/help.info
index 96adf2c9c129064f591ffa2043a487b40031fdcc..f6201852d765357e1f3757fd91665a5de3f59ab0 100644
--- a/modules/help/help.info
+++ b/modules/help/help.info
@@ -8,8 +8,8 @@ files[] = help.module
 files[] = help.admin.inc
 files[] = help.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/help/help.module b/modules/help/help.module
index 90dd729d9a93a95b655d554bc3a339d6bec0ff07..6b78a5d6eb12447ef443cf2e990ad61d34378384 100644
--- a/modules/help/help.module
+++ b/modules/help/help.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: help.module,v 1.96 2010/01/12 23:04:47 webchick Exp $
+// $Id: help.module,v 1.99 2010/10/04 14:54:10 webchick Exp $
 
 /**
  * @file
@@ -12,7 +12,7 @@
 function help_menu() {
   $items['admin/help'] = array(
     'title' => 'Help',
-    'description' => 'Reference for usage, configuration, and modules',
+    'description' => 'Reference for usage, configuration, and modules.',
     'page callback' => 'help_main',
     'access arguments' => array('access administration pages'),
     'weight' => 9,
@@ -25,7 +25,7 @@ function help_menu() {
       'page callback' => 'help_page',
       'page arguments' => array(2),
       'access arguments' => array('access administration pages'),
-      'type' => MENU_CALLBACK,
+      'type' => MENU_VISIBLE_IN_BREADCRUMB,
       'file' => 'help.admin.inc',
     );
   }
diff --git a/modules/image/image-rtl.css b/modules/image/image-rtl.css
index 5eb14199437051129aa822d60c13d256abde3ed0..e068b7e0fb5288db296214e61041cf31357ccf4d 100644
--- a/modules/image/image-rtl.css
+++ b/modules/image/image-rtl.css
@@ -1,12 +1,12 @@
-/* $Id: image-rtl.css,v 1.1 2009/10/12 05:22:57 webchick Exp $ */
+/* $Id: image-rtl.css,v 1.2 2010/09/27 03:56:14 webchick Exp $ */
 
 /**
  * Image upload widget.
  */
 div.image-preview {
-  float: right; /* RTL */
-  padding: 0 0 10px 10px; /* RTL */
+  float: right;
+  padding: 0 0 10px 10px;
 }
 div.image-widget-data {
-  float: right; /* RTL */
+  float: right;
 }
diff --git a/modules/image/image.admin.inc b/modules/image/image.admin.inc
index cb42324df13fcf0a75c278f4a6c6f93124da37f3..40c892c5867c278870c0691a8124acd4cbb5cf9d 100644
--- a/modules/image/image.admin.inc
+++ b/modules/image/image.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: image.admin.inc,v 1.21 2010/07/30 02:47:28 dries Exp $
+// $Id: image.admin.inc,v 1.25 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -116,7 +116,7 @@ function image_style_form($form, &$form_state, $style) {
   }
 
   // Build the new image effect addition form and add it to the effect list.
-  $new_effect_options = array('' => t('Select a new effect'));
+  $new_effect_options = array();
   foreach (image_effect_definitions() as $effect => $definition) {
     $new_effect_options[$effect] = check_plain($definition['label']);
   }
@@ -128,6 +128,7 @@ function image_style_form($form, &$form_state, $style) {
   $form['effects']['new']['new'] = array(
     '#type' => 'select',
     '#options' => $new_effect_options,
+    '#empty_option' => t('Select a new effect'),
   );
   $form['effects']['new']['weight'] = array(
     '#type' => 'weight',
@@ -164,7 +165,6 @@ function image_style_form($form, &$form_state, $style) {
 function image_style_form_add_validate($form, &$form_state) {
   if (!$form_state['values']['new']) {
     form_error($form['effects']['new']['new'], t('Select an effect to add.'));
-    $form_state['rebuild'] = TRUE;
   }
 }
 
@@ -291,11 +291,11 @@ function image_style_delete_form($form, $form_state, $style) {
   $form_state['image_style'] = $style;
 
   $replacement_styles = array_diff_key(image_style_options(), array($style['name'] => ''));
-  $replacement_styles[''] = t('No replacement, just delete');
   $form['replacement'] = array(
     '#title' => t('Replacement style'),
     '#type' => 'select',
     '#options' => $replacement_styles,
+    '#empty_option' => t('No replacement, just delete'),
   );
 
   return confirm_form(
@@ -793,7 +793,7 @@ function theme_image_style_preview($variables) {
   $output .= '<div class="preview-image-wrapper">';
   $output .= t('original') . ' (' . l(t('view actual size'), $original_path) . ')';
   $output .= '<div class="preview-image original-image" style="' . $original_attributes['style'] . '">';
-  $output .= '<a href="' . url($original_path) . '?' . time() . '">' . theme('image', array('path' => $original_path . '?' . time(), 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes, 'getsize' => FALSE)) . '</a>';
+  $output .= '<a href="' . url($original_path) . '?' . time() . '">' . theme('image', array('path' => $original_path . '?' . time(), 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes)) . '</a>';
   $output .= '<div class="height" style="height: ' . $original_height . 'px"><span>' . $original_image['height'] . 'px</span></div>';
   $output .= '<div class="width" style="width: ' . $original_width . 'px"><span>' . $original_image['width'] . 'px</span></div>';
   $output .= '</div>'; // End preview-image.
@@ -803,7 +803,7 @@ function theme_image_style_preview($variables) {
   $output .= '<div class="preview-image-wrapper">';
   $output .= check_plain($style['name']) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')';
   $output .= '<div class="preview-image modified-image" style="' . $preview_attributes['style'] . '">';
-  $output .= '<a href="' . file_create_url($preview_file) . '?' . time() . '">' . theme('image', array('path' => file_create_url($preview_file) . '?' . time(), 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes, 'getsize' => FALSE)) . '</a>';
+  $output .= '<a href="' . file_create_url($preview_file) . '?' . time() . '">' . theme('image', array('path' => file_create_url($preview_file) . '?' . time(), 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes)) . '</a>';
   $output .= '<div class="height" style="height: ' . $preview_height . 'px"><span>' . $preview_image['height'] . 'px</span></div>';
   $output .= '<div class="width" style="width: ' . $preview_width . 'px"><span>' . $preview_image['width'] . 'px</span></div>';
   $output .= '</div>'; // End preview-image.
diff --git a/modules/image/image.css b/modules/image/image.css
index 57d88e3a223827a97887d5da8c19b3668fda777a..0ae839bed1ca1c2bfccfa812b4abacbe6eaf6ea9 100644
--- a/modules/image/image.css
+++ b/modules/image/image.css
@@ -1,14 +1,14 @@
-/* $Id: image.css,v 1.1 2009/10/12 05:22:57 webchick Exp $ */
+/* $Id: image.css,v 1.2 2010/09/27 03:56:14 webchick Exp $ */
 
 /**
  * Image upload widget.
  */
 div.image-preview {
-  float: left; /* RTL */
-  padding: 0 10px 10px 0; /* RTL */
+  float: left; /* LTR */
+  padding: 0 10px 10px 0; /* LTR */
 }
 div.image-widget-data {
-  float: left; /* RTL */
+  float: left; /* LTR */
 }
 div.image-widget-data input.text-field {
   width: auto;
diff --git a/modules/image/image.field.inc b/modules/image/image.field.inc
index f5f4d02bf7af65869b57d9fe24233f9dba8ba591..7e5daa6241ae44fa7c7d65c4c16fb0699f879e41 100644
--- a/modules/image/image.field.inc
+++ b/modules/image/image.field.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: image.field.inc,v 1.27 2010/09/09 23:28:16 webchick Exp $
+// $Id: image.field.inc,v 1.30 2010/10/04 18:00:45 dries Exp $
 
 /**
  * @file
@@ -269,7 +269,7 @@ function image_field_widget_settings_form($field, $instance) {
   $form['preview_image_style'] = array(
     '#title' => t('Preview image style'),
     '#type' => 'select',
-    '#options' => array('' => '<' . t('no preview') . '>') + image_style_options(FALSE),
+    '#options' => image_style_options(FALSE),
     '#default_value' => $settings['preview_image_style'],
     '#description' => t('The preview image will be shown while editing the content.'),
     '#weight' => 15,
@@ -338,7 +338,7 @@ function image_field_widget_process($element, &$form_state, $form) {
   if ($element['#file'] && $widget_settings['preview_image_style']) {
     $element['preview'] = array(
       '#type' => 'markup',
-      '#markup' => theme('image_style', array('style_name' => $widget_settings['preview_image_style'], 'path' => $element['#file']->uri, 'getsize' => FALSE)),
+      '#markup' => theme('image_style', array('style_name' => $widget_settings['preview_image_style'], 'path' => $element['#file']->uri)),
     );
   }
 
@@ -418,16 +418,16 @@ function image_field_formatter_settings_form($field, $instance, $view_mode, $for
   $display = $instance['display'][$view_mode];
   $settings = $display['settings'];
 
-  $image_styles = array('' => t('None (original image)')) + image_style_options(FALSE);
+  $image_styles = image_style_options(FALSE);
   $form['image_style'] = array(
     '#title' => t('Image style'),
     '#type' => 'select',
     '#default_value' => $settings['image_style'],
+    '#empty_option' => t('None (original image)'),
     '#options' => $image_styles,
   );
 
   $link_types = array(
-    '' => t('<none>'),
     'content' => t('Content'),
     'file' => t('File'),
   );
diff --git a/modules/image/image.info b/modules/image/image.info
index 10b53813034d18b0f1e9148164e5ae050aad9a48..744e7b51dce143412951d057fa073af10e1b2c7b 100644
--- a/modules/image/image.info
+++ b/modules/image/image.info
@@ -13,8 +13,8 @@ files[] = image.install
 files[] = image.test
 configure = admin/config/media/image-styles
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/image/image.module b/modules/image/image.module
index 71c96e3b55fc3f9d59bf2e2525d8e1366880e45b..3260031ebba83ad6a0a1d58bd239ff6e9ebf6b50 100644
--- a/modules/image/image.module
+++ b/modules/image/image.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: image.module,v 1.50 2010/09/11 05:07:22 webchick Exp $
+// $Id: image.module,v 1.53 2010/10/03 05:14:58 webchick Exp $
 
 /**
  * @file
@@ -72,7 +72,7 @@ function image_menu() {
   $items = array();
 
   // Generate image derivatives of publicly available files.
-  // If clean URLs are disabled, image derivatives will always be served 
+  // If clean URLs are disabled, image derivatives will always be served
   // through the menu system.
   // If clean URLs are enabled and the image derivative already exists,
   // PHP will be bypassed.
@@ -125,7 +125,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_style_form', 5),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/delete/%image_style'] = array(
@@ -135,7 +134,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_style_delete_form', 5),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/revert/%image_style'] = array(
@@ -145,7 +143,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_style_revert_form', 5),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/edit/%image_style/effects/%image_effect'] = array(
@@ -155,7 +152,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_effect_form', 5, 7),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/edit/%image_style/effects/%image_effect/delete'] = array(
@@ -165,7 +161,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_effect_delete_form', 5, 7),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
   $items['admin/config/media/image-styles/edit/%image_style/add/%image_effect_definition'] = array(
@@ -175,7 +170,6 @@ function image_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('image_effect_form', 5, 7),
     'access arguments' => array('administer image styles'),
-    'type' => MENU_CALLBACK,
     'file' => 'image.admin.inc',
   );
 
@@ -647,7 +641,7 @@ function image_style_options($include_empty = TRUE) {
  * Menu callback; Given a style and image path, generate a derivative.
  *
  * After generating an image, transfer it to the requesting agent.
- * 
+ *
  * @param $style
  *   The image style
  */
@@ -656,7 +650,7 @@ function image_style_deliver($style, $scheme) {
   if (!$style || !file_stream_wrapper_valid_scheme($scheme)) {
     drupal_exit();
   }
-  
+
   $args = func_get_args();
   array_shift($args);
   array_shift($args);
@@ -664,8 +658,8 @@ function image_style_deliver($style, $scheme) {
 
   $image_uri = $scheme . '://' . $target;
   $derivative_uri = image_style_path($style['name'], $image_uri);
-  
-  // If using the private scheme, let other modules provide headers and 
+
+  // If using the private scheme, let other modules provide headers and
   // control access to the file.
   if ($scheme == 'private') {
     if (file_exists($derivative_uri)) {
@@ -1105,20 +1099,9 @@ function theme_image_style($variables) {
     $style_path = image_style_url($style_name, $path);
   }
   $variables['path'] = $style_path;
-  $variables['getsize'] = FALSE;
   return theme('image', $variables);
 }
 
-/**
- * Accept a percentage and return it in pixels.
- */
-function image_filter_percent($value, $current_pixels) {
-  if (strpos($value, '%') !== FALSE) {
-    $value = str_replace('%', '', $value) * 0.01 * $current_pixels;
-  }
-  return $value;
-}
-
 /**
  * Accept a keyword (center, top, left, etc) and return it as a pixel offset.
  *
diff --git a/modules/image/image.test b/modules/image/image.test
index 2691f63184079dac1045d05084e98710ab2082d9..483f9fa5851df99f3417e923594930d8f5cab031 100644
--- a/modules/image/image.test
+++ b/modules/image/image.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: image.test,v 1.30 2010/09/11 21:14:31 webchick Exp $
+// $Id: image.test,v 1.31 2010/09/22 03:24:09 dries Exp $
 
 /**
  * @file
@@ -650,7 +650,6 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
     $image_uri = $node->{$field_name}[LANGUAGE_NONE][0]['uri'];
     $image_info = array(
       'path' => $image_uri,
-      'getsize' => TRUE,
     );
     $default_output = theme('image', $image_info);
     $this->assertRaw($default_output, t('Default formatter displaying correctly on full node view.'));
@@ -746,7 +745,6 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
     $node = node_load($nid, NULL, TRUE);
     $image_info = array(
       'path' => image_style_url('medium', $node->{$field_name}[LANGUAGE_NONE][0]['uri']),
-      'getsize' => FALSE,
     );
     $default_output = theme('image', $image_info);
     $this->assertRaw($default_output, t("Preview image is displayed using 'medium' style."));
@@ -756,7 +754,6 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
       'path' => $node->{$field_name}[LANGUAGE_NONE][0]['uri'],
       'alt' => $this->randomName(),
       'title' => $this->randomName(),
-      'getsize' => TRUE,
     );
     $edit = array(
       $field_name . '[' . LANGUAGE_NONE . '][0][alt]' => $image_info['alt'],
@@ -793,7 +790,7 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
     field_info_cache_clear();
     $field = field_info_field($field_name);
     $image = file_load($field['settings']['default_image']);
-    $default_output = theme('image', array('path' => $image->uri, 'getsize' => TRUE));
+    $default_output = theme('image', array('path' => $image->uri));
     $this->drupalGet('node/' . $node->nid);
     $this->assertRaw($default_output, t('Default image displayed when no user supplied image is present.'));
 
@@ -803,7 +800,6 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
     $node = node_load($nid, NULL, TRUE);
     $image_info = array(
       'path' => $node->{$field_name}[LANGUAGE_NONE][0]['uri'],
-      'getsize' => TRUE,
     );
     $image_output = theme('image', $image_info);
     $this->drupalGet('node/' . $nid);
diff --git a/modules/image/tests/image_module_test.info b/modules/image/tests/image_module_test.info
index 8f9512050e430fcee3d52616e17a9fbc00805a9c..4e113ee256f7e8a3b30a6735e50d317617c6d455 100644
--- a/modules/image/tests/image_module_test.info
+++ b/modules/image/tests/image_module_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = image_module_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/locale/locale.admin.inc b/modules/locale/locale.admin.inc
index d3a75c5de36b0d81598eea7597269f4aedd2e12c..3ce0a7bf2e76ad30c413c99512571eafbeb5cace 100644
--- a/modules/locale/locale.admin.inc
+++ b/modules/locale/locale.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: locale.admin.inc,v 1.17 2010/07/30 02:47:28 dries Exp $
+// $Id: locale.admin.inc,v 1.19 2010/10/04 18:00:46 dries Exp $
 
 /**
  * @file
@@ -854,7 +854,8 @@ function locale_translation_filter_form() {
       $form['filters']['status'][$key] = array(
         '#title' => $filter['title'],
         '#type' => 'select',
-        '#multiple' => FALSE,
+        '#empty_value' => 'all',
+        '#empty_option' => $filter['options']['all'],
         '#size' => 0,
         '#options' => $filter['options'],
       );
diff --git a/modules/locale/locale.info b/modules/locale/locale.info
index e1335db92fefa82ad53a371a7cd416e2514a36ee..3b81e864795a798563449c89695b210d25d185c9 100644
--- a/modules/locale/locale.info
+++ b/modules/locale/locale.info
@@ -10,8 +10,8 @@ files[] = locale.admin.inc
 files[] = locale.test
 configure = admin/config/regional/language
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/locale/locale.install b/modules/locale/locale.install
index 630659925b6b48ad65fd1239cff94e8151666395..2fc1e46c5e827e3c0d4d57bc6898c9724bd09884 100644
--- a/modules/locale/locale.install
+++ b/modules/locale/locale.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: locale.install,v 1.65 2010/08/27 11:07:36 webchick Exp $
+// $Id: locale.install,v 1.68 2010/10/05 20:04:18 webchick Exp $
 
 /**
  * @file
@@ -46,6 +46,7 @@ function locale_update_7000() {
  */
 function locale_update_7001() {
   require_once DRUPAL_ROOT . '/includes/language.inc';
+  require_once DRUPAL_ROOT . '/includes/locale.inc';
   require_once DRUPAL_ROOT . '/modules/locale/locale.module';
 
   switch (variable_get('language_negotiation', 0)) {
@@ -62,9 +63,12 @@ function locale_update_7001() {
       // Drupal 7 path prefixes are always shown if not empty. Hence we need to
       // ensure that the default language has an empty prefix to avoid breaking
       // the site URLs with a prefix that previously was missing.
+      $default = language_default();
+      $default->prefix = '';
+      variable_set('language_default', $default);
       db_update('languages')
-        ->fields(array('prefix' => ''))
-        ->condition('language', language_default()->language)
+        ->fields(array('prefix' => $default->prefix))
+        ->condition('language', $default->language)
         ->execute();
       break;
 
@@ -90,26 +94,12 @@ function locale_update_7001() {
   $provider_weights = array_flip(array_keys(locale_language_negotiation_info()));
   variable_set("locale_language_providers_weight_$type", $provider_weights);
 
-  // Update language switcher block delta.
-  db_update('block')
-    ->fields(array('delta' => $type))
-    ->condition('module', 'locale')
-    ->condition('delta', 0)
-    ->execute();
-
   // Unset the old language negotiation system variable.
   variable_del('language_negotiation');
 
   return array();
 }
 
-/**
- * Allow longer javascript file names.
- */
-function locale_update_7002() {
-  // Update moved to update_fix_d7_requirements().
-}
-
 /**
  * @} End of "defgroup updates-6.x-to-7.x"
  */
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 162faa01d9f979cf24ebc0b94363330308cb827e..34b30337325d6e0cc263c4c90eb4cce241daaff4 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: locale.module,v 1.298 2010/09/09 23:01:48 dries Exp $
+// $Id: locale.module,v 1.302 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @file
@@ -12,32 +12,6 @@
  *   Gettext portable object files are supported.
  */
 
-/**
- * The language is determined using a URL language indicator:
- * path prefix or domain according to the configuration.
- */
-define('LOCALE_LANGUAGE_NEGOTIATION_URL', 'locale-url');
-
-/**
- * The language is set based on the browser language settings.
- */
-define('LOCALE_LANGUAGE_NEGOTIATION_BROWSER', 'locale-browser');
-
-/**
- * The language is determined using the current interface language.
- */
-define('LOCALE_LANGUAGE_NEGOTIATION_INTERFACE', 'locale-interface');
-
-/**
- * The language is set based on the user language settings.
- */
-define('LOCALE_LANGUAGE_NEGOTIATION_USER', 'locale-user');
-
-/**
- * The language is set based on the request/session parameters.
- */
-define('LOCALE_LANGUAGE_NEGOTIATION_SESSION', 'locale-session');
-
 // ---------------------------------------------------------------------------------
 // Hook implementations
 
@@ -136,6 +110,7 @@ function locale_menu() {
     'page arguments' => array('locale_language_providers_url_form'),
     'access arguments' => array('administer languages'),
     'file' => 'locale.admin.inc',
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
   );
   $items['admin/config/regional/language/configure/session'] = array(
     'title' => 'Session language detection configuration',
@@ -143,6 +118,7 @@ function locale_menu() {
     'page arguments' => array('locale_language_providers_session_form'),
     'access arguments' => array('administer languages'),
     'file' => 'locale.admin.inc',
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
   );
   $items['admin/config/regional/language/edit/%'] = array(
     'title' => 'Edit language',
@@ -150,7 +126,6 @@ function locale_menu() {
     'page arguments' => array('locale_languages_edit_form', 5),
     'access arguments' => array('administer languages'),
     'file' => 'locale.admin.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['admin/config/regional/language/delete/%'] = array(
     'title' => 'Confirm',
@@ -158,7 +133,6 @@ function locale_menu() {
     'page arguments' => array('locale_languages_delete_form', 5),
     'access arguments' => array('administer languages'),
     'file' => 'locale.admin.inc',
-    'type' => MENU_CALLBACK,
   );
 
   // Translation functionality
@@ -205,7 +179,6 @@ function locale_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('locale_translate_edit_form', 5),
     'access arguments' => array('translate interface'),
-    'type' => MENU_CALLBACK,
     'file' => 'locale.admin.inc',
   );
   $items['admin/config/regional/translate/delete/%'] = array(
@@ -213,7 +186,6 @@ function locale_menu() {
     'page callback' => 'locale_translate_delete_page',
     'page arguments' => array(5),
     'access arguments' => array('translate interface'),
-    'type' => MENU_CALLBACK,
     'file' => 'locale.admin.inc',
   );
 
@@ -233,7 +205,6 @@ function locale_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('locale_date_format_form', 5),
     'access arguments' => array('administer site configuration'),
-    'type' => MENU_CALLBACK,
     'file' => 'locale.admin.inc',
   );
   $items['admin/config/regional/date-time/locale/%/reset'] = array(
@@ -242,7 +213,6 @@ function locale_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('locale_date_format_reset_form', 5),
     'access arguments' => array('administer site configuration'),
-    'type' => MENU_CALLBACK,
     'file' => 'locale.admin.inc',
   );
 
@@ -537,6 +507,7 @@ function locale_entity_info_alter(&$entity_info) {
  *   specified.
  */
 function locale_language_types_info() {
+  require_once DRUPAL_ROOT . '/includes/locale.inc';
   return array(
     LANGUAGE_TYPE_INTERFACE => array(
       'name' => t('User interface text'),
@@ -909,7 +880,7 @@ function locale_library_alter(&$libraries, $module) {
   global $language;
   if ($module == 'system' && isset($libraries['system']['ui.datepicker'])) {
     $datepicker = drupal_get_path('module', 'locale') . '/locale.datepicker.js';
-    $libraries['system']['ui.datepicker']['js'][$datepicker] = array('weight' => JS_THEME);
+    $libraries['system']['ui.datepicker']['js'][$datepicker] = array('group' => JS_THEME);
     $libraries['system']['ui.datepicker']['js'][] = array(
       'data' => array(
         'jqueryuidatepicker' => array(
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index d016648b1adea704ff250f07bca092c6ebed6dd6..31bd5f5496dc3ec8f9d956d19b63b0c357b0bb47 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: locale.test,v 1.79 2010/09/01 20:08:17 dries Exp $
+// $Id: locale.test,v 1.80 2010/10/05 17:57:09 webchick Exp $
 
 /**
  * @file
@@ -1170,10 +1170,9 @@ class LocaleLanguageSwitchingFunctionalTest extends DrupalWebTestCase {
     );
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
 
-    // Set language negotiation.
-    drupal_load('module', 'locale');
-    include_once DRUPAL_ROOT . '/includes/language.inc';
-    language_negotiation_set($language_type, locale_language_negotiation_info());
+    // Enable URL language detection and selection.
+    $edit = array('language[enabled][locale-url]' => '1');
+    $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
 
     // Assert that the language switching block is displayed on the frontpage.
     $this->drupalGet('');
@@ -1452,6 +1451,12 @@ class LocalePathFunctionalTest extends DrupalWebTestCase {
     );
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
 
+    // Check that the "xx" front page is not available when path prefixes are
+    // not enabled yet.
+    $this->drupalPost('admin/config/regional/language/configure', array(), t('Save settings'));
+    $this->drupalGet($prefix);
+    $this->assertResponse(404, t('The "xx" front page is not available yet.'));
+
     // Enable URL language detection and selection.
     $edit = array('language[enabled][locale-url]' => 1);
     $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
@@ -1835,6 +1840,10 @@ class LocaleMultilingualFieldsFunctionalTest extends DrupalWebTestCase {
     require_once DRUPAL_ROOT . '/includes/locale.inc';
     locale_add_language('it', 'Italian', 'Italiano', LANGUAGE_LTR, '', '', TRUE, FALSE);
 
+    // Enable URL language detection and selection.
+    $edit = array('language[enabled][locale-url]' => '1');
+    $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
+
     // Set "Basic page" content type to use multilingual support.
     $edit = array(
       'language_content_type' => 1,
diff --git a/modules/locale/tests/locale_test.info b/modules/locale/tests/locale_test.info
index 4ae0f4a1a11f92acdf401245ff3edf10e5368c00..3cdc2693d06ba9f96c7388329492fe0b88fedbe3 100644
--- a/modules/locale/tests/locale_test.info
+++ b/modules/locale/tests/locale_test.info
@@ -7,8 +7,8 @@ files[] = locale_test.module
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/menu/menu.admin.inc b/modules/menu/menu.admin.inc
index 48d3022fea21d95486d9391bd1b4604df2fc4849..f93293b7170db270a05ede44a9f1e20a866be5c7 100644
--- a/modules/menu/menu.admin.inc
+++ b/modules/menu/menu.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.admin.inc,v 1.84 2010/09/07 22:12:05 dries Exp $
+// $Id: menu.admin.inc,v 1.87 2010/10/04 18:00:46 dries Exp $
 
 /**
  * @file
@@ -259,6 +259,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
     // This is an add form, initialize the menu link.
     $item = array('link_title' => '', 'mlid' => 0, 'plid' => 0, 'menu_name' => $menu['menu_name'], 'weight' => 0, 'link_path' => '', 'options' => array(), 'module' => 'menu', 'expanded' => 0, 'hidden' => 0, 'has_children' => 0);
   }
+  $form['actions'] = array('#type' => 'actions');
   $form['link_title'] = array(
     '#type' => 'textfield',
     '#title' => t('Menu link title'),
@@ -288,7 +289,7 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
       '#description' => t('The path for this menu link. This can be an internal Drupal path such as %add-node or an external URL such as %drupal. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => 'node/add', '%drupal' => 'http://drupal.org')),
       '#required' => TRUE,
     );
-    $form['delete'] = array(
+    $form['actions']['delete'] = array(
       '#type' => 'submit',
       '#value' => t('Delete'),
       '#access' => $item['mlid'],
@@ -344,7 +345,6 @@ function menu_edit_item($form, &$form_state, $type, $item, $menu) {
     '#default_value' => $item['weight'],
     '#description' => t('Optional. In the menu, the heavier links will sink and the lighter links will be positioned nearer the top.'),
   );
-  $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
 
   return $form;
@@ -680,22 +680,22 @@ function menu_configure() {
   $menu_options = menu_get_menus();
 
   $main = variable_get('menu_main_links_source', 'main-menu');
-  $main_options = array_merge($menu_options, array('' => t('No Main links')));
   $form['menu_main_links_source'] = array(
     '#type' => 'select',
     '#title' => t('Source for the Main links'),
     '#default_value' => variable_get('menu_main_links_source', 'main-menu'),
-    '#options' => $main_options,
+    '#empty_option' => t('No Main links'),
+    '#options' => $menu_options,
     '#tree' => FALSE,
     '#description' => t('Select what should be displayed as the Main links (typically at the top of the page).'),
   );
 
-  $secondary_options = array_merge($menu_options, array('' => t('No Secondary links')));
   $form['menu_secondary_links_source'] = array(
     '#type' => 'select',
     '#title' => t('Source for the Secondary links'),
     '#default_value' => variable_get('menu_secondary_links_source', 'user-menu'),
-    '#options' => $secondary_options,
+    '#empty_option' => t('No Secondary links'),
+    '#options' => $menu_options,
     '#tree' => FALSE,
     '#description' => t("Select the source for the Secondary links. An advanced option allows you to use the same source for both Main links (currently %main) and Secondary links: if your source menu has two levels of hierarchy, the top level menu links will appear in the Main links, and the children of the active link will appear in the Secondary links." , array('%main' => $main_options[$main])),
   );
diff --git a/modules/menu/menu.info b/modules/menu/menu.info
index 5317a1441621b3dc84552c6492e92d9257e312e4..11855f6f53fc8eb606c6abbcb778f4ead7ecde12 100644
--- a/modules/menu/menu.info
+++ b/modules/menu/menu.info
@@ -10,8 +10,8 @@ files[] = menu.install
 files[] = menu.test
 configure = admin/structure/menu
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/menu/menu.module b/modules/menu/menu.module
index 4fed193bbc773322b1a7084cdd6f257ec36f4519..44b3772decde94abac404a95e270a7c37b37a472 100644
--- a/modules/menu/menu.module
+++ b/modules/menu/menu.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.module,v 1.232 2010/09/09 23:01:48 dries Exp $
+// $Id: menu.module,v 1.233 2010/09/24 00:37:43 dries Exp $
 
 /**
  * @file
@@ -95,7 +95,6 @@ function menu_menu() {
     'title callback' => 'menu_overview_title',
     'title arguments' => array(4),
     'access arguments' => array('administer menu'),
-    'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
   $items['admin/structure/menu/manage/%menu/list'] = array(
@@ -126,7 +125,6 @@ function menu_menu() {
     'page callback' => 'menu_delete_menu_page',
     'page arguments' => array(4),
     'access arguments' => array('administer menu'),
-    'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
   $items['admin/structure/menu/item/%menu_link/edit'] = array(
@@ -134,7 +132,6 @@ function menu_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_item', 'edit', 4, NULL),
     'access arguments' => array('administer menu'),
-    'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
   $items['admin/structure/menu/item/%menu_link/reset'] = array(
@@ -142,7 +139,6 @@ function menu_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_reset_item_confirm', 4),
     'access arguments' => array('administer menu'),
-    'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
   $items['admin/structure/menu/item/%menu_link/delete'] = array(
@@ -150,7 +146,6 @@ function menu_menu() {
     'page callback' => 'menu_item_delete_page',
     'page arguments' => array(4),
     'access arguments' => array('administer menu'),
-    'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
   return $items;
@@ -707,7 +702,7 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
   $form['menu']['menu_options'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Available menus'),
-    '#default_value' => variable_get('menu_options_' . $type->type, array('main-menu' => 'main-menu')),
+    '#default_value' => variable_get('menu_options_' . $type->type, array('main-menu')),
     '#options' => $menu_options,
     '#description' => t('The menus available to place links in for this content type.'),
   );
diff --git a/modules/menu/menu.test b/modules/menu/menu.test
index e2cfe7ec8da73849a96ee5e4958b7a08c53b01f2..22a527781bbd748fa0c4997c69bb2b73f0795847 100644
--- a/modules/menu/menu.test
+++ b/modules/menu/menu.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.test,v 1.40 2010/08/30 00:22:03 webchick Exp $
+// $Id: menu.test,v 1.41 2010/09/24 00:37:43 dries Exp $
 
 /**
  * @file
@@ -112,14 +112,14 @@ class MenuTestCase extends DrupalWebTestCase {
 
     // Assert the new menu.
     $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
-    $this->assertText($title, t('Custom menu was added.'));
+    $this->assertRaw($title, t('Custom menu was added.'));
 
     // Edit the menu.
     $new_title = $this->randomName(16);
     $menu['title'] = $new_title;
     menu_save($menu);
     $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
-    $this->assertText($new_title, t('Custom menu was edited.'));
+    $this->assertRaw($new_title, t('Custom menu was edited.'));
   }
 
   /**
diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc
index ce7442701dc8c33ecc6878f61d24539fb6324d2a..a9a70a1b3dbee070f8c46bd48b32ab22d2250a7a 100644
--- a/modules/node/content_types.inc
+++ b/modules/node/content_types.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: content_types.inc,v 1.117 2010/09/03 17:47:20 dries Exp $
+// $Id: content_types.inc,v 1.118 2010/10/07 00:28:20 webchick Exp $
 
 /**
  * @file
@@ -320,6 +320,9 @@ function node_type_form_submit($form, &$form_state) {
   $type->custom = $form_state['values']['custom'];
   $type->modified = TRUE;
   $type->locked = $form_state['values']['locked'];
+  if (isset($form['#node_type']->module)) {
+    $type->module = $form['#node_type']->module;
+  }
 
   if ($op == t('Delete content type')) {
     $form_state['redirect'] = 'admin/structure/types/manage/' . str_replace('_', '-', $type->old_type) . '/delete';
diff --git a/modules/node/node.admin.inc b/modules/node/node.admin.inc
index de8ecbe04931f0943393191ed114f78d2e23c28b..07c25512e6e5f4cc32aad6fdc1fc741af239f054 100644
--- a/modules/node/node.admin.inc
+++ b/modules/node/node.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.admin.inc,v 1.98 2010/08/30 06:26:45 webchick Exp $
+// $Id: node.admin.inc,v 1.100 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -148,7 +148,7 @@ function node_filter_form() {
   $form['filters'] = array(
     '#type' => 'fieldset',
     '#title' => t('Show only items where'),
-    '#theme' => 'node_filters',
+    '#theme' => 'exposed_filters__node',
   );
   foreach ($session as $filter) {
     list($type, $value) = $filter;
@@ -163,11 +163,12 @@ function node_filter_form() {
     else {
       $value = $filters[$type]['options'][$value];
     }
+    $t_args = array('%property' => $filters[$type]['title'], '%value' => $value);
     if ($i++) {
-      $form['filters']['current'][] = array('#markup' => t('<em>and</em> where <strong>%type</strong> is <strong>%value</strong>', array('%type' => $filters[$type]['title'], '%value' => $value)));
+      $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args));
     }
     else {
-      $form['filters']['current'][] = array('#markup' => t('<strong>%type</strong> is <strong>%value</strong>', array('%type' => $filters[$type]['title'], '%value' => $value)));
+      $form['filters']['current'][] = array('#markup' => t('where %property is %value', $t_args));
     }
     if (in_array($type, array('type', 'language'))) {
       // Remove the option if it is already being filtered on.
@@ -175,9 +176,17 @@ function node_filter_form() {
     }
   }
 
+  $form['filters']['status'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('clearfix')),
+    '#prefix' => ($i ? '<div class="additional-filters">' . t('and where') . '</div>' : ''),
+  );
+  $form['filters']['status']['filters'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('filters')),
+  );
   foreach ($filters as $key => $filter) {
-    $names[$key] = $filter['title'];
-    $form['filters']['status'][$key] = array(
+    $form['filters']['status']['filters'][$key] = array(
       '#type' => 'select',
       '#options' => $filter['options'],
       '#title' => $filter['title'],
@@ -185,15 +194,17 @@ function node_filter_form() {
     );
   }
 
-  $form['filters']['actions'] = array(
+  $form['filters']['status']['actions'] = array(
     '#type' => 'actions',
-    '#id' => 'node-admin-buttons',
     '#attributes' => array('class' => array('container-inline')),
   );
-  $form['filters']['actions']['submit'] = array('#type' => 'submit', '#value' => (count($session) ? t('Refine') : t('Filter')));
+  $form['filters']['status']['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => count($session) ? t('Refine') : t('Filter'),
+  );
   if (count($session)) {
-    $form['filters']['actions']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
-    $form['filters']['actions']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
+    $form['filters']['status']['actions']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
+    $form['filters']['status']['actions']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
   }
 
   drupal_add_js('misc/form.js');
@@ -201,46 +212,6 @@ function node_filter_form() {
   return $form;
 }
 
-/**
- * Returns HTML for a node administration filter selector.
- *
- * @param $variables
- *   An associative array containing:
- *   - form: A render element representing the form.
- *
- * @ingroup themeable
- */
-function theme_node_filters($variables) {
-  $form = $variables['form'];
-  $output = '';
-
-  $output .= '<ul class="clearfix">';
-  if (!empty($form['current'])) {
-    foreach (element_children($form['current']) as $key) {
-      $output .= '<li>' . drupal_render($form['current'][$key]) . '</li>';
-    }
-  }
-  $output .= '</ul>';
-
-  $output .= '<div class="clearfix">';
-
-  $output .= '<dl class="multiselect">' . (!empty($form['current']) ? '<dt><em>' . t('and') . '</em> ' . t('where') . '</dt>' : '');
-
-  $output .= '<dd>';
-
-  foreach (element_children($form['status']) as $key) {
-    $output .= drupal_render($form['status'][$key]);
-  }
-  $output .= '</dd>';
-
-  $output .= '</dl>';
-  $output .= drupal_render($form['actions']);
-
-  $output .= '</div>';
-
-  return $output;
-}
-
 /**
  * Process result from node administration filter form.
  */
@@ -546,7 +517,7 @@ function node_admin_nodes() {
     );
   }
 
-  $form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
+  $form['pager'] = array('#markup' => theme('pager'));
   return $form;
 }
 
diff --git a/modules/node/node.api.php b/modules/node/node.api.php
index b99d72bd7287c1af1be0e40b950ac5202b263bf7..73c457bcc741233f141c4b6622f6c7b9bd71d7c2 100644
--- a/modules/node/node.api.php
+++ b/modules/node/node.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.api.php,v 1.73 2010/09/03 19:56:51 dries Exp $
+// $Id: node.api.php,v 1.77 2010/10/05 02:21:26 dries Exp $
 
 /**
  * @file
@@ -138,7 +138,10 @@
  * an array of the list IDs that this user is a member of.
  *
  * A node access module may implement as many realms as necessary to
- * properly define the access privileges for the nodes.
+ * properly define the access privileges for the nodes. Note that the system
+ * makes no distinction between published and unpublished nodes. It is the
+ * module's responsibility to provide appropriate realms to limit access to
+ * unpublished content.
  *
  * @param $account
  *   The user object whose grants are requested.
@@ -169,6 +172,12 @@ function hook_node_grants($account, $op) {
  * interested, it must respond with an array of permissions arrays for that
  * node.
  *
+ * Node access grants apply regardless of the published or unpublished status
+ * of the node. Implementations must make sure not to grant access to
+ * unpublished nodes if they don't want to change the standard access control
+ * behavior. Your module may need to create a separate access realm to handle
+ * access to unpublished nodes.
+ *
  * Note that the grant values in the return value from your hook must be
  * integers and not boolean TRUE and FALSE.
  *
@@ -177,7 +186,9 @@ function hook_node_grants($account, $op) {
  *   hook_node_grants().
  * - 'gid': A 'grant ID' from hook_node_grants().
  * - 'grant_view': If set to 1 a user that has been identified as a member
- *   of this gid within this realm can view this node.
+ *   of this gid within this realm can view this node. This should usually be
+ *   set to $node->status. Failure to do so may expose unpublished content
+ *   to some users.
  * - 'grant_update': If set to 1 a user that has been identified as a member
  *   of this gid within this realm can edit this node.
  * - 'grant_delete': If set to 1 a user that has been identified as a member
@@ -187,28 +198,58 @@ function hook_node_grants($account, $op) {
  *   priority will not be written. If there is any doubt, it is best to
  *   leave this 0.
  *
+ *
+ * When an implementation is interested in a node but want to deny access to
+ * everyone, it may return a "deny all" grant:
+ *
+ * @code
+ * $grants[] = array(
+ *   'realm' => 'all',
+ *   'gid' => 0,
+ *   'grant_view' => 0,
+ *   'grant_update' => 0,
+ *   'grant_delete' => 0,
+ *   'priority' => 1,
+ * );
+ * @endcode
+ *
+ * Setting the priority should cancel out other grants. In the case of a
+ * conflict between modules, it is safer to use hook_node_access_records_alter()
+ * to return only the deny grant.
+ *
+ * Note: a deny all grant is not written to the database; denies are implicit.
+ *
+ * @see node_access_write_grants()
+ *
+ * @param $node
+ *   The node that has just been saved.
+ *
+ * @return
+ *   An array of grants as defined above.
+ *
  * @ingroup node_access
  */
 function hook_node_access_records($node) {
-  if (node_access_example_disabling()) {
-    return;
-  }
-
   // We only care about the node if it has been marked private. If not, it is
   // treated just like any other node and we completely ignore it.
   if ($node->private) {
     $grants = array();
-    $grants[] = array(
-      'realm' => 'example',
-      'gid' => 1,
-      'grant_view' => 1,
-      'grant_update' => 0,
-      'grant_delete' => 0,
-      'priority' => 0,
-    );
-
+    // Only published nodes should be viewable to all users. If we allow access
+    // blindly here, then all users could view an unpublished node.
+    if ($node->status) {
+      $grants[] = array(
+        'realm' => 'example',
+        'gid' => 1,
+        'grant_view' => 1,
+        'grant_update' => 0,
+        'grant_delete' => 0,
+        'priority' => 0,
+      );
+    }
     // For the example_author array, the GID is equivalent to a UID, which
-    // means there are many many groups of just 1 user.
+    // means there are many groups of just 1 user.
+    // Note that an author can always view his or her nodes, even if they
+    // have status unpublished.
     $grants[] = array(
       'realm' => 'example_author',
       'gid' => $node->uid,
@@ -217,6 +258,7 @@ function hook_node_access_records($node) {
       'grant_delete' => 1,
       'priority' => 0,
     );
+
     return $grants;
   }
 }
@@ -238,6 +280,8 @@ function hook_node_access_records($node) {
  * user must have one or more matching permissions in order to complete the
  * requested operation.
  *
+ * A module may deny all access to a node by setting $grants to an empty array.
+ *
  * @see hook_node_grants()
  * @see hook_node_grants_alter()
  *
@@ -281,6 +325,8 @@ function hook_node_access_records_alter(&$grants, $node) {
  * The resulting grants are then checked against the records stored in the
  * {node_access} table to determine if the operation may be completed.
  *
+ * A module may deny all access to a user by setting $grants to an empty array.
+ *
  * @see hook_node_access_records()
  * @see hook_node_access_records_alter()
  *
@@ -702,18 +748,20 @@ function hook_node_submit($node, $form, &$form_state) {
  * the RSS item generated for this node.
  * For details on how this is used, see node_feed().
  *
- * @see taxonomy_node_view()
- * @see upload_node_view()
+ * @see blog_node_view()
+ * @see forum_node_view()
  * @see comment_node_view()
  *
  * @param $node
  *   The node that is being assembled for rendering.
  * @param $view_mode
  *   The $view_mode parameter from node_view().
+ * @param $langcode
+ *   The language code used for rendering.
  *
  * @ingroup node_api_hooks
  */
-function hook_node_view($node, $view_mode) {
+function hook_node_view($node, $view_mode, $langcode) {
   $node->content['my_additional_field'] = array(
     '#markup' => $additional_field,
     '#weight' => 10,
diff --git a/modules/node/node.css b/modules/node/node.css
index 5a725f0a4b35e6147dda382439d7f78cd3a093cf..1df32e34143ac69fb2468d84c898b7d902caf233 100644
--- a/modules/node/node.css
+++ b/modules/node/node.css
@@ -1,4 +1,4 @@
-/* $Id: node.css,v 1.17 2010/04/28 20:08:39 dries Exp $ */
+/* $Id: node.css,v 1.18 2010/09/17 14:53:21 dries Exp $ */
 
 .node-unpublished {
   background-color: #fff4f4;
@@ -6,22 +6,6 @@
 .preview .node {
   background-color: #ffffea;
 }
-/* Override the default multiselect layout in system-behavior.css. */
-#node-admin-content dl.multiselect dd,
-dl.multiselect dd .form-item {
-  width: 20em; /* 6em label + 14em select */
-}
-#node-admin-content dl.multiselect dd .form-item label {
-  display: block;
-  float: left; /* LTR */
-  width: 6em;
-  font-weight: normal;
-}
-#node-admin-buttons {
-  float: left; /* LTR */
-  margin-left: 0.5em; /* LTR */
-  clear: right; /* LTR */
-}
 td.revision-current {
   background: #ffc;
 }
diff --git a/modules/node/node.info b/modules/node/node.info
index 1f52b5640c7ee0bc5142ee340f9b798b706bf767..4c3e8a5afa6bd06d564d8a4c17ae6752e5b1b16f 100644
--- a/modules/node/node.info
+++ b/modules/node/node.info
@@ -15,8 +15,8 @@ required = TRUE
 configure = admin/structure/types
 stylesheets[all][] = node.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/node/node.install b/modules/node/node.install
index 108ef5a3dc9581a84d787f84511a1d4fc964fbb2..1f429760dc6131d854e5e94feb9674f4c5f59f2e 100644
--- a/modules/node/node.install
+++ b/modules/node/node.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.install,v 1.55 2010/09/13 05:50:09 webchick Exp $
+// $Id: node.install,v 1.60 2010/10/07 00:28:20 webchick Exp $
 
 /**
  * @file
@@ -294,6 +294,12 @@ function node_schema() {
         'length' => 255,
         'not null' => TRUE,
       ),
+      'module' => array(
+        'description' => 'The module defining this node type.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ),
       'description' => array(
         'description' => 'A brief description of this type.',
         'type' => 'text',
@@ -344,6 +350,13 @@ function node_schema() {
         'default' => 0,
         'size' => 'tiny',
       ),
+      'disabled' => array(
+        'description' => 'A boolean indicating whether the node type is disabled.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'size' => 'tiny'
+      ),
       'orig_type' => array(
         'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
         'type' => 'varchar',
@@ -411,6 +424,9 @@ function node_update_dependencies() {
   // the Field module has been enabled, but before upgrading field data.
   $dependencies['node'][7006] = array(
     'system' => 7049,
+    // It must also run after filter_update_7000() because it needs to query
+    // the list of existing text formats.
+    'filter' => 7000,
   );
   $dependencies['system'][7050] = array(
     'node' => 7006,
@@ -435,16 +451,40 @@ function _update_7000_node_get_types() {
  */
 
 /**
- * Fix node type 'module' attribute to avoid name-space conflicts.
+ * Upgrade the node type table and fix node type 'module' attribute to avoid name-space conflicts.
  */
 function node_update_7000() {
+  // Rename the module column to base.
+  db_change_field('node_type', 'module', 'base', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE));
+
+  db_add_field('node_type', 'module', array(
+    'description' => 'The module defining this node type.',
+    'type' => 'varchar',
+    'default' => '',
+    'length' => 255,
+    'not null' => TRUE,
+  ));
+
+  db_add_field('node_type', 'disabled', array(
+    'description' => 'A boolean indicating whether the node type is disabled.',
+    'type' => 'int',
+    'not null' => TRUE,
+    'default' => 0,
+    'size' => 'tiny'
+  ));
+
+  $modules = db_select('system', 's')
+    ->fields('s', array('name'))
+    ->condition('type', 'module');
   db_update('node_type')
-    ->fields(array('module' => 'node_content'))
-    ->condition('module', 'node')
+    ->expression('module', 'base')
+    ->condition('base', $modules, 'IN')
     ->execute();
 
-  // Rename the module column to base.
-  db_change_field('node_type', 'module', 'base', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE));
+  db_update('node_type')
+    ->fields(array('base' => 'node_content'))
+    ->condition('base', 'node')
+    ->execute();
 }
 
 /**
@@ -482,10 +522,9 @@ function node_update_7004() {
   // Map old preview setting to new values order.
   $original_preview ? $original_preview = 2 : $original_preview = 1;
   drupal_static_reset('_node_types_build');
-  $type_list = node_type_get_types();
 
   // Apply original settings to all types.
-  foreach ($type_list as $type => $entity) {
+  foreach (_update_7000_node_get_types() as $type => $type_object) {
     variable_set('teaser_length_' . $type, $original_length);
     variable_set('node_preview_' . $type, $original_preview);
   }
@@ -497,7 +536,7 @@ function node_update_7004() {
  * Add status/comment/promote and sticky columns to the {node_revision} table.
  */
 function node_update_7005() {
-  foreach(array('status', 'comment', 'promote', 'sticky') as $column) {
+  foreach (array('status', 'comment', 'promote', 'sticky') as $column) {
     db_add_field('node_revision', $column, array(
       'type' => 'int',
       'not null' => TRUE,
@@ -514,18 +553,27 @@ function node_update_7006(&$sandbox) {
 
   // Get node type info for every invocation.
   drupal_static_reset('_node_types_build');
-  $node_types = node_type_get_types();
 
   if (!isset($sandbox['total'])) {
     // Initial invocation.
 
+    // First, create the body field.
+    $body_field = array(
+      'field_name' => 'body',
+      'type' => 'text_with_summary',
+      'module' => 'text',
+      'cardinality' => 1,
+      'entity_types' => array('node'),
+      'translatable' => TRUE,
+    );
+    _update_7000_field_create_field($body_field);
+
+    $default_trim_length = variable_get('teaser_length', 600);
+
     // Get node type info, specifically the body field settings.
-    $result = db_select('node_type', 'node_type')
-      ->fields('node_type')
-      ->execute();
-    foreach ($result as $type_object) {
-      $node_types[$type_object->type] = $type_object;
-    }
+    $node_types = _update_7000_node_get_types();
+
+    // Create default settings for orphan nodes.
     $extra_types = db_query('SELECT DISTINCT type FROM {node} WHERE type NOT IN (:types)', array(':types' => array_keys($node_types)))->fetchCol();
     foreach ($extra_types as $type) {
       $type_object = new stdClass;
@@ -538,26 +586,38 @@ function node_update_7006(&$sandbox) {
       $node_types[$type_object->type] = $type_object;
     }
 
-    $default_trim_length = variable_get('teaser_length', 600);
     // Add body field instances for existing node types.
     foreach ($node_types as $node_type) {
       if ($node_type->has_body) {
-        $instance = node_add_body_field($node_type, $node_type->body_label);
-        // Update newly created instance to convert teaser_length variable
-        // into formatter settings.
         $trim_length = variable_get('teaser_length_' . $node_type->type, $default_trim_length);
-        $instance_changed = FALSE;
-        foreach ($instance['display'] as $view_mode => $view_mode_info) {
-          if ($view_mode_info['type'] == 'text_trimmed' || $view_mode_info['type'] == 'text_summary_or_trimmed') {
-            if (!isset($view_mode_info['settings']['trim_length'])) {
-              $instance['display'][$view_mode]['settings']['trim_length'] = $trim_length;
-              $instance_changed = TRUE;
-            }
-          }
-        }
-        if ($instance_changed) {
-          field_update_instance($instance);
-        }
+
+        $instance = array(
+          'entity_type' => 'node',
+          'bundle' => $node_type->type,
+          'label' => $node_type->body_label,
+          'widget' => array(
+            'type' => 'text_textarea_with_summary',
+            'settings' => array(
+              'rows' => 20,
+              'summary_rows' => 5,
+            ),
+            'weight' => -4,
+            'module' => 'text',
+          ),
+          'settings' => array('display_summary' => TRUE),
+          'display' => array(
+            'default' => array(
+              'label' => 'hidden',
+              'type' => 'text_default',
+            ),
+            'teaser' => array(
+              'label' => 'hidden',
+              'type' => 'text_summary_or_trimmed',
+              'trim_length' => $trim_length,
+            ),
+          ),
+        );
+        _update_7000_field_create_instance($body_field, $instance);
         variable_del('teaser_length_' . $node_type->type);
       }
       // Leave 'teaser_length' variable for aggregator module upgrade.
@@ -567,27 +627,28 @@ function node_update_7006(&$sandbox) {
       );
     }
 
+    // Used below when updating the stored text format of each node body.
+    $sandbox['existing_text_formats'] = db_query("SELECT format FROM {filter_format}")->fetchCol();
+
     // Initialize state for future calls.
     $sandbox['last'] = 0;
     $sandbox['count'] = 0;
 
     $query = db_select('node', 'n');
-    $query->join('node_revision', 'nr', 'n.vid = nr.vid');
+    $query->join('node_revision', 'nr', 'n.nid = nr.nid');
     $sandbox['total'] = $query->countQuery()->execute()->fetchField();
+
+    $sandbox['body_field_id'] = $body_field['id'];
   }
   else {
     // Subsequent invocations.
 
-    // Grab the body field ID for field_sql_storage_field_storage_write().
-    $body_field = field_info_field('body');
-    $body_field_id = $body_field['id'];
-
     $found = FALSE;
     if ($sandbox['total']) {
       // Operate on every revision of every node (whee!), in batches.
       $batch_size = 200;
       $query = db_select('node_revision', 'nr');
-      $query->innerJoin('node', 'n', 'n.vid = nr.vid');
+      $query->innerJoin('node', 'n', 'n.nid = nr.nid');
       $query
         ->fields('nr', array('nid', 'vid', 'body', 'teaser', 'format'))
         ->fields('n', array('type', 'status', 'comment', 'promote', 'sticky', 'language'))
@@ -596,7 +657,7 @@ function node_update_7006(&$sandbox) {
         ->range(0, $batch_size);
       $revisions = $query->execute();
 
-      // Load each reversion of each node, set up 'body'
+      // Load each revision of each node, set up 'body'
       // appropriately, and save the node's field data.  Note that
       // node_load() will not return the body or teaser values from
       // {node_revision} because those columns have been removed from the
@@ -625,14 +686,23 @@ function node_update_7006(&$sandbox) {
             $revision->body = substr($revision->body, strlen($break));
           }
           $node->body[$langcode][0]['value'] = $revision->body;
-          // Explicitly store the current default text format if the revision
-          // did not have its own text format. Similar conversions for other
-          // core modules are performed in filter_update_7005(), but we do this
-          // one here since we are already migrating the data.
-          $node->body[$langcode][0]['format'] = !empty($revision->format) ? $revision->format : variable_get('filter_default_format', 1);
+          // Update the revision's text format for the changes to the Drupal 7
+          // filter system. This uses the same kind of logic that occurs, for
+          // example, in user_update_7010(), but we do this here rather than
+          // via a separate set of database queries, since we are already
+          // migrating the data.
+          if (empty($revision->body) && empty($revision->format)) {
+            $node->body[$langcode][0]['format'] = NULL;
+          }
+          elseif (!in_array($revision->format, $sandbox['existing_text_formats'])) {
+            $node->body[$langcode][0]['format'] = variable_get('filter_default_format', 1);
+          }
+          else {
+            $node->body[$langcode][0]['format'] = $revision->format;
+          }
           // This is a core update and no contrib modules are enabled yet, so
           // we can assume default field storage for a faster update.
-          field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array($body_field_id));
+          _update_7000_field_sql_storage_write('node', $node->type, $node->nid, $node->vid, 'body', $node->body);
         }
 
         // Migrate the status columns to the {node_revision} table.
@@ -684,7 +754,7 @@ function node_update_7007() {
 function node_update_7008() {
   $roles = user_roles(FALSE, 'administer nodes');
   foreach ($roles as $rid => $role) {
-    user_role_grant_permissions($rid, array('access content overview'));
+    _update_7000_user_role_grant_permissions($rid, array('access content overview'), 'node');
   }
 }
 
diff --git a/modules/node/node.module b/modules/node/node.module
index ffd6ed84c90b2cb740f97cd9bc2862a2450398ee..b12b91b4a522e603ba744346ad71162f5bbb6388 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.module,v 1.1298 2010/09/11 06:03:11 webchick Exp $
+// $Id: node.module,v 1.1305 2010/10/07 00:28:20 webchick Exp $
 
 /**
  * @file
@@ -132,10 +132,6 @@ function node_theme() {
     'node_search_admin' => array(
       'render element' => 'form',
     ),
-    'node_filters' => array(
-      'render element' => 'form',
-      'file' => 'node.admin.inc',
-    ),
     'node_add_list' => array(
       'variables' => array('content' => NULL),
       'file' => 'node.pages.inc',
@@ -465,16 +461,7 @@ function node_type_get_name($node) {
  * and obsolete types.
  */
 function node_types_rebuild() {
-  // Reset and load updated node types.
-  drupal_static_reset('_node_types_build');
-  foreach (node_type_get_types() as $type => $info) {
-    if (!empty($info->is_new)) {
-      node_type_save($info);
-    }
-    if (!empty($info->disabled)) {
-      node_type_delete($info->type);
-    }
-  }
+  _node_types_build(TRUE);
 }
 
 /**
@@ -517,6 +504,8 @@ function node_type_save($info) {
     'custom' => (int) $type->custom,
     'modified' => (int) $type->modified,
     'locked' => (int) $type->locked,
+    'disabled' => (int) $type->disabled,
+    'module' => $type->module,
   );
 
   if ($is_existing) {
@@ -664,6 +653,8 @@ function node_type_update_nodes($old_type, $type) {
  * These two information sources are not synchronized during module installation
  * until node_types_rebuild() is called.
  *
+ * @param $rebuild
+ *  TRUE to rebuild node types. Equivalent to calling node_types_rebuild().
  * @return
  *   Associative array with two components:
  *   - names: Associative array of the names of node types, keyed by the type.
@@ -677,42 +668,66 @@ function node_type_update_nodes($old_type, $type) {
  *   implementations, but are still in the database. These are indicated in the
  *   type object by $type->disabled being set to TRUE.
  */
-function _node_types_build() {
-  $_node_types = &drupal_static(__FUNCTION__);
-  if (is_object($_node_types)) {
-    return $_node_types;
+function _node_types_build($rebuild = FALSE) {
+  if (!$rebuild) {
+    $_node_types = &drupal_static(__FUNCTION__);
+    if (is_object($_node_types)) {
+      return $_node_types;
+    }
   }
+
   $_node_types = (object)array('types' => array(), 'names' => array());
 
-  $info_array = module_invoke_all('node_info');
-  foreach ($info_array as $type => $info) {
-    $info['type'] = $type;
-    $_node_types->types[$type] = node_type_set_defaults($info);
-    $_node_types->names[$type] = $info['name'];
+  foreach (module_implements('node_info') as $module) {
+    $info_array = module_invoke($module, 'node_info');
+    foreach ($info_array as $type => $info) {
+      $info['type'] = $type;
+      $_node_types->types[$type] = node_type_set_defaults($info);
+      $_node_types->types[$type]->module = $module;
+      $_node_types->names[$type] = $info['name'];
+    }
   }
-  $type_result = db_select('node_type', 'nt')
+  $query = db_select('node_type', 'nt')
     ->addTag('translatable')
     ->addTag('node_type_access')
     ->fields('nt')
-    ->orderBy('nt.type', 'ASC')
-    ->execute();
-  foreach ($type_result as $type_object) {
+    ->orderBy('nt.type', 'ASC');
+  if (!$rebuild) {
+    $query->condition('disabled', 0);
+  }
+  foreach ($query->execute() as $type_object) {
+    $type_db = $type_object->type;
+    // Original disabled value.
+    $disabled = $type_object->disabled;
     // Check for node types from disabled modules and mark their types for removal.
     // Types defined by the node module in the database (rather than by a separate
     // module using hook_node_info) have a base value of 'node_content'. The isset()
     // check prevents errors on old (pre-Drupal 7) databases.
-    if (isset($type_object->base) && $type_object->base != 'node_content' && empty($info_array[$type_object->type])) {
+    if (isset($type_object->base) && $type_object->base != 'node_content' && empty($info_array[$type_db])) {
       $type_object->disabled = TRUE;
     }
-    if (!isset($_node_types->types[$type_object->type]) || $type_object->modified) {
-      $_node_types->types[$type_object->type] = $type_object;
-      $_node_types->names[$type_object->type] = $type_object->name;
+    if (isset($info_array[$type_db])) {
+      $type_object->disabled = FALSE;
+    }
+    if (!isset($_node_types->types[$type_db]) || $type_object->modified) {
+      $_node_types->types[$type_db] = $type_object;
+      $_node_types->names[$type_db] = $type_object->name;
 
-      if ($type_object->type != $type_object->orig_type) {
+      if ($type_db != $type_object->orig_type) {
         unset($_node_types->types[$type_object->orig_type]);
         unset($_node_types->names[$type_object->orig_type]);
       }
     }
+    $_node_types->types[$type_db]->disabled = $type_object->disabled;
+    $_node_types->types[$type_db]->disabled_changed = $disabled != $type_object->disabled;
+  }
+
+  if ($rebuild) {
+    foreach ($_node_types->types as $type => $type_object) {
+      if (!empty($type_object->is_new) || !empty($type_object->disabled_changed)) {
+        node_type_save($type_object);
+      }
+    }
   }
 
   asort($_node_types->names);
@@ -746,6 +761,7 @@ function node_type_set_defaults($info = array()) {
     $type->custom = 0;
     $type->modified = 0;
     $type->locked = 1;
+    $type->disabled = 0;
     $type->is_new = 1;
 
     $type->has_title = 1;
@@ -761,6 +777,9 @@ function node_type_set_defaults($info = array()) {
   if (!$new_type->has_title) {
     $new_type->title_label = '';
   }
+  if (empty($new_type->module)) {
+    $new_type->module = $new_type->base == 'node_content' ? 'node' : '';
+  }
   $new_type->orig_type = isset($info['type']) ? $info['type'] : '';
 
   return $new_type;
@@ -1212,13 +1231,20 @@ function node_revision_delete($revision_id) {
  *   A node object.
  * @param $view_mode
  *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  *
  * @return
  *   An array as expected by drupal_render().
  */
-function node_view($node, $view_mode = 'full') {
+function node_view($node, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Populate $node->content with a render() array.
-  node_build_content($node, $view_mode);
+  node_build_content($node, $view_mode, $langcode);
 
   $build = $node->content;
   // We don't need duplicate rendering info in node->content.
@@ -1228,7 +1254,9 @@ function node_view($node, $view_mode = 'full') {
     '#theme' => 'node',
     '#node' => $node,
     '#view_mode' => $view_mode,
+    '#language' => $langcode,
   );
+
   // Add contextual links for this node, except when the node is already being
   // displayed on its own page. Modules may alter this behavior (for example,
   // to restrict contextual links to certain view modes) by implementing
@@ -1267,8 +1295,15 @@ function node_view($node, $view_mode = 'full') {
  *   A node object.
  * @param $view_mode
  *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  */
-function node_build_content($node, $view_mode = 'full') {
+function node_build_content($node, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Remove previously built content, if exists.
   $node->content = array();
 
@@ -1284,7 +1319,7 @@ function node_build_content($node, $view_mode = 'full') {
   // twice.
   field_attach_prepare_view('node', array($node->nid => $node), $view_mode);
   entity_prepare_view('node', array($node->nid => $node));
-  $node->content += field_attach_view('node', $node, $view_mode);
+  $node->content += field_attach_view('node', $node, $view_mode, $langcode);
 
   // Always display a read more link on teasers because we have no way
   // to know when a teaser view is different than a full view.
@@ -1303,7 +1338,7 @@ function node_build_content($node, $view_mode = 'full') {
   );
 
   // Allow modules to make their own additions to the node.
-  module_invoke_all('node_view', $node, $view_mode);
+  module_invoke_all('node_view', $node, $view_mode, $langcode);
 }
 
 /**
@@ -1848,12 +1883,10 @@ function node_menu() {
     'title' => 'Delete',
     'page arguments' => array('node_type_delete_confirm', 4),
     'access arguments' => array('administer content types'),
-    'type' => MENU_CALLBACK,
     'file' => 'content_types.inc',
   );
 
   $items['node'] = array(
-    'title' => 'Content',
     'page callback' => 'node_page_default',
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
@@ -1883,7 +1916,7 @@ function node_menu() {
       'title' => $type->name,
       'title callback' => 'check_plain',
       'page callback' => 'node_add',
-      'page arguments' => array(2),
+      'page arguments' => array($type->type),
       'access callback' => 'node_access',
       'access arguments' => array('create', $type->type),
       'description' => $type->description,
@@ -1899,7 +1932,6 @@ function node_menu() {
     'page arguments' => array(1),
     'access callback' => 'node_access',
     'access arguments' => array('view', 1),
-    'type' => MENU_CALLBACK,
   );
   $items['node/%node/view'] = array(
     'title' => 'View',
@@ -1947,7 +1979,6 @@ function node_menu() {
     'page arguments' => array(1, TRUE),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1),
-    'type' => MENU_CALLBACK,
   );
   $items['node/%node/revisions/%/revert'] = array(
     'title' => 'Revert to earlier revision',
@@ -1956,7 +1987,6 @@ function node_menu() {
     'page arguments' => array('node_revision_revert_confirm', 1),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1, 'update'),
-    'type' => MENU_CALLBACK,
     'file' => 'node.pages.inc',
   );
   $items['node/%node/revisions/%/delete'] = array(
@@ -1966,7 +1996,6 @@ function node_menu() {
     'page arguments' => array('node_revision_delete_confirm', 1),
     'access callback' => '_node_revision_access',
     'access arguments' => array(1, 'delete'),
-    'type' => MENU_CALLBACK,
     'file' => 'node.pages.inc',
   );
   return $items;
@@ -2444,15 +2473,19 @@ function node_feed($nids = FALSE, $channel = array()) {
  *   View mode, e.g. 'full', 'teaser'...
  * @param $weight
  *   An integer representing the weight of the first node in the list.
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
+ *
  * @return
  *   An array in the format expected by drupal_render().
  */
-function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0) {
+function node_view_multiple($nodes, $view_mode = 'teaser', $weight = 0, $langcode = NULL) {
   field_attach_prepare_view('node', $nodes, $view_mode);
   entity_prepare_view('node', $nodes);
   $build = array();
   foreach ($nodes as $node) {
-    $build['nodes'][$node->nid] = node_view($node, $view_mode);
+    $build['nodes'][$node->nid] = node_view($node, $view_mode, $langcode);
     $build['nodes'][$node->nid]['#weight'] = $weight;
     $weight++;
   }
@@ -3166,8 +3199,8 @@ function node_access_acquire_grants($node, $delete = TRUE) {
   $grants = module_invoke_all('node_access_records', $node);
   // Let modules alter the grants.
   drupal_alter('node_access_records', $grants, $node);
-  // If no grants are set, then use the default grant.
-  if (empty($grants)) {
+  // If no grants are set and the node is published, then use the default grant.
+  if (empty($grants) && !empty($node->status)) {
     $grants[] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
   }
   else {
@@ -3216,7 +3249,7 @@ function node_access_write_grants($node, $grants, $realm = NULL, $delete = TRUE)
   }
 
   // Only perform work when node_access modules are active.
-  if (count(module_implements('node_grants'))) {
+  if (!empty($grants) && count(module_implements('node_grants'))) {
     $query = db_insert('node_access')->fields(array('nid', 'realm', 'gid', 'grant_view', 'grant_update', 'grant_delete'));
     foreach ($grants as $grant) {
       if ($realm && $realm != $grant['realm']) {
@@ -3586,7 +3619,7 @@ function node_save_action($node) {
 function node_assign_owner_action($node, $context) {
   $node->uid = $context['owner_uid'];
   $owner_name = db_query("SELECT name FROM {users} WHERE uid = :uid", array(':uid' => $context['owner_uid']))->fetchField();
-  watchdog('action', 'Changed owner of @type %title to uid %name.', array('@type' =>  node_type_get_type($node), '%title' => $node->title, '%name' => $owner_name));
+  watchdog('action', 'Changed owner of @type %title to uid %name.', array('@type' =>  node_type_get_name($node), '%title' => $node->title, '%name' => $owner_name));
 }
 
 /**
diff --git a/modules/node/node.test b/modules/node/node.test
index d6179b5bf486016df857c97371cbd0c243bf12c9..7e5eff7546e80cbcddef3428690801b0f03eec38 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: node.test,v 1.94 2010/08/30 00:22:03 webchick Exp $
+// $Id: node.test,v 1.97 2010/10/07 00:28:20 webchick Exp $
 
 /**
  * Test the node_load_multiple() function.
@@ -770,7 +770,7 @@ class NodeRSSContentTestCase extends DrupalWebTestCase {
 
 /**
  * Test case to verify basic node_access functionality.
- * @todo Cover hook_access in a separate test class.
+ * @todo Cover hook_node_access in a separate test class.
  * hook_node_access_records is covered in another test class.
  */
 class NodeAccessUnitTest extends DrupalWebTestCase {
@@ -821,6 +821,9 @@ class NodeAccessUnitTest extends DrupalWebTestCase {
     $node3 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user3->uid));
     $this->assertNodeAccess(array('view' => FALSE), $node3, $web_user3);
 
+    // User cannot create content without permission.
+    $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user3);
+
     // User can 'view own unpublished content', but another user cannot.
     $web_user4 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
     $web_user5 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
@@ -830,7 +833,6 @@ class NodeAccessUnitTest extends DrupalWebTestCase {
 
     // Tests the default access provided for a published node.
     $node5 = $this->drupalCreateNode();
-    $this->assertNodeAccess(array('create' => FALSE), 'page', $web_user3);
     $this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node5, $web_user3);
   }
 }
@@ -909,6 +911,12 @@ class NodeAccessRecordsUnitTest extends DrupalWebTestCase {
       drupal_alter('node_grants', $altered_grants, $web_user, $op);
       $this->assertNotEqual($grants, $altered_grants, t('Altered the %op grant for a user.', array('%op' => $op)));
     }
+
+    // Check that core does not grant access to an unpublished node when an
+    // empty $grants array is returned.
+    $node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE));
+    $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->nid))->fetchAll();
+    $this->assertEqual(count($records), 0, t('Returned no records for unpublished node.'));
   }
 }
 
@@ -1140,6 +1148,82 @@ class NodeTypeTestCase extends DrupalWebTestCase {
   }
 }
 
+/**
+ * Test node type customizations persistence.
+ */
+class NodeTypePersistenceTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Node type persist',
+      'description' => 'Ensures that node type customization survives module enabling and disabling.',
+      'group' => 'Node',
+    );
+  }
+
+  /**
+   * Test node type customizations persist through disable and uninstall.
+   */
+  function testNodeTypeCustomizationPersistence() {
+    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules'));
+    $this->drupalLogin($web_user);
+    $poll_key = 'modules[Core][poll][enable]';
+    $poll_enable = array($poll_key => "1");
+    $poll_disable = array($poll_key => FALSE);
+
+    // Enable poll and verify that the node type is in the DB and is not
+    // disabled.
+    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
+    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
+    $this->assertNotIdentical($disabled, FALSE, t('Poll node type found in the database'));
+    $this->assertEqual($disabled, 0, t('Poll node type is not disabled'));
+
+    // Check that poll node type (uncustomized) shows up.
+    $this->drupalGet('node/add');
+    $this->assertText('poll', t('poll type is found on node/add'));
+
+    // Customize poll description.
+    $description = $this->randomName();
+    $edit = array('description' => $description);
+    $this->drupalPost('admin/structure/types/manage/poll', $edit, t('Save content type'));
+
+    // Check that poll node type customization shows up.
+    $this->drupalGet('node/add');
+    $this->assertText($description, t('Customized description found'));
+
+    // Disable poll and check that the node type gets disabled.
+    $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
+    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
+    $this->assertEqual($disabled, 1, t('Poll node type is disabled'));
+    $this->drupalGet('node/add');
+    $this->assertNoText('poll', t('poll type is not found on node/add'));
+
+    // Reenable poll and check that the customization survived the module
+    // disable.
+    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
+    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
+    $this->assertNotIdentical($disabled, FALSE, t('Poll node type found in the database'));
+    $this->assertEqual($disabled, 0, t('Poll node type is not disabled'));
+    $this->drupalGet('node/add');
+    $this->assertText($description, t('Customized description found'));
+
+    // Disable and uninstall poll.
+    $this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
+    $edit = array('uninstall[poll]' => 'poll');
+    $this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
+    $this->drupalPost(NULL, array(), t('Uninstall'));
+    $disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
+    $this->assertTrue($disabled, t('Poll node type is in the database and is disabled'));
+    $this->drupalGet('node/add');
+    $this->assertNoText('poll', t('poll type is no longer found on node/add'));
+
+    // Reenable poll and check that the customization survived the module
+    // uninstall.
+    $this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
+    $this->drupalGet('node/add');
+    $this->assertText($description, t('Customized description is found even after uninstall and reenable.'));
+  }
+}
+
 /**
  * Rebuild the node_access table.
  */
@@ -1224,7 +1308,9 @@ class NodeAdminTestCase extends DrupalWebTestCase {
       'status' => 'status-1',
     );
     $this->drupalPost(NULL, $edit, t('Filter'));
-    $this->assertRaw(t('<strong>%type</strong> is <strong>%value</strong>', array('%type' => t('status'), '%value' => t('published'))), t('Content list is filtered by status.'));
+
+    $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), t('Content list is filtered by status.'));
+
     $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
     $this->assertLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
     $this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
@@ -1234,8 +1320,10 @@ class NodeAdminTestCase extends DrupalWebTestCase {
       'type' => 'page',
     );
     $this->drupalPost(NULL, $edit, t('Refine'));
-    $this->assertRaw(t('<strong>%type</strong> is <strong>%value</strong>', array('%type' => t('status'), '%value' => t('published'))), t('Content list is filtered by status.'));
-    $this->assertRaw(t('<strong>%type</strong> is <strong>%value</strong>', array('%type' => t('type'), '%value' => 'Basic page')), t('Content list is filtered by content type.'));
+
+    $this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), t('Content list is filtered by status.'));
+    $this->assertRaw(t('and where %property is %value', array('%property' => t('type'), '%value' => 'Basic page')), t('Content list is filtered by content type.'));
+
     $this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
     $this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
 
diff --git a/modules/node/tests/node_access_test.info b/modules/node/tests/node_access_test.info
index 8e5fee3d44a2003826af9e42c04d802452b47a6a..9f111a44db95ec0f05003073fa513fe0c717795c 100644
--- a/modules/node/tests/node_access_test.info
+++ b/modules/node/tests/node_access_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = node_access_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/node/tests/node_presave_test.info b/modules/node/tests/node_presave_test.info
index 48ab18563efb6c09b7fe7b686eefbbaf9f39b7bd..d63891915b4e4d1d0b5a42cf7b975229f2e17e3d 100644
--- a/modules/node/tests/node_presave_test.info
+++ b/modules/node/tests/node_presave_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = node_presave_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/node/tests/node_test.info b/modules/node/tests/node_test.info
index 2cc4105b1b26a210e896f384c7811c275b5efe3a..097e84e864023bac51fcc52fa7e09df9b8fde7e6 100644
--- a/modules/node/tests/node_test.info
+++ b/modules/node/tests/node_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = node_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/node/tests/node_test.module b/modules/node/tests/node_test.module
index 5b4058b82424f5b45053d1de03c17a8029165ae8..23334d1edbe0a583f4444c4b2f87deff2beb2360 100644
--- a/modules/node/tests/node_test.module
+++ b/modules/node/tests/node_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: node_test.module,v 1.11 2010/04/20 09:30:21 webchick Exp $
+// $Id: node_test.module,v 1.12 2010/09/29 14:08:54 dries Exp $
 
 /**
  * @file
@@ -52,6 +52,10 @@ function node_test_node_grants($account, $op) {
  * Implements hook_node_access_records().
  */
 function node_test_node_access_records($node) {
+  // Return nothing when testing for empty responses.
+  if (!empty($node->disable_node_access)) {
+    return;
+  }
   $grants = array();
   if ($node->type == 'article') {
     // Create grant in arbitrary article_realm for article nodes.
diff --git a/modules/node/tests/node_test_exception.info b/modules/node/tests/node_test_exception.info
index b7bf6816a01932e4fa4154175472e73a33359b60..8933ae58ddad2ecb2a2e93506f6bf371be9c18f1 100644
--- a/modules/node/tests/node_test_exception.info
+++ b/modules/node/tests/node_test_exception.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = node_test_exception.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/openid/openid.info b/modules/openid/openid.info
index f616ce7ba34c92bd64006f8b8233f31ea6a0544e..50a153cad3e37fd4eb0a73ba883559bbb3f14fed 100644
--- a/modules/openid/openid.info
+++ b/modules/openid/openid.info
@@ -10,8 +10,8 @@ files[] = openid.pages.inc
 files[] = openid.install
 files[] = openid.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/openid/openid.module b/modules/openid/openid.module
index c5fb70c8c071bc0fc72b2877c241f1c9ff13c50a..0559b5b92e90658e81ee4cddba23608e053ec1c1 100644
--- a/modules/openid/openid.module
+++ b/modules/openid/openid.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: openid.module,v 1.95 2010/08/22 22:00:16 dries Exp $
+// $Id: openid.module,v 1.96 2010/09/24 00:37:43 dries Exp $
 
 /**
  * @file
@@ -32,7 +32,6 @@ function openid_menu() {
     'page arguments' => array('openid_user_delete_form', 1),
     'access callback' => 'user_edit_access',
     'access arguments' => array(1),
-    'type' => MENU_CALLBACK,
     'file' => 'openid.pages.inc',
   );
   return $items;
diff --git a/modules/openid/tests/openid_test.info b/modules/openid/tests/openid_test.info
index d5c84495ca9d66e4189025d0f3921a9bb8204262..73b2cd491f96fc5ffcce0e6a45ab5b7902ae0639 100644
--- a/modules/openid/tests/openid_test.info
+++ b/modules/openid/tests/openid_test.info
@@ -9,8 +9,8 @@ files[] = openid_test.module
 dependencies[] = openid
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/overlay/overlay-parent.js b/modules/overlay/overlay-parent.js
index 607b8b40bc6b1bdef3cb0c7cd1107cecdd5c4c2a..bba953580fc7f1ead06da33d11a85a2d47b00937 100644
--- a/modules/overlay/overlay-parent.js
+++ b/modules/overlay/overlay-parent.js
@@ -1,4 +1,4 @@
-// $Id: overlay-parent.js,v 1.54 2010/08/18 02:25:50 dries Exp $
+// $Id: overlay-parent.js,v 1.55 2010/09/29 00:50:46 dries Exp $
 
 (function ($) {
 
@@ -816,14 +816,14 @@ Drupal.overlay.getDisplacement = function (region) {
  * Theme function to create the overlay iframe element.
  */
 Drupal.theme.prototype.overlayContainer = function () {
-  return '<div id="overlay-container" role="dialog"><div class="overlay-modal-background"></div></div>';
+  return '<div id="overlay-container"><div class="overlay-modal-background"></div></div>';
 };
 
 /**
  * Theme function to create an overlay iframe element.
  */
 Drupal.theme.prototype.overlayElement = function (url) {
-  return '<iframe class="overlay-element" frameborder="0" scrolling="auto" allowtransparency="true" role="document"></iframe>';
+  return '<iframe class="overlay-element" frameborder="0" scrolling="auto" allowtransparency="true"></iframe>';
 };
 
 })(jQuery);
diff --git a/modules/overlay/overlay.info b/modules/overlay/overlay.info
index 4d3fb25bd3db3751e0be56cdddc160b0d1ee7d59..3d105f86e8a5f17dafd3e26479dc06bf44f03f48 100644
--- a/modules/overlay/overlay.info
+++ b/modules/overlay/overlay.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = overlay.module
 files[] = overlay.install
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/overlay/overlay.tpl.php b/modules/overlay/overlay.tpl.php
index e8aba59da70c3302978f8417439c4fc0488457d4..0bf1336309f18dcbc72cd41ee619fcd331a1a886 100644
--- a/modules/overlay/overlay.tpl.php
+++ b/modules/overlay/overlay.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: overlay.tpl.php,v 1.3 2010/07/11 22:03:45 dries Exp $
+// $Id: overlay.tpl.php,v 1.4 2010/09/16 19:47:45 dries Exp $
 
 /**
  * @file
@@ -29,7 +29,7 @@
     <div id="overlay-close-wrapper">
       <a id="overlay-close" href="#" class="overlay-close"><span class="element-invisible"><?php print t('Close overlay'); ?></span></a>
     </div>
-    <?php if ($tabs): ?><ul id="overlay-tabs"><?php print render($tabs); ?></ul><?php endif; ?>
+    <?php if ($tabs): ?><h2 class="element-invisible"><?php print t('Primary tabs'); ?></h2><ul id="overlay-tabs"><?php print render($tabs); ?></ul><?php endif; ?>
   </div>
   <div id="overlay-content"<?php print $content_attributes; ?>>
     <?php print $page; ?>
diff --git a/modules/path/path.info b/modules/path/path.info
index 812450e9d7bfa91f97ce0c5c0802d0699d851e40..c3cbc783f3eeee6e68e7d12710ba35f0f5930037 100644
--- a/modules/path/path.info
+++ b/modules/path/path.info
@@ -9,8 +9,8 @@ files[] = path.admin.inc
 files[] = path.test
 configure = admin/config/search/path
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/path/path.module b/modules/path/path.module
index bc4f48026c08e66a79422145b2212265ecf2dba8..8b85d5e29b6264920a4dab79adcddef6c347f757 100644
--- a/modules/path/path.module
+++ b/modules/path/path.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: path.module,v 1.184 2010/09/09 23:01:48 dries Exp $
+// $Id: path.module,v 1.185 2010/09/24 00:37:44 dries Exp $
 
 /**
  * @file
@@ -66,7 +66,6 @@ function path_menu() {
     'page callback' => 'path_admin_edit',
     'page arguments' => array(5),
     'access arguments' => array('administer url aliases'),
-    'type' => MENU_CALLBACK,
     'file' => 'path.admin.inc',
   );
   $items['admin/config/search/path/delete/%path'] = array(
@@ -74,7 +73,6 @@ function path_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('path_admin_delete_confirm', 5),
     'access arguments' => array('administer url aliases'),
-    'type' => MENU_CALLBACK,
     'file' => 'path.admin.inc',
   );
   $items['admin/config/search/path/list'] = array(
diff --git a/modules/php/php.info b/modules/php/php.info
index cff8a01b4e9b492168b38243e18846d8e76b5c76..282d58c2339005000b1b340dc9d71eeac3bdcce4 100644
--- a/modules/php/php.info
+++ b/modules/php/php.info
@@ -8,8 +8,8 @@ files[] = php.module
 files[] = php.install
 files[] = php.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/poll/poll.info b/modules/poll/poll.info
index bc4b3bc8538b2e24018c1a6f1f5fefbcbcf33f95..5dba7d7757764bcff25f31db8bc3e3729c05b306 100644
--- a/modules/poll/poll.info
+++ b/modules/poll/poll.info
@@ -11,8 +11,8 @@ files[] = poll.test
 files[] = poll.tokens.inc
 stylesheets[all][] = poll.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/poll/poll.module b/modules/poll/poll.module
index afadf50ecdfc01b0941ba426c0d65165e18a75a3..f65c20296c289910bd09da2f255af19c9323f0fb 100644
--- a/modules/poll/poll.module
+++ b/modules/poll/poll.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: poll.module,v 1.356 2010/09/09 23:01:48 dries Exp $
+// $Id: poll.module,v 1.357 2010/09/24 02:05:55 dries Exp $
 
 /**
  * @file
@@ -568,12 +568,11 @@ function poll_update($node) {
       db_merge('poll_choice')
         ->key(array('chid' => $choice['chid']))
         ->fields(array(
-          'nid' => $node->nid,
           'chtext' => $choice['chtext'],
           'chvotes' => (int) $choice['chvotes'],
           'weight' => $choice['weight'],
         ))
-        ->updateExcept('nid')
+        ->insertFields(array('nid' => $node->nid))
         ->execute();
     }
     else {
diff --git a/modules/poll/poll.pages.inc b/modules/poll/poll.pages.inc
index 51503a71924c621397b2ad2357a2336a33f0515d..3b6dcf6e751ddc2819868e9cb808208117c6efbf 100644
--- a/modules/poll/poll.pages.inc
+++ b/modules/poll/poll.pages.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: poll.pages.inc,v 1.27 2010/01/09 21:54:01 webchick Exp $
+// $Id: poll.pages.inc,v 1.28 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -42,7 +42,7 @@ function poll_page() {
     $output .= '<li>' . l($node->title, "node/$node->nid") . ' - ' . format_plural($node->votes, '1 vote', '@count votes') . ' - ' . ($node->active ? t('open') : t('closed')) . '</li>';
   }
   $output .= '</ul>';
-  $output .= theme("pager", array('tags' => NULL));
+  $output .= theme('pager');
   return $output;
 }
 
diff --git a/modules/profile/profile.info b/modules/profile/profile.info
index c5cac1bd18b7d154b6559d3012bff203611b5077..ac348755adecd3e3ce0ac759c28f8ab1874a79ce 100644
--- a/modules/profile/profile.info
+++ b/modules/profile/profile.info
@@ -11,8 +11,8 @@ files[] = profile.install
 files[] = profile.test
 configure = admin/config/people/profile
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/profile/profile.module b/modules/profile/profile.module
index efeb768459f97064ecfcd9eb7b170ff34e3ceda0..d4855d2c5b6f93db3ab714fb7568ca064d0bdc98 100644
--- a/modules/profile/profile.module
+++ b/modules/profile/profile.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: profile.module,v 1.292 2010/07/10 01:44:28 dries Exp $
+// $Id: profile.module,v 1.294 2010/10/01 15:24:18 webchick Exp $
 
 /**
  * @file
@@ -98,8 +98,8 @@ function profile_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('profile_field_form'),
     'access arguments' => array('administer users'),
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'profile.admin.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['admin/config/people/profile/autocomplete'] = array(
     'title' => 'Profile category autocomplete',
@@ -113,16 +113,16 @@ function profile_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('profile_field_form'),
     'access arguments' => array('administer users'),
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'profile.admin.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['admin/config/people/profile/delete'] = array(
     'title' => 'Delete field',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('profile_field_delete'),
     'access arguments' => array('administer users'),
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'profile.admin.inc',
-    'type' => MENU_CALLBACK,
   );
   $items['profile/autocomplete'] = array(
     'title' => 'Profile autocomplete',
diff --git a/modules/profile/profile.pages.inc b/modules/profile/profile.pages.inc
index 79d024cda99cef65621e9a12f656f3fb973d3d8b..128c8845e0859e5796b8e7be61bfcccd92e6c355 100644
--- a/modules/profile/profile.pages.inc
+++ b/modules/profile/profile.pages.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: profile.pages.inc,v 1.26 2010/08/17 13:50:52 dries Exp $
+// $Id: profile.pages.inc,v 1.27 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -74,7 +74,7 @@ function profile_browse() {
       $content .= theme('profile_listing', array('account' => $account, 'fields' => $profile));
     }
     $output = theme('profile_wrapper', array('content' => $content));
-    $output .= theme('pager', array('tags' => NULL));
+    $output .= theme('pager');
 
     if ($field->type == 'selection' || $field->type == 'list' || $field->type == 'textfield') {
       $title = strtr(check_plain($field->page), array('%value' => drupal_placeholder($value)));
@@ -111,7 +111,7 @@ function profile_browse() {
       $content .= theme('profile_listing', array('account' => $account, 'fields' => $profile));
     }
     $output = theme('profile_wrapper', array('content' => $content));
-    $output .= theme('pager', array('tags' => NULL));
+    $output .= theme('pager');
 
     drupal_set_title(t('User list'));
     return $output;
diff --git a/modules/rdf/rdf.api.php b/modules/rdf/rdf.api.php
index 25a67f8167609971300c6b8af9ee3d71a08aacc4..aed1f4669afb1d0a4694395af279ccdd4e408089 100644
--- a/modules/rdf/rdf.api.php
+++ b/modules/rdf/rdf.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: rdf.api.php,v 1.5 2010/09/09 20:22:00 dries Exp $
+// $Id: rdf.api.php,v 1.6 2010/10/01 01:44:39 webchick Exp $
 
 /**
  * @file
@@ -20,19 +20,19 @@
  *
  * @return
  *   A list of mapping structures, where each mapping is an associative array:
- *   - type: The name of an entity type, e.g. 'node' or 'comment'.
- *   - bundle: The name of the bundle, e.g. 'blog', or RDF_DEFAULT_BUNDLE for
- *     default mappings.
+ *   - type: The name of an entity type (e.g., 'node', 'comment', and so on.)
+ *   - bundle: The name of the bundle (e.g., 'page', 'blog', or
+ *     RDF_DEFAULT_BUNDLE for default mappings.)
  *   - mapping: The mapping structure which applies to the entity type and
  *     bundle. A mapping structure is an array with keys corresponding to
  *     existing field instances in the bundle. Each field is then described in
- *     terms of RDF mapping:
+ *     terms of the RDF mapping:
  *     - predicates: An array of RDF predicates which describe the relation
  *       between the bundle (RDF subject) and the value of the field (RDF
- *       object). This value is either some text, another bundle or a URL in
+ *       object). This value is either some text, another bundle, or a URI in
  *       general.
  *     - datatype: Is used along with 'callback' to format data so that it is
- *       readable by machine. A typical example is a date which can be written
+ *       readable by machines. A typical example is a date which can be written
  *       in many different formats but should be translated into a uniform
  *       format for machine consumption.
  *     - callback: A function name to invoke for 'datatype'.
diff --git a/modules/rdf/rdf.info b/modules/rdf/rdf.info
index bf42f4e1d394922af9cf15d992a80a503e5acf0e..a74cb4030a4a2e2d0346cda4a23924fa92745416 100644
--- a/modules/rdf/rdf.info
+++ b/modules/rdf/rdf.info
@@ -8,8 +8,8 @@ files[] = rdf.install
 files[] = rdf.module
 files[] = rdf.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/rdf/rdf.install b/modules/rdf/rdf.install
index 590b2141475f0428e718fafd0a621273edb5db6b..04a9c86aa61ae41c8c77fddd2585dbf5edf51e86 100644
--- a/modules/rdf/rdf.install
+++ b/modules/rdf/rdf.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: rdf.install,v 1.4 2010/06/25 17:47:22 dries Exp $
+// $Id: rdf.install,v 1.5 2010/10/01 01:44:39 webchick Exp $
 
 /**
  * @file
@@ -48,4 +48,3 @@ function rdf_install() {
   $modules = module_implements('rdf_mapping');
   rdf_modules_installed($modules);
 }
-
diff --git a/modules/rdf/rdf.module b/modules/rdf/rdf.module
index f47926ed68a0c085fccf5c375b92a1c9dffd9d4b..26f71b259845658912b76192b0894bff4dd91537 100644
--- a/modules/rdf/rdf.module
+++ b/modules/rdf/rdf.module
@@ -1,9 +1,9 @@
 <?php
-// $Id: rdf.module,v 1.45 2010/09/09 20:22:00 dries Exp $
+// $Id: rdf.module,v 1.46 2010/10/01 01:44:39 webchick Exp $
 
 /**
  * @file
- * Enables semantically enriched output for Drupal sites.
+ * Enables semantically enriched output for Drupal sites in the form of RDFa.
  */
 
 /**
@@ -14,7 +14,7 @@ function rdf_help($path, $arg) {
     case 'admin/help#rdf':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('The RDF module enriches your content with metadata to let other applications (e.g. search engines, aggregators) better understand its relationships and attributes. This semantically enriched, machine-readable RDF output for Drupal sites uses the <a href="@rdfa">RDFa specification</a>. Other modules can define mappings of their data to RDFa properties, and the RDF module makes the data available to the theme. The core Drupal modules define RDF mappings for their information, and the core Drupal themes output the RDF meta-data information along with the human-readable visual information. For more information, see the online handbook entry for <a href="@rdf">RDF module</a>.', array('@rdfa' => 'http://www.w3.org/TR/xhtml-rdfa-primer/', '@rdf' => 'http://drupal.org/handbook/modules/rdf')) . '</p>';
+      $output .= '<p>' . t('The RDF module enriches your content with metadata to let other applications (e.g., search engines, aggregators, and so on) better understand its relationships and attributes. This semantically enriched, machine-readable output for Drupal sites uses the <a href="@rdfa">RDFa specification</a> which allows RDF data to be embedded in HTML markup. Other modules can define mappings of their data to RDF terms, and the RDF module makes this RDF data available to the theme. The core Drupal modules define RDF mappings for their data model, and the core Drupal themes output this RDF metadata information along with the human-readable visual information. For more information, see the online handbook entry for <a href="@rdf">RDF module</a>.', array('@rdfa' => 'http://www.w3.org/TR/xhtml-rdfa-primer/', '@rdf' => 'http://drupal.org/handbook/modules/rdf')) . '</p>';
       return $output;
   }
 }
@@ -22,16 +22,18 @@ function rdf_help($path, $arg) {
 /**
  * @defgroup rdf RDF Mapping API
  * @{
- * Functions to describe entities and bundles for RDFa.
+ * Functions to describe entities and bundles in RDF.
  *
- * RDF module introduces RDFa to Drupal, which provides a set of XHTML
- * attributes to augment visual data with machine-readable hints.
+ * The RDF module introduces RDF and RDFa to Drupal. RDF is a W3C standard to
+ * describe structured data. RDF can be serialized as RDFa in XHTML attributes
+ * to augment visual data with machine-readable hints.
+ * @see http://www.w3.org/RDF/
  * @see http://www.w3.org/TR/xhtml-rdfa-primer/
  *
- * Modules can provide mappings of their bundles' data and metadata to RDFa
- * properties using the appropriate vocabularies. This module takes care of
- * injecting that data into variables available to themers in the .tpl files.
- * All Drupal core themes are coded to be RDFa compatible.
+ * Modules can provide mappings of their bundles' data and metadata to RDF
+ * classes and properties. This module takes care of injecting these mappings
+ * into variables available to theme functions and templates. All Drupal core
+ * themes are coded to be RDFa compatible.
  *
  * Example mapping from node.module:
  * @code
@@ -66,9 +68,9 @@ function rdf_help($path, $arg) {
  * RDF bundle flag: Default bundle.
  *
  * Implementations of hook_rdf_mapping() should use this constant for the
- * 'bundle' key when defining a generic set of RDF mappings for an entity type.
- * The defined with this constant (the default bundle mapping ) will be used
- * when a new bundle is installed if there is no mapping defined for the bundle.
+ * 'bundle' key when defining a default set of RDF mappings for an entity type.
+ * Each bundle will inherit the default mappings defined for the entity type
+ * unless the bundle defines its own specific mappings.
  */
 define('RDF_DEFAULT_BUNDLE', '');
 
@@ -90,14 +92,15 @@ function rdf_rdf_namespaces() {
 }
 
 /**
- * Returns an array of RDF namespaces defined via hook_rdf_namespaces().
+ * Returns an array of RDF namespaces defined in modules that implement
+ * hook_rdf_namespaces().
  */
 function rdf_get_namespaces() {
   $rdf_namespaces = module_invoke_all('rdf_namespaces');
   // module_invoke_all() uses array_merge_recursive() which might return nested
-  // arrays if several modules redefine the same prefix multiple times.
-  // We need to ensure the array of namespaces is flat and only contains
-  // strings as URIs.
+  // arrays if several modules redefine the same prefix multiple times. We need
+  // to ensure the array of namespaces is flat and only contains strings as
+  // URIs.
   foreach ($rdf_namespaces as $prefix => $uri) {
     if (is_array($uri)) {
       if (count(array_unique($uri)) == 1) {
@@ -106,8 +109,9 @@ function rdf_get_namespaces() {
         $rdf_namespaces[$prefix] = $uri[0];
       }
       else {
-        // There are conflicting namespaces for this prefix, do not include it
-        // in order to avoid asserting any inaccurate RDF statement.
+        // There are conflicting namespaces for this prefix, do not include
+        // duplicates in order to avoid asserting any inaccurate RDF
+        // statements.
         unset($rdf_namespaces[$prefix]);
       }
     }
@@ -116,7 +120,7 @@ function rdf_get_namespaces() {
 }
 
 /**
- * Returns the mapping for attributes of a given type/bundle pair.
+ * Returns the mapping for attributes of a given entity type/bundle pair.
  *
  * @param $type
  *   An entity type.
@@ -124,17 +128,17 @@ function rdf_get_namespaces() {
  *   (optional) A bundle name.
  *
  * @return
- *   The mapping corresponding to the requested type/bundle pair or an empty
- *   array.
+ *   The mapping corresponding to the requested entity type/bundle pair or an
+ *   empty array.
  */
 function rdf_mapping_load($type, $bundle = RDF_DEFAULT_BUNDLE) {
-  // Retrieves the bundle specific mapping from the entity info.
+  // Retrieves the bundle-specific mapping from the entity info.
   $entity_info = entity_get_info($type);
   if (!empty($entity_info['bundles'][$bundle]['rdf_mapping'])) {
     return $entity_info['bundles'][$bundle]['rdf_mapping'];
   }
-  // If there is no mapping defined for this bundle, returns the default mapping
-  // that is defined for this entity type.
+  // If there is no mapping defined for this bundle, we return the default
+  // mapping that is defined for this entity type.
   else {
     return _rdf_get_default_mapping($type);
   }
@@ -145,7 +149,7 @@ function rdf_mapping_load($type, $bundle = RDF_DEFAULT_BUNDLE) {
  */
 
 /**
- * Returns the default RDF mapping for a given entity type.
+ * Helper function to get the default RDF mapping for a given entity type.
  *
  * @param $type
  *   An entity type, e.g. 'node' or 'comment'.
@@ -158,7 +162,7 @@ function _rdf_get_default_mapping($type) {
   $default_mappings = &drupal_static(__FUNCTION__);
 
   if (!isset($default_mappings)) {
-    // Get all modules implementing hook_rdf_mapping().
+    // Get all of the modules that implement hook_rdf_mapping().
     $modules = module_implements('rdf_mapping');
 
     // Only consider the default entity mapping definitions.
@@ -176,7 +180,7 @@ function _rdf_get_default_mapping($type) {
 }
 
 /**
- * Helper function to retrieve a RDF mapping from the database.
+ * Helper function to retrieve an RDF mapping from the database.
  *
  * @param $type
  *   The entity type the mapping refers to.
@@ -184,7 +188,7 @@ function _rdf_get_default_mapping($type) {
  *   The bundle the mapping refers to.
  *
  * @return
- *   A RDF mapping structure or FALSE if no record was found.
+ *   An RDF mapping structure or an empty array if no record was found.
  */
 function _rdf_mapping_load($type, $bundle) {
   $mapping = db_select('rdf_mapping')
@@ -209,9 +213,9 @@ function _rdf_mapping_load($type, $bundle) {
  * Saves an RDF mapping to the database.
  *
  * Takes a mapping structure returned by hook_rdf_mapping() implementations
- * and creates or updates a record mapping for each encountered
- * type, bundle pair. If available, adds default values for non-existent
- * mapping keys.
+ * and creates or updates a record mapping for each encountered entity
+ * type/bundle pair. If available, adds default values for non-existent mapping
+ * keys.
  *
  * @param $mapping
  *   The RDF mapping to save, as an array.
@@ -263,8 +267,8 @@ function rdf_mapping_delete($type, $bundle) {
 /**
  * Builds an array of RDFa attributes for a given mapping. This array will
  * typically be passed through drupal_attributes() to create the attributes
- * variables that are available to tpl.php template files. These include
- * $attributes, $title_attributes, $content_attributes and the field specific
+ * variables that are available to template files. These include $attributes,
+ * $title_attributes, $content_attributes and the field-specific
  * $item_attributes variables. For more information, see
  * theme_rdf_template_variable_wrapper().
  *
@@ -354,13 +358,13 @@ function rdf_modules_uninstalled($modules) {
 /**
  * Implements hook_entity_info_alter().
  *
- * Adds the proper RDF mapping to each entity type, bundle pair.
+ * Adds the proper RDF mapping to each entity type/bundle pair.
  *
  * @todo May need to move the comment below to another place.
  * This hook should not be used by modules to alter the bundle mappings.
- * The UI should always be authoritative. UI mappings are stored in the database
- * and if hook_entity_info_alter was used to override module defined mappings,
- * it would override the user defined mapping as well.
+ * The UI should always be authoritative. UI mappings are stored in the
+ * database and if hook_entity_info_alter was used to override module defined
+ * mappings, it would override the user defined mapping as well.
  */
 function rdf_entity_info_alter(&$entity_info) {
   // Loop through each entity type and its bundles.
@@ -396,6 +400,9 @@ function rdf_entity_load($entities, $type) {
  */
 function rdf_comment_load($comments) {
   foreach ($comments as $comment) {
+    // Pages with many comments can show poor performance. This information
+    // isn't needed until rdf_preprocess_comment() is called, but set it here
+    // to optimize performance for websites that implement an entity cache.
     $comment->rdf_data['date'] = rdf_rdfa_attributes($comment->rdf_mapping['created'], $comment->created);
     $comment->rdf_data['nid_uri'] = url('node/' . $comment->nid);
     if ($comment->pid) {
@@ -429,8 +436,8 @@ function rdf_theme() {
  */
 function rdf_process(&$variables, $hook) {
   // Handles attributes needed for content not covered by title, content,
-  // and field items. Does this by adjusting the variable sent to the template
-  // so that the template doesn't have to worry about it. See 
+  // and field items. It does this by adjusting the variable sent to the
+  // template so that the template doesn't have to worry about it. See
   // theme_rdf_template_variable_wrapper().
   if (!empty($variables['rdf_template_variable_attributes_array'])) {
     foreach ($variables['rdf_template_variable_attributes_array'] as $variable_name => $attributes) {
@@ -459,20 +466,21 @@ function rdf_process(&$variables, $hook) {
  */
 function rdf_preprocess_node(&$variables) {
   // Adds RDFa markup to the node container. The about attribute specifies the
-  // URI of the resource described within the HTML element, while the typeof
-  // attribute indicates its RDF type (foaf:Document, or sioc:Person, etc.).
+  // URI of the resource described within the HTML element, while the @typeof
+  // attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so
+  // on.)
   $variables['attributes_array']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
   $variables['attributes_array']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
 
   // Adds RDFa markup to the title of the node. Because the RDFa markup is
-  // added to the h2 tag which might contain HTML code, we specify an
-  // empty datatype to ensure the value of the title read by the RDFa parsers
-  // is a literal.
+  // added to the <h2> tag which might contain HTML code, we specify an empty
+  // datatype to ensure the value of the title read by the RDFa parsers is a
+  // literal.
   $variables['title_attributes_array']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates'];
   $variables['title_attributes_array']['datatype'] = '';
 
   // In full node mode, the title is not displayed by node.tpl.php so it is
-  // added in the head tag of the HTML page.
+  // added in the <head> tag of the HTML page.
   if ($variables['page']) {
     $element = array(
       '#tag' => 'meta',
@@ -505,15 +513,16 @@ function rdf_preprocess_node(&$variables) {
       $comment_count_attributes['content'] = $variables['node']->comment_count;
       $comment_count_attributes['datatype'] = $variables['node']->rdf_mapping['comment_count']['datatype'];
       // According to RDFa parsing rule number 4, a new subject URI is created
-      // from the href attribute if no rel/rev attribute is present. To get
-      // the original node URL from the about attribute of the parent container
-      // we set an empty rel attribute which triggers rule number 5. See
+      // from the href attribute if no rel/rev attribute is present. To get the
+      // original node URL from the about attribute of the parent container we
+      // set an empty rel attribute which triggers rule number 5. See
       // http://www.w3.org/TR/rdfa-syntax/#sec_5.5.
       $comment_count_attributes['rel'] = '';
       $variables['content']['links']['#links']['comment-comments']['attributes'] += $comment_count_attributes;
     }
     // In full node view, the number of comments is not displayed by
-    // node.tpl.php so it is expressed in RDFa in the <head> tag.
+    // node.tpl.php so it is expressed in RDFa in the <head> tag of the HTML
+    // page.
     if ($variables['page'] && user_access('access comments')) {
       $element = array(
         '#tag' => 'meta',
@@ -541,9 +550,9 @@ function rdf_preprocess_field(&$variables) {
     foreach ($element['#items'] as $delta => $item) {
       $variables['item_attributes_array'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
       // If this field is an image, RDFa will not output correctly when the
-      // image is in a containing 'a' tag. If the field is a file, RDFa will
-      // not output correctly if the filetype icon comes before the link to
-      // the file. We correct this by adding a resource attribute to the div if
+      // image is in a containing <a> tag. If the field is a file, RDFa will
+      // not output correctly if the filetype icon comes before the link to the
+      // file. We correct this by adding a resource attribute to the div if
       // this field has a URI.
       if (isset($item['uri'])) {
         if (!empty($element[$delta]['#image_style'])) {
@@ -565,7 +574,7 @@ function rdf_preprocess_user_profile(&$variables) {
   $uri = entity_uri('user', $account);
 
   // Adds RDFa markup to the user profile page. Fields displayed in this page
-  // will automatically describe the user.  
+  // will automatically describe the user.
   if (!empty($account->rdf_mapping['rdftype'])) {
     $variables['attributes_array']['typeof'] = $account->rdf_mapping['rdftype'];
     $variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
@@ -608,11 +617,11 @@ function rdf_preprocess_username(&$variables) {
   }
 
   // $variables['account'] is a pseudo account object, and as such, does not
-  // contain the rdf mappings for the user; in the case of nodes and comments,
-  // it contains the mappings for the node or comment object instead. However
-  // while the rdf mappings are available from a full user_load(), this should
-  // be avoided for performance reasons. Since the type and bundle for
-  // users is already known, call rdf_mapping_load() directly.
+  // contain the RDF mappings for the user. In the case of nodes and comments,
+  // it contains the mappings for the node or comment object instead. However,
+  // while the RDF mappings are available from a full user_load(), this should
+  // be avoided for performance reasons. Since the type and bundle for users is
+  // already known, call rdf_mapping_load() directly.
   $rdf_mapping = rdf_mapping_load('user', 'user');
 
   // The profile URI is used to identify the user account. The about attribute
@@ -621,18 +630,18 @@ function rdf_preprocess_username(&$variables) {
   // to the current user, we use its URI in order to identify the user in RDF.
   // We do not use this attribute for the anonymous user because we do not have
   // a user profile URI for it (only a homepage which cannot be used as user
-  // profile in RDF).
+  // profile in RDF.)
   if ($variables['uid'] > 0) {
     $variables['attributes_array']['about'] = url('user/' . $variables['uid']);
   }
 
   $attributes = array();
-  // The 'typeof' attribute specifies the RDF type(s) of this resource. They
+  // The typeof attribute specifies the RDF type(s) of this resource. They
   // are defined in the 'rdftype' property of the user RDF mapping.
   if (!empty($rdf_mapping['rdftype'])) {
     $attributes['typeof'] = $rdf_mapping['rdftype'];
   }
-  // Annotate the user name in RDFa. The attribute 'property' is used here
+  // Annotate the user name in RDFa. The property attribute is used here
   // because the user name is a literal.
   if (!empty($rdf_mapping['name'])) {
     $attributes['property'] = $rdf_mapping['name']['predicates'];
@@ -642,8 +651,8 @@ function rdf_preprocess_username(&$variables) {
     $attributes['rel'] = $rdf_mapping['homepage']['predicates'];
   }
   // The remaining attributes can have multiple values listed, with whitespace
-  // separating the values in the RDFa attribute
-  // (http://www.w3.org/TR/rdfa-syntax/#rdfa-attributes).
+  // separating the values in the RDFa attributes
+  // (see http://www.w3.org/TR/rdfa-syntax/#rdfa-attributes).
   // Therefore, merge rather than override so as not to clobber values set by
   // earlier preprocess functions.
   $variables['attributes_array'] = array_merge_recursive($variables['attributes_array'], $attributes);
@@ -657,7 +666,8 @@ function rdf_preprocess_comment(&$variables) {
   if (!empty($comment->rdf_mapping['rdftype'])) {
     // Adds RDFa markup to the comment container. The about attribute specifies
     // the URI of the resource described within the HTML element, while the
-    // typeof attribute indicates its RDF type (e.g. sioc:Post, etc.).
+    // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document,
+    // and so on.)
     $uri = entity_uri('comment', $comment);
     $variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
     $variables['attributes_array']['typeof'] = $comment->rdf_mapping['rdftype'];
@@ -665,6 +675,8 @@ function rdf_preprocess_comment(&$variables) {
 
   // Adds RDFa markup for the date of the comment.
   if (!empty($comment->rdf_mapping['created'])) {
+    // The comment date is precomputed as part of the rdf_data so that it can be
+    // cached as part of the entity.
     $date_attributes_array = $comment->rdf_data['date'];
     $variables['rdf_template_variable_attributes_array']['created'] = $date_attributes_array;
   }
@@ -673,10 +685,10 @@ function rdf_preprocess_comment(&$variables) {
     $variables['rdf_template_variable_attributes_array']['author']['rel'] = $comment->rdf_mapping['uid']['predicates'];
   }
   if (!empty($comment->rdf_mapping['title'])) {
-    // Adds RDFa markup to the subject of the comment. Because the RDFa markup is
-    // added to an h3 tag which might contain HTML code, we specify an empty
-    // datatype to ensure the value of the title read by the RDFa parsers is a
-    // literal.
+    // Adds RDFa markup to the subject of the comment. Because the RDFa markup
+    // is added to an <h3> tag which might contain HTML code, we specify an
+    // empty datatype to ensure the value of the title read by the RDFa parsers
+    // is a literal.
     $variables['title_attributes_array']['property'] = $comment->rdf_mapping['title']['predicates'];
     $variables['title_attributes_array']['datatype'] = '';
   }
@@ -684,14 +696,18 @@ function rdf_preprocess_comment(&$variables) {
   // Annotates the parent relationship between the current comment and the node
   // it belongs to. If available, the parent comment is also annotated.
   if (!empty($comment->rdf_mapping['pid'])) {
-    // Relation to parent node.
+    // Adds the relation to the parent node.
     $parent_node_attributes['rel'] = $comment->rdf_mapping['pid']['predicates'];
+    // The parent node URI is precomputed as part of the rdf_data so that it can
+    // be cached as part of the entity.
     $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri'];
     $variables['rdf_metadata_attributes_array'][] = $parent_node_attributes;
 
-    // Relation to parent comment if it exists.
+    // Adds the relation to parent comment, if it exists.
     if ($comment->pid != 0) {
       $parent_comment_attributes['rel'] = $comment->rdf_mapping['pid']['predicates'];
+      // The parent comment URI is precomputed as part of the rdf_data so that
+      // it can be cached as part of the entity.
       $parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri'];
       $variables['rdf_metadata_attributes_array'][] = $parent_comment_attributes;
     }
@@ -702,7 +718,7 @@ function rdf_preprocess_comment(&$variables) {
  * Implements MODULE_preprocess_HOOK().
  */
 function rdf_preprocess_taxonomy_term(&$variables) {
-  // Adds the RDF type of the term and the term name in a meta tag.
+  // Adds the RDF type of the term and the term name in a <meta> tag.
   $term = $variables['term'];
   $term_label_meta = array(
       '#tag' => 'meta',
@@ -725,9 +741,9 @@ function rdf_field_attach_view_alter(&$output, $context) {
     $element = &$output[$field_name];
     if ($element['#field_type'] == 'taxonomy_term_reference' && $element['#formatter'] == 'taxonomy_term_reference_link') {
       foreach ($element['#items'] as $delta => $item) {
-        // This function is invoked during entity preview when
-        // taxonomy term reference items might contain free-tagging
-        // terms that do not exist yet and thus have no $item['taxonomy_term'].
+        // This function is invoked during entity preview when taxonomy term
+        // reference items might contain free-tagging terms that do not exist
+        // yet and thus have no $item['taxonomy_term'].
         if (isset($item['taxonomy_term'])) {
           $term = $item['taxonomy_term'];
           if (!empty($term->rdf_mapping['rdftype'])) {
@@ -750,19 +766,20 @@ function rdf_preprocess_image(&$variables) {
 }
 
 /**
- * Returns HTML for a template variable wrapped in an HTML element with the desired attributes.
+ * Returns HTML for a template variable wrapped in an HTML element with the
+ * RDF attributes.
  *
  * This is called by rdf_process() shortly before the theme system renders
  * a template file. It is called once for each template variable for which
  * additional attributes are needed. While template files are responsible for
  * rendering the attributes for the template's primary object (via the
  * $attributes variable), title (via the $title_attributes variable), and
- * content (via the $content_attributes variable), additional template variables
- * that need containing attributes are routed through this function, allowing
- * the template file to receive properly wrapped variables.
+ * content (via the $content_attributes variable), additional template
+ * variables that need containing attributes are routed through this function,
+ * allowing the template file to receive properly wrapped variables.
  *
  * Tip for themers: if you're already outputting a wrapper element around a
- * particular template variable in your template file and if you don't want
+ * particular template variable in your template file, and if you don't want
  * an extra wrapper element, you can override this function to not wrap that
  * variable and instead print the following inside your template file:
  * @code
@@ -777,7 +794,7 @@ function rdf_preprocess_image(&$variables) {
  *     - hook: The theme hook that will use the wrapped content. This
  *       corresponds to the key within the theme registry for this template.
  *       For example, if this content is about to be used in node.tpl.php or
- *       node-TYPE.tpl.php, then the 'hook' is 'node'.
+ *       node-[type].tpl.php, then the 'hook' is 'node'.
  *     - variable_name: The name of the variable by which the template will
  *       refer to this content. Each template file has documentation about
  *       the variables it uses. For example, if this function is called in
@@ -786,9 +803,9 @@ function rdf_preprocess_image(&$variables) {
  *     - variables: The full array of variables about to be passed to the
  *       template.
  *   - inline: TRUE if the content contains only inline HTML elements and
- *     therefore can be validly wrapped by a 'span' tag. FALSE if the content
+ *     therefore can be validly wrapped by a <span> tag. FALSE if the content
  *     might contain block level HTML elements and therefore cannot be validly
- *     wrapped by a 'span' tag. Modules implementing preprocess functions that
+ *     wrapped by a <span> tag. Modules implementing preprocess functions that
  *     set 'rdf_template_variable_attributes_array' for a particular template
  *     variable that might contain block level HTML must also implement
  *     hook_preprocess_rdf_template_variable_wrapper() and set 'inline' to FALSE
@@ -816,8 +833,8 @@ function theme_rdf_template_variable_wrapper($variables) {
  * Sometimes it is useful to export data which is not semantically present in
  * the HTML output. For example, a hierarchy of comments is visible for a human
  * but not for machines because this hiearchy is not present in the DOM tree.
- * We can express it in RDFa via empty span tags. These aren't visible and give
- * machines extra information about the content and its structure.
+ * We can express it in RDFa via empty <span> tags. These aren't visible and
+ * give machines extra information about the content and its structure.
  *
  * @param $variables
  *   An associative array containing:
@@ -832,13 +849,14 @@ function theme_rdf_template_variable_wrapper($variables) {
 function theme_rdf_metadata($variables) {
   $output = '';
   foreach ($variables['metadata'] as $attributes) {
-    // Add a class, so developers viewing html source have a reference for why
-    // there are empty spans in the document. Also can be used to set a CSS
-    // display:none rule in a theme where empty spans affect display.
+    // Add a class so that developers viewing the HTML source can see why there
+    // are empty <span> tags in the document. The class can also be used to set
+    // a CSS display:none rule in a theme where empty spans affect display.
     $attributes['class'][] = 'rdf-meta';
-    // XHTML+RDFa doctype allows either <span></span> or <span />, but for
-    // maximum browser compatibility, W3C recommends the former when serving
-    // pages using the text/html media type: http://www.w3.org/TR/xhtml1/#C_3.
+    // The XHTML+RDFa doctype allows either <span></span> or <span /> syntax to
+    // be used, but for maximum browser compatibility, W3C recommends the
+    // former when serving pages using the text/html media type, see
+    // http://www.w3.org/TR/xhtml1/#C_3.
     $output .= '<span' . drupal_attributes($attributes) . '></span>';
   }
   return $output;
diff --git a/modules/rdf/rdf.test b/modules/rdf/rdf.test
index a856f93f30959f5f7fc6679deaa53771c7a66bbe..f0b83a58e85568d695f0f04813733ef5b8a77278 100644
--- a/modules/rdf/rdf.test
+++ b/modules/rdf/rdf.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: rdf.test,v 1.27 2010/09/09 20:22:00 dries Exp $
+// $Id: rdf.test,v 1.28 2010/10/05 06:17:28 webchick Exp $
 
 /**
  * @file
@@ -411,7 +411,7 @@ class RdfCommentAttributesTestCase extends CommentHelperCase {
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
       'post comments' => TRUE,
-      'post comments without approval' => TRUE,
+      'skip comment approval' => TRUE,
     ));
     // Allows anonymous to leave their contact information.
     $this->setCommentAnonymous(COMMENT_ANONYMOUS_MAY_CONTACT);
@@ -569,7 +569,7 @@ class RdfTrackerAttributesTestCase extends DrupalWebTestCase {
       'create article content' => TRUE,
       'access comments' => TRUE,
       'post comments' => TRUE,
-      'post comments without approval' => TRUE,
+      'skip comment approval' => TRUE,
     ));
   }
 
diff --git a/modules/rdf/tests/rdf_test.info b/modules/rdf/tests/rdf_test.info
index f1caf96de5ede0c1616739c3dd222e215bdc4be8..5f23bd1fe1ba1b91e46e1aa7e1071ae48ee4faa5 100644
--- a/modules/rdf/tests/rdf_test.info
+++ b/modules/rdf/tests/rdf_test.info
@@ -8,8 +8,8 @@ files[] = rdf_test.install
 files[] = rdf_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/search/search.admin.inc b/modules/search/search.admin.inc
index 2b05748edde60ce3072d3b049e0f9deaad1be32f..bde2d0f03d5879f9d0018ac3ef5a6cda6747c088 100644
--- a/modules/search/search.admin.inc
+++ b/modules/search/search.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: search.admin.inc,v 1.16 2010/08/05 07:11:15 webchick Exp $
+// $Id: search.admin.inc,v 1.18 2010/09/28 02:30:31 dries Exp $
 
 /**
  * @file
@@ -60,7 +60,7 @@ function search_admin_settings($form) {
   // Collect some stats
   $remaining = 0;
   $total = 0;
-  foreach(variable_get('search_active_modules', array('node', 'user')) as $module) {
+  foreach (variable_get('search_active_modules', array('node', 'user')) as $module) {
     if ($status = module_invoke($module, 'search_status')) {
       $remaining += $status['remaining'];
       $total += $status['total'];
@@ -124,7 +124,7 @@ function search_admin_settings($form) {
   $form['active']['search_default_module'] = array(
     '#title' => t('Default search module'),
     '#type' => 'radios',
-    '#default_value' => 'node',
+    '#default_value' => variable_get('search_default_module', 'node'),
     '#options' => _search_get_module_names(),
     '#description' => t('Choose which search module is the default.')
   );
@@ -132,7 +132,7 @@ function search_admin_settings($form) {
   $form['#submit'][] = 'search_admin_settings_submit';
 
   // Per module settings
-  foreach(variable_get('search_active_modules', array('node', 'user')) as $module) {
+  foreach (variable_get('search_active_modules', array('node', 'user')) as $module) {
     $added_form = module_invoke($module, 'search_admin');
     if (is_array($added_form)) {
       $form = array_merge($form, $added_form);
diff --git a/modules/search/search.api.php b/modules/search/search.api.php
index d003567654c65510f2635b2bcc06b4a1d84bf145..1be1fcd1f86c7853ac7b77236eaa37887a18e764 100644
--- a/modules/search/search.api.php
+++ b/modules/search/search.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: search.api.php,v 1.29 2010/08/18 18:40:50 dries Exp $
+// $Id: search.api.php,v 1.30 2010/09/27 01:08:40 dries Exp $
 
 /**
  * @file
@@ -168,7 +168,7 @@ function hook_search_admin() {
  * search_expression_insert() may also be helpful for adding custom search
  * parameters to the search expression.
  *
- * See node_execute_search() for an example of a module that uses the search
+ * See node_search_execute() for an example of a module that uses the search
  * index, and user_execute_search() for an example that doesn't ues the search
  * index.
  *
diff --git a/modules/search/search.extender.inc b/modules/search/search.extender.inc
index 907c6ece03a065f9dd16b0b37a44b6206fe76ac9..afb6c1f15c9f656fc3459db38f6e301ef28e0e4c 100644
--- a/modules/search/search.extender.inc
+++ b/modules/search/search.extender.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: search.extender.inc,v 1.7 2010/09/01 01:43:50 webchick Exp $
+// $Id: search.extender.inc,v 1.8 2010/09/24 21:24:14 webchick Exp $
 
 /**
  * @file
@@ -415,10 +415,6 @@ class SearchQuery extends SelectQueryExtender {
       // Add default score.
       $this->addScore('i.relevance');
     }
-    if (count($this->getOrderBy()) == 0) {
-      // Add default order.
-      $this->orderBy('calculated_score', 'DESC');
-    }
 
     if (count($this->multiply)) {
       // Add the total multiplicator as many times as requested to maintain
@@ -436,6 +432,11 @@ class SearchQuery extends SelectQueryExtender {
     // Convert scores to an expression.
     $this->addExpression('SUM(' . implode(' + ', $this->scores) . ')', 'calculated_score', $this->scoresArguments);
 
+    if (count($this->getOrderBy()) == 0) {
+      // Add default order after adding the expression.
+      $this->orderBy('calculated_score', 'DESC');
+    }
+
     // Add tag and useful metadata.
     $this
       ->addTag('search_' . $this->type)
diff --git a/modules/search/search.info b/modules/search/search.info
index 681da5d83de1060bab2157e32857bb0e5c82513c..7da514b0881794f1ca338a0b81839f2491f2723f 100644
--- a/modules/search/search.info
+++ b/modules/search/search.info
@@ -13,8 +13,8 @@ files[] = search.extender.inc
 configure = admin/config/search/settings
 stylesheets[all][] = search.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/search/search.module b/modules/search/search.module
index 2772c8e58f228258d334085ec16304997a7817fc..a73da3c9e1e46ebc174dc77fb213691b9c309d4e 100644
--- a/modules/search/search.module
+++ b/modules/search/search.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: search.module,v 1.359 2010/09/05 02:21:38 dries Exp $
+// $Id: search.module,v 1.363 2010/10/01 15:24:18 webchick Exp $
 
 /**
  * @file
@@ -173,7 +173,6 @@ function search_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('search_admin_settings'),
     'access arguments' => array('administer search'),
-    'type' => MENU_NORMAL_ITEM,
     'weight' => -10,
     'file' => 'search.admin.inc',
   );
@@ -182,7 +181,7 @@ function search_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('search_reindex_confirm'),
     'access arguments' => array('administer search'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'search.admin.inc',
   );
 
@@ -354,7 +353,7 @@ function search_cron() {
   // to date.
   drupal_register_shutdown_function('search_update_totals');
 
-  foreach(variable_get('search_active_modules', array('node', 'user')) as $module) {
+  foreach (variable_get('search_active_modules', array('node', 'user')) as $module) {
     // Update word index
     module_invoke($module, 'update_index');
   }
@@ -960,7 +959,7 @@ function search_form($form, &$form_state, $action = '', $keys = '', $type = NULL
   if (!$action) {
     $action = 'search/' . $module_info['path'];
   }
-  if (is_null($prompt)) {
+  if (!isset($prompt)) {
     $prompt = t('Enter your keywords');
   }
 
diff --git a/modules/search/search.test b/modules/search/search.test
index 3dbbd1b562dd3b42da6957abc1d1176744edd5fe..18796617cf31d236c7e7c1071a36b6f994947ba1 100644
--- a/modules/search/search.test
+++ b/modules/search/search.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: search.test,v 1.74 2010/09/04 13:33:53 dries Exp $
+// $Id: search.test,v 1.76 2010/10/05 06:17:29 webchick Exp $
 
 // The search index can contain different types of content. Typically the type is 'node'.
 // Here we test with _test_ and _test2_ as the type.
@@ -236,13 +236,16 @@ class SearchMatchTestCase extends DrupalWebTestCase {
   }
 }
 
-class SearchBikeShed extends DrupalWebTestCase {
+/**
+ * Tests the bike shed text on no results page, and text on the search page.
+ */
+class SearchPageText extends DrupalWebTestCase {
   protected $searching_user;
 
   public static function getInfo() {
     return array(
-      'name' => 'Bike shed',
-      'description' => 'Tests the bike shed text on the no results page.',
+      'name' => 'Search page text',
+      'description' => 'Tests the bike shed text on the no results page, and various other text on search pages.',
       'group' => 'Search'
     );
   }
@@ -251,18 +254,31 @@ class SearchBikeShed extends DrupalWebTestCase {
     parent::setUp('search');
 
     // Create user.
-    $this->searching_user = $this->drupalCreateUser(array('search content'));
+    $this->searching_user = $this->drupalCreateUser(array('search content', 'access user profiles'));
   }
 
-  function testFailedSearch() {
+  /**
+   * Tests the failed search text, and various other text on the search page.
+   */
+  function testSearchText() {
     $this->drupalLogin($this->searching_user);
     $this->drupalGet('search/node');
     $this->assertText(t('Enter your keywords'));
+    $this->assertText(t('Search'));
+    $title = t('Search') . ' | Drupal';
+    $this->assertTitle($title, 'Search page title is correct');
 
     $edit = array();
     $edit['keys'] = 'bike shed ' . $this->randomName();
     $this->drupalPost('search/node', $edit, t('Search'));
     $this->assertText(t('Consider loosening your query with OR. bike OR shed will often show more results than bike shed.'), t('Help text is displayed when search returns no results.'));
+    $this->assertText(t('Search'));
+    $this->assertTitle($title, 'Search page title is correct');
+
+    $edit['keys'] = $this->searching_user->name;
+    $this->drupalPost('search/user', $edit, t('Search'));
+    $this->assertText(t('Search'));
+    $this->assertTitle($title, 'Search page title is correct');
   }
 }
 
@@ -347,7 +363,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
 
   function testRankings() {
     // Login with sufficient privileges.
-    $this->drupalLogin($this->drupalCreateUser(array('post comments without approval', 'create page content')));
+    $this->drupalLogin($this->drupalCreateUser(array('skip comment approval', 'create page content')));
 
     // Build a list of the rankings to test.
     $node_ranks = array('sticky', 'promote', 'relevance', 'recent', 'comments', 'views');
@@ -502,7 +518,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
    */
   function testDoubleRankings() {
     // Login with sufficient privileges.
-    $this->drupalLogin($this->drupalCreateUser(array('post comments without approval', 'create page content')));
+    $this->drupalLogin($this->drupalCreateUser(array('skip comment approval', 'create page content')));
 
     // See testRankings() above - build a node that will rank high for sticky.
     $settings = array(
@@ -679,7 +695,7 @@ class SearchCommentTestCase extends DrupalWebTestCase {
       filter_permission_name($full_html_format),
       'administer permissions',
       'create page content',
-      'post comments without approval',
+      'skip comment approval',
       'access comments',
     );
     $this->admin_user = $this->drupalCreateUser($permissions);
@@ -933,7 +949,7 @@ class SearchCommentCountToggleTestCase extends DrupalWebTestCase {
     parent::setUp('search');
 
     // Create searching user.
-    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'post comments without approval'));
+    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'skip comment approval'));
 
     // Create initial nodes.
     $node_params = array('type' => 'article', 'body' => array(LANGUAGE_NONE => array(array('value' => 'SearchCommentToggleTestCase'))));
@@ -1066,7 +1082,7 @@ class SearchKeywordsConditions extends DrupalWebTestCase {
   function setUp() {
     parent::setUp('search', 'search_extra_type');
     // Create searching user.
-    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'post comments without approval'));
+    $this->searching_user = $this->drupalCreateUser(array('search content', 'access content', 'access comments', 'skip comment approval'));
     // Login with sufficient privileges.
     $this->drupalLogin($this->searching_user);
     // Test with all search modules enabled.
diff --git a/modules/search/tests/search_embedded_form.info b/modules/search/tests/search_embedded_form.info
index 50de79e8aa2155dd95d1f4254eb6849cdc36376f..8c256467f45d70d2e39776446663ef2af1424df9 100644
--- a/modules/search/tests/search_embedded_form.info
+++ b/modules/search/tests/search_embedded_form.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = search_embedded_form.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/search/tests/search_extra_type.info b/modules/search/tests/search_extra_type.info
index cbf66ec9e72603fcf10f25e8d53e46feab221805..35b300674e958b03eaedbac1d7924e2088fe7ee0 100644
--- a/modules/search/tests/search_extra_type.info
+++ b/modules/search/tests/search_extra_type.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = search_extra_type.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/shortcut/shortcut.info b/modules/shortcut/shortcut.info
index 7cfa243e1b50aac142b2f0528436faf49a822be6..84d5db36ef7b158cf87eb032b09e128d29e5625f 100644
--- a/modules/shortcut/shortcut.info
+++ b/modules/shortcut/shortcut.info
@@ -10,8 +10,8 @@ files[] = shortcut.install
 files[] = shortcut.test
 configure = admin/config/user-interface/shortcut
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/shortcut/shortcut.module b/modules/shortcut/shortcut.module
index 455961f1c08efad7331e079c9df1b97995db3350..8b35fb36bb869475bc8e5e7b1e99a7f13a471a29 100644
--- a/modules/shortcut/shortcut.module
+++ b/modules/shortcut/shortcut.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: shortcut.module,v 1.26 2010/08/03 23:07:01 dries Exp $
+// $Id: shortcut.module,v 1.27 2010/09/24 00:37:44 dries Exp $
 
 /**
  * @file
@@ -91,7 +91,6 @@ function shortcut_menu() {
     'title arguments' => array(4),
     'access callback' => 'shortcut_set_edit_access',
     'access arguments' => array(4),
-    'type' => MENU_CALLBACK,
     'file' => 'shortcut.admin.inc',
   );
   $items['admin/config/user-interface/shortcut/%shortcut_set/links'] = array(
@@ -114,7 +113,6 @@ function shortcut_menu() {
     'page arguments' => array('shortcut_set_delete_form', 4),
     'access callback' => 'shortcut_set_delete_access',
     'access arguments' => array(4),
-    'type' => MENU_CALLBACK,
     'file' => 'shortcut.admin.inc',
   );
   $items['admin/config/user-interface/shortcut/%shortcut_set/add-link'] = array(
@@ -141,7 +139,6 @@ function shortcut_menu() {
     'page arguments' => array('shortcut_link_edit', 5),
     'access callback' => 'shortcut_link_access',
     'access arguments' => array(5),
-    'type' => MENU_CALLBACK,
     'file' => 'shortcut.admin.inc',
   );
   $items['admin/config/user-interface/shortcut/link/%menu_link/delete'] = array(
@@ -150,7 +147,6 @@ function shortcut_menu() {
     'page arguments' => array('shortcut_link_delete', 5),
     'access callback' => 'shortcut_link_access',
     'access arguments' => array(5),
-    'type' => MENU_CALLBACK,
     'file' => 'shortcut.admin.inc',
   );
   $items['user/%user/shortcuts'] = array(
diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php
index 088b39c47278edad07e2ae311edfe38e2bd9a531..3355fc248a50ba813bfeb4cf1094352ee93639bb 100644
--- a/modules/simpletest/drupal_web_test_case.php
+++ b/modules/simpletest/drupal_web_test_case.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: drupal_web_test_case.php,v 1.232 2010/09/11 21:14:31 webchick Exp $
+// $Id: drupal_web_test_case.php,v 1.240 2010/10/05 06:17:29 webchick Exp $
 
 /**
  * Global variable that holds information about the tests being run.
@@ -603,7 +603,11 @@ class DrupalUnitTestCase extends DrupalTestCase {
 
     // Generate temporary prefixed database to ensure that tests have a clean starting point.
     $this->databasePrefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
-    $conf['file_public_path'] = $this->originalFileDirectory . '/' . $this->databasePrefix;
+
+    // Create test directory.
+    $public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
+    file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    $conf['file_public_path'] = $public_files_directory;
 
     // Clone the current connection and replace the current prefix.
     $connection_info = Database::getConnectionInfo('default');
@@ -689,6 +693,13 @@ class DrupalWebTestCase extends DrupalTestCase {
    */
   protected $plainTextContent;
 
+  /**
+   * The value of the Drupal.settings JavaScript variable for the page currently loaded in the internal browser.
+   *
+   * @var Array
+   */
+  protected $drupalSettings;
+
   /**
    * The parsed version of the page.
    *
@@ -980,7 +991,7 @@ class DrupalWebTestCase extends DrupalTestCase {
    *   A fully loaded user object with pass_raw property, or FALSE if account
    *   creation fails.
    */
-  protected function drupalCreateUser($permissions = array('access comments', 'access content', 'post comments', 'post comments without approval')) {
+  protected function drupalCreateUser($permissions = array('access comments', 'access content', 'post comments', 'skip comment approval')) {
     // Create a role with the given permission set.
     if (!($rid = $this->drupalCreateRole($permissions))) {
       return FALSE;
@@ -1304,9 +1315,6 @@ class DrupalWebTestCase extends DrupalTestCase {
     drupal_static_reset();
     drupal_flush_all_caches();
 
-    // Register actions declared by any modules.
-    actions_synchronize();
-
     // Reload global $conf array and permissions.
     $this->refreshVariables();
     $this->checkPermissions(array(), TRUE);
@@ -1698,8 +1706,14 @@ class DrupalWebTestCase extends DrupalTestCase {
    *   Note that this is not the Drupal $form_id, but rather the HTML ID of the
    *   form, which is typically the same thing but with hyphens replacing the
    *   underscores.
-   */
-  protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL) {
+   * @param $extra_post
+   *   (optional) A string of additional data to append to the POST submission.
+   *   This can be used to add POST data for which there are no HTML fields, as
+   *   is done by drupalPostAJAX(). This string is literally appended to the
+   *   POST data, so it must already be urlencoded and contain a leading "&"
+   *   (e.g., "&extra_var1=hello+world&extra_var2=you%26me").
+   */
+  protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) {
     $submit_matches = FALSE;
     $ajax = is_array($submit);
     if (isset($path)) {
@@ -1750,23 +1764,7 @@ class DrupalWebTestCase extends DrupalTestCase {
               // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
               $post[$key] = urlencode($key) . '=' . urlencode($value);
             }
-            // For AJAX requests, add '_triggering_element_*' and
-            // 'ajax_html_ids' to the POST data, as ajax.js does.
-            if ($ajax) {
-              if (is_array($submit['triggering_element'])) {
-                // Get the first key/value pair in the array.
-                $post['_triggering_element_value'] = '_triggering_element_value=' . urlencode(reset($submit['triggering_element']));
-                $post['_triggering_element_name'] = '_triggering_element_name=' . urlencode(key($submit['triggering_element']));
-              }
-              else {
-                $post['_triggering_element_name'] = '_triggering_element_name=' . urlencode($submit['triggering_element']);
-              }
-              foreach ($this->xpath('//*[@id]') as $element) {
-                $id = (string) $element['id'];
-                $post[] = urlencode('ajax_html_ids[]') . '=' . urlencode($id);
-              }
-            }
-            $post = implode('&', $post);
+            $post = implode('&', $post) . $extra_post;
           }
           $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POST => TRUE, CURLOPT_POSTFIELDS => $post, CURLOPT_HTTPHEADER => $headers));
           // Ensure that any changes to variables in the other thread are picked up.
@@ -1803,70 +1801,131 @@ class DrupalWebTestCase extends DrupalTestCase {
    *
    * @see ajax.js
    */
-  protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path = 'system/ajax', array $options = array(), array $headers = array(), $form_html_id = NULL, $ajax_settings = array()) {
+  protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path = 'system/ajax', array $options = array(), array $headers = array(), $form_html_id = NULL, $ajax_settings = NULL) {
     // Get the content of the initial page prior to calling drupalPost(), since
     // drupalPost() replaces $this->content.
     if (isset($path)) {
       $this->drupalGet($path, $options);
     }
-    $content = $this->drupalGetContent();
-    $return = drupal_json_decode($this->drupalPost(NULL, $edit, array('path' => $ajax_path, 'triggering_element' => $triggering_element), $options, $headers, $form_html_id));
+    $content = $this->content;
+    $drupal_settings = $this->drupalSettings;
+
+    // Get the AJAX settings bound to the triggering element.
+    if (!isset($ajax_settings)) {
+      if (is_array($triggering_element)) {
+        $xpath = '//*[@name="' . key($triggering_element) . '" and @value="' . current($triggering_element) . '"]';
+      }
+      else {
+        $xpath = '//*[@name="' . $triggering_element . '"]';
+      }
+      if (isset($form_html_id)) {
+        $xpath = '//form[@id="' . $form_html_id . '"]' . $xpath;
+      }
+      $element = $this->xpath($xpath);
+      $element_id = (string) $element[0]['id'];
+      $ajax_settings = $drupal_settings['ajax'][$element_id];
+    }
+
+    // Add extra information to the POST data as ajax.js does.
+    $extra_post = '';
+    if (isset($ajax_settings['submit'])) {
+      foreach ($ajax_settings['submit'] as $key => $value) {
+        $extra_post .= '&' . urlencode($key) . '=' . urlencode($value);
+      }
+    }
+    foreach ($this->xpath('//*[@id]') as $element) {
+      $id = (string) $element['id'];
+      $extra_post .= '&' . urlencode('ajax_html_ids[]') . '=' . urlencode($id);
+    }
+
+    // Submit the POST request.
+    $return = drupal_json_decode($this->drupalPost(NULL, $edit, array('path' => $ajax_path, 'triggering_element' => $triggering_element), $options, $headers, $form_html_id, $extra_post));
 
-    // We need $ajax_settings['wrapper'] to perform DOM manipulation.
+    // Change the page content by applying the returned commands.
     if (!empty($ajax_settings) && !empty($return)) {
+      // ajax.js applies some defaults to the settings object, so do the same
+      // for what's used by this function.
+      $ajax_settings += array(
+        'method' => 'replaceWith',
+      );
       // DOM can load HTML soup. But, HTML soup can throw warnings, suppress
       // them.
       @$dom = DOMDocument::loadHTML($content);
       foreach ($return as $command) {
-        // @todo ajax.js can process commands other than 'insert' and can
-        //   process commands that include a 'selector', but these are hard to
-        //   emulate with DOMDocument. For now, we only implement 'insert'
-        //   commands that use $ajax_settings['wrapper'].
-        if ($command['command'] == 'insert' && !isset($command['selector'])) {
-          // $dom->getElementById() doesn't work when drupalPostAJAX() is
-          // invoked multiple times for a page, so use XPath instead. This also
-          // sets us up for adding support for $command['selector'], though it
-          // will require transforming a jQuery selector to XPath.
-          $xpath = new DOMXPath($dom);
-          $wrapperNode = $xpath->query('//*[@id="' . $ajax_settings['wrapper'] . '"]')->item(0);
-          if ($wrapperNode) {
-            // ajax.js adds an enclosing DIV to work around a Safari bug.
-            $newDom = new DOMDocument();
-            $newDom->loadHTML('<div>' . $command['data'] . '</div>');
-            $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
-            $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
-            // The "method" is a jQuery DOM manipulation function. Emulate each
-            // one using PHP's DOMNode API.
-            switch ($method) {
-              case 'replaceWith':
-                $wrapperNode->parentNode->replaceChild($newNode, $wrapperNode);
-                break;
-              case 'append':
-                $wrapperNode->appendChild($newNode);
-                break;
-              case 'prepend':
-                // If no firstChild, insertBefore() falls back to appendChild().
-                $wrapperNode->insertBefore($newNode, $wrapperNode->firstChild);
-                break;
-              case 'before':
-                $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode);
-                break;
-              case 'after':
-                // If no nextSibling, insertBefore() falls back to appendChild().
-                $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode->nextSibling);
-                break;
-              case 'html':
-                foreach ($wrapperNode->childNodes as $childNode) {
-                  $wrapperNode->removeChild($childNode);
+        switch ($command['command']) {
+          case 'settings':
+            $drupal_settings = array_merge_recursive($drupal_settings, $command['settings']);
+            break;
+
+          case 'insert':
+            // @todo ajax.js can process commands that include a 'selector', but
+            //   these are hard to emulate with DOMDocument. For now, we only
+            //   implement 'insert' commands that use $ajax_settings['wrapper'].
+            if (!isset($command['selector'])) {
+              // $dom->getElementById() doesn't work when drupalPostAJAX() is
+              // invoked multiple times for a page, so use XPath instead. This
+              // also sets us up for adding support for $command['selector'] in
+              // the future, once we figure out how to transform a jQuery
+              // selector to XPath.
+              $xpath = new DOMXPath($dom);
+              $wrapperNode = $xpath->query('//*[@id="' . $ajax_settings['wrapper'] . '"]')->item(0);
+              if ($wrapperNode) {
+                // ajax.js adds an enclosing DIV to work around a Safari bug.
+                $newDom = new DOMDocument();
+                $newDom->loadHTML('<div>' . $command['data'] . '</div>');
+                $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
+                $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
+                // The "method" is a jQuery DOM manipulation function. Emulate
+                // each one using PHP's DOMNode API.
+                switch ($method) {
+                  case 'replaceWith':
+                    $wrapperNode->parentNode->replaceChild($newNode, $wrapperNode);
+                    break;
+                  case 'append':
+                    $wrapperNode->appendChild($newNode);
+                    break;
+                  case 'prepend':
+                    // If no firstChild, insertBefore() falls back to
+                    // appendChild().
+                    $wrapperNode->insertBefore($newNode, $wrapperNode->firstChild);
+                    break;
+                  case 'before':
+                    $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode);
+                    break;
+                  case 'after':
+                    // If no nextSibling, insertBefore() falls back to
+                    // appendChild().
+                    $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode->nextSibling);
+                    break;
+                  case 'html':
+                    foreach ($wrapperNode->childNodes as $childNode) {
+                      $wrapperNode->removeChild($childNode);
+                    }
+                    $wrapperNode->appendChild($newNode);
+                    break;
                 }
-                $wrapperNode->appendChild($newNode);
-                break;
+              }
             }
-          }
+            break;
+
+          // @todo Add suitable implementations for these commands in order to
+          //   have full test coverage of what ajax.js can do.
+          case 'remove':
+            break;
+          case 'changed':
+            break;
+          case 'css':
+            break;
+          case 'data':
+            break;
+          case 'restripe':
+            break;
         }
       }
-      $this->drupalSetContent($dom->saveHTML());
+      $content = $dom->saveHTML();
     }
+    $this->drupalSetContent($content);
+    $this->drupalSetSettings($drupal_settings);
     return $return;
   }
 
@@ -2397,6 +2456,13 @@ class DrupalWebTestCase extends DrupalTestCase {
     return $this->content;
   }
 
+  /**
+   * Gets the value of the Drupal.settings JavaScript variable for the currently loaded page.
+   */
+  protected function drupalGetSettings() {
+    return $this->drupalSettings;
+  }
+
   /**
    * Gets an array containing all e-mails sent during this test case.
    *
@@ -2435,6 +2501,42 @@ class DrupalWebTestCase extends DrupalTestCase {
     $this->url = $url;
     $this->plainTextContent = FALSE;
     $this->elements = FALSE;
+    $this->drupalSettings = array();
+    if (preg_match('/jQuery\.extend\(Drupal\.settings, (.*?)\);/', $content, $matches)) {
+      $this->drupalSettings = drupal_json_decode($matches[1]);
+    }
+  }
+
+  /**
+   * Sets the value of the Drupal.settings JavaScript variable for the currently loaded page.
+   */
+  protected function drupalSetSettings($settings) {
+    $this->drupalSettings = $settings;
+  }
+
+  /**
+   * Pass if the internal browser's URL matches the given path.
+   *
+   * @param $path
+   *   The expected system path.
+   * @param $options
+   *   (optional) Any additional options to pass for $path to url().
+   * @param $message
+   *   Message to display.
+   * @param $group
+   *   The group this message belongs to, defaults to 'Other'.
+   *
+   * @return
+   *   TRUE on pass, FALSE on fail.
+   */
+  protected function assertUrl($path, array $options = array(), $message = '', $group = 'Other') {
+    if (!$message) {
+      $message = t('Current URL is @url.', array(
+        '@url' => var_export(url($path, $options), TRUE),
+      ));
+    }
+    $options['absolute'] = TRUE;
+    return $this->assertEqual($this->getUrl(), url($path, $options), $message, $group);
   }
 
   /**
@@ -2662,7 +2764,14 @@ class DrupalWebTestCase extends DrupalTestCase {
    *   TRUE on pass, FALSE on fail.
    */
   protected function assertTitle($title, $message = '', $group = 'Other') {
-    return $this->assertEqual(current($this->xpath('//title')), $title, $message, $group);
+    $actual = (string) current($this->xpath('//title'));
+    if (!$message) {
+      $message = t('Page title @actual is equal to @expected.', array(
+        '@actual' => var_export($actual, TRUE),
+        '@expected' => var_export($title, TRUE),
+      ));
+    }
+    return $this->assertEqual($actual, $title, $message, $group);
   }
 
   /**
@@ -2678,7 +2787,14 @@ class DrupalWebTestCase extends DrupalTestCase {
    *   TRUE on pass, FALSE on fail.
    */
   protected function assertNoTitle($title, $message = '', $group = 'Other') {
-    return $this->assertNotEqual(current($this->xpath('//title')), $title, $message, $group);
+    $actual = (string) current($this->xpath('//title'));
+    if (!$message) {
+      $message = t('Page title @actual is not equal to @unexpected.', array(
+        '@actual' => var_export($actual, TRUE),
+        '@unexpected' => var_export($title, TRUE),
+      ));
+    }
+    return $this->assertNotEqual($actual, $title, $message, $group);
   }
 
   /**
@@ -3015,6 +3131,24 @@ class DrupalWebTestCase extends DrupalTestCase {
     return $this->assertTrue($match, $message ? $message : t('HTTP response expected !code, actual !curl_code', array('!code' => $code, '!curl_code' => $curl_code)), t('Browser'));
   }
 
+  /**
+   * Assert the page did not return the specified response code.
+   *
+   * @param $code
+   *   Response code. For example 200 is a successful page request. For a list
+   *   of all codes see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
+   * @param $message
+   *   Message to display.
+   *
+   * @return
+   *   Assertion result.
+   */
+  protected function assertNoResponse($code, $message = '') {
+    $curl_code = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
+    $match = is_array($code) ? in_array($curl_code, $code) : $curl_code == $code;
+    return $this->assertFalse($match, $message ? $message : t('HTTP response not expected !code, actual !curl_code', array('!code' => $code, '!curl_code' => $curl_code)), t('Browser'));
+  }
+
   /**
    * Asserts that the most recently sent e-mail message has the given value.
    *
diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info
index 3c34a4ceb9feed84433cc53de4325dc01d0f6cda..80b7e1f4d55de3482f8e7fc25af09d12b42b2b91 100644
--- a/modules/simpletest/simpletest.info
+++ b/modules/simpletest/simpletest.info
@@ -1,4 +1,4 @@
-; $Id: simpletest.info,v 1.22 2010/09/13 05:50:09 webchick Exp $
+; $Id: simpletest.info,v 1.24 2010/10/05 20:04:19 webchick Exp $
 name = Testing
 description = Provides a framework for unit and functional testing.
 package = Core
@@ -42,9 +42,11 @@ files[] = tests/upgrade/upgrade.test
 files[] = tests/upgrade/upgrade.comment.test
 files[] = tests/upgrade/upgrade.node.test
 files[] = tests/upgrade/upgrade.taxonomy.test
+files[] = tests/upgrade/upgrade.upload.test
+files[] = tests/upgrade/upgrade.locale.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/simpletest.module b/modules/simpletest/simpletest.module
index 10fc6fbb75f339d0baf0a055e3368fc777cc4717..e06a4c5503eb9af55edba8e5b989e655013111f1 100644
--- a/modules/simpletest/simpletest.module
+++ b/modules/simpletest/simpletest.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: simpletest.module,v 1.93 2010/09/01 20:08:17 dries Exp $
+// $Id: simpletest.module,v 1.94 2010/09/24 00:37:44 dries Exp $
 
 /**
  * @file
@@ -56,7 +56,6 @@ function simpletest_menu() {
     'page arguments' => array('simpletest_result_form', 5),
     'description' => 'View result of tests.',
     'access arguments' => array('administer unit tests'),
-    'type' => MENU_CALLBACK,
     'file' => 'simpletest.pages.inc',
   );
   return $items;
diff --git a/modules/simpletest/simpletest.test b/modules/simpletest/simpletest.test
index 252da04e1a5f544bcb483e846282df3e8a710959..736b93e4a50ea1996b5a959db4a7fa02c06fdc70 100644
--- a/modules/simpletest/simpletest.test
+++ b/modules/simpletest/simpletest.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: simpletest.test,v 1.45 2010/09/01 20:08:17 dries Exp $
+// $Id: simpletest.test,v 1.46 2010/09/28 02:30:32 dries Exp $
 
 class SimpleTestFunctionalTest extends DrupalWebTestCase {
   /**
@@ -385,7 +385,7 @@ class SimpleTestMailCaptureTestCase extends DrupalWebTestCase {
 
     // Assert that the e-mail was sent by iterating over the message properties
     // and ensuring that they are captured intact.
-    foreach($message as $field => $value) {
+    foreach ($message as $field => $value) {
       $this->assertMail($field, $value, t('The e-mail was sent and the value for property @field is intact.', array('@field' => $field)), t('E-mail'));
     }
 
diff --git a/modules/simpletest/tests/actions_loop_test.info b/modules/simpletest/tests/actions_loop_test.info
index 94bb49e8712fd97443ec41e0828b1682ee054b57..342f7bea6d77f5051aebf2af805e161e7a163417 100644
--- a/modules/simpletest/tests/actions_loop_test.info
+++ b/modules/simpletest/tests/actions_loop_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = actions_loop_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/ajax.test b/modules/simpletest/tests/ajax.test
index 232074f22e19ee3cb1ddefc420fc7ced029d0693..836daf36bb2723c8816b8ac8d5b9965a5b965e2a 100644
--- a/modules/simpletest/tests/ajax.test
+++ b/modules/simpletest/tests/ajax.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: ajax.test,v 1.14 2010/08/05 23:53:38 webchick Exp $
+// $Id: ajax.test,v 1.19 2010/10/04 17:46:01 dries Exp $
 
 class AJAXTestCase extends DrupalWebTestCase {
   function setUp() {
@@ -11,18 +11,47 @@ class AJAXTestCase extends DrupalWebTestCase {
   }
 
   /**
-   * Returns the passed-in commands array without the initial settings command.
+   * Assert that a command with the required properties exists within the array of AJAX commands returned by the server.
    *
-   * Depending on factors that may be irrelevant to a particular test,
-   * ajax_render() may prepend a settings command. This function allows the test
-   * to only have to concern itself with the commands that were passed to
-   * ajax_render().
+   * The AJAX framework, via the ajax_deliver() and ajax_render() functions,
+   * returns an array of commands. This array sometimes includes commands
+   * automatically provided by the framework in addition to commands returned by
+   * a particular page callback. During testing, we're usually interested that a
+   * particular command is present, and don't care whether other commands
+   * precede or follow the one we're interested in. Additionally, the command
+   * we're interested in may include additional data that we're not interested
+   * in. Therefore, this function simply asserts that one of the commands in
+   * $haystack contains all of the keys and values in $needle. Furthermore, if
+   * $needle contains a 'settings' key with an array value, we simply assert
+   * that all keys and values within that array are present in the command we're
+   * checking, and do not consider it a failure if the actual command contains
+   * additional settings that aren't part of $needle.
+   *
+   * @param $haystack
+   *   An array of AJAX commands returned by the server.
+   * @param $needle
+   *   Array of info we're expecting in one of those commands.
+   * @param $message
+   *   An assertion message.
    */
-  protected function discardSettings($commands) {
-    if ($commands[0]['command'] == 'settings') {
-      array_shift($commands);
+  protected function assertCommand($haystack, $needle, $message) {
+    $found = FALSE;
+    foreach ($haystack as $command) {
+      // If the command has additional settings that we're not testing for, do
+      // not consider that a failure.
+      if (isset($command['settings']) && is_array($command['settings']) && isset($needle['settings']) && is_array($needle['settings'])) {
+        $command['settings'] = array_intersect_key($command['settings'], $needle['settings']);
+      }
+      // If the command has additional data that we're not testing for, do not
+      // consider that a failure. Also, == instead of ===, because we don't
+      // require the key/value pairs to be in any particular order
+      // (http://www.php.net/manual/en/language.operators.array.php).
+      if (array_intersect_key($command, $needle) == $needle) {
+        $found = TRUE;
+        break;
+      }
     }
-    return $commands;
+    $this->assertTrue($found, $message);
   }
 }
 
@@ -39,30 +68,46 @@ class AJAXFrameworkTestCase extends AJAXTestCase {
   }
 
   /**
-   * Test proper passing of JavaScript settings via ajax_render().
+   * Test that ajax_render() returns JavaScript settings generated during the page request.
+   *
+   * @todo Add tests to ensure that ajax_render() returns commands for new CSS
+   *   and JavaScript files to be loaded by the page. See
+   *   http://drupal.org/node/561858.
    */
   function testAJAXRender() {
-    $result = $this->drupalGetAJAX('ajax-test/render');
-    // Verify that JavaScript settings are contained (always first).
-    $this->assertIdentical($result[0]['command'], 'settings', t('drupal_add_js() settings are contained first.'));
-    // Verify that basePath is contained in JavaScript settings.
-    $this->assertEqual($result[0]['settings']['basePath'], base_path(), t('Base path is contained in JavaScript settings.'));
+    $commands = $this->drupalGetAJAX('ajax-test/render');
+
+    // Verify that there is a command to load settings added with
+    // drupal_add_js().
+    $expected = array(
+      'command' => 'settings',
+      'settings' => array('basePath' => base_path(), 'ajax' => 'test'),
+    );
+    $this->assertCommand($commands, $expected, t('ajax_render() loads settings added with drupal_add_js().'));
   }
 
   /**
    * Test behavior of ajax_render_error().
    */
   function testAJAXRenderError() {
-    $result = $this->discardSettings($this->drupalGetAJAX('ajax-test/render-error'));
     // Verify default error message.
-    $this->assertEqual($result[0]['command'], 'alert', t('ajax_render_error() invokes alert command.'));
-    $this->assertEqual($result[0]['text'], t('An error occurred while handling the request: The server received invalid input.'), t('Default error message is output.'));
+    $commands = $this->drupalGetAJAX('ajax-test/render-error');
+    $expected = array(
+      'command' => 'alert',
+      'text' => t('An error occurred while handling the request: The server received invalid input.'),
+    );
+    $this->assertCommand($commands, $expected, t('ajax_render_error() invokes alert command.'));
+
     // Verify custom error message.
     $edit = array(
       'message' => 'Custom error message.',
     );
-    $result = $this->discardSettings($this->drupalGetAJAX('ajax-test/render-error', array('query' => $edit)));
-    $this->assertEqual($result[0]['text'], $edit['message'], t('Custom error message is output.'));
+    $commands = $this->drupalGetAJAX('ajax-test/render-error', array('query' => $edit));
+    $expected = array(
+      'command' => 'alert',
+      'text' => $edit['message'],
+    );
+     $this->assertCommand($commands, $expected, t('Custom error message is output.'));
   }
 }
 
@@ -78,19 +123,6 @@ class AJAXCommandsTestCase extends AJAXTestCase {
     );
   }
 
-  /**
-   * Test ajax_command_settings().
-   */
-  function testAJAXRender() {
-    $commands = array();
-    $commands[] = ajax_command_settings(array('foo' => 42));
-    $result = $this->drupalGetAJAX('ajax-test/render', array('query' => array('commands' => $commands)));
-    // Verify that JavaScript settings are contained (always first).
-    $this->assertIdentical($result[0]['command'], 'settings', t('drupal_add_js() settings are contained first.'));
-    // Verify that the custom setting is contained.
-    $this->assertEqual($result[1]['settings']['foo'], 42, t('Custom setting is output.'));
-  }
-
   /**
    * Test the various AJAX Commands.
    */
@@ -102,69 +134,124 @@ class AJAXCommandsTestCase extends AJAXTestCase {
     $edit = array();
 
     // Tests the 'after' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'After': Click to put something after the div"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'after' && $command['data'] == 'This will be placed after', "'after' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'After': Click to put something after the div")));
+    $expected = array(
+      'command' => 'insert',
+      'method' => 'after',
+      'data' => 'This will be placed after',
+    );
+    $this->assertCommand($commands, $expected, "'after' AJAX command issued with correct data");
 
     // Tests the 'alert' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Alert': Click to alert"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'alert' && $command['text'] == 'Alert', "'alert' AJAX Command issued with correct text");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Alert': Click to alert")));
+    $expected = array(
+      'command' => 'alert',
+      'text' => 'Alert',
+    );
+    $this->assertCommand($commands, $expected, "'alert' AJAX Command issued with correct text");
 
     // Tests the 'append' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Append': Click to append something"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'append' && $command['data'] == 'Appended text', "'append' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'Append': Click to append something")));
+    $expected = array(
+      'command' => 'insert',
+      'method' => 'append',
+      'data' => 'Appended text',
+    );
+    $this->assertCommand($commands, $expected, "'append' AJAX command issued with correct data");
 
     // Tests the 'before' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'before': Click to put something before the div"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'before' && $command['data'] == 'Before text', "'before' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'before': Click to put something before the div")));
+    $expected = array(
+      'command' => 'insert',
+      'method' => 'before',
+      'data' => 'Before text',
+    );
+    $this->assertCommand($commands, $expected, "'before' AJAX command issued with correct data");
 
     // Tests the 'changed' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'changed' && $command['selector'] == '#changed_div', "'changed' AJAX command issued with correct selector");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed.")));
+    $expected = array(
+      'command' => 'changed',
+      'selector' => '#changed_div',
+    );
+    $this->assertCommand($commands, $expected, "'changed' AJAX command issued with correct selector");
 
     // Tests the 'changed' command using the second argument.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed with asterisk."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'changed' && $command['selector'] == '#changed_div' && $command['asterisk'] == '#changed_div_mark_this', "'changed' AJAX command (with asterisk) issued with correct selector");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX changed: Click to mark div changed with asterisk.")));
+    $expected = array(
+      'command' => 'changed',
+      'selector' => '#changed_div',
+      'asterisk' => '#changed_div_mark_this',
+    );
+    $this->assertCommand($commands, $expected, "'changed' AJAX command (with asterisk) issued with correct selector");
 
     // Tests the 'css' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("Set the the '#box' div to be blue."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'css' && $command['selector'] == '#css_div' && $command['argument']['background-color'] == 'blue', "'css' AJAX command issued with correct selector");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("Set the the '#box' div to be blue.")));
+    $expected = array(
+      'command' => 'css',
+      'selector' => '#css_div',
+      'argument' => array('background-color' => 'blue'),
+    );
+    $this->assertCommand($commands, $expected, "'css' AJAX command issued with correct selector");
 
     // Tests the 'data' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX data command: Issue command."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'data' && $command['name'] == 'testkey' && $command['value'] == 'testvalue', "'data' AJAX command issued with correct key and value");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX data command: Issue command.")));
+    $expected = array(
+      'command' => 'data',
+      'name' => 'testkey',
+      'value' => 'testvalue',
+    );
+    $this->assertCommand($commands, $expected, "'data' AJAX command issued with correct key and value");
 
     // Tests the 'html' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX html: Replace the HTML in a selector."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'html' && $command['data'] == 'replacement text', "'html' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX html: Replace the HTML in a selector.")));
+    $expected = array(
+      'command' => 'insert',
+      'method' => 'html',
+      'data' => 'replacement text',
+    );
+    $this->assertCommand($commands, $expected, "'html' AJAX command issued with correct data");
 
     // Tests the 'insert' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX insert: Let client insert based on #ajax['method']."))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == NULL && $command['data'] == 'insert replacement text', "'insert' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX insert: Let client insert based on #ajax['method'].")));
+    $expected = array(
+      'command' => 'insert',
+      'data' => 'insert replacement text',
+    );
+    $this->assertCommand($commands, $expected, "'insert' AJAX command issued with correct data");
 
     // Tests the 'prepend' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'prepend': Click to prepend something"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'insert' && $command['method'] == 'prepend' && $command['data'] == 'prepended text', "'prepend' AJAX command issued with correct data");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'prepend': Click to prepend something")));
+    $expected = array(
+      'command' => 'insert',
+      'method' => 'prepend',
+      'data' => 'prepended text',
+    );
+    $this->assertCommand($commands, $expected, "'prepend' AJAX command issued with correct data");
 
     // Tests the 'remove' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'remove': Click to remove text"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'remove' && $command['selector'] == '#remove_text', "'remove' AJAX command issued with correct command and selector");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'remove': Click to remove text")));
+    $expected = array(
+      'command' => 'remove',
+      'selector' => '#remove_text',
+    );
+    $this->assertCommand($commands, $expected, "'remove' AJAX command issued with correct command and selector");
 
     // Tests the 'restripe' command.
-    $commands = $this->discardSettings($this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'restripe' command"))));
-    $command = $commands[0];
-    $this->assertTrue($command['command'] == 'restripe' && $command['selector'] == '#restripe_table', "'restripe' AJAX command issued with correct selector");
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'restripe' command")));
+    $expected = array(
+      'command' => 'restripe',
+      'selector' => '#restripe_table',
+    );
+    $this->assertCommand($commands, $expected, "'restripe' AJAX command issued with correct selector");
+
+    // Tests the 'settings' command.
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'settings' command")));
+    $expected = array(
+      'command' => 'settings',
+      'settings' => array('ajax_forms_test' => array('foo' => 42)),
+    );
+    $this->assertCommand($commands, $expected, "'settings' AJAX command issued with correct data");
   }
 }
 
@@ -192,23 +279,29 @@ class AJAXFormValuesTestCase extends AJAXTestCase {
    */
   function testSimpleAJAXFormValue() {
     // Verify form values of a select element.
-    foreach(array('red', 'green', 'blue') as $item) {
+    foreach (array('red', 'green', 'blue') as $item) {
       $edit = array(
         'select' => $item,
       );
-      $commands = $this->discardSettings($this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'select'));
-      $data_command = $commands[1];
-      $this->assertEqual($data_command['value'], $item);
+      $commands = $this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'select');
+      $expected = array(
+        'command' => 'data',
+        'value' => $item,
+      );
+      $this->assertCommand($commands, $expected, "verification of AJAX form values from a selectbox issued with a correct value");
     }
 
     // Verify form values of a checkbox element.
-    foreach(array(FALSE, TRUE) as $item) {
+    foreach (array(FALSE, TRUE) as $item) {
       $edit = array(
         'checkbox' => $item,
       );
-      $commands = $this->discardSettings($this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'checkbox'));
-      $data_command = $commands[1];
-      $this->assertEqual((int) $data_command['value'], (int) $item);
+      $commands = $this->drupalPostAJAX('ajax_forms_test_get_form', $edit, 'checkbox');
+      $expected = array(
+        'command' => 'data',
+        'value' => (int) $item,
+      );
+      $this->assertCommand($commands, $expected, "verification of AJAX form values from a checkbox issued with a correct value");
     }
   }
 }
@@ -269,24 +362,17 @@ class AJAXMultiFormTestCase extends AJAXTestCase {
     // of field items and "add more" button for the multi-valued field within
     // each form.
     $this->drupalGet('form-test/two-instances-of-same-form');
-    foreach ($field_xpaths as $form_id => $field_xpath) {
+    foreach ($field_xpaths as $form_html_id => $field_xpath) {
       $this->assert(count($this->xpath($field_xpath . $field_items_xpath_suffix)) == 1, t('Found the correct number of field items on the initial page.'));
       $this->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button on the initial page.'));
     }
     $this->assertNoDuplicateIds(t('Initial page contains unique IDs'), 'Other');
 
     // Submit the "add more" button of each form twice. After each corresponding
-    // page update, ensure the same as above. To successfully implement
-    // consecutive AJAX submissions, we need to manage $settings as ajax.js
-    // does for Drupal.settings.
-    preg_match('/jQuery\.extend\(Drupal\.settings, (.*?)\);/', $this->content, $matches);
-    $settings = drupal_json_decode($matches[1]);
-    foreach ($field_xpaths as $form_id => $field_xpath) {
-      for ($i=0; $i<2; $i++) {
-        $button = $this->xpath($field_xpath . $button_xpath_suffix);
-        $button_id = (string) $button[0]['id'];
-        $commands = $this->drupalPostAJAX(NULL, array(), array($button_name => $button_value), 'system/ajax', array(), array(), $form_id, $settings['ajax'][$button_id]);
-        $settings = array_merge_recursive($settings, $commands[0]['settings']);
+    // page update, ensure the same as above.
+    foreach ($field_xpaths as $form_html_id => $field_xpath) {
+      for ($i = 0; $i < 2; $i++) {
+        $this->drupalPostAJAX(NULL, array(), array($button_name => $button_value), 'system/ajax', array(), array(), $form_html_id);
         $this->assert(count($this->xpath($field_xpath . $field_items_xpath_suffix)) == $i+2, t('Found the correct number of field items after an AJAX submission.'));
         $this->assertFieldByXPath($field_xpath . $button_xpath_suffix, NULL, t('Found the "add more" button after an AJAX submission.'));
         $this->assertNoDuplicateIds(t('Updated page contains unique IDs'), 'Other');
@@ -326,4 +412,3 @@ class AJAXElementValidation extends AJAXTestCase {
     $this->assertText('ajax_forms_test_validation_form_callback invoked', t('The correct callback was invoked'));
   }
 }
-
diff --git a/modules/simpletest/tests/ajax_forms_test.info b/modules/simpletest/tests/ajax_forms_test.info
index 2da1410f14199c0e2a2482ed6a91f980b2e45655..7317778e9b8f74c2be02c87674dd6bed42d16799 100644
--- a/modules/simpletest/tests/ajax_forms_test.info
+++ b/modules/simpletest/tests/ajax_forms_test.info
@@ -7,8 +7,8 @@ files[] = ajax_forms_test.module
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/ajax_forms_test.module b/modules/simpletest/tests/ajax_forms_test.module
index 3f7c765b7350c75deacc7d46c7fc46b528c6fa7e..22cba5d677a535538b38869408097620a26c86aa 100644
--- a/modules/simpletest/tests/ajax_forms_test.module
+++ b/modules/simpletest/tests/ajax_forms_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: ajax_forms_test.module,v 1.7 2010/05/06 05:59:31 webchick Exp $
+// $Id: ajax_forms_test.module,v 1.8 2010/10/04 17:46:01 dries Exp $
 
 /**
  * @file
@@ -217,7 +217,7 @@ function ajax_forms_test_ajax_commands_form($form, &$form_state) {
     '#suffix' => '<div id="remove_div"><div id="remove_text">text to be removed</div></div>',
   );
 
-  // Show off the AJAX 'restripe' command.
+  // Shows the AJAX 'restripe' command.
   $form['restripe_command_example'] = array(
     '#type' => 'submit',
     '#value' => t("AJAX 'restripe' command"),
@@ -230,8 +230,17 @@ function ajax_forms_test_ajax_commands_form($form, &$form_state) {
                   <tr ><td>second row</td></tr>
                   </table>
                   </div>',
+  );
 
-
+  // Demonstrates the AJAX 'settings' command. The 'settings' command has
+  // nothing visual to "show", but it can be tested via SimpleTest and via
+  // Firebug.
+  $form['settings_command_example'] = array(
+    '#type' => 'submit',
+    '#value' => t("AJAX 'settings' command"),
+    '#ajax' => array(
+      'callback' => 'ajax_forms_test_advanced_commands_settings_callback',
+    ),
   );
 
   $form['submit'] = array(
@@ -367,7 +376,15 @@ function ajax_forms_test_advanced_commands_restripe_callback($form, $form_state)
   return array('#type' => 'ajax', '#commands' => $commands);
 }
 
-
+/**
+ * AJAX callback for 'settings'.
+ */
+function ajax_forms_test_advanced_commands_settings_callback($form, $form_state) {
+  $commands = array();
+  $setting['ajax_forms_test']['foo'] = 42;
+  $commands[] = ajax_command_settings($setting);
+  return array('#type' => 'ajax', '#commands' => $commands);
+}
 
 /**
  * This form and its related submit and callback functions demonstrate
diff --git a/modules/simpletest/tests/ajax_test.info b/modules/simpletest/tests/ajax_test.info
index d2691e8d8e63ea32352227f95515b9e4cbe31617..2bff63efe4f7319650a0d7e60608d4b3bde328f0 100644
--- a/modules/simpletest/tests/ajax_test.info
+++ b/modules/simpletest/tests/ajax_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = ajax_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/ajax_test.module b/modules/simpletest/tests/ajax_test.module
index 46d36b02e844c68a3ceb33f3d55b1365e7462d39..21762bdac558bc3f15cc247089de3eb9129c6bbe 100644
--- a/modules/simpletest/tests/ajax_test.module
+++ b/modules/simpletest/tests/ajax_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: ajax_test.module,v 1.3 2010/03/13 06:55:50 dries Exp $
+// $Id: ajax_test.module,v 1.4 2010/10/04 17:46:01 dries Exp $
 
 /**
  * @file
@@ -28,21 +28,15 @@ function ajax_test_menu() {
 }
 
 /**
- * Menu callback; Returns $_GET['commands'] suitable for use by ajax_deliver().
+ * Menu callback; Return an element suitable for use by ajax_deliver().
  *
  * Additionally ensures that ajax_render() incorporates JavaScript settings
- * by invoking drupal_add_js() with a dummy setting.
+ * generated during the page request by invoking drupal_add_js() with a dummy
+ * setting.
  */
 function ajax_test_render() {
-  // Prepare AJAX commands.
-  $commands = array();
-  if (!empty($_GET['commands'])) {
-    $commands = $_GET['commands'];
-  }
-  // Add a dummy JS setting.
   drupal_add_js(array('ajax' => 'test'), 'setting');
-
-  return array('#type' => 'ajax', '#commands' => $commands);
+  return array('#type' => 'ajax', '#commands' => array());
 }
 
 /**
diff --git a/modules/simpletest/tests/batch.test b/modules/simpletest/tests/batch.test
index 0e0ee2e5b54c847a67ad7433a860887318f4957c..1511209ee0434266ace9f63e267a1bbe72989ec3 100644
--- a/modules/simpletest/tests/batch.test
+++ b/modules/simpletest/tests/batch.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: batch.test,v 1.14 2010/09/04 13:33:53 dries Exp $
+// $Id: batch.test,v 1.15 2010/10/03 02:42:25 dries Exp $
 
 /**
  * @file
@@ -27,7 +27,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
    */
   function testBatchNoForm() {
     // Displaying the page triggers batch 1.
-    $this->drupalGet('batch_test/no_form');
+    $this->drupalGet('batch-test/no-form');
     $this->assertBatchMessages($this->_resultMessages(1), t('Batch for step 2 performed successfully.'));
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), t('Execution order was correct.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
@@ -39,34 +39,34 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
   function testBatchForm() {
     // Batch 0: no operation.
     $edit = array('batch' => 'batch_0');
-    $this->drupalPost('batch_test/simple', $edit, 'Submit');
+    $this->drupalPost('batch-test/simple', $edit, 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_0'), t('Batch with no operation performed successfully.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
 
     // Batch 1: several simple operations.
     $edit = array('batch' => 'batch_1');
-    $this->drupalPost('batch_test/simple', $edit, 'Submit');
+    $this->drupalPost('batch-test/simple', $edit, 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_1'), t('Batch with simple operations performed successfully.'));
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_1'), t('Execution order was correct.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
 
     // Batch 2: one multistep operation.
     $edit = array('batch' => 'batch_2');
-    $this->drupalPost('batch_test/simple', $edit, 'Submit');
+    $this->drupalPost('batch-test/simple', $edit, 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_2'), t('Batch with multistep operation performed successfully.'));
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_2'), t('Execution order was correct.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
 
     // Batch 3: simple + multistep combined.
     $edit = array('batch' => 'batch_3');
-    $this->drupalPost('batch_test/simple', $edit, 'Submit');
+    $this->drupalPost('batch-test/simple', $edit, 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_3'), t('Batch with simple and multistep operations performed successfully.'));
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_3'), t('Execution order was correct.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
 
     // Batch 4: nested batch.
     $edit = array('batch' => 'batch_4');
-    $this->drupalPost('batch_test/simple', $edit, 'Submit');
+    $this->drupalPost('batch-test/simple', $edit, 'Submit');
     $this->assertBatchMessages($this->_resultMessages('batch_4'), t('Nested batch performed successfully.'));
     $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_4'), t('Execution order was correct.'));
     $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
@@ -76,7 +76,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
    * Test batches defined in a multistep form.
    */
   function testBatchFormMultistep() {
-    $this->drupalGet('batch_test/multistep');
+    $this->drupalGet('batch-test/multistep');
     $this->assertText('step 1', t('Form is displayed in step 1.'));
 
     // First step triggers batch 1.
@@ -100,7 +100,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
     // handlers. Each submit handler modify the submitted 'value'.
     $value = rand(0, 255);
     $edit = array('value' => $value);
-    $this->drupalPost('batch_test/chained', $edit, 'Submit');
+    $this->drupalPost('batch-test/chained', $edit, 'Submit');
     // Check that result messages are present and in the correct order.
     $this->assertBatchMessages($this->_resultMessages('chained'), t('Batches defined in separate submit handlers performed successfully.'));
     // The stack contains execution order of batch callbacks and submit
@@ -118,7 +118,7 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
     // Batches 1, 2 and 3 are triggered in sequence by different submit
     // handlers. Each submit handler modify the submitted 'value'.
     $value = rand(0, 255);
-    $this->drupalGet('batch_test/programmatic/' . $value);
+    $this->drupalGet('batch-test/programmatic/' . $value);
     // Check that result messages are present and in the correct order.
     $this->assertBatchMessages($this->_resultMessages('chained'), t('Batches defined in separate submit handlers performed successfully.'));
     // The stack contains execution order of batch callbacks and submit
@@ -134,10 +134,23 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
     // Displaying the page triggers a batch that programmatically submits a
     // form.
     $value = rand(0, 255);
-    $this->drupalGet('batch_test/nested_programmatic/' . $value);
+    $this->drupalGet('batch-test/nested-programmatic/' . $value);
     $this->assertEqual(batch_test_stack(), array('mock form submitted with value = ' . $value), t('drupal_form_submit() ran successfully within a batch operation.'));
   }
 
+  /**
+   * Test batches that return $context['finished'] > 1 do in fact complete.
+   * See http://drupal.org/node/600836
+   */
+  function testBatchLargePercentage() {
+    // Displaying the page triggers batch 5.
+    $this->drupalGet('batch-test/large-percentage');
+    $this->assertBatchMessages($this->_resultMessages(1), t('Batch for step 2 performed successfully.'));
+    $this->assertEqual(batch_test_stack(), $this->_resultStack('batch_5'), t('Execution order was correct.'));
+    $this->assertText('Redirection successful.', t('Redirection after batch execution is correct.'));
+  }
+
+
   /**
    * Will trigger a pass if the texts were found in order in the raw content.
    *
@@ -197,6 +210,12 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
         $stack = array_merge($stack, $this->_resultStack('batch_2'));
         break;
 
+      case 'batch_5':
+        for ($i = 1; $i <= 10; $i++) {
+          $stack[] = "op 5 id $i";
+        }
+        break;
+
       case 'chained':
         $stack[] = 'submit handler 1';
         $stack[] = 'value = ' . $value;
@@ -242,6 +261,10 @@ class BatchProcessingTestCase extends DrupalWebTestCase {
         $messages = array_merge($messages, $this->_resultMessages('batch_2'));
         break;
 
+      case 'batch_5':
+        $messages[] = 'results for batch 5<br />op 1: processed 10 elements. $context[\'finished\'] > 1 returned from batch process, with success.';
+        break;
+
       case 'chained':
         $messages = array_merge($messages, $this->_resultMessages('batch_1'));
         $messages = array_merge($messages, $this->_resultMessages('batch_2'));
@@ -280,7 +303,7 @@ class BatchPageTestCase extends DrupalWebTestCase {
     // theme that was used during batch execution (which the batch callback
     // function saved as a variable) matches the theme used on the
     // administrative page.
-    $this->drupalGet('admin/batch_test/test_theme');
+    $this->drupalGet('admin/batch-test/test-theme');
     // The stack should contain the name of the the used on the progress page.
     $this->assertEqual(batch_test_stack(), array('seven'), t('A progressive batch correctly uses the theme of the page that started the batch.'));
   }
diff --git a/modules/simpletest/tests/batch_test.callbacks.inc b/modules/simpletest/tests/batch_test.callbacks.inc
index a96c133a9a5e2e0b290c6f68bf93ee16e4f823b1..40308c73ae7e4acb5c46013ec347463d7f4351b5 100644
--- a/modules/simpletest/tests/batch_test.callbacks.inc
+++ b/modules/simpletest/tests/batch_test.callbacks.inc
@@ -1,6 +1,6 @@
 <?php
 
-// $Id: batch_test.callbacks.inc,v 1.1 2010/01/08 06:36:34 webchick Exp $
+// $Id: batch_test.callbacks.inc,v 1.2 2010/10/03 02:42:25 dries Exp $
 
 /**
  * @file
@@ -12,6 +12,7 @@
  */
 function _batch_test_callback_1($id, $sleep, &$context) {
   // No-op, but ensure the batch take a couple iterations.
+  // Batch needs time to run for the test, so sleep a bit.
   usleep($sleep);
   // Track execution, and store some result for post-processing in the
   // 'finished' callback.
@@ -33,6 +34,7 @@ function _batch_test_callback_2($start, $total, $sleep, &$context) {
   $limit = 5;
   for ($i = 0; $i < $limit && $context['sandbox']['count'] < $total; $i++) {
     // No-op, but ensure the batch take a couple iterations.
+    // Batch needs time to run for the test, so sleep a bit.
     usleep($sleep);
     // Track execution, and store some result for post-processing in the
     // 'finished' callback.
@@ -51,6 +53,21 @@ function _batch_test_callback_2($start, $total, $sleep, &$context) {
   }
 }
 
+/**
+ * Simple batch operation.
+ */
+function _batch_test_callback_5($id, $sleep, &$context) {
+  // No-op, but ensure the batch take a couple iterations.
+  // Batch needs time to run for the test, so sleep a bit.
+  usleep($sleep);
+  // Track execution, and store some result for post-processing in the
+  // 'finished' callback.
+  batch_test_stack("op 5 id $id");
+  $context['results'][5][] = $id;
+  // This test is to test finished > 1
+  $context['finished'] = 3.14;
+}
+
 /**
  * Batch operation setting up its own batch.
  */
@@ -116,3 +133,10 @@ function _batch_test_finished_3($success, $results, $operations) {
 function _batch_test_finished_4($success, $results, $operations) {
   _batch_test_finished_helper(4, $success, $results, $operations);
 }
+
+/**
+ * 'finished' callback for batch 5.
+ */
+function _batch_test_finished_5($success, $results, $operations) {
+  _batch_test_finished_helper(5, $success, $results, $operations);
+}
diff --git a/modules/simpletest/tests/batch_test.info b/modules/simpletest/tests/batch_test.info
index cf5a8b3b83fe45d5279bb45b6254aa085383d84f..4ed7d68cffdd1e51d930cf84af45a0ce8f7140fa 100644
--- a/modules/simpletest/tests/batch_test.info
+++ b/modules/simpletest/tests/batch_test.info
@@ -8,8 +8,8 @@ files[] = batch_test.module
 files[] = batch_test.callbacks.inc
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/batch_test.module b/modules/simpletest/tests/batch_test.module
index 14e793122e102fac32571a7c8834f13444b0fe09..c8710df456ae19c6fbb00f3dc71eedbf66d7e5ab 100644
--- a/modules/simpletest/tests/batch_test.module
+++ b/modules/simpletest/tests/batch_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: batch_test.module,v 1.1 2010/01/08 06:36:34 webchick Exp $
+// $Id: batch_test.module,v 1.3 2010/10/03 02:42:25 dries Exp $
 
 /**
  * @file
@@ -12,20 +12,20 @@
 function batch_test_menu() {
   $items = array();
 
-  $items['batch_test'] = array(
+  $items['batch-test'] = array(
     'title' => 'Batch test',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('batch_test_simple_form'),
     'access callback' => TRUE,
   );
   // Simple form: one submit handler, setting a batch.
-  $items['batch_test/simple'] = array(
+  $items['batch-test/simple'] = array(
     'title' => 'Simple',
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => 0,
   );
   // Multistep form: two steps, each setting a batch.
-  $items['batch_test/multistep'] = array(
+  $items['batch-test/multistep'] = array(
     'title' => 'Multistep',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('batch_test_multistep_form'),
@@ -34,7 +34,7 @@ function batch_test_menu() {
     'weight' => 1,
   );
   // Chained form: four submit handlers, several of which set a batch.
-  $items['batch_test/chained'] = array(
+  $items['batch-test/chained'] = array(
     'title' => 'Chained',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('batch_test_chained_form'),
@@ -44,7 +44,7 @@ function batch_test_menu() {
   );
   // Programmatic form: the page submits the 'Chained' form through
   // drupal_form_submit().
-  $items['batch_test/programmatic'] = array(
+  $items['batch-test/programmatic'] = array(
     'title' => 'Programmatic',
     'page callback' => 'batch_test_programmatic',
     'access callback' => TRUE,
@@ -52,32 +52,39 @@ function batch_test_menu() {
     'weight' => 3,
   );
   // No form: fire a batch simply by accessing a page.
-  $items['batch_test/no_form'] = array(
+  $items['batch-test/no-form'] = array(
     'title' => 'Simple page',
     'page callback' => 'batch_test_no_form',
     'access callback' => TRUE,
     'type' => MENU_LOCAL_TASK,
     'weight' => 4,
   );
+  // No form: fire a batch; return > 100% complete
+  $items['batch-test/large-percentage'] = array(
+    'title' => 'Simple page with batch over 100% complete',
+    'page callback' => 'batch_test_large_percentage',
+    'access callback' => TRUE,
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 5,
+  );
   // Tests programmatic form submission within a batch operation.
-  $items['batch_test/nested_programmatic'] = array(
+  $items['batch-test/nested-programmatic'] = array(
     'title' => 'Nested programmatic',
     'page callback' => 'batch_test_nested_drupal_form_submit',
     'access callback' => TRUE,
     'type' => MENU_LOCAL_TASK,
-    'weight' => 5,
+    'weight' => 6,
   );
   // Landing page to test redirects.
-  $items['batch_test/redirect'] = array(
+  $items['batch-test/redirect'] = array(
     'title' => 'Redirect',
     'page callback' => 'batch_test_redirect_page',
     'access callback' => TRUE,
     'type' => MENU_LOCAL_TASK,
-    'weight' => 6,
+    'weight' => 7,
   );
-  //
   // This item lives under 'admin' so that the page uses the admin theme.
-  $items['admin/batch_test/test_theme'] = array(
+  $items['admin/batch-test/test-theme'] = array(
     'page callback' => 'batch_test_theme_batch',
     'access callback' => TRUE,
     'type' => MENU_CALLBACK,
@@ -118,7 +125,7 @@ function batch_test_simple_form_submit($form, &$form_state) {
   $function = '_batch_test_' . $form_state['values']['batch'];
   batch_set($function());
 
-  $form_state['redirect'] = 'batch_test/redirect';
+  $form_state['redirect'] = 'batch-test/redirect';
 }
 
 
@@ -162,7 +169,7 @@ function batch_test_multistep_form_submit($form, &$form_state) {
   }
 
   // This will only be effective on the last step.
-  $form_state['redirect'] = 'batch_test/redirect';
+  $form_state['redirect'] = 'batch-test/redirect';
 }
 
 /**
@@ -244,7 +251,7 @@ function batch_test_chained_form_submit_4($form, &$form_state) {
   batch_set(_batch_test_batch_3());
 
   // This is the redirect that should prevail.
-  $form_state['redirect'] = 'batch_test/redirect';
+  $form_state['redirect'] = 'batch-test/redirect';
 }
 
 /**
@@ -267,7 +274,7 @@ function batch_test_nested_drupal_form_submit($value = 1) {
     array('_batch_test_nested_drupal_form_submit_callback', array($value)),
   );
   batch_set($batch);
-  batch_process('batch_test/redirect');
+  batch_process('batch-test/redirect');
 }
 
 /**
@@ -307,7 +314,17 @@ function batch_test_no_form() {
   batch_test_stack(NULL, TRUE);
 
   batch_set(_batch_test_batch_1());
-  batch_process('batch_test/redirect');
+  batch_process('batch-test/redirect');
+}
+
+/**
+ * Menu callback: fire a batch process without a form submission.
+ */
+function batch_test_large_percentage() {
+  batch_test_stack(NULL, TRUE);
+
+  batch_set(_batch_test_batch_5());
+  batch_process('batch-test/redirect');
 }
 
 /**
@@ -432,6 +449,28 @@ function _batch_test_batch_4() {
   return $batch;
 }
 
+/**
+ * Batch 5: repeats a simple operation.
+ *
+ * Operations: op 1 from 1 to 10.
+ */
+function _batch_test_batch_5() {
+  // Ensure the batch takes at least two iterations.
+  $total = 10;
+  $sleep = (1000000 / $total) * 2;
+
+  $operations = array();
+  for ($i = 1; $i <= $total; $i++) {
+    $operations[] = array('_batch_test_callback_5', array($i, $sleep));
+  }
+  $batch = array(
+    'operations' => $operations,
+    'finished' => '_batch_test_finished_5',
+    'file' => drupal_get_path('module', 'batch_test'). '/batch_test.callbacks.inc',
+  );
+  return $batch;
+}
+
 /**
  * Menu callback: run a batch for testing theme used on the progress page.
  */
@@ -443,7 +482,7 @@ function batch_test_theme_batch() {
     ),
   );
   batch_set($batch);
-  batch_process('batch_test/redirect');
+  batch_process('batch-test/redirect');
 }
 
 /**
@@ -466,7 +505,7 @@ function batch_test_stack($data = NULL, $reset = FALSE) {
   if ($reset) {
     variable_del('batch_test_stack');
   }
-  if (is_null($data)) {
+  if (!isset($data)) {
     return variable_get('batch_test_stack', array());
   }
   $stack = variable_get('batch_test_stack', array());
diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test
index 93ec55a9bfa5c4e93581ed584f8fd08f585e25df..61e8e05c3fb252a114de8336bbb38dd0b331810c 100644
--- a/modules/simpletest/tests/common.test
+++ b/modules/simpletest/tests/common.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: common.test,v 1.125 2010/09/09 20:22:00 dries Exp $
+// $Id: common.test,v 1.129 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @file
@@ -655,7 +655,7 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
   function testRenderInlinePreprocess() {
     $css = 'body { padding: 0px; }';
     $css_preprocessed = '<style type="text/css" media="all">' . drupal_load_stylesheet_content($css, TRUE) . '</style>';
-    drupal_add_css($css, array('type' => 'inline', 'preprocess' => TRUE));
+    drupal_add_css($css, array('type' => 'inline'));
     $styles = drupal_get_css();
     $this->assertEqual(trim($styles), $css_preprocessed, t('Rendering preprocessed inline CSS adds it to the page.'));
   }
@@ -665,7 +665,7 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
    */
   function testRenderInlineNoPreprocess() {
     $css = 'body { padding: 0px; }';
-    drupal_add_css($css, array('type' => 'inline'));
+    drupal_add_css($css, array('type' => 'inline', 'preprocess' => FALSE));
     $styles = drupal_get_css();
     $this->assertTrue(strpos($styles, $css) > 0, t('Rendering non-preprocessed inline CSS adds it to the page.'));
   }
@@ -675,7 +675,9 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
    */
   function testRenderInlineFullPage() {
     $css = 'body { font-size: 254px; }';
-    $expected = $css;
+    // Inline CSS is minified unless 'preprocess' => FALSE is passed as a
+    // drupal_add_css() option.
+    $expected = 'body{font-size:254px;}';
 
     // Create a node, using the PHP filter that tests drupal_add_css().
     $php_format_id = db_query_range('SELECT format FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'PHP code'))->fetchField();
@@ -706,14 +708,14 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
     drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css');
     // A few system CSS files, ordered in a strange way.
     $system_path = drupal_get_path('module', 'system');
-    drupal_add_css($system_path . '/system-behavior.css', array('weight' => CSS_SYSTEM));
-    drupal_add_css($system_path . '/system.css', array('weight' => CSS_SYSTEM - 10));
-    drupal_add_css($system_path . '/system-menus.css', array('weight' => CSS_SYSTEM));
+    drupal_add_css($system_path . '/system.menus.css', array('group' => CSS_SYSTEM));
+    drupal_add_css($system_path . '/system.base.css', array('group' => CSS_SYSTEM, 'weight' => -10));
+    drupal_add_css($system_path . '/system.theme.css', array('group' => CSS_SYSTEM));
 
     $expected = array(
-      $system_path . '/system.css',
-      $system_path . '/system-behavior.css',
-      $system_path . '/system-menus.css',
+      $system_path . '/system.base.css',
+      $system_path . '/system.menus.css',
+      $system_path . '/system.theme.css',
       drupal_get_path('module', 'simpletest') . '/simpletest.css',
     );
 
@@ -735,35 +737,39 @@ class CascadingStylesheetsTestCase extends DrupalWebTestCase {
    * Test CSS override.
    */
   function testRenderOverride() {
-    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
-    drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
+    $system = drupal_get_path('module', 'system');
+    $simpletest = drupal_get_path('module', 'simpletest');
+
+    drupal_add_css($system . '/system.base.css');
+    drupal_add_css($simpletest . '/tests/system.base.css');
 
     // The dummy stylesheet should be the only one included.
     $styles = drupal_get_css();
-    $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') !== FALSE, t('The overriding CSS file is output.'));
-    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') === FALSE, t('The overriden CSS file is not output.'));
+    $this->assert(strpos($styles, $simpletest . '/tests/system.base.css') !== FALSE, t('The overriding CSS file is output.'));
+    $this->assert(strpos($styles, $system . '/system.base.css') === FALSE, t('The overridden CSS file is not output.'));
 
-    drupal_add_css(drupal_get_path('module', 'simpletest') . '/tests/system.css');
-    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
+    drupal_add_css($simpletest . '/tests/system.base.css');
+    drupal_add_css($system . '/system.base.css');
 
     // The standard stylesheet should be the only one included.
     $styles = drupal_get_css();
-    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system.css') !== FALSE, t('The overriding CSS file is output.'));
-    $this->assert(strpos($styles, drupal_get_path('module', 'simpletest') . '/tests/system.css') === FALSE, t('The overriden CSS file is not output.'));
+    $this->assert(strpos($styles, $system . '/system.base.css') !== FALSE, t('The overriding CSS file is output.'));
+    $this->assert(strpos($styles, $simpletest . '/tests/system.base.css') === FALSE, t('The overridden CSS file is not output.'));
   }
 
   /**
    * Tests Locale module's CSS Alter to include RTL overrides.
    */
   function testAlter() {
-    // Switch the language to a right to left language and add system.css.
+    // Switch the language to a right to left language and add system.base.css.
     global $language;
     $language->direction = LANGUAGE_RTL;
-    drupal_add_css(drupal_get_path('module', 'system') . '/system.css');
+    $path = drupal_get_path('module', 'system');
+    drupal_add_css($path . '/system.base.css');
 
-    // Check to see if system-rtl.css was also added.
+    // Check to see if system.base-rtl.css was also added.
     $styles = drupal_get_css();
-    $this->assert(strpos($styles, drupal_get_path('module', 'system') . '/system-rtl.css') !== FALSE, t('CSS is alterable as right to left overrides are added.'));
+    $this->assert(strpos($styles, $path . '/system.base-rtl.css') !== FALSE, t('CSS is alterable as right to left overrides are added.'));
 
     // Change the language back to left to right.
     $language->direction = LANGUAGE_LTR;
@@ -1237,12 +1243,20 @@ class JavaScriptTestCase extends DrupalWebTestCase {
     $this->assertFalse($javascript['misc/collapse.js']['preprocess'], t('Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.'));
   }
 
+  /**
+   * Test adding a JavaScript file with a different group.
+   */
+  function testDifferentGroup() {
+    $javascript = drupal_add_js('misc/collapse.js', array('group' => JS_THEME));
+    $this->assertEqual($javascript['misc/collapse.js']['group'], JS_THEME, t('Adding a JavaScript file with a different group caches the given group.'));
+  }
+
   /**
    * Test adding a JavaScript file with a different weight.
    */
   function testDifferentWeight() {
-    $javascript = drupal_add_js('misc/collapse.js', array('weight' => JS_THEME));
-    $this->assertEqual($javascript['misc/collapse.js']['weight'], JS_THEME, t('Adding a JavaScript file with a different weight caches the given weight.'));
+    $javascript = drupal_add_js('misc/collapse.js', array('weight' => 2));
+    $this->assertEqual($javascript['misc/collapse.js']['weight'], 2, t('Adding a JavaScript file with a different weight caches the given weight.'));
   }
 
   /**
@@ -1291,7 +1305,10 @@ class JavaScriptTestCase extends DrupalWebTestCase {
    * Test rendering the JavaScript with a file's weight above jQuery's.
    */
   function testRenderDifferentWeight() {
-    drupal_add_js('misc/collapse.js', array('weight' => JS_LIBRARY - 21));
+    // JavaScript files are sorted first by group, then by the 'every_page'
+    // flag, then by weight (see drupal_sort_css_js()), so to test the effect of
+    // weight, we need the other two options to be the same.
+    drupal_add_js('misc/collapse.js', array('group' => JS_LIBRARY, 'every_page' => TRUE, 'weight' => -21));
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'misc/collapse.js') < strpos($javascript, 'misc/jquery.js'), t('Rendering a JavaScript file above jQuery.'));
   }
@@ -1304,7 +1321,7 @@ class JavaScriptTestCase extends DrupalWebTestCase {
   function testAlter() {
     // Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest.
     drupal_add_js('misc/tableselect.js');
-    drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => JS_THEME));
+    drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => 9999));
 
     // Render the JavaScript, testing if simpletest.js was altered to be before
     // tableselect.js. See simpletest_js_alter() to see where this alteration
@@ -1389,11 +1406,11 @@ class JavaScriptTestCase extends DrupalWebTestCase {
 /**
  * Tests for drupal_render().
  */
-class DrupalRenderUnitTestCase extends DrupalWebTestCase {
+class DrupalRenderTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
-      'name' => 'Drupal render',
-      'description' => 'Performs unit tests on drupal_render().',
+      'name' => 'drupal_render()',
+      'description' => 'Performs functional tests on drupal_render().',
       'group' => 'System',
     );
   }
@@ -1470,6 +1487,132 @@ class DrupalRenderUnitTestCase extends DrupalWebTestCase {
     // Test that passing arguments to the theme function works.
     $this->assertEqual(drupal_render($element), $element['#foo'] . $element['#bar'], 'Passing arguments to theme functions works');
   }
+
+  /**
+   * Test rendering form elements without passing through form_builder().
+   */
+  function testDrupalRenderFormElements() {
+    // Define a series of form elements.
+    $element = array(
+      '#type' => 'button',
+      '#value' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'submit'));
+
+    $element = array(
+      '#type' => 'textfield',
+      '#title' => $this->randomName(),
+      '#value' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'text'));
+
+    $element = array(
+      '#type' => 'password',
+      '#title' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'password'));
+
+    $element = array(
+      '#type' => 'textarea',
+      '#title' => $this->randomName(),
+      '#value' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//textarea');
+
+    $element = array(
+      '#type' => 'radio',
+      '#title' => $this->randomName(),
+      '#value' => FALSE,
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'radio'));
+
+    $element = array(
+      '#type' => 'checkbox',
+      '#title' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'checkbox'));
+
+    $element = array(
+      '#type' => 'select',
+      '#title' => $this->randomName(),
+      '#options' => array(
+        0 => $this->randomName(),
+        1 => $this->randomName(),
+      ),
+    );
+    $this->assertRenderedElement($element, '//select');
+
+    $element = array(
+      '#type' => 'file',
+      '#title' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'file'));
+
+    $element = array(
+      '#type' => 'item',
+      '#title' => $this->randomName(),
+      '#markup' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//div[contains(@class, :class) and contains(., :markup)]/label[contains(., :label)]', array(
+      ':class' => 'form-type-item',
+      ':markup' => $element['#markup'],
+      ':label' => $element['#title'],
+    ));
+
+    $element = array(
+      '#type' => 'hidden',
+      '#title' => $this->randomName(),
+      '#value' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//input[@type=:type]', array(':type' => 'hidden'));
+
+    $element = array(
+      '#type' => 'link',
+      '#title' => $this->randomName(),
+      '#href' => $this->randomName(),
+      '#options' => array(
+        'absolute' => TRUE,
+      ),
+    );
+    $this->assertRenderedElement($element, '//a[@href=:href and contains(., :title)]', array(
+      ':href' => url($element['#href'], array('absolute' => TRUE)),
+      ':title' => $element['#title'],
+    ));
+
+    $element = array(
+      '#type' => 'fieldset',
+      '#title' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//fieldset/legend[contains(., :title)]', array(
+      ':title' => $element['#title'],
+    ));
+
+    $element['item'] = array(
+      '#type' => 'item',
+      '#title' => $this->randomName(),
+      '#markup' => $this->randomName(),
+    );
+    $this->assertRenderedElement($element, '//fieldset/div/div[contains(@class, :class) and contains(., :markup)]', array(
+      ':class' => 'form-type-item',
+      ':markup' => $element['item']['#markup'],
+    ));
+  }
+
+  protected function assertRenderedElement(array $element, $xpath, array $xpath_args = array()) {
+    $original_element = $element;
+    $this->drupalSetContent(drupal_render($element));
+    $this->verbose('<pre>' .  check_plain(var_export($original_element, TRUE)) . '</pre>'
+      . '<pre>' .  check_plain(var_export($element, TRUE)) . '</pre>'
+      . '<hr />' . $this->drupalGetContent()
+    );
+
+    // @see DrupalWebTestCase::xpath()
+    $xpath = $this->buildXPathQuery($xpath, $xpath_args);
+    $element += array('#value' => NULL);
+    $this->assertFieldByXPath($xpath, $element['#value'], t('#type @type was properly rendered.', array(
+      '@type' => var_export($element['#type'], TRUE),
+    )));
+  }
 }
 
 /**
@@ -1759,14 +1902,34 @@ class DrupalErrorCollectionUnitTest extends DrupalWebTestCase {
     }
   }
 
+  /**
+   * Error handler that collects errors in an array.
+   *
+   * This test class is trying to verify that simpletest correctly sees errors
+   * and warnings. However, it can't generate errors and warnings that
+   * propagate up to the testing framework itself, or these tests would always
+   * fail. So, this special copy of error() doesn't propagate the errors up
+   * the class hierarchy. It just stuffs them into a protected collectedErrors
+   * array for various assertions to inspect.
+   */
   protected function error($message = '', $group = 'Other', array $caller = NULL) {
-    // This function overiddes DrupalWebTestCase::error(). We collect an error...
-    $this->collectedErrors[] = array(
-      'message' => $message,
-      'group' => $group,
-      'caller' => $caller
-    );
-    // ... and ignore it.
+    // Due to a WTF elsewhere, simpletest treats debug() and verbose()
+    // messages as if they were an 'error'. But, we don't want to collect
+    // those here. This function just wants to collect the real errors (PHP
+    // notices, PHP fatal errors, etc.), and let all the 'errors' from the
+    // 'User notice' group bubble up to the parent classes to be handled (and
+    // eventually displayed) as normal.
+    if ($group == 'User notice') {
+      parent::error($message, $group, $caller);
+    }
+    // Everything else should be collected but not propagated.
+    else {
+      $this->collectedErrors[] = array(
+        'message' => $message,
+        'group' => $group,
+        'caller' => $caller
+      );
+    }
   }
 
   /**
diff --git a/modules/simpletest/tests/common_test.css b/modules/simpletest/tests/common_test.css
new file mode 100644
index 0000000000000000000000000000000000000000..0bbfdf24845049b289db5f91195d779e21dfb39e
--- /dev/null
+++ b/modules/simpletest/tests/common_test.css
@@ -0,0 +1,3 @@
+/* $Id: common_test.css,v 1.1 2010/10/03 05:11:16 webchick Exp $ */
+
+/* This file is for testing CSS file inclusion, no contents are necessary. */
diff --git a/modules/simpletest/tests/common_test.info b/modules/simpletest/tests/common_test.info
index 8996c0b833371c7bd86d055421e93cd6a30ab925..25091744c9633664395208aef272906ead3d3cc4 100644
--- a/modules/simpletest/tests/common_test.info
+++ b/modules/simpletest/tests/common_test.info
@@ -9,8 +9,8 @@ stylesheets[all][] = common_test.css
 stylesheets[print][] = common_test.print.css
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/common_test.print.css b/modules/simpletest/tests/common_test.print.css
new file mode 100644
index 0000000000000000000000000000000000000000..2528fafaf0fefba848dac2930a6899b001037c46
--- /dev/null
+++ b/modules/simpletest/tests/common_test.print.css
@@ -0,0 +1,3 @@
+/* $Id: common_test.print.css,v 1.1 2010/10/03 05:11:16 webchick Exp $ */
+
+/* This file is for testing CSS file inclusion, no contents are necessary. */
diff --git a/modules/simpletest/tests/database_test.info b/modules/simpletest/tests/database_test.info
index 81a4af64b3913160738fd0bf9bd39b09bba28a21..b3426f746daadd3f737f2dc20b68de221718b778 100644
--- a/modules/simpletest/tests/database_test.info
+++ b/modules/simpletest/tests/database_test.info
@@ -8,8 +8,8 @@ files[] = database_test.install
 version = VERSION
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index 38c1fa9f600d6ca0250486bd36d3577a7762d356..5418d6ab8c238176e3f743c10f65345ac843a27d 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: database_test.test,v 1.101 2010/09/09 23:18:30 webchick Exp $
+// $Id: database_test.test,v 1.103 2010/09/24 02:05:55 dries Exp $
 
 /**
  * Dummy class for fetching into a class.
@@ -1093,18 +1093,15 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
   }
 
   /**
-   * Confirm that we can merge-update a record successfully, with exclusion.
+   * Confirm that we can merge-update a record successfully, with different insert and update.
    */
   function testMergeUpdateExcept() {
     $num_records_before = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
 
     db_merge('test_people')
       ->key(array('job' => 'Speaker'))
-      ->fields(array(
-        'age' => 31,
-        'name' => 'Tiffany',
-      ))
-      ->updateExcept('age')
+      ->insertFields(array('age' => 31))
+      ->updateFields(array('name' => 'Tiffany'))
       ->execute();
 
     $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
@@ -1124,11 +1121,13 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
 
     db_merge('test_people')
       ->key(array('job' => 'Speaker'))
-      ->fields(array(
+      ->insertFields(array(
         'age' => 31,
         'name' => 'Tiffany',
       ))
-      ->update(array('name' => 'Joe'))
+      ->updateFields(array(
+        'name' => 'Joe',
+      ))
       ->execute();
 
     $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
@@ -1155,10 +1154,8 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
     // which is what is supposed to happen.
     db_merge('test_people')
       ->key(array('job' => 'Speaker'))
-      ->fields(array(
-        'age' => 31,
-        'name' => 'Tiffany',
-      ))
+      ->fields(array('name' => 'Tiffany'))
+      ->insertFields(array('age' => 31))
       ->expression('age', 'age + :age', array(':age' => 4))
       ->execute();
 
@@ -1210,8 +1207,7 @@ class DatabaseMergeTestCase extends DatabaseTestCase {
 
     db_merge('test_people')
       ->key(array('job' => 'Speaker'))
-      ->fields(array('age' => 31))
-      ->updateExcept(array('age'))
+      ->insertFields(array('age' => 31))
       ->execute();
 
     $num_records_after = db_query('SELECT COUNT(*) FROM {test_people}')->fetchField();
@@ -2091,7 +2087,6 @@ class DatabaseSelectComplexTestCase2 extends DatabaseTestCase {
     $str = (string) $query;
 
     // Verify that the string only has one copy of condition placeholder 0.
-    debug($str);
     $pos = strpos($str, 'db_condition_placeholder_0', 0);
     $pos2 = strpos($str, 'db_condition_placeholder_0', $pos + 1);
     $this->assertFalse($pos2, "Condition placeholder is not repeated");
@@ -2216,13 +2211,13 @@ class DatabaseSelectPagerDefaultTestCase extends DatabaseTestCase {
       ->fetchCol();
     $this->assertEqual($ages, array('George', 'Ringo'), t('Pager query with having expression returned the correct ages.'));
   }
-  
+
   /**
   * Confirm that every pager gets a valid non-overlaping element ID.
   */
   function testElementNumbers() {
     $_GET['page'] = '3, 2, 1, 0';
-    
+
     $name = db_select('test', 't')->extend('PagerDefault')
       ->element(2)
       ->fields('t', array('name'))
@@ -2231,7 +2226,7 @@ class DatabaseSelectPagerDefaultTestCase extends DatabaseTestCase {
       ->execute()
       ->fetchField();
     $this->assertEqual($name, 'Paul', t('Pager query #1 with a specified element ID returned the correct results.'));
-    
+
     // Setting an element smaller than the previous one
     // should not overwrite the pager $maxElement with a smaller value.
     $name = db_select('test', 't')->extend('PagerDefault')
@@ -2242,7 +2237,7 @@ class DatabaseSelectPagerDefaultTestCase extends DatabaseTestCase {
       ->execute()
       ->fetchField();
     $this->assertEqual($name, 'George', t('Pager query #2 with a specified element ID returned the correct results.'));
-  
+
     $name = db_select('test', 't')->extend('PagerDefault')
       ->fields('t', array('name'))
       ->orderBy('age')
@@ -2250,7 +2245,7 @@ class DatabaseSelectPagerDefaultTestCase extends DatabaseTestCase {
       ->execute()
       ->fetchField();
     $this->assertEqual($name, 'John', t('Pager query #3 with a generated element ID returned the correct results.'));
-    
+
     unset($_GET['page']);
   }
 }
diff --git a/modules/simpletest/tests/entity_cache_test.info b/modules/simpletest/tests/entity_cache_test.info
index 1cfdb47107dff74b8ee450e6ed587492bd1f1d95..b34ccedc81cf686962e23662df590bef7f87f899 100644
--- a/modules/simpletest/tests/entity_cache_test.info
+++ b/modules/simpletest/tests/entity_cache_test.info
@@ -8,8 +8,8 @@ files[] = entity_cache_test.module
 dependencies[] = entity_cache_test_dependency
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/entity_cache_test_dependency.info b/modules/simpletest/tests/entity_cache_test_dependency.info
index bab6ea2206aa1d2e21b8686eb1ff7e3f029d63f3..d20d42503d15c4986cfca3f0ff9a85b72165936e 100644
--- a/modules/simpletest/tests/entity_cache_test_dependency.info
+++ b/modules/simpletest/tests/entity_cache_test_dependency.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = entity_cache_test_dependency.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/entity_query.test b/modules/simpletest/tests/entity_query.test
index 638a3fb72b5dcb70f52153c3e925a36c177e0328..da76b692dcad08c6875ddfc3bdfa53d3a06e0c5a 100644
--- a/modules/simpletest/tests/entity_query.test
+++ b/modules/simpletest/tests/entity_query.test
@@ -1,6 +1,6 @@
 <?php
 
-// $Id: entity_query.test,v 1.11 2010/09/13 06:03:21 webchick Exp $
+// $Id: entity_query.test,v 1.13 2010/10/06 13:57:47 dries Exp $
 
 /**
  * @file
@@ -295,7 +295,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       array('test_entity_bundle_key', 2),
       array('test_entity_bundle_key', 1),
     ), t('Test sort entity entity_id in descending order.'), TRUE);
-    
+
     // Test entity sort by entity_id, with a field condition.
     $query = new EntityFieldQuery();
     $query
@@ -351,7 +351,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       array('test_entity_bundle_key', 2),
       array('test_entity_bundle_key', 1),
     ), t('Test sort entity entity_id property in descending order.'), TRUE);
-    
+
     // Test property sort by entity id, with a field condition.
     $query = new EntityFieldQuery();
     $query
@@ -394,7 +394,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       array('test_entity_bundle_key', 1),
       array('test_entity_bundle_key', 6),
       array('test_entity_bundle_key', 5),
-    ), t('Test sort entity bundle in ascending order.'), TRUE);
+    ), t('Test sort entity bundle in ascending order, property in descending order.'), TRUE);
 
     $query = new EntityFieldQuery();
     $query
@@ -408,38 +408,67 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       array('test_entity_bundle_key', 2),
       array('test_entity_bundle_key', 3),
       array('test_entity_bundle_key', 4),
-    ), t('Test sort entity bundle in descending order.'), TRUE);
-    
+    ), t('Test sort entity bundle in descending order, property in ascending order.'), TRUE);
+
     // Test entity sort by bundle, with a field condition.
     $query = new EntityFieldQuery();
     $query
       ->entityCondition('entity_type', 'test_entity_bundle_key')
       ->fieldCondition($this->fields[0], 'value', 0, '>')
       ->entityOrderBy('bundle', 'ASC')
-      ->propertyOrderBy('ftid', 'ASC');
+      ->propertyOrderBy('ftid', 'DESC');
     $this->assertEntityFieldQuery($query, array(
-      array('test_entity_bundle_key', 1),
-      array('test_entity_bundle_key', 2),
-      array('test_entity_bundle_key', 3),
       array('test_entity_bundle_key', 4),
-      array('test_entity_bundle_key', 5),
+      array('test_entity_bundle_key', 3),
+      array('test_entity_bundle_key', 2),
+      array('test_entity_bundle_key', 1),
       array('test_entity_bundle_key', 6),
-    ), t('Test sort entity bundle in ascending order, with a field condition.'), TRUE);
+      array('test_entity_bundle_key', 5),
+    ), t('Test sort entity bundle in ascending order, property in descending order, with a field condition.'), TRUE);
 
     $query = new EntityFieldQuery();
     $query
       ->entityCondition('entity_type', 'test_entity_bundle_key')
       ->fieldCondition($this->fields[0], 'value', 0, '>')
       ->entityOrderBy('bundle', 'DESC')
-      ->propertyOrderBy('ftid', 'DESC');
+      ->propertyOrderBy('ftid', 'ASC');
     $this->assertEntityFieldQuery($query, array(
-      array('test_entity_bundle_key', 6),
       array('test_entity_bundle_key', 5),
+      array('test_entity_bundle_key', 6),
+      array('test_entity_bundle_key', 1),
+      array('test_entity_bundle_key', 2),
+      array('test_entity_bundle_key', 3),
+      array('test_entity_bundle_key', 4),
+    ), t('Test sort entity bundle in descending order, property in ascending order, with a field condition.'), TRUE);
+
+    // Test entity sort by bundle, field.
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity_bundle_key')
+      ->entityOrderBy('bundle', 'ASC')
+      ->fieldOrderBy($this->fields[0], 'value', 'DESC');
+    $this->assertEntityFieldQuery($query, array(
       array('test_entity_bundle_key', 4),
       array('test_entity_bundle_key', 3),
       array('test_entity_bundle_key', 2),
       array('test_entity_bundle_key', 1),
-    ), t('Test sort entity bundle in descending order, with a field condition.'), TRUE);
+      array('test_entity_bundle_key', 6),
+      array('test_entity_bundle_key', 5),
+    ), t('Test sort entity bundle in ascending order, field in descending order.'), TRUE);
+
+    $query = new EntityFieldQuery();
+    $query
+      ->entityCondition('entity_type', 'test_entity_bundle_key')
+      ->entityOrderBy('bundle', 'DESC')
+      ->fieldOrderBy($this->fields[0], 'value', 'ASC');
+    $this->assertEntityFieldQuery($query, array(
+      array('test_entity_bundle_key', 5),
+      array('test_entity_bundle_key', 6),
+      array('test_entity_bundle_key', 1),
+      array('test_entity_bundle_key', 2),
+      array('test_entity_bundle_key', 3),
+      array('test_entity_bundle_key', 4),
+    ), t('Test sort entity bundle in descending order, field in ascending order.'), TRUE);
 
     // Test entity sort by revision_id.
     $query = new EntityFieldQuery();
@@ -463,7 +492,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
       array('test_entity', 2),
       array('test_entity', 1),
     ), t('Test sort entity revision_id in descending order.'), TRUE);
-    
+
     // Test entity sort by revision_id, with a field condition.
     $query = new EntityFieldQuery();
     $query
@@ -652,16 +681,20 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
     $query = new EntityFieldQuery();
     $query
       ->entityCondition('entity_type', 'test_entity_bundle_key')
-      ->propertyCondition('ftid', 1, 'CONTAINS');
+      ->propertyCondition('fttype', 'und', 'CONTAINS');
     $this->assertEntityFieldQuery($query, array(
       array('test_entity_bundle_key', 1),
+      array('test_entity_bundle_key', 2),
+      array('test_entity_bundle_key', 3),
+      array('test_entity_bundle_key', 4),
+      array('test_entity_bundle_key', 5),
+      array('test_entity_bundle_key', 6),
     ), t('Test the "contains" operation on a property.'));
 
     $query = new EntityFieldQuery();
-    $query->fieldCondition($this->fields[0], 'value', 3, 'CONTAINS');
+    $query->fieldCondition($this->fields[1], 'shape', 'uar', 'CONTAINS');
     $this->assertEntityFieldQuery($query, array(
-      array('test_entity_bundle_key', 3),
-      array('test_entity', 3),
+      array('test_entity_bundle', 5),
     ), t('Test the "contains" operation on a field.'));
 
     $query = new EntityFieldQuery();
diff --git a/modules/simpletest/tests/error_test.info b/modules/simpletest/tests/error_test.info
index e079762e0c421ca433edee09c4d0044adb4a082a..5560212aae1b3aebcc779b32639332da561ce79e 100644
--- a/modules/simpletest/tests/error_test.info
+++ b/modules/simpletest/tests/error_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = error_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/file.test b/modules/simpletest/tests/file.test
index ea53dcd18f19ae8f521d5feb2d0168456433a60a..369db87897db1b2905b68a92ce40af1ed8954612 100644
--- a/modules/simpletest/tests/file.test
+++ b/modules/simpletest/tests/file.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: file.test,v 1.67 2010/09/11 21:14:31 webchick Exp $
+// $Id: file.test,v 1.71 2010/10/05 06:23:18 webchick Exp $
 
 /**
  *  @file
@@ -174,7 +174,7 @@ class FileTestCase extends DrupalWebTestCase {
    */
   function createDirectory($path = NULL) {
     // A directory to operate on.
-    if (is_null($path)) {
+    if (!isset($path)) {
       $path = file_default_scheme() . '://' . $this->randomName();
     }
     $this->assertTrue(drupal_mkdir($path) && is_dir($path), t('Directory was created successfully.'));
@@ -198,12 +198,12 @@ class FileTestCase extends DrupalWebTestCase {
    *   File object.
    */
   function createFile($filepath = NULL, $contents = NULL, $scheme = 'public') {
-    if (is_null($filepath)) {
+    if (!isset($filepath)) {
       $filepath = $this->randomName();
     }
     $filepath = $scheme . '://' . $filepath;
 
-    if (is_null($contents)) {
+    if (!isset($contents)) {
       $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
     }
 
@@ -282,7 +282,7 @@ class FileHookTestCase extends FileTestCase {
   function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
     $actual_count = count(file_test_get_calls($hook));
 
-    if (is_null($message)) {
+    if (!isset($message)) {
       if ($actual_count == $expected_count) {
         $message = t('hook_file_@name was called correctly.', array('@name' => $hook));
       }
@@ -899,7 +899,6 @@ class FileDirectoryTest extends FileTestCase {
       // in the directory on any recent version of Windows.
 
       // Make directory read only.
-      debug($directory);
       @drupal_chmod($directory, 0444);
       $this->assertFalse(file_prepare_directory($directory, 0), t('Error reported for a non-writeable directory.'), 'File');
 
@@ -973,8 +972,19 @@ class FileDirectoryTest extends FileTestCase {
     $path = file_destination($destination, FILE_EXISTS_ERROR);
     $this->assertEqual($path, FALSE, t('An error is returned when filepath destination already exists with FILE_EXISTS_ERROR.'), 'File');
   }
-}
 
+  /**
+   * Ensure that the file_directory_temp() function always returns a value.
+   */
+  function testFileDirectoryTemp() {
+    // Start with an empty variable to ensure we have a clean slate.
+    variable_set('file_temporary_path', '');
+    $tmp_directory = file_directory_temp();
+    $this->assertEqual(empty($tmp_directory), FALSE, t('file_directory_temp() returned a non-empty value.'));
+    $setting = variable_get('file_temporary_path', '');
+    $this->assertEqual($setting, $tmp_directory, t("The 'file_temporary_path' variable has the same value that file_directory_temp() returned."));
+  }
+}
 
 /**
  * Tests the file_scan_directory() function.
@@ -1972,25 +1982,36 @@ class FileUsageTest extends FileTestCase {
         'module' => 'testing',
         'type' => 'bar',
         'id' => 2,
-        'count' => 2
+        'count' => 3,
       ))
       ->execute();
 
+    // Normal decrement.
     file_usage_delete($file, 'testing', 'bar', 2);
     $count = db_select('file_usage', 'f')
       ->fields('f', array('count'))
       ->condition('f.fid', $file->fid)
       ->execute()
       ->fetchField();
-    $this->assertEqual(1, $count, t('The count was decremented correctly.'));
+    $this->assertEqual(2, $count, t('The count was decremented correctly.'));
+
+    // Multiple decrement and removal.
+    file_usage_delete($file, 'testing', 'bar', 2, 2);
+    $count = db_select('file_usage', 'f')
+      ->fields('f', array('count'))
+      ->condition('f.fid', $file->fid)
+      ->execute()
+      ->fetchField();
+    $this->assertIdentical(FALSE, $count, t('The count was removed entirely when empty.'));
 
+    // Non-existent decrement.
     file_usage_delete($file, 'testing', 'bar', 2);
     $count = db_select('file_usage', 'f')
       ->fields('f', array('count'))
       ->condition('f.fid', $file->fid)
       ->execute()
       ->fetchField();
-    $this->assertEqual(0, $count, t('The count was decremented correctly.'));
+    $this->assertIdentical(FALSE, $count, t('Decrementing non-exist record complete.'));
   }
 }
 
diff --git a/modules/simpletest/tests/file_test.info b/modules/simpletest/tests/file_test.info
index 76d53eba7d2a91a87c5dfb463999d23f7a14ff58..fd0413fe18477b0c111b7852dc34f6257df10642 100644
--- a/modules/simpletest/tests/file_test.info
+++ b/modules/simpletest/tests/file_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = file_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/filter_test.info b/modules/simpletest/tests/filter_test.info
index e46f6c7ad20080364948a841928175a62c6a9650..5e0c784a8f055bfdfd0e1639f3bb47d5ccf63e93 100644
--- a/modules/simpletest/tests/filter_test.info
+++ b/modules/simpletest/tests/filter_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = filter_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/filter_test.module b/modules/simpletest/tests/filter_test.module
index 076c14a490dddbf8a53afa22488071369441afa6..9d896f3bc87528a0c2a3e2b186d4d62f07b542c8 100644
--- a/modules/simpletest/tests/filter_test.module
+++ b/modules/simpletest/tests/filter_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: filter_test.module,v 1.5 2010/08/22 12:55:04 dries Exp $
+// $Id: filter_test.module,v 1.6 2010/09/18 02:18:35 dries Exp $
 
 /**
  * @file
@@ -21,10 +21,10 @@ function filter_test_filter_format_update($format) {
 }
 
 /**
- * Implements hook_filter_format_delete().
+ * Implements hook_filter_format_disable().
  */
-function filter_test_filter_format_delete($format, $default) {
-  drupal_set_message('hook_filter_format_delete invoked.');
+function filter_test_filter_format_disable($format) {
+  drupal_set_message('hook_filter_format_disable invoked.');
 }
 
 /**
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 17eea5133c93eef0aace948ec04eb1181a4f08aa..661fef9b6ba9cf6ce614e540e53abbcf662ff250 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: form.test,v 1.64 2010/09/13 06:41:23 webchick Exp $
+// $Id: form.test,v 1.72 2010/10/04 18:00:46 dries Exp $
 
 /**
  * @file
@@ -152,6 +152,70 @@ class FormsTestCase extends DrupalWebTestCase {
     }
   }
 
+  /**
+   * Tests validation of #type 'select' elements.
+   */
+  function testSelect() {
+    $form = $form_state = array();
+    $form = form_test_select($form, $form_state);
+    $error = '!name field is required.';
+    $this->drupalGet('form-test/select');
+
+    // Posting without any values should throw validation errors.
+    $this->drupalPost(NULL, array(), 'Submit');
+    $this->assertNoText(t($error, array('!name' => $form['select']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['select_required']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['select_optional']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['empty_value']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['empty_value_one']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_optional']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_option']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_empty_option_optional']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_value']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['no_default_empty_value_one']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['no_default_empty_value_optional']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['multiple']['#title'])));
+    $this->assertNoText(t($error, array('!name' => $form['multiple_no_default']['#title'])));
+    $this->assertText(t($error, array('!name' => $form['multiple_no_default_required']['#title'])));
+
+    // Post values for required fields.
+    $edit = array(
+      'no_default' => 'three',
+      'no_default_empty_option' => 'three',
+      'no_default_empty_value' => 'three',
+      'no_default_empty_value_one' => 'three',
+      'multiple_no_default_required[]' => 'three',
+    );
+    $this->drupalPost(NULL, $edit, 'Submit');
+    $values = drupal_json_decode($this->drupalGetContent());
+
+    // Verify expected values.
+    $expected = array(
+      'select' => 'one',
+      'empty_value' => 'one',
+      'empty_value_one' => 'one',
+      'no_default' => 'three',
+      'no_default_optional' => 'one',
+      'no_default_optional_empty_value' => '',
+      'no_default_empty_option' => 'three',
+      'no_default_empty_option_optional' => '',
+      'no_default_empty_value' => 'three',
+      'no_default_empty_value_one' => 'three',
+      'no_default_empty_value_optional' => 0,
+      'multiple' => array('two' => 'two'),
+      'multiple_no_default' => array(),
+      'multiple_no_default_required' => array('three' => 'three'),
+    );
+    foreach ($expected as $key => $value) {
+      $this->assertIdentical($values[$key], $value, t('@name: @actual is equal to @expected.', array(
+        '@name' => $key,
+        '@actual' => var_export($values[$key], TRUE),
+        '@expected' => var_export($value, TRUE),
+      )));
+    }
+  }
+
   /**
    * Test handling of disabled elements.
    *
@@ -464,15 +528,15 @@ class FormsElementsLabelsTestCase extends DrupalWebTestCase {
     $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required"]/span[@class="form-required"]');
     $this->assertTrue(isset($elements[0]), t("Label tag with required marker preceeds required textfield with no title."));
 
+    $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="element-invisible"]');
+    $this->assertTrue(isset($elements[0]), t("Label preceeding field and label class is element-invisible."));
+
     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="form-required"]');
     $this->assertFalse(isset($elements[0]), t("No required marker on non-required field."));
 
     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-after"]/following-sibling::label[@for="edit-form-textfield-test-title-after" and @class="option"]');
     $this->assertTrue(isset($elements[0]), t("Label after field and label option class correct for text field."));
 
-    $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/following-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="element-invisible"]');
-    $this->assertTrue(isset($elements[0]), t("Label after field and label class is element-invisible."));
-
     $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-no-show"]');
     $this->assertFalse(isset($elements[0]), t("No label tag when title set not to display."));
 
@@ -727,24 +791,21 @@ class FormsFormStorageTestCase extends DrupalWebTestCase {
     $this->assertText('Form constructions: 1');
 
     $edit = array('title' => 'new', 'value' => 'value_is_set');
-    // Reload the form, but don't rebuild.
-    $this->drupalPost(NULL, $edit, 'Reload');
-    $this->assertText('Form constructions: 2');
 
-    // Now use form rebuilding triggered by a submit button.
+    // Use form rebuilding triggered by a submit button.
     $this->drupalPost(NULL, $edit, 'Continue submit');
+    $this->assertText('Form constructions: 2');
     $this->assertText('Form constructions: 3');
-    $this->assertText('Form constructions: 4');
 
     // Reset the form to the values of the storage, using a form rebuild
     // triggered by button of type button.
     $this->drupalPost(NULL, array('title' => 'changed'), 'Reset');
     $this->assertFieldByName('title', 'new', 'Values have been resetted.');
     // After rebuilding, the form has been cached.
-    $this->assertText('Form constructions: 5');
+    $this->assertText('Form constructions: 4');
 
     $this->drupalPost(NULL, $edit, 'Save');
-    $this->assertText('Form constructions: 5');
+    $this->assertText('Form constructions: 4');
     $this->assertText('Title: new', t('The form storage has stored the values.'));
   }
 
@@ -756,11 +817,8 @@ class FormsFormStorageTestCase extends DrupalWebTestCase {
     $this->assertText('Form constructions: 1');
 
     $edit = array('title' => 'new', 'value' => 'value_is_set');
-    // Reload the form, but don't rebuild.
-    $this->drupalPost(NULL, $edit, 'Reload');
-    $this->assertNoText('Form constructions');
 
-    // Now use form rebuilding triggered by a submit button.
+    // Use form rebuilding triggered by a submit button.
     $this->drupalPost(NULL, $edit, 'Continue submit');
     $this->assertText('Form constructions: 2');
 
@@ -830,7 +888,7 @@ class FormsFormStorageTestCase extends DrupalWebTestCase {
       array(),
       array('query' => array('cache' => 1)),
     );
-    foreach($run_options as $options) {
+    foreach ($run_options as $options) {
       $this->drupalPost('form-test/state-persist', array(), t('Submit'), $options);
       // The submit handler outputs the value in $form_state, assert it's there.
       $this->assertText('State persisted.');
@@ -996,11 +1054,7 @@ class FormsRebuildTestCase extends DrupalWebTestCase {
     // submission and verify it worked by ensuring the updated page has two text
     // field items in the field for which we just added an item.
     $this->drupalGet('node/add/page');
-    preg_match('/jQuery\.extend\(Drupal\.settings, (.*?)\);/', $this->content, $matches);
-    $settings = drupal_json_decode($matches[1]);
-    $button = $this->xpath('//input[@name="field_ajax_test_add_more"]');
-    $button_id = (string) $button[0]['id'];
-    $this->drupalPostAJAX(NULL, array(), array('field_ajax_test_add_more' => t('Add another item')), 'system/ajax', array(), array(), 'page-node-form', $settings['ajax'][$button_id]);
+    $this->drupalPostAJAX(NULL, array(), array('field_ajax_test_add_more' => t('Add another item')), 'system/ajax', array(), array(), 'page-node-form');
     $this->assert(count($this->xpath('//div[contains(@class, "field-name-field-ajax-test")]//input[@type="text"]')) == 2, t('AJAX submission succeeded.'));
 
     // Submit the form with the non-AJAX "Save" button, leaving the title field
diff --git a/modules/simpletest/tests/form_test.file.inc b/modules/simpletest/tests/form_test.file.inc
index aeef156f5fc99e01f6bd44efa02bef72e8cc721c..ea2dab2b247bef4629edf601ac0f4b8d29de489e 100644
--- a/modules/simpletest/tests/form_test.file.inc
+++ b/modules/simpletest/tests/form_test.file.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: form_test.file.inc,v 1.1 2010/07/17 18:52:39 dries Exp $
+// $Id: form_test.file.inc,v 1.4 2010/09/19 18:39:18 dries Exp $
 
 /**
  * @file
@@ -13,11 +13,17 @@
 function form_test_load_include_menu($form, &$form_state) {
   // Submit the form via AJAX. That way the FAPI has to care about including
   // the file specified in hook_menu().
+  $ajax_wrapper_id = drupal_html_id('form-test-load-include-menu-ajax-wrapper');
+  $form['ajax_wrapper'] = array(
+    '#markup' => '<div id="' . $ajax_wrapper_id . '"></div>',
+  );
   $form['button'] = array(
     '#type' => 'submit',
     '#value' => t('Save'),
     '#submit' => array('form_test_load_include_submit'),
     '#ajax' => array(
+      'wrapper' => $ajax_wrapper_id,
+      'method' => 'append',
       'callback' => 'form_test_load_include_menu_ajax',
     ),
   );
@@ -32,9 +38,12 @@ function form_test_load_include_submit($form, $form_state) {
 }
 
 /**
- * Ajax callback for the file inclusion via menu test. We don't need to return
- * anything as the messages are added automatically.
+ * Ajax callback for the file inclusion via menu test.
  */
 function form_test_load_include_menu_ajax($form) {
+  // We don't need to return anything, since #ajax['method'] is 'append', which
+  // does not remove the original #ajax['wrapper'] element, and status messages
+  // are automatically added by the AJAX framework as long as there's a wrapper
+  // element to add them to.
   return '';
 }
diff --git a/modules/simpletest/tests/form_test.info b/modules/simpletest/tests/form_test.info
index 17b1a2725acedc47c31e100fb012359a6c828757..08738f2a491371c4dab06377f4fa0f517d71237d 100644
--- a/modules/simpletest/tests/form_test.info
+++ b/modules/simpletest/tests/form_test.info
@@ -8,8 +8,8 @@ files[] = form_test.module
 files[] = form_test.file.inc
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index bbfd9414d5a004ab071e63d32b68c17890e5ef11..1788bc254cf5a67d8328226d417f7df985be3c7d 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: form_test.module,v 1.48 2010/08/27 11:54:32 webchick Exp $
+// $Id: form_test.module,v 1.51 2010/10/04 18:00:46 dries Exp $
 
 /**
  * @file
@@ -92,6 +92,12 @@ function form_test_menu() {
     'access callback' => TRUE,
     'type' => MENU_CALLBACK,
   );
+  $items['form-test/select'] = array(
+    'title' => t('Select'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('form_test_select'),
+    'access callback' => TRUE,
+  );
 
   $items['form-test/disabled-elements'] = array(
     'title' => t('Form test'),
@@ -516,16 +522,10 @@ function form_test_storage_form($form, &$form_state) {
     '#default_value' => $form_state['storage']['thing']['value'],
     '#element_validate' => array('form_test_storage_element_validate_value_cached'),
   );
-  $form['button'] = array(
-    '#type' => 'button',
-    '#value' => 'Reload',
-    // Reload the form (don't rebuild), thus we start at the initial step again.
-  );
   $form['continue_button'] = array(
     '#type' => 'button',
     '#value' => 'Reset',
     // Rebuilds the form without keeping the values.
-    '#validate' => array('form_storage_test_form_continue_validate'),
   );
   $form['continue_submit'] = array(
     '#type' => 'submit',
@@ -570,15 +570,6 @@ function form_storage_test_form_continue_submit($form, &$form_state) {
   $form_state['rebuild'] = TRUE;
 }
 
-/**
- * Form validation handler, which doesn't preserve the values but rebuilds the
- * form. We cannot use a submit handler here, as buttons of type button don't
- * submit the form.
- */
-function form_storage_test_form_continue_validate($form, &$form_state) {
-  $form_state['rebuild'] = TRUE;
-}
-
 /**
  * Form submit handler to finish multi-step form.
  */
@@ -785,6 +776,115 @@ function _form_test_checkbox_submit($form, &$form_state) {
   exit();
 }
 
+/**
+ * Builds a form to test #type 'select' validation.
+ */
+function form_test_select($form, &$form_state) {
+  $base = array(
+    '#type' => 'select',
+    '#options' => drupal_map_assoc(array('one', 'two', 'three')),
+  );
+
+  $form['select'] = $base + array(
+    '#title' => '#default_value one',
+    '#default_value' => 'one',
+  );
+  $form['select_required'] = $base + array(
+    '#title' => '#default_value one, #required',
+    '#required' => TRUE,
+    '#default_value' => 'one',
+  );
+  $form['select_optional'] = $base + array(
+    '#title' => '#default_value one, not #required',
+    '#required' => FALSE,
+    '#default_value' => 'one',
+  );
+  $form['empty_value'] = $base + array(
+    '#title' => '#default_value one, #required, #empty_value 0',
+    '#required' => TRUE,
+    '#default_value' => 'one',
+    '#empty_value' => 0,
+  );
+  $form['empty_value_one'] = $base + array(
+    '#title' => '#default_value = #empty_value, #required',
+    '#required' => TRUE,
+    '#default_value' => 'one',
+    '#empty_value' => 'one',
+  );
+
+  $form['no_default'] = $base + array(
+    '#title' => 'No #default_value, #required',
+    '#required' => TRUE,
+  );
+  $form['no_default_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required',
+    '#required' => FALSE,
+    '#description' => 'Should result in "one", because it is not required and there is no #empty_value requested, so default browser behavior of preselecting first option is in effect.',
+  );
+  $form['no_default_optional_empty_value'] = $base + array(
+    '#title' => 'No #default_value, not #required, #empty_value empty string',
+    '#empty_value' => '',
+    '#required' => FALSE,
+    '#description' => 'Should result in an empty string (due to #empty_value), because it is optional.',
+  );
+
+  $form['no_default_empty_option'] = $base + array(
+    '#title' => 'No #default_value, #required, #empty_option',
+    '#required' => TRUE,
+    '#empty_option' => '- Choose -',
+  );
+  $form['no_default_empty_option_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required, #empty_option',
+    '#empty_option' => '- Dismiss -',
+    '#description' => 'Should result in an empty string (default of #empty_value), because it is optional.',
+  );
+
+  $form['no_default_empty_value'] = $base + array(
+    '#title' => 'No #default_value, #required, #empty_value 0',
+    '#required' => TRUE,
+    '#empty_value' => 0,
+    '#description' => 'Should never result in 0.',
+  );
+  $form['no_default_empty_value_one'] = $base + array(
+    '#title' => 'No #default_value, #required, #empty_value one',
+    '#required' => TRUE,
+    '#empty_value' => 'one',
+    '#description' => 'A mistakenly assigned #empty_value contained in #options should not be valid.',
+  );
+  $form['no_default_empty_value_optional'] = $base + array(
+    '#title' => 'No #default_value, not #required, #empty_value 0',
+    '#required' => FALSE,
+    '#empty_value' => 0,
+    '#description' => 'Should result in 0, because it is optional.',
+  );
+
+  $form['multiple'] = $base + array(
+    '#title' => '#multiple, #default_value two',
+    '#default_value' => array('two'),
+    '#multiple' => TRUE,
+  );
+  $form['multiple_no_default'] = $base + array(
+    '#title' => '#multiple, no #default_value',
+    '#multiple' => TRUE,
+  );
+  $form['multiple_no_default_required'] = $base + array(
+    '#title' => '#multiple, #required, no #default_value',
+    '#required' => TRUE,
+    '#multiple' => TRUE,
+  );
+
+  $form['submit'] = array('#type' => 'submit', '#value' => 'Submit');
+  return $form;
+}
+
+/**
+ * Form submit handler for form_test_select().
+ */
+function form_test_select_submit($form, &$form_state) {
+  drupal_json_output($form_state['values']);
+  exit();
+}
+
 /**
  * Build a form to test disabled elements.
  */
diff --git a/modules/simpletest/tests/image_test.info b/modules/simpletest/tests/image_test.info
index 7903c885b7e3c6caee3d92cfdb50f0f9604eac7b..0caf3c805569b149369db100241e42a7aa143afd 100644
--- a/modules/simpletest/tests/image_test.info
+++ b/modules/simpletest/tests/image_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = image_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/menu.test b/modules/simpletest/tests/menu.test
index 91058d5eccaa146ca8fc7f32c9687ae24d42bf4b..81643ded67fa8a3ce89256bcea331aa8bcaf539d 100644
--- a/modules/simpletest/tests/menu.test
+++ b/modules/simpletest/tests/menu.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu.test,v 1.34 2010/08/08 19:35:49 dries Exp $
+// $Id: menu.test,v 1.36 2010/10/01 15:24:18 webchick Exp $
 
 /**
  * @file
@@ -525,3 +525,555 @@ class MenuTreeDataTestCase extends DrupalUnitTestCase {
     return $this->assert($link1['mlid'] == $link2['mlid'], $message ? $message : t('First link is identical to second link'));
   }
 }
+
+/**
+ * Menu breadcrumbs related tests.
+ */
+class MenuBreadcrumbTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Breadcrumbs',
+      'description' => 'Tests breadcrumbs functionality.',
+      'group' => 'Menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('menu_test'));
+    $perms = array_keys(module_invoke_all('permission'));
+    $this->admin_user = $this->drupalCreateUser($perms);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Tests breadcrumbs on node and administrative paths.
+   */
+  function testBreadCrumbs() {
+    // Prepare common base breadcrumb elements.
+    $home = array('<front>' => 'Home');
+    $admin = $home + array('admin' => t('Administration'));
+    $config = $admin + array('admin/config' => t('Configuration'));
+    $type = 'article';
+    $langcode = LANGUAGE_NONE;
+
+    // Verify breadcrumbs for default local tasks.
+    $expected = array(
+      'menu-test' => t('Menu test root'),
+    );
+    $title = t('Breadcrumbs test: Local tasks');
+    $trail = $home + $expected;
+    $tree = $expected + array(
+      'menu-test/breadcrumb/tasks' => $title,
+    );
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/first', $trail, $title, $tree);
+    $trail += array(
+      'menu-test/breadcrumb/tasks' => t('Breadcrumbs test: Local tasks'),
+    );
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/second', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/first', $trail, $title, $tree);
+    $trail += array(
+      'menu-test/breadcrumb/tasks/second' => t('Second'),
+    );
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/second', $trail, $title, $tree);
+
+    // Verify Taxonomy administration breadcrumbs.
+    $trail = $admin + array(
+      'admin/structure' => t('Structure'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy', $trail);
+
+    $trail += array(
+      'admin/structure/taxonomy' => t('Taxonomy'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags', $trail);
+    $trail += array(
+      'admin/structure/taxonomy/tags' => t('Tags'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/edit', $trail);
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/fields', $trail);
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/add', $trail);
+
+    // Verify Menu administration breadcrumbs.
+    $trail = $admin + array(
+      'admin/structure' => t('Structure'),
+    );
+    $this->assertBreadcrumb('admin/structure/menu', $trail);
+
+    $trail += array(
+      'admin/structure/menu' => t('Menus'),
+    );
+    $this->assertBreadcrumb('admin/structure/menu/manage/navigation', $trail);
+    $trail += array(
+      'admin/structure/menu/manage/navigation' => t('Navigation'),
+    );
+    $this->assertBreadcrumb('admin/structure/menu/manage/navigation/edit', $trail);
+    $this->assertBreadcrumb('admin/structure/menu/manage/navigation/add', $trail);
+
+    // Verify Node administration breadcrumbs.
+    $trail = $admin + array(
+      'admin/structure' => t('Structure'),
+      'admin/structure/types' => t('Content types'),
+    );
+    $this->assertBreadcrumb('admin/structure/types/add', $trail);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type", $trail);
+    $trail += array(
+      "admin/structure/types/manage/$type" => t('Article'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields", $trail);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/display", $trail);
+    $trail_teaser = $trail + array(
+      "admin/structure/types/manage/$type/display" => t('Manage display'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/display/teaser", $trail_teaser);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/comment/fields", $trail);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/comment/display", $trail);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/delete", $trail);
+    $trail += array(
+      "admin/structure/types/manage/$type/fields" => t('Manage fields'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body", $trail);
+    $trail += array(
+      "admin/structure/types/manage/$type/fields/body" => t('Body'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body/widget-type", $trail);
+
+    // Verify Filter text format administration breadcrumbs.
+    $format = db_query_range("SELECT format, name FROM {filter_format}", 1, 1)->fetch();
+    $format_id = $format->format;
+    $trail = $config + array(
+      'admin/config/content' => t('Content authoring'),
+    );
+    $this->assertBreadcrumb('admin/config/content/formats', $trail);
+
+    $trail += array(
+      'admin/config/content/formats' => t('Text formats'),
+    );
+    $this->assertBreadcrumb('admin/config/content/formats/add', $trail);
+    $this->assertBreadcrumb("admin/config/content/formats/$format_id", $trail);
+    $trail += array(
+      "admin/config/content/formats/$format_id" => $format->name,
+    );
+    $this->assertBreadcrumb("admin/config/content/formats/$format_id/disable", $trail);
+
+    // Verify node breadcrumbs (without menu link).
+    $node1 = $this->drupalCreateNode();
+    $nid1 = $node1->nid;
+    $trail = $home;
+    $this->assertBreadcrumb("node/$nid1", $trail);
+    // Also verify that the node does not appear elsewhere (e.g., menu trees).
+    $this->assertNoLink($node1->title);
+    // The node itself should not be contained in the breadcrumb on the default
+    // local task, since there is no difference between both pages.
+    $this->assertBreadcrumb("node/$nid1/view", $trail);
+    // Also verify that the node does not appear elsewhere (e.g., menu trees).
+    $this->assertNoLink($node1->title);
+
+    $trail += array(
+      "node/$nid1" => $node1->title,
+    );
+    $this->assertBreadcrumb("node/$nid1/edit", $trail);
+
+    // Verify that breadcrumb on node listing page contains "Home" only.
+    $trail = array();
+    $this->assertBreadcrumb('node', $trail);
+
+    // Verify node breadcrumbs (in menu).
+    // Do this separately for Main menu and Navigation menu, since only the
+    // latter is a preferred menu by default.
+    // @todo Also test all themes? Manually testing led to the suspicion that
+    //   breadcrumbs may differ, possibly due to template.php overrides.
+    $menus = array('main-menu', 'navigation');
+    // Alter node type menu settings.
+    variable_set("menu_options_$type", $menus);
+    variable_set("menu_parent_$type", 'navigation:0');
+
+    foreach ($menus as $menu) {
+      // Create a parent node in the current menu.
+      $title = $this->randomName();
+      $node2 = $this->drupalCreateNode(array(
+        'type' => $type,
+        'title' => $title,
+        'menu' => array(
+          'enabled' => 1,
+          'link_title' => 'Parent ' . $title,
+          'description' => '',
+          'menu_name' => $menu,
+          'plid' => 0,
+        ),
+      ));
+      $nid2 = $node2->nid;
+
+      $trail = $home;
+      $tree = array(
+        "node/$nid2" => $node2->menu['link_title'],
+      );
+      $this->assertBreadcrumb("node/$nid2", $trail, $node2->title, $tree);
+      // The node itself should not be contained in the breadcrumb on the
+      // default local task, since there is no difference between both pages.
+      $this->assertBreadcrumb("node/$nid2/view", $trail, $node2->title, $tree);
+      $trail += array(
+        "node/$nid2" => $node2->menu['link_title'],
+      );
+      $this->assertBreadcrumb("node/$nid2/edit", $trail);
+
+      // Create a child node in the current menu.
+      $title = $this->randomName();
+      $node3 = $this->drupalCreateNode(array(
+        'type' => $type,
+        'title' => $title,
+        'menu' => array(
+          'enabled' => 1,
+          'link_title' => 'Child ' . $title,
+          'description' => '',
+          'menu_name' => $menu,
+          'plid' => $node2->menu['mlid'],
+        ),
+      ));
+      $nid3 = $node3->nid;
+
+      $this->assertBreadcrumb("node/$nid3", $trail, $node3->title, $tree, FALSE);
+      // The node itself should not be contained in the breadcrumb on the
+      // default local task, since there is no difference between both pages.
+      $this->assertBreadcrumb("node/$nid3/view", $trail, $node3->title, $tree, FALSE);
+      $trail += array(
+        "node/$nid3" => $node3->menu['link_title'],
+      );
+      $tree += array(
+        "node/$nid3" => $node3->menu['link_title'],
+      );
+      $this->assertBreadcrumb("node/$nid3/edit", $trail);
+
+      // Verify that node listing page still contains "Home" only.
+      $trail = array();
+      $this->assertBreadcrumb('node', $trail);
+
+      if ($menu == 'navigation') {
+        $parent = $node2;
+        $child = $node3;
+      }
+    }
+
+    // Create a Navigation menu link for 'node', move the last parent node menu
+    // link below it, and verify a full breadcrumb for the last child node.
+    $menu = 'navigation';
+    $edit = array(
+      'link_title' => 'Root',
+      'link_path' => 'node',
+    );
+    $this->drupalPost("admin/structure/menu/manage/$menu/add", $edit, t('Save'));
+    $link = db_query('SELECT * FROM {menu_links} WHERE link_title = :title', array(':title' => 'Root'))->fetchAssoc();
+
+    $edit = array(
+      'menu[parent]' => $link['menu_name'] . ':' . $link['mlid'],
+    );
+    $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save'));
+    $expected = array(
+      "node" => $link['link_title'],
+    );
+    $trail = $home + $expected;
+    $tree = $expected + array(
+      "node/{$parent->nid}" => $parent->menu['link_title'],
+    );
+    $this->assertBreadcrumb(NULL, $trail, $parent->title, $tree);
+    $trail += array(
+      "node/{$parent->nid}" => $parent->menu['link_title'],
+    );
+    $tree += array(
+      "node/{$child->nid}" => $child->menu['link_title'],
+    );
+    $this->assertBreadcrumb("node/{$child->nid}", $trail, $child->title, $tree);
+
+    // Add a taxonomy term/tag to last node, and add a link for that term to the
+    // Navigation menu.
+    $tags = array(
+      'Drupal' => array(),
+      'Breadcrumbs' => array(),
+    );
+    $edit = array(
+      "field_tags[$langcode]" => implode(',', array_keys($tags)),
+    );
+    $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save'));
+
+    // Put both terms into a hierarchy Drupal » Breadcrumbs. Required for both
+    // the menu links and the terms itself, since taxonomy_term_page() resets
+    // the breadcrumb based on taxonomy term hierarchy.
+    $parent_tid = 0;
+    foreach ($tags as $name => $null) {
+      $terms = taxonomy_term_load_multiple(NULL, array('name' => $name));
+      $term = reset($terms);
+      $tags[$name]['term'] = $term;
+      if ($parent_tid) {
+        $edit = array(
+          'parent[]' => array($parent_tid),
+        );
+        $this->drupalPost("taxonomy/term/{$term->tid}/edit", $edit, t('Save'));
+      }
+      $parent_tid = $term->tid;
+    }
+    $parent_mlid = 0;
+    foreach ($tags as $name => $data) {
+      $term = $data['term'];
+      $edit = array(
+        'link_title' => "$name link",
+        'link_path' => "taxonomy/term/{$term->tid}",
+        'parent' => "$menu:{$parent_mlid}",
+      );
+      $this->drupalPost("admin/structure/menu/manage/$menu/add", $edit, t('Save'));
+      $tags[$name]['link'] = db_query('SELECT * FROM {menu_links} WHERE link_title = :title AND link_path = :href', array(
+        ':title' => $edit['link_title'],
+        ':href' => $edit['link_path'],
+      ))->fetchAssoc();
+      $tags[$name]['link']['link_path'] = $edit['link_path'];
+      $parent_mlid = $tags[$name]['link']['mlid'];
+    }
+
+    // Verify expected breadcrumbs for menu links.
+    $trail = $home;
+    $tree = array();
+    foreach ($tags as $name => $data) {
+      $term = $data['term'];
+      $link = $data['link'];
+
+      $tree += array(
+        $link['link_path'] => $link['link_title'],
+      );
+      // @todo Normally, you'd expect $term->name as page title here.
+      $this->assertBreadcrumb($link['link_path'], $trail, $link['link_title'], $tree);
+      $this->assertRaw(check_plain($parent->title), 'Tagged node found.');
+
+      // Additionally make sure that this link appears only once; i.e., the
+      // untranslated menu links automatically generated from menu router items
+      // ('taxonomy/term/%') should never be translated and appear in any menu
+      // other than the breadcrumb trail.
+      $elements = $this->xpath('//div[@id=:menu]/descendant::a[@href=:href]', array(
+        ':menu' => 'block-system-navigation',
+        ':href' => url($link['link_path']),
+      ));
+      $this->assertTrue(count($elements) == 1, "Link to {$link['link_path']} appears only once.");
+
+      // Next iteration should expect this tag as parent link.
+      // Note: Term name, not link name, due to taxonomy_term_page().
+      $trail += array(
+        $link['link_path'] => $term->name,
+      );
+    }
+
+    // Verify breadcrumbs on user and user/%.
+    // We need to log back in and out below, and cannot simply grant the
+    // 'administer users' permission, since user_page() makes your head explode.
+    user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array(
+      'access user profiles',
+    ));
+    $this->drupalLogout();
+
+    // Verify breadcrumb on front page.
+    $this->assertBreadcrumb('<front>', array());
+
+    $trail = $home;
+    $this->assertBreadcrumb('user', $trail, t('User account'));
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid, $trail, $this->admin_user->name);
+
+    $this->drupalLogin($this->admin_user);
+    $trail += array(
+      'user/' . $this->admin_user->uid => $this->admin_user->name,
+    );
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid . '/edit', $trail, $this->admin_user->name);
+
+    // Add a Navigation menu links for 'user' and $this->admin_user.
+    // Although it may be faster to manage these links via low-level API
+    // functions, there's a lot that can go wrong in doing so.
+    $edit = array(
+      'link_title' => 'User',
+      'link_path' => 'user',
+    );
+    $this->drupalPost("admin/structure/menu/manage/$menu/add", $edit, t('Save'));
+    $link_user = db_query('SELECT * FROM {menu_links} WHERE link_title = :title AND link_path = :href', array(
+      ':title' => $edit['link_title'],
+      ':href' => $edit['link_path'],
+    ))->fetchAssoc();
+
+    $edit = array(
+      'link_title' => $this->admin_user->name . ' link',
+      'link_path' => 'user/' . $this->admin_user->uid,
+    );
+    $this->drupalPost("admin/structure/menu/manage/$menu/add", $edit, t('Save'));
+    $link_admin_user = db_query('SELECT * FROM {menu_links} WHERE link_title = :title AND link_path = :href', array(
+      ':title' => $edit['link_title'],
+      ':href' => $edit['link_path'],
+    ))->fetchAssoc();
+
+    // Verify expected breadcrumbs for the two separate links.
+    $this->drupalLogout();
+    $trail = $home;
+    $tree = array(
+      $link_user['link_path'] => $link_user['link_title'],
+    );
+    $this->assertBreadcrumb('user', $trail, $link_user['link_title'], $tree);
+    $tree = array(
+      $link_admin_user['link_path'] => $link_admin_user['link_title'],
+    );
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid, $trail, $link_admin_user['link_title'], $tree);
+
+    $this->drupalLogin($this->admin_user);
+    $trail += array(
+      $link_admin_user['link_path'] => $link_admin_user['link_title'],
+    );
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid . '/edit', $trail, $link_admin_user['link_title'], $tree, FALSE);
+
+    // Move 'user/%' below 'user' and verify again.
+    $edit = array(
+      'parent' => "$menu:{$link_user['mlid']}",
+    );
+    $this->drupalPost("admin/structure/menu/item/{$link_admin_user['mlid']}/edit", $edit, t('Save'));
+
+    $this->drupalLogout();
+    $trail = $home;
+    $tree = array(
+      $link_user['link_path'] => $link_user['link_title'],
+    );
+    $this->assertBreadcrumb('user', $trail, $link_user['link_title'], $tree);
+    $trail += array(
+      $link_user['link_path'] => $link_user['link_title'],
+    );
+    $tree += array(
+      $link_admin_user['link_path'] => $link_admin_user['link_title'],
+    );
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid, $trail, $link_admin_user['link_title'], $tree);
+
+    $this->drupalLogin($this->admin_user);
+    $trail += array(
+      $link_admin_user['link_path'] => $link_admin_user['link_title'],
+    );
+    $this->assertBreadcrumb('user/' . $this->admin_user->uid . '/edit', $trail, $link_admin_user['link_title'], $tree, FALSE);
+
+    // Create an only slightly privileged user being able to access site reports
+    // but not administration pages.
+    $this->web_user = $this->drupalCreateUser(array(
+      'access site reports',
+    ));
+    $this->drupalLogin($this->web_user);
+
+    // Verify that we can access recent log entries, there is a corresponding
+    // page title, and that the breadcrumb is empty (because the user is not
+    // able to access "Administer", so the trail cannot recurse into it).
+    $trail = array();
+    $this->assertBreadcrumb('admin', $trail, t('Access denied'));
+    $this->assertResponse(403);
+
+    $trail = $home;
+    $this->assertBreadcrumb('admin/reports', $trail, t('Reports'));
+    $this->assertNoResponse(403);
+
+    $this->assertBreadcrumb('admin/reports/dblog', $trail, t('Recent log messages'));
+    $this->assertNoResponse(403);
+  }
+
+  /**
+   * Assert that a given path shows certain breadcrumb links.
+   *
+   * @param string $goto
+   *   (optional) A system path to pass to DrupalWebTestCase::drupalGet().
+   * @param array $trail
+   *   An associative array whose keys are expected breadcrumb link paths and
+   *   whose values are expected breadcrumb link texts (not sanitized).
+   * @param string $page_title
+   *   (optional) A page title to additionally assert via
+   *   DrupalWebTestCase::assertTitle(). Without site name suffix.
+   * @param array $tree
+   *   (optional) An associative array whose keys are link paths and whose
+   *   values are link titles (not sanitized) of an expected active trail in a
+   *   menu tree output on the page.
+   * @param $last_active
+   *   (optional) Whether the last link in $tree is expected to be active (TRUE)
+   *   or just to be in the active trail (FALSE).
+   */
+  protected function assertBreadcrumb($goto, array $trail, $page_title = NULL, array $tree = array(), $last_active = TRUE) {
+    if (isset($goto)) {
+      $this->drupalGet($goto);
+    }
+    // Compare paths with actual breadcrumb.
+    $parts = $this->getParts();
+    $pass = TRUE;
+    foreach ($trail as $path => $title) {
+      $url = url($path);
+      $part = array_shift($parts);
+      $pass = ($pass && $part['href'] === $url && $part['text'] === check_plain($title));
+    }
+    // No parts must be left, or an expected "Home" will always pass.
+    $pass = ($pass && empty($parts));
+
+    $this->assertTrue($pass, t('Breadcrumb %parts found on @path.', array(
+      '%parts' => implode(' » ', $trail),
+      '@path' => $this->getUrl(),
+    )));
+
+    // Additionally assert page title, if given.
+    if (isset($page_title)) {
+      $this->assertTitle(strtr('@title | Drupal', array('@title' => $page_title)));
+    }
+
+    // Additionally assert active trail in a menu tree output, if given.
+    if ($tree) {
+      end($tree);
+      $active_link_path = key($tree);
+      $active_link_title = array_pop($tree);
+      $xpath = '';
+      if ($tree) {
+        $i = 0;
+        foreach ($tree as $link_path => $link_title) {
+          $part_xpath = (!$i ? '//' : '/following-sibling::ul/descendant::');
+          $part_xpath .= 'li[contains(@class, :class)]/a[contains(@href, :href) and contains(text(), :title)]';
+          $part_args = array(
+            ':class' => 'active-trail',
+            ':href' => url($link_path),
+            ':title' => $link_title,
+          );
+          $xpath .= $this->buildXPathQuery($part_xpath, $part_args);
+          $i++;
+        }
+        $elements = $this->xpath($xpath);
+        $this->assertTrue(!empty($elements), t('Active trail to current page was found in menu tree.'));
+
+        // Append prefix for active link asserted below.
+        $xpath .= '/following-sibling::ul/descendant::';
+      }
+      else {
+        $xpath .= '//';
+      }
+      $xpath_last_active = ($last_active ? 'and contains(@class, :class-active)' : '');
+      $xpath .= 'li[contains(@class, :class-trail)]/a[contains(@href, :href) ' . $xpath_last_active . 'and contains(text(), :title)]';
+      $args = array(
+        ':class-trail' => 'active-trail',
+        ':class-active' => 'active',
+        ':href' => url($active_link_path),
+        ':title' => $active_link_title,
+      );
+      $elements = $this->xpath($xpath, $args);
+      $this->assertTrue(!empty($elements), t('Active link %title was found in menu tree, including active trail links %tree.', array(
+        '%title' => $active_link_title,
+        '%tree' => implode(' » ', $tree),
+      )));
+    }
+  }
+
+  /**
+   * Returns the breadcrumb contents of the current page in the internal browser.
+   */
+  protected function getParts() {
+    $parts = array();
+    $elements = $this->xpath('//div[@class="breadcrumb"]/a');
+    if (!empty($elements)) {
+      foreach ($elements as $element) {
+        $parts[] = array(
+          'text' => (string) $element,
+          'href' => (string) $element['href'],
+          'title' => (string) $element['title'],
+        );
+      }
+    }
+    return $parts;
+  }
+}
diff --git a/modules/simpletest/tests/menu_test.info b/modules/simpletest/tests/menu_test.info
index 6ad9c2b4059b56b71750207f6b6a737e7e28b7bf..b1896e2c3dbff3652ef243194a84dc0d74e1360c 100644
--- a/modules/simpletest/tests/menu_test.info
+++ b/modules/simpletest/tests/menu_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = menu_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/menu_test.module b/modules/simpletest/tests/menu_test.module
index 4f84b158b94a5f774aa41029f750513897c2569d..be1233278890f78533c9eff2c51f02d232d60256 100644
--- a/modules/simpletest/tests/menu_test.module
+++ b/modules/simpletest/tests/menu_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: menu_test.module,v 1.15 2010/07/07 08:05:01 webchick Exp $
+// $Id: menu_test.module,v 1.17 2010/10/01 15:24:18 webchick Exp $
 
 /**
  * @file
@@ -77,7 +77,7 @@ function menu_test_menu() {
     'access arguments' => array('access content'),
   );
   $items['menu-test/hidden'] = array(
-    'title' => 'Menu test parent',
+    'title' => 'Hidden test root',
     'page callback' => 'node_page_default',
     'access arguments' => array('access content'),
   );
@@ -110,7 +110,6 @@ function menu_test_menu() {
     'title' => 'Customize menu',
     'page callback' => 'node_page_default',
     'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
   );
   $items['menu-test/hidden/menu/manage/%menu/list'] = array(
     'title' => 'List links',
@@ -135,7 +134,6 @@ function menu_test_menu() {
     'title' => 'Delete menu',
     'page callback' => 'node_page_default',
     'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
   );
 
   // Hidden tests; two dynamic arguments.
@@ -173,6 +171,41 @@ function menu_test_menu() {
     'context' => MENU_CONTEXT_NONE,
   );
 
+  // Breadcrumbs tests.
+  // @see MenuBreadcrumbTestCase
+  $base = array(
+    'page callback' => 'menu_test_callback',
+    'access callback' => TRUE,
+  );
+  // Local tasks: Second level below default local task.
+  $items['menu-test/breadcrumb/tasks'] = array(
+    'title' => 'Breadcrumbs test: Local tasks',
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/first'] = array(
+    'title' => 'First',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/second'] = array(
+    'title' => 'Second',
+    'type' => MENU_LOCAL_TASK,
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/first/first'] = array(
+    'title' => 'First first',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/first/second'] = array(
+    'title' => 'First second',
+    'type' => MENU_LOCAL_TASK,
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/second/first'] = array(
+    'title' => 'Second first',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  ) + $base;
+  $items['menu-test/breadcrumb/tasks/second/second'] = array(
+    'title' => 'Second second',
+    'type' => MENU_LOCAL_TASK,
+  ) + $base;
+
   // File inheritance tests. This menu item should inherit the page callback
   // system_admin_menu_block_page() and therefore render its children as links
   // on the page.
@@ -186,7 +219,6 @@ function menu_test_menu() {
     'description' => 'File inheritance test description',
     'page callback' => 'menu_test_callback',
     'access arguments' => array('access content'),
-    'type' => MENU_LOCAL_TASK,
   );
 
   $items['menu_login_callback'] = array(
diff --git a/modules/simpletest/tests/module_test.info b/modules/simpletest/tests/module_test.info
index d40aa343fb22fcfd04e14c3243d2c4dd1f4bc4c4..e7325a2bea34dbe2d83e7c711f10dbe60512563e 100644
--- a/modules/simpletest/tests/module_test.info
+++ b/modules/simpletest/tests/module_test.info
@@ -8,8 +8,8 @@ files[] = module_test.module
 files[] = module_test.file.inc
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/module_test.module b/modules/simpletest/tests/module_test.module
index c84a45758697feedce727aa06b676037fa500bee..a379ce956a2b809294e193d400318c6f16a1f834 100644
--- a/modules/simpletest/tests/module_test.module
+++ b/modules/simpletest/tests/module_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: module_test.module,v 1.6 2010/04/22 18:56:31 dries Exp $
+// $Id: module_test.module,v 1.8 2010/10/05 00:22:24 webchick Exp $
 
 /**
  * Implements hook_permission().
@@ -36,6 +36,9 @@ function module_test_system_info_alter(&$info, $file, $type) {
       $info['dependencies'][] = 'php';
     }
   }
+  if ($file->name == 'seven' && $type == 'theme') {
+    $info['regions']['test_region'] = t('Test region');
+  }
 }
 
 /**
@@ -47,3 +50,10 @@ function module_test_hook_info() {
   );
   return $hooks;
 }
+
+/**
+ * Implements hook_modules_enabled().
+ */
+function module_test_modules_enabled($modules) {
+  variable_set('test_module_enable_order', $modules);
+}
diff --git a/modules/simpletest/tests/requirements1_test.info b/modules/simpletest/tests/requirements1_test.info
index 9e269ab5b4f37ffe011445148de1bf5249786611..2bcdb9aa4ce306ec105bf8a4f6130cca76b166fe 100644
--- a/modules/simpletest/tests/requirements1_test.info
+++ b/modules/simpletest/tests/requirements1_test.info
@@ -8,8 +8,8 @@ files[] = requirements1_test.install
 files[] = requirements1_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/requirements2_test.info b/modules/simpletest/tests/requirements2_test.info
index ba6e576e8b8a880137d1581651b8a50ce74db650..1265a6ef086a908c3d48dbf987e073cd5d0d4d2a 100644
--- a/modules/simpletest/tests/requirements2_test.info
+++ b/modules/simpletest/tests/requirements2_test.info
@@ -9,8 +9,8 @@ core = 7.x
 files[] = requirements2_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/schema.test b/modules/simpletest/tests/schema.test
index 0f815b7ab5e6bacfff99acf997581557e8973551..b9964a1afb2132af843f00a7d60ab50a3631235e 100644
--- a/modules/simpletest/tests/schema.test
+++ b/modules/simpletest/tests/schema.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: schema.test,v 1.21 2010/08/05 23:53:38 webchick Exp $
+// $Id: schema.test,v 1.22 2010/09/28 02:30:32 dries Exp $
 
 /**
  * @file
@@ -169,7 +169,7 @@ class SchemaTestCase extends DrupalWebTestCase {
     }
 
     // Finally, check each column and try to insert invalid values into them.
-    foreach($table_spec['fields'] as $column_name => $column_spec) {
+    foreach ($table_spec['fields'] as $column_name => $column_spec) {
       $this->assertTrue(db_field_exists($table_name, $column_name), t('Unsigned @type column was created.', array('@type' => $column_spec['type'])));
       $this->assertFalse($this->tryUnsignedInsert($table_name, $column_name), t('Unsigned @type column rejected a negative value.', array('@type' => $column_spec['type'])));
     }
diff --git a/modules/simpletest/tests/session_test.info b/modules/simpletest/tests/session_test.info
index 570a15f46a4602a27b519831de9dd148c93bb2ac..167e6a175449f25e7a45f2afd6e9f2692e670410 100644
--- a/modules/simpletest/tests/session_test.info
+++ b/modules/simpletest/tests/session_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = session_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/system.base.css b/modules/simpletest/tests/system.base.css
new file mode 100644
index 0000000000000000000000000000000000000000..a1348a510e296c66f87935e1747f8a89d40a9c6a
--- /dev/null
+++ b/modules/simpletest/tests/system.base.css
@@ -0,0 +1,7 @@
+/* $Id: system.base.css,v 1.1 2010/10/06 03:34:09 webchick Exp $ */
+
+/**
+ * This file is for testing CSS file override in
+ * CascadingStylesheetsTestCase::testRenderOverride().
+ * No contents are necessary.
+ */
diff --git a/modules/simpletest/tests/system_dependencies_test.info b/modules/simpletest/tests/system_dependencies_test.info
index 77ba2a83f31b347c5da9030df1d3dd0884aaae16..ebbf0d527ab2aac1f0aa2e0c51139d1078770744 100644
--- a/modules/simpletest/tests/system_dependencies_test.info
+++ b/modules/simpletest/tests/system_dependencies_test.info
@@ -8,8 +8,8 @@ files[] = system_dependencies_test.module
 hidden = TRUE
 dependencies[] = _missing_dependency
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/system_test.info b/modules/simpletest/tests/system_test.info
index 079d22fd53ad6a18bd74357fe3cb8e4d9877218b..0e4d11103b1b7712075913e388167b451b025d9b 100644
--- a/modules/simpletest/tests/system_test.info
+++ b/modules/simpletest/tests/system_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = system_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/taxonomy_test.info b/modules/simpletest/tests/taxonomy_test.info
index 94b2c01373d2a7b43ed4b403385365d7514478bb..1868421eee4f01a983700f89ee8046de6173731c 100644
--- a/modules/simpletest/tests/taxonomy_test.info
+++ b/modules/simpletest/tests/taxonomy_test.info
@@ -8,8 +8,8 @@ files[] = taxonomy_test.module
 hidden = TRUE
 dependencies[] = taxonomy
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/theme.test b/modules/simpletest/tests/theme.test
index 1b5c1c84d7de35f7f74149be4dff54eadb195cfd..09e03d4517aa9653995e5efe0c908c08a2da4eb0 100644
--- a/modules/simpletest/tests/theme.test
+++ b/modules/simpletest/tests/theme.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: theme.test,v 1.20 2010/08/22 12:46:21 dries Exp $
+// $Id: theme.test,v 1.22 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -74,6 +74,29 @@ class ThemeUnitTest extends DrupalWebTestCase {
     $this->drupalGet('theme-test/alter');
     $this->assertText('The altered data is test_theme_theme_test_alter_alter was invoked.', t('The theme was able to implement an alter hook during page building before anything was rendered.'));
   }
+
+  /**
+   * Ensures a theme's .info file is able to override a module CSS file from being added to the page.
+   *
+   * @see test_theme.info
+   */
+  function testCSSOverride() {
+    // Reuse the same page as in testPreprocessForSuggestions(). We're testing
+    // what is output to the HTML HEAD based on what is in a theme's .info file,
+    // so it doesn't matter what page we get, as long as it is themed with the
+    // test theme. First we test with CSS aggregation disabled.
+    variable_set('preprocess_css', 0);
+    $this->drupalGet('theme-test/suggestion');
+    $this->assertNoText('system.base.css', t('The theme\'s .info file is able to override a module CSS file from being added to the page.'));
+
+    // Also test with aggregation enabled, simply ensuring no PHP errors are
+    // triggered during drupal_build_css_cache() when a source file doesn't
+    // exist. Then allow remaining tests to continue with aggregation disabled
+    // by default.
+    variable_set('preprocess_css', 1);
+    $this->drupalGet('theme-test/suggestion');
+    variable_set('preprocess_css', 0);
+  }
 }
 
 /**
@@ -159,7 +182,7 @@ class ThemeItemListUnitTest extends DrupalWebTestCase {
 </ul></div></li>
 <li class="last">e</li>
 </ul></div>';
-    $output = theme('item_list', array('items' => $items, 'type' => 'ul', 'title' => NULL, 'attributes' => array()));
+    $output = theme('item_list', array('items' => $items));
     $this->assertIdentical($expected, $output, 'Nested list is rendered correctly.');
   }
 }
diff --git a/modules/simpletest/tests/theme_test.info b/modules/simpletest/tests/theme_test.info
index ab59809d428ad272dd2bd0d14a9807687a1b0743..3f168f3a1b4a5fa980b5fd1b82b9886a506d02d3 100644
--- a/modules/simpletest/tests/theme_test.info
+++ b/modules/simpletest/tests/theme_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = theme_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/update_test_1.info b/modules/simpletest/tests/update_test_1.info
index 350de123e785a012883a9981a33cc9db730bd401..44579a1dedf6e014c2c2b8da56e17d2e1b5c5268 100644
--- a/modules/simpletest/tests/update_test_1.info
+++ b/modules/simpletest/tests/update_test_1.info
@@ -8,8 +8,8 @@ files[] = update_test_1.module
 files[] = update_test_1.install
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/update_test_2.info b/modules/simpletest/tests/update_test_2.info
index 90595f0ea3064e9b7e09db102a25a28355272ae5..3955cddf3fa009a7e6af06b497a2b8a7e1d05c49 100644
--- a/modules/simpletest/tests/update_test_2.info
+++ b/modules/simpletest/tests/update_test_2.info
@@ -8,8 +8,8 @@ files[] = update_test_2.module
 files[] = update_test_2.install
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/update_test_3.info b/modules/simpletest/tests/update_test_3.info
index 015493b7724f6b200a9ddb7951532843ec14fc7b..baeea5f94e57bed8ef3529061c43ee2616917686 100644
--- a/modules/simpletest/tests/update_test_3.info
+++ b/modules/simpletest/tests/update_test_3.info
@@ -8,8 +8,8 @@ files[] = update_test_3.module
 files[] = update_test_3.install
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/upgrade/drupal-6.filled.database.php b/modules/simpletest/tests/upgrade/drupal-6.filled.database.php
index d603da94c76424ff4c0c03555d11d43fba701b44..1a0f4643e04ee7167bcbbad0f6c6c88de418869a 100644
--- a/modules/simpletest/tests/upgrade/drupal-6.filled.database.php
+++ b/modules/simpletest/tests/upgrade/drupal-6.filled.database.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: drupal-6.filled.database.php,v 1.3 2010/09/11 00:39:49 webchick Exp $
+// $Id: drupal-6.filled.database.php,v 1.4 2010/10/04 14:51:16 webchick Exp $
 
 /**
  * @file
@@ -13265,6 +13265,11 @@ db_insert('term_node')->fields(array(
   'vid',
   'tid',
 ))
+->values(array(
+  'nid' => '1',
+  'vid' => '1',
+  'tid' => '0',
+))
 ->values(array(
   'nid' => '1',
   'vid' => '1',
diff --git a/modules/simpletest/tests/upgrade/drupal-6.locale.database.php b/modules/simpletest/tests/upgrade/drupal-6.locale.database.php
new file mode 100644
index 0000000000000000000000000000000000000000..e96ca3ab5b17cc3b8528d9604385876ee87fe2ac
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-6.locale.database.php
@@ -0,0 +1,277 @@
+<?php
+// $Id: drupal-6.locale.database.php,v 1.1 2010/10/05 20:04:19 webchick Exp $
+
+/**
+ * Database additions for locale tests.
+ */
+
+db_create_table('languages', array(
+  'fields' => array(
+    'language' => array(
+      'type' => 'varchar',
+      'length' => 12,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'name' => array(
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'native' => array(
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'direction' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'enabled' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'plurals' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'formula' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'domain' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'prefix' => array(
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'weight' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'javascript' => array(
+      'type' => 'varchar',
+      'length' => 32,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+  ),
+  'primary key' => array(
+    'language',
+  ),
+  'indexes' => array(
+    'list' => array(
+      'weight',
+      'name',
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'languages',
+));
+db_insert('languages')->fields(array(
+  'language',
+  'name',
+  'native',
+  'direction',
+  'enabled',
+  'plurals',
+  'formula',
+  'domain',
+  'prefix',
+  'weight',
+  'javascript',
+))
+->values(array(
+  'language' => 'en',
+  'name' => 'English',
+  'native' => 'English',
+  'direction' => '0',
+  'enabled' => '1',
+  'plurals' => '0',
+  'formula' => '',
+  'domain' => 'http://en.example.com',
+  'prefix' => 'en',
+  'weight' => '0',
+  'javascript' => '',
+))
+->values(array(
+  'language' => 'fr',
+  'name' => 'French',
+  'native' => 'Français',
+  'direction' => '0',
+  'enabled' => '1',
+  'plurals' => '2',
+  'formula' => '($n>1)',
+  'domain' => '',
+  'prefix' => 'fr',
+  'weight' => '-3',
+  'javascript' => '51e92dcfe1491f4595b9df7f3b287753',
+))
+->execute();
+
+db_create_table('locales_source', array(
+  'fields' => array(
+    'lid' => array(
+      'type' => 'serial',
+      'not null' => TRUE,
+    ),
+    'location' => array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'textgroup' => array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => 'default',
+    ),
+    'source' => array(
+      'type' => 'text',
+      'mysql_type' => 'blob',
+      'not null' => TRUE,
+    ),
+    'version' => array(
+      'type' => 'varchar',
+      'length' => 20,
+      'not null' => TRUE,
+      'default' => 'none',
+    ),
+  ),
+  'primary key' => array(
+    'lid',
+  ),
+  'indexes' => array(
+    'source' => array(
+      array(
+        'source',
+        30,
+      ),
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'locales_source',
+));
+
+db_create_table('locales_target', array(
+  'fields' => array(
+    'lid' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'translation' => array(
+      'type' => 'text',
+      'mysql_type' => 'blob',
+      'not null' => TRUE,
+    ),
+    'language' => array(
+      'type' => 'varchar',
+      'length' => 12,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'plid' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'plural' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+  ),
+  'primary key' => array(
+    'language',
+    'lid',
+    'plural',
+  ),
+  'indexes' => array(
+    'lid' => array(
+      'lid',
+    ),
+    'plid' => array(
+      'plid',
+    ),
+    'plural' => array(
+      'plural',
+    ),
+  ),
+  'module' => 'locale',
+  'name' => 'locales_target',
+));
+
+// Enable the locale module.
+db_update('system')->fields(array(
+  'status' => 1,
+  'schema_version' => '6006',
+))
+->condition('type', 'module')
+->condition('name', 'locale')
+->execute();
+
+// Set the default language.
+db_insert('variable')->fields(array(
+  'name',
+  'value',
+))
+->values(array(
+  'name' => 'language_default',
+  'value' => 'O:8:"stdClass":11:{s:8:"language";s:2:"fr";s:4:"name";s:6:"French";s:6:"native";s:9:"Français";s:9:"direction";s:1:"0";s:7:"enabled";i:1;s:7:"plurals";s:1:"2";s:7:"formula";s:6:"($n>1)";s:6:"domain";s:0:"";s:6:"prefix";s:0:"";s:6:"weight";s:2:"-3";s:10:"javascript";s:32:"51e92dcfe1491f4595b9df7f3b287753";}',
+))
+->values(array(
+  'name' => 'language_count',
+  'value' => 'i:2;',
+))
+->values(array(
+  'name' => 'language_negotiation',
+  'value' => 'i:0;',
+))
+->execute();
+
+// Add the language switcher block in the left region.
+db_insert('blocks')->fields(array(
+  'module',
+  'delta',
+  'theme',
+  'status',
+  'weight',
+  'region',
+  'custom',
+  'throttle',
+  'visibility',
+  'pages',
+  'title',
+  'cache',
+))
+->values(array(
+  'module' => 'locale',
+  'delta' => '0',
+  'theme' => 'garland',
+  'status' => '1',
+  'weight' => '0',
+  'region' => 'left',
+  'custom' => '0',
+  'throttle' => '0',
+  'visibility' => '0',
+  'pages' => '',
+  'title' => '',
+  'cache' => '-1',
+))
+->execute();
diff --git a/modules/simpletest/tests/upgrade/drupal-6.upload.database.php b/modules/simpletest/tests/upgrade/drupal-6.upload.database.php
new file mode 100644
index 0000000000000000000000000000000000000000..68ea00a4d4172193d2d4b674444e8416740db6ef
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/drupal-6.upload.database.php
@@ -0,0 +1,358 @@
+<?php
+// $Id: drupal-6.upload.database.php,v 1.1 2010/10/03 23:19:52 webchick Exp $
+
+db_insert('files')->fields(array(
+  'fid',
+  'uid',
+  'filename',
+  'filepath',
+  'filemime',
+  'filesize',
+  'status',
+  'timestamp',
+))
+->values(array(
+  'fid' => '1',
+  'uid' => '1',
+  'filename' => 'powered-blue-80x15.png',
+  'filepath' => 'sites/default/files/powered-blue-80x15.png',
+  'filemime' => 'image/png',
+  'filesize' => '1011',
+  'status' => '1',
+  'timestamp' => '1285700240',
+))
+->values(array(
+  'fid' => '2',
+  'uid' => '1',
+  'filename' => 'powered-blue-80x15.png',
+  'filepath' => 'sites/default/files/powered-blue-80x15_0.png',
+  'filemime' => 'image/png',
+  'filesize' => '1011',
+  'status' => '1',
+  'timestamp' => '1285700317',
+))
+->values(array(
+  'fid' => '3',
+  'uid' => '1',
+  'filename' => 'powered-blue-88x31.png',
+  'filepath' => 'sites/default/files/powered-blue-88x31.png',
+  'filemime' => 'image/png',
+  'filesize' => '2113',
+  'status' => '1',
+  'timestamp' => '1285700343',
+))
+->values(array(
+  'fid' => '4',
+  'uid' => '1',
+  'filename' => 'powered-blue-135x42.png',
+  'filepath' => 'sites/default/files/powered-blue-135x42.png',
+  'filemime' => 'image/png',
+  'filesize' => '3027',
+  'status' => '1',
+  'timestamp' => '1285700366',
+))
+->values(array(
+  'fid' => '5',
+  'uid' => '1',
+  'filename' => 'powered-black-80x15.png',
+  'filepath' => 'sites/default/files/powered-black-80x15.png',
+  'filemime' => 'image/png',
+  'filesize' => '1467',
+  'status' => '1',
+  'timestamp' => '1285700529',
+))
+->values(array(
+  'fid' => '6',
+  'uid' => '1',
+  'filename' => 'powered-black-135x42.png',
+  'filepath' => 'sites/default/files/powered-black-135x42.png',
+  'filemime' => 'image/png',
+  'filesize' => '2817',
+  'status' => '1',
+  'timestamp' => '1285700552',
+))
+->values(array(
+  'fid' => '7',
+  'uid' => '1',
+  'filename' => 'forum-hot-new.png',
+  'filepath' => 'sites/default/files/forum-hot-new.png',
+  'filemime' => 'image/png',
+  'filesize' => '237',
+  'status' => '1',
+  'timestamp' => '1285708937',
+))
+->values(array(
+  'fid' => '8',
+  'uid' => '1',
+  'filename' => 'forum-hot.png',
+  'filepath' => 'sites/default/files/forum-hot.png',
+  'filemime' => 'image/png',
+  'filesize' => '229',
+  'status' => '1',
+  'timestamp' => '1285708944',
+))
+->values(array(
+  'fid' => '9',
+  'uid' => '1',
+  'filename' => 'forum-new.png',
+  'filepath' => 'sites/default/files/forum-new.png',
+  'filemime' => 'image/png',
+  'filesize' => '175',
+  'status' => '1',
+  'timestamp' => '1285708950',
+))
+->values(array(
+  'fid' => '10',
+  'uid' => '1',
+  'filename' => 'forum-sticky.png',
+  'filepath' => 'sites/default/files/forum-sticky.png',
+  'filemime' => 'image/png',
+  'filesize' => '329',
+  'status' => '1',
+  'timestamp' => '1285708957',
+))
+->execute();
+
+db_insert('node')->fields(array(
+  'nid',
+  'vid',
+  'type',
+  'language',
+  'title',
+  'uid',
+  'status',
+  'created',
+  'changed',
+  'comment',
+  'promote',
+  'moderate',
+  'sticky',
+  'tnid',
+  'translate',
+))
+->values(array(
+  'nid' => '38',
+  'vid' => '51',
+  'type' => 'page',
+  'language' => '',
+  'title' => 'node title 38 revision 51',
+  'uid' => '1',
+  'status' => '1',
+  'created' => '1285700317',
+  'changed' => '1285700600',
+  'comment' => '0',
+  'promote' => '0',
+  'moderate' => '0',
+  'sticky' => '0',
+  'tnid' => '0',
+  'translate' => '0',
+))
+->values(array(
+  'nid' => '39',
+  'vid' => '52',
+  'type' => 'page',
+  'language' => '',
+  'title' => 'node title 39 revision 53',
+  'uid' => '1',
+  'status' => '1',
+  'created' => '1285709012',
+  'changed' => '1285709012',
+  'comment' => '0',
+  'promote' => '0',
+  'moderate' => '0',
+  'sticky' => '0',
+  'tnid' => '0',
+  'translate' => '0',
+))
+ ->execute();
+
+db_insert('node_revisions')->fields(array(
+  'nid',
+  'vid',
+  'uid',
+  'title',
+  'body',
+  'teaser',
+  'log',
+  'timestamp',
+  'format',
+))
+->values(array(
+  'nid' => '38',
+  'vid' => '50',
+  'uid' => '1',
+  'title' => 'node title 38 revision 50',
+  'body' => "Attachments:\r\npowered-blue-80x15.png\r\npowered-blue-88x31.png\r\npowered-blue-135x42.png",
+  'teaser' => "Attachments:\r\npowered-blue-80x15.png\r\npowered-blue-88x31.png\r\npowered-blue-135x42.png",
+  'log' => '',
+  'timestamp' => '1285700487',
+  'format' => '1',
+))
+->values(array(
+  'nid' => '38',
+  'vid' => '51',
+  'uid' => '1',
+  'title' => 'node title 38 revision 51',
+  'body' => "Attachments:\r\npowered-blue-88x31.png\r\npowered-black-80x15.png\r\npowered-black-135x42.png",
+  'teaser' => "Attachments:\r\npowered-blue-88x31.png\r\npowered-black-80x15.png\r\npowered-black-135x42.png",
+  'log' => '',
+  'timestamp' => '1285700600',
+  'format' => '1',
+))
+->values(array(
+  'nid' => '39',
+  'vid' => '52',
+  'uid' => '1',
+  'title' => 'node title 39 revision 53',
+  'body' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png",
+  'teaser' => "Attachments:\r\nforum-hot-new.png\r\nforum-hot.png\r\nforum-sticky.png\r\nforum-new.png",
+  'log' => '',
+  'timestamp' => '1285709012',
+  'format' => '1',
+))
+ ->execute();
+
+db_create_table('upload', array(
+  'fields' => array(
+    'fid' => array(
+      'type' => 'int',
+      'unsigned' => TRUE,
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'nid' => array(
+      'type' => 'int',
+      'unsigned' => TRUE,
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'vid' => array(
+      'type' => 'int',
+      'unsigned' => TRUE,
+      'not null' => TRUE,
+      'default' => 0,
+    ),
+    'description' => array(
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+    ),
+    'list' => array(
+      'type' => 'int',
+      'unsigned' => TRUE,
+      'not null' => TRUE,
+      'default' => 0,
+      'size' => 'tiny',
+    ),
+    'weight' => array(
+      'type' => 'int',
+      'not null' => TRUE,
+      'default' => 0,
+      'size' => 'tiny',
+    ),
+  ),
+  'primary key' => array(
+    'vid',
+    'fid',
+  ),
+  'indexes' => array(
+    'fid' => array(
+      'fid',
+    ),
+    'nid' => array(
+      'nid',
+    ),
+  ),
+  'module' => 'upload',
+  'name' => 'upload',
+));
+db_insert('upload')->fields(array(
+  'fid',
+  'nid',
+  'vid',
+  'description',
+  'list',
+  'weight',
+))
+->values(array(
+  'fid' => '2',
+  'nid' => '38',
+  'vid' => '50',
+  'description' => 'powered-blue-80x15.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '3',
+  'nid' => '38',
+  'vid' => '50',
+  'description' => 'powered-blue-88x31.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '4',
+  'nid' => '38',
+  'vid' => '50',
+  'description' => 'powered-blue-135x42.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '3',
+  'nid' => '38',
+  'vid' => '51',
+  'description' => 'powered-blue-88x31.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '5',
+  'nid' => '38',
+  'vid' => '51',
+  'description' => 'powered-black-80x15.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '6',
+  'nid' => '38',
+  'vid' => '51',
+  'description' => 'powered-black-135x42.png',
+  'list' => '1',
+  'weight' => '0',
+))
+->values(array(
+  'fid' => '7',
+  'nid' => '39',
+  'vid' => '52',
+  'description' => 'forum-hot-new.png',
+  'list' => '1',
+  'weight' => '-4',
+))
+->values(array(
+  'fid' => '8',
+  'nid' => '39',
+  'vid' => '52',
+  'description' => 'forum-hot.png',
+  'list' => '1',
+  'weight' => '-3',
+))
+->values(array(
+  'fid' => '10',
+  'nid' => '39',
+  'vid' => '52',
+  'description' => 'forum-sticky.png',
+  'list' => '1',
+  'weight' => '-2',
+))
+->values(array(
+  'fid' => '9',
+  'nid' => '39',
+  'vid' => '52',
+  'description' => 'forum-new.png',
+  'list' => '1',
+  'weight' => '-1',
+))
+->execute();
diff --git a/modules/simpletest/tests/upgrade/upgrade.locale.test b/modules/simpletest/tests/upgrade/upgrade.locale.test
new file mode 100644
index 0000000000000000000000000000000000000000..2d83acdb47910c078e1137740d3a758914170f48
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/upgrade.locale.test
@@ -0,0 +1,144 @@
+<?php
+// $Id: upgrade.locale.test,v 1.1 2010/10/06 20:38:29 webchick Exp $
+
+/**
+ * Upgrade test for locale.module.
+ */
+class LocaleUpgradePathTestCase extends UpgradePathTestCase {
+  public static function getInfo() {
+    return array(
+      'name'  => 'Locale upgrade path',
+      'description'  => 'Upgrade path tests for the Locale module.',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    // Path to the database dump files.
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php',
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.locale.database.php',
+    );
+    parent::setUp();
+
+    $this->uninstallModulesExcept(array('locale', 'comment'));
+  }
+
+  /**
+   * Test a successful upgrade (no negotiation).
+   */
+  public function testLocaleUpgrade() {
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // No prefixed page should exist.
+    $this->drupalGet('en');
+    $this->assertResponse(404);
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+  }
+
+  /**
+   * Test an upgrade with path-based negotiation.
+   */
+  public function testLocaleUpgradePathDefault() {
+    // LANGUAGE_NEGOTIATION_PATH_DEFAULT.
+    $this->variable_set('language_negotiation', 1);
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+
+    // The French prefix should not be active because French is the default language.
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+
+    // The English prefix should be active.
+    $this->assertPageInLanguage('en', 'en');
+  }
+
+  /**
+   * Test an upgrade with path-based (with fallback) negotiation.
+   */
+  public function testLocaleUpgradePathFallback() {
+    // LANGUAGE_NEGOTIATION_PATH.
+    $this->variable_set('language_negotiation', 2);
+
+    // Set the language of the admin user to English.
+    db_update('users')
+      ->fields(array('language' => 'en'))
+      ->condition('uid', 1)
+      ->execute();
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // Both prefixes should be active.
+    $this->assertPageInLanguage('fr', 'fr');
+    $this->assertPageInLanguage('en', 'en');
+
+    // The home page should be in the admin user language.
+    $this->assertPageInLanguage('', 'en');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+  }
+
+  /**
+   * Test an upgrade with domain-based negotiation.
+   */
+  public function testLocaleUpgradeDomain() {
+    // LANGUAGE_NEGOTIATION_DOMAIN.
+    $this->variable_set('language_negotiation', 3);
+
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+
+    // The home page should be in French.
+    $this->assertPageInLanguage('', 'fr');
+
+    // The language switcher block should be displayed.
+    $this->assertRaw('block-locale-language', t('The language switcher block is displayed.'));
+
+    // The language switcher block should point to http://en.example.com.
+    $language_links = $this->xpath('//ul[contains(@class, :class)]/li/a', array(':class' => 'language-switcher-locale-url'));
+    $found_english_link = FALSE;
+    foreach ($language_links as $link) {
+      if ((string) $link['href'] == 'http://en.example.com/') {
+        $found_english_link = TRUE;
+      }
+    }
+    $this->assertTrue($found_english_link, t('The English link points to the correct domain.'));
+
+    // Both prefixes should be inactive.
+    $this->drupalGet('en');
+    $this->assertResponse(404);
+    $this->drupalGet('fr');
+    $this->assertResponse(404);
+
+  }
+
+  /**
+   * Asserts that a page exists and is in the specified language.
+   */
+  public function assertPageInLanguage($path = NULL, $langcode) {
+    if (isset($path)) {
+      $this->drupalGet($path);
+    }
+
+    if (!$this->assertResponse(200)) {
+      return FALSE;
+    }
+
+    if ($this->parse()) {
+      return $this->assertIdentical($langcode, (string) $this->elements['xml:lang']);
+    }
+    else {
+      return FALSE;
+    }
+  }
+}
diff --git a/modules/simpletest/tests/upgrade/upgrade.node.test b/modules/simpletest/tests/upgrade/upgrade.node.test
index a3e2b10f35850cd5f89b5efd3e848d52e8e71b05..d5d03b11c62c8a54610407470f78dcb46b46e208 100644
--- a/modules/simpletest/tests/upgrade/upgrade.node.test
+++ b/modules/simpletest/tests/upgrade/upgrade.node.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: upgrade.node.test,v 1.2 2010/09/13 05:50:09 webchick Exp $
+// $Id: upgrade.node.test,v 1.3 2010/10/01 22:03:29 webchick Exp $
 
 /**
  * Upgrade test for node bodies.
@@ -26,10 +26,19 @@ class NodeBodyUpgradePathTestCase extends UpgradePathTestCase {
   /**
    * Test a successful upgrade.
    */
-  public function testNodyBodyUpgrade() {
+  public function testNodeBodyUpgrade() {
     $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
     $this->drupalGet("content/1263769200");
     $this->assertText('node body (broken) - 37');
+
+    // Find a published node revision and make sure it still has a body.
+    $revision = db_query_range("SELECT r.nid, r.vid FROM {node_revision} r JOIN {node} n ON n.nid = r.nid WHERE n.status = 1 AND n.type <> 'poll' AND n.vid <> r.vid", 0, 1)->fetch();
+    $revision = node_load($revision->nid, $revision->vid);
+    $this->assertTrue(!empty($revision->body), 'Non-current node revisions still have a node body.');
+    // Find an unpublished node revision and make sure it still has a body.
+    $revision = db_query_range("SELECT r.nid, r.vid FROM {node_revision} r JOIN {node} n ON n.nid = r.nid WHERE n.status = 0 AND n.type <> 'poll' AND n.vid <> r.vid", 0, 1)->fetch();
+    $revision = node_load($revision->nid, $revision->vid);
+    $this->assertTrue(!empty($revision->body), 'Unpublished non-current node revisions still have a node body.');
   }
 }
 
diff --git a/modules/simpletest/tests/upgrade/upgrade.taxonomy.test b/modules/simpletest/tests/upgrade/upgrade.taxonomy.test
index 3d2d0fb726de588998fdbc7bb362076784ca31ea..b3f795ae0403d3974bce260e310ac0e63e5dfa68 100644
--- a/modules/simpletest/tests/upgrade/upgrade.taxonomy.test
+++ b/modules/simpletest/tests/upgrade/upgrade.taxonomy.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: upgrade.taxonomy.test,v 1.2 2010/09/13 05:50:09 webchick Exp $
+// $Id: upgrade.taxonomy.test,v 1.6 2010/10/06 21:53:41 webchick Exp $
 
 /**
  * Test taxonomy upgrades.
@@ -34,8 +34,8 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
         foreach ($field['settings']['allowed_values'] as $tree) {
           // Prefer valid taxonomy term reference fields for a given vocabulary
           // when they exist.
-          if (empty($instances[$tree['vid']]) || $instances[$tree['vid']] == 'taxonomyextra') {
-            $instances[$tree['vid']] = $field['field_name'];
+          if (empty($instances[$tree['vocabulary']]) || $instances[$tree['vocabulary']] == 'taxonomyextra') {
+            $instances[$tree['vocabulary']] = $field['field_name'];
           }
         }
       }
@@ -59,8 +59,10 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
 
     // Check that the node type 'page' has been associated to a taxonomy
     // reference field for each vocabulary.
-    $vocabularies = taxonomy_get_vocabularies();
-    $voc_keys = array_keys($vocabularies);
+    $voc_keys = array();
+    foreach (taxonomy_get_vocabularies() as $vocab) {
+      $voc_keys[] = $vocab->machine_name;
+    }
     $instances = $this->instanceVocabularies('node', 'page');
     $inst_keys = array_keys($instances);
     sort($voc_keys);
@@ -70,7 +72,7 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
     // Node type 'story' was not explicitly in $vocabulary->nodes but
     // each node of type 'story' was associated to one or more terms.
     // Check that the node type 'story' has been associated only to
-    // the taxonomyextra field. 
+    // the taxonomyextra field.
     $instances = $this->instanceVocabularies('node', 'story');
     $field_names = array_flip($instances);
     $this->assertEqual(count($field_names), 1, t('Only one taxonomy term field instance exists for story nodes'));
@@ -88,6 +90,8 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
     $nodes += node_load_multiple(array(), array('type' => 'story'));
     $terms = db_select('taxonomy_term_data', 'td')
       ->fields('td')
+      ->orderBy('vid')
+      ->orderBy('tid')
       ->execute()
       ->fetchAllAssoc('tid');
     field_attach_prepare_view('node', $nodes, 'full');
@@ -95,27 +99,67 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
       $node->content = field_attach_view('node', $node, 'full');
       $render = drupal_render($node->content);
       $this->drupalSetContent($render);
-      debug("Testing node $nid");
       $this->verbose($render);
+
+      $vocabulary_seen = array();
       foreach ($terms as $tid => $term) {
+        // In our test database, each node is arbitrary associated with all
+        // terms except two: one whose tid is ($nid) and one whose tid is
+        // (49 - $nid).
+        $should_be_displayed = ($tid != $nid) && ($tid + $nid != 49);
+
+        // Only vocabularies 13 to 24 are properly associated with the node
+        // type 'page'. All other node types are not associated with any
+        // vocabulary, but still are associated with terms. Those terms
+        // will be moved to the taxonomy extra field.
+        if ($node->type == 'page' && $term->vid >= 13 && $term->vid <= 24) {
+          $vocabulary = taxonomy_vocabulary_load($term->vid);
+          $field_class = 'field-name-' . strtr('taxonomy_' . $vocabulary->machine_name, '_', '-');;
+        }
+        else {
+          $field_class = 'field-name-taxonomyextra';
+        }
+
+        // Odd vocabularies are single, so any additional term will be moved
+        // to the taxonomy extra field.
+        if ($should_be_displayed) {
+          if ($term->vid % 2 == 1 && !empty($vocabulary_seen[$term->vid])) {
+            $field_class = 'field-name-taxonomyextra';
+          }
+          $vocabulary_seen[$term->vid] = TRUE;
+        }
+
         $args = array(
           '%name' => $term->name,
-          '@tid' => $tid,
+          '@field' => $field_class,
           '%nid' => $nid,
         );
 
         // Use link rather than term name because migrated term names can be
         // substrings of other term names. e.g. "term 1 of vocabulary 2" is
         // found when "term 1 of vocabulary 20" is output.
-        $link = l($term->name, 'taxonomy/term/' . $term->tid);
-        if (($tid == $nid) || ($tid + $nid == 49)) {
-          $this->assertNoRaw($link, t('Term %name (@tid) is not displayed on node %nid', $args));
+        $term_path = url('taxonomy/term/' . $term->tid);
+        if (!$should_be_displayed) {
+          // Look for any link with the term path.
+          $links = $this->xpath('//a[@href=:term_path]', array(':term_path' => $term_path));
+          $this->assertFalse($links, t('Term %name (@field) is not displayed on node %nid', $args));
         }
         else {
-          $this->assertRaw($link, t('Term %name (@tid) is displayed on node %nid', $args));
+          // Look for a link with the term path inside the correct field.
+          // We search for "SPACE + class + SPACE" to avoid matching a substring
+          // of the class.
+          $links = $this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :field_class)]//a[@href=:term_path]', array(':field_class' => ' ' . $field_class . ' ', ':term_path' => $term_path));
+          $this->assertTrue($links, t('Term %name (@field) is displayed on node %nid', $args));
         }
       }
 
+      // nid 1, revision 1 had a bogus record in {term_node} pointing to term
+      // ID 0. Make sure we ignored this instead of generating a bogus term.
+      if ($node->nid == 1) {
+        $link = l($term->name, 'taxonomy/term/0');
+        $this->assertNoRaw($link, t('Bogus term (tid 0) is not displayed on node 1 vid %old_vid.', $args));
+      }
+
       // The first 12 nodes have two revisions. For nodes with
       // revisions, check that the oldest revision is associated only
       // to terms whose ID is equal to the node ID or 49 less the node ID.
@@ -134,10 +178,10 @@ class UpgradePathTaxonomyTestCase extends UpgradePathTestCase {
 
         $term = $terms[$node->nid];
         $link = l($term->name, 'taxonomy/term/' . $term->tid);
-        $this->assertRaw($link, t('Term %name (@tid) is displayed on node %nid vid %old_vid.', $args));
+        $this->assertRaw($link, t('Term %name (@field) is displayed on node %nid vid %old_vid.', $args));
         $term = $terms[49-$node->nid];
         $link = l($term->name, 'taxonomy/term/' . $term->tid);
-        $this->assertRaw($link, t('Term %name (@tid) is displayed on node %nid %old_vid.', $args));
+        $this->assertRaw($link, t('Term %name (@field) is displayed on node %nid %old_vid.', $args));
       }
       else {
         $this->assertEqual(count($revisions), 1, t('Node %nid has one revision.', $args));
diff --git a/modules/simpletest/tests/upgrade/upgrade.test b/modules/simpletest/tests/upgrade/upgrade.test
index c793fc75856e33db0b5cc17df5cbe762eba48416..0c819d09d548967fbe35d2fabdcc824a13af66ee 100644
--- a/modules/simpletest/tests/upgrade/upgrade.test
+++ b/modules/simpletest/tests/upgrade/upgrade.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: upgrade.test,v 1.7 2010/09/13 05:50:09 webchick Exp $
+// $Id: upgrade.test,v 1.8 2010/10/01 18:37:22 webchick Exp $
 
 /**
  * Perform end-to-end tests of the upgrade path.
@@ -283,9 +283,6 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
     drupal_static_reset();
     drupal_flush_all_caches();
 
-    // Register actions declared by any modules.
-    actions_synchronize();
-
     // Reload global $conf array and permissions.
     $this->refreshVariables();
     $this->checkPermissions(array(), TRUE);
diff --git a/modules/simpletest/tests/upgrade/upgrade.upload.test b/modules/simpletest/tests/upgrade/upgrade.upload.test
new file mode 100644
index 0000000000000000000000000000000000000000..a758420328034ef551ba3a189cff94159500e083
--- /dev/null
+++ b/modules/simpletest/tests/upgrade/upgrade.upload.test
@@ -0,0 +1,66 @@
+<?php
+// $Id: upgrade.upload.test,v 1.1 2010/10/03 23:19:52 webchick Exp $
+
+/**
+ * Upgrade test for comment.module.
+ */
+class UploadUpgradePathTestCase extends UpgradePathTestCase {
+  public static function getInfo() {
+    return array(
+      'name'  => 'Upload upgrade path',
+      'description'  => 'Upload upgrade path tests.',
+      'group' => 'Upgrade path',
+    );
+  }
+
+  public function setUp() {
+    // Path to the database dump files.
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php',
+      drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.upload.database.php',
+    );
+    parent::setUp();
+
+    $this->uninstallModulesExcept(array('upload'));
+  }
+
+  /**
+   * Test a successful upgrade.
+   */
+  public function testUploadUpgrade() {
+    $this->assertTrue($this->performUpgrade(), t('The upgrade was completed successfully.'));
+    $query = new EntityFieldQuery();
+    $query->entityCondition('entity_type', 'node');
+    $query->entityCondition('bundle', 'page');
+    $query->age(FIELD_LOAD_REVISION);
+    $query->fieldCondition('upload');
+    $entities = $query->execute();
+    $revisions = $entities['node'];
+    // Node revisions 50-52 should have uploaded files.
+    $this->assertTrue((isset($revisions[50]) && isset($revisions[51]) && isset($revisions[52])), 'Nodes with uploaded files now contain filefield data.');
+    // The test database lists uploaded filenames in the body of each node with
+    // uploaded files attached. Make sure all files are there in the same order.
+    foreach ($revisions as $vid => $revision) {
+      $node = node_load($revision->nid, $vid);
+
+      // Assemble a list of the filenames as recorded in the node body before
+      // the upgrade.
+      $recorded_filenames = preg_split('/\s+/', $node->body[LANGUAGE_NONE][0]['value']);
+      // The first line of the node body should be "Attachments:"
+      if (strstr($recorded_filenames[0], "Attachments:")) {
+        unset($recorded_filenames[0]);
+      }
+      $recorded_filenames = array_values($recorded_filenames);
+
+      $files = $node->upload[LANGUAGE_NONE];
+      // Assemble a list of the filenames as they exist after the upgrade.
+      $filenames = array();
+      foreach ($files as $file) {
+        $filenames[] = $file['filename'];
+      }
+
+      $diff = array_diff($filenames, $recorded_filenames);
+      $this->assertTrue(empty($diff), 'The uploaded files are present in the same order after the upgrade.');
+    }
+  }
+}
diff --git a/modules/simpletest/tests/url_alter_test.info b/modules/simpletest/tests/url_alter_test.info
index 2281be8e077cdf3d6aab53e39d6aa217ac2a67e8..97b453616d76caf3b1adb6963f528733141d5bb2 100644
--- a/modules/simpletest/tests/url_alter_test.info
+++ b/modules/simpletest/tests/url_alter_test.info
@@ -8,8 +8,8 @@ files[] = url_alter_test.module
 files[] = url_alter_test.install
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/xmlrpc.test b/modules/simpletest/tests/xmlrpc.test
index 8b8f2b55db7cf89d0bcfd17c817c444835679c96..3a3fe3435d5ca61070e3a679ef8d3135cbe9f160 100644
--- a/modules/simpletest/tests/xmlrpc.test
+++ b/modules/simpletest/tests/xmlrpc.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: xmlrpc.test,v 1.20 2010/08/14 03:15:01 dries Exp $
+// $Id: xmlrpc.test,v 1.21 2010/10/02 01:22:41 dries Exp $
 
 /**
  * Perform basic XML-RPC tests that do not require addition callbacks.
@@ -188,8 +188,8 @@ class XMLRPCValidator1IncTestCase extends DrupalWebTestCase {
 class XMLRPCMessagesTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
-      'name'  => 'XML-RPC message',
-      'description' => 'Test large messages.',
+      'name'  => 'XML-RPC message and alteration',
+      'description' => 'Test large messages and method alterations.',
       'group' => 'XML-RPC',
     );
   }
@@ -211,4 +211,25 @@ class XMLRPCMessagesTestCase extends DrupalWebTestCase {
       $this->assertEqual($xml_message_l, $xml_message_r, t('XML-RPC messages.messageSizedInKB of %s Kb size received', array('%s' => $size)));
     }
   }
+
+  /**
+   * Ensure that hook_xmlrpc_alter() can hide even builtin methods.
+   */
+  protected function testAlterListMethods() {
+
+    // Ensure xmlrpc_test_xmlrpc_alter() is disabled and retrieve regular list of methods.
+    variable_set('xmlrpc_test_xmlrpc_alter', FALSE);
+    $url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php';
+    $methods1 = xmlrpc($url, array('system.listMethods' => array()));
+
+    // Enable the alter hook and retrieve the list of methods again.
+    variable_set('xmlrpc_test_xmlrpc_alter', TRUE);
+    $methods2 = xmlrpc($url, array('system.listMethods' => array()));
+
+    $diff = array_diff($methods1, $methods2);
+    $this->assertTrue(is_array($diff) && !empty($diff), t('Method list is altered by hook_xmlrpc_alter'));
+    $removed = reset($diff);
+    $this->assertEqual($removed, 'system.methodSignature', t('Hiding builting system.methodSignature with hook_xmlrpc_alter works'));
+  }
+
 }
diff --git a/modules/simpletest/tests/xmlrpc_test.info b/modules/simpletest/tests/xmlrpc_test.info
index e7099cfb091714aa12a5f86c311783d528c109f6..9be23bff29d739338877a156a5aeba9f0e91b8cc 100644
--- a/modules/simpletest/tests/xmlrpc_test.info
+++ b/modules/simpletest/tests/xmlrpc_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = xmlrpc_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/simpletest/tests/xmlrpc_test.module b/modules/simpletest/tests/xmlrpc_test.module
index 80ddb5d0b48260516ba33acbc45f516ff5423674..f226aff65d28dae8ebb992707870762311c07e43 100644
--- a/modules/simpletest/tests/xmlrpc_test.module
+++ b/modules/simpletest/tests/xmlrpc_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: xmlrpc_test.module,v 1.5 2009/12/04 16:49:47 dries Exp $
+// $Id: xmlrpc_test.module,v 1.7 2010/10/02 01:22:41 dries Exp $
 
 function xmlrpc_test_arrayOfStructsTest($array) {
   $sum = 0;
@@ -63,6 +63,29 @@ function xmlrpc_test_xmlrpc() {
   );
 }
 
+/**
+ * Implements hook_xmlrpc_alter().
+ *
+ * Hide (or not) the system.methodSignature() service depending on a variable.
+ */
+function xmlrpc_test_xmlrpc_alter(&$services) {
+  if (variable_get('xmlrpc_test_xmlrpc_alter', FALSE)) {
+    $remove = NULL;
+    foreach ($services as $key => $value) {
+      if (!is_array($value)) {
+        continue;
+      }
+      if ($value[0] == 'system.methodSignature') {
+        $remove = $key;
+        break;
+      }
+    }
+    if (isset($remove)) {
+      unset($services[$remove]);
+    }
+  }
+}
+
 /**
  * Created a message of the desired size in KB.
  *
@@ -81,7 +104,7 @@ function xmlrpc_test_message_sized_in_kb($size) {
     $line['word_' . $i] = $word;
   }
 
-  for($i = 0; $i < $size; $i++) {
+  for ($i = 0; $i < $size; $i++) {
     $message['line_' . $i] = $line;
   }
 
diff --git a/modules/statistics/statistics.info b/modules/statistics/statistics.info
index 581b126db6a92e907d4c918bff52b21052e22d80..d7c56a67f4cc6648040c1b38ec7d4a83e7a327a3 100644
--- a/modules/statistics/statistics.info
+++ b/modules/statistics/statistics.info
@@ -12,8 +12,8 @@ files[] = statistics.test
 files[] = statistics.tokens.inc
 configure = admin/config/system/statistics
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/statistics/statistics.module b/modules/statistics/statistics.module
index 01f4de76c6d67fee955da380da57be2af1d9b022..23aac1f0a8a7f609d118d342dfa8857a5ca134d9 100644
--- a/modules/statistics/statistics.module
+++ b/modules/statistics/statistics.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: statistics.module,v 1.338 2010/08/30 05:58:46 webchick Exp $
+// $Id: statistics.module,v 1.339 2010/09/24 00:37:44 dries Exp $
 
 /**
  * @file
@@ -163,7 +163,6 @@ function statistics_menu() {
     'page callback' => 'statistics_access_log',
     'page arguments' => array(3),
     'access arguments' => array('access statistics'),
-    'type' => MENU_CALLBACK,
     'file' => 'statistics.admin.inc',
   );
   $items['admin/config/system/statistics'] = array(
diff --git a/modules/statistics/statistics.test b/modules/statistics/statistics.test
index 6a9da4f377c19a3ee6a596214010cc64ce6f5470..80f26e74b70330ad1bf99429d5236a019951f5be 100644
--- a/modules/statistics/statistics.test
+++ b/modules/statistics/statistics.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: statistics.test,v 1.22 2010/08/05 23:53:39 webchick Exp $
+// $Id: statistics.test,v 1.23 2010/09/24 00:37:44 dries Exp $
 
 /**
  * Sets up a base class for the Statistics module.
@@ -10,7 +10,15 @@ class StatisticsTestCase extends DrupalWebTestCase {
     parent::setUp('statistics');
 
     // Create user.
-    $this->blocking_user = $this->drupalCreateUser(array('block IP addresses', 'access statistics', 'administer blocks', 'administer statistics', 'administer users'));
+    $this->blocking_user = $this->drupalCreateUser(array(
+      'access administration pages',
+      'access site reports',
+      'access statistics',
+      'block IP addresses',
+      'administer blocks',
+      'administer statistics',
+      'administer users',
+    ));
     $this->drupalLogin($this->blocking_user);
 
     // Enable access logging.
diff --git a/modules/syslog/syslog.info b/modules/syslog/syslog.info
index b447adf364d04f1efa2226409f1c2e3d8a84bae2..61a704e26f36c166a1ab48870953cc06cd616382 100644
--- a/modules/syslog/syslog.info
+++ b/modules/syslog/syslog.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = syslog.module
 files[] = syslog.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/syslog/syslog.module b/modules/syslog/syslog.module
index d0a48dfdef6564a7f563217801ea219bd4877e01..83fc512a8ffc9af924230b9598fc005e42eb4467 100644
--- a/modules/syslog/syslog.module
+++ b/modules/syslog/syslog.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: syslog.module,v 1.37 2010/08/18 01:54:36 dries Exp $
+// $Id: syslog.module,v 1.38 2010/09/26 23:31:36 dries Exp $
 
 /**
  * @file
@@ -103,7 +103,7 @@ function syslog_watchdog(array $log_entry) {
     '!referer'     => $log_entry['referer'],
     '!uid'         => $log_entry['user']->uid,
     '!link'        => strip_tags($log_entry['link']),
-    '!message'     => strip_tags(is_null($log_entry['variables']) ? $log_entry['message'] : strtr($log_entry['message'], $log_entry['variables'])),
+    '!message'     => strip_tags(!isset($log_entry['variables']) ? $log_entry['message'] : strtr($log_entry['message'], $log_entry['variables'])),
   ));
 
   syslog($log_entry['severity'], $message);
diff --git a/modules/system/admin-rtl.css b/modules/system/admin-rtl.css
deleted file mode 100644
index cbf6195c8b7f291e1ce89338bbe969a0a03a4d9e..0000000000000000000000000000000000000000
--- a/modules/system/admin-rtl.css
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id: admin-rtl.css,v 1.7 2010/04/28 20:08:39 dries Exp $ */
-
-div.admin-panel .body {
-  padding: 0 8px 2px 4px;
-}
-
-div.admin .left {
-  float: right;
-  margin-left: 0;
-  margin-right: 1em;
-}
-div.admin .right {
-  float: left;
-  margin-left: 1em;
-  margin-right: 0;
-}
-
-div.admin .expert-link {
-  text-align: left;
-  margin-right: 0;
-  margin-left: 1em;
-  padding-right: 0;
-  padding-left: 4px;
-}
-
-table.system-status-report th,
-table.system-status-report tr.merge-up td {
-  padding-right: 30px;
-}
-
-table.system-status-report th {
-  background-position: 95% 50%;
-}
-
-table.screenshot {
-  margin-left: 1em;
-}
-
-.date-container {
-  clear: right;
-}
-.date-container .select-container,
-.date-container .custom-container {
-  float: right;
-}
-.date-container .custom-container {
-  margin-left: 0;
-  margin-right: 15px;
-}
-
diff --git a/modules/system/admin.css b/modules/system/admin.css
deleted file mode 100644
index 54df5af5ee07172c6dccbb03f336a02d2466258e..0000000000000000000000000000000000000000
--- a/modules/system/admin.css
+++ /dev/null
@@ -1,140 +0,0 @@
-/* $Id: admin.css,v 1.22 2010/04/28 20:08:39 dries Exp $ */
-
-/*
-** Formatting for administration page
-*/
-div.admin-panel {
-  margin: 0;
-  padding: 5px 5px 15px 5px;
-}
-
-div.admin-panel .description {
-  margin: 0 0 3px;
-  padding: 2px 0 3px 0;
-}
-
-div.admin-panel .body {
-  padding: 0 4px 2px 8px; /* LTR */
-}
-
-div.admin {
-  padding-top: 15px;
-}
-
-div.admin .left {
-  float: left; /* LTR */
-  width: 47%;
-  margin-left: 1em; /* LTR */
-}
-div.admin .right {
-  float: right; /* LTR */
-  width: 47%;
-  margin-right: 1em; /* LTR */
-}
-
-div.admin .expert-link {
-  text-align: right; /* LTR */
-  margin-right: 1em; /* LTR */
-  padding-right: 4px; /* LTR */
-}
-
-table.package {
-  width: 100%;
-}
-table.package .description {
-  width: 100%;
-}
-table.package .version {
-  direction: ltr;
-}
-div.admin-requirements,
-div.admin-required {
-  font-size: 0.9em;
-  color: #444;
-}
-span.admin-disabled {
-  color: #800;
-}
-span.admin-enabled {
-  color: #080;
-}
-span.admin-missing {
-  color: #f00;
-}
-
-/**
- * Formatting for status report
- */
-table.system-status-report th {
-  border-bottom: 1px solid #ccc;
-}
-table.system-status-report th,
-table.system-status-report tr.merge-up td {
-  padding-left: 30px; /* LTR */
-}
-table.system-status-report th {
-  background-repeat: no-repeat;
-  background-position: 5px 50%; /* LTR */
-  padding-top: 6px;
-  padding-bottom: 6px;
-}
-table.system-status-report tr.error th {
-  background-image: url(../../misc/watchdog-error.png);
-}
-table.system-status-report tr.warning th {
-  background-image: url(../../misc/watchdog-warning.png);
-}
-table.system-status-report tr.ok th {
-  background-image: url(../../misc/watchdog-ok.png);
-}
-
-/**
- * Formatting for theme configuration
- */
-.theme-settings-left {
-  float: left;
-  width: 49%;
-}
-.theme-settings-right {
-  float: right;
-  width: 49%;
-}
-.theme-settings-bottom {
-  clear: both;
-}
-
-/**
- * Formatting for theme overview
- */
-table.screenshot {
-  margin-right: 1em; /* LTR */
-}
-.theme-info h2 {
-  margin-bottom: 0;
-}
-.theme-info p {
-  margin-top: 0;
-}
-
-
-/**
- * Date and time settings page
- */
-.date-container {
-  overflow: auto;
-  clear: left; /* LTR */
-}
-.date-container .form-item {
-  margin-top: 0;
-}
-.date-container .select-container,
-.date-container .custom-container {
-  float: left; /* LTR */
-}
-.date-container .custom-container {
-  margin-left: 15px; /* LTR */
-  width: 50%;
-}
-html.js .custom-container label {
-  visibility: hidden;
-}
diff --git a/modules/system/image.gd.inc b/modules/system/image.gd.inc
index d035ab1ee664a66de753a9994b81798013052a93..17befdea821f2c3aaf9a98c0bb0455927fd2197f 100644
--- a/modules/system/image.gd.inc
+++ b/modules/system/image.gd.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: image.gd.inc,v 1.16 2010/07/19 22:20:49 dries Exp $
+// $Id: image.gd.inc,v 1.17 2010/09/21 15:28:11 dries Exp $
 
 /**
  * @file
@@ -244,18 +244,24 @@ function image_gd_load(stdClass $image) {
  * @param $image
  *   An image object.
  * @param $destination
- *   A string file path where the image should be saved.
- * @param $extension
- *   A string containing one of the following extensions: gif, jpg, jpeg, png.
+ *   A string file URI or path where the image should be saved.
  * @return
  *   TRUE or FALSE, based on success.
  *
  * @see image_save()
  */
 function image_gd_save(stdClass $image, $destination) {
-  // Convert URI to a normal path because PHP apparently has some gaps in stream wrapper support.
-  if ($wrapper = file_stream_wrapper_get_instance_by_uri($destination)) {
-    $destination = $wrapper->realpath();
+  $scheme = file_uri_scheme($destination);
+  // Work around lack of stream wrapper support in imagejpeg() and imagepng().
+  if ($scheme && file_stream_wrapper_valid_scheme($scheme)) {
+    // If destination is not local, save image to temporary local file.
+    $local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL);
+    if (!isset($local_wrappers[$scheme])) {
+      $permanent_destination = $destination;
+      $destination = drupal_tempnam('temporary://', 'gd_');
+    }
+    // Convert stream wrapper URI to normal path.
+    $destination = drupal_realpath($destination);
   }
 
   $extension = str_replace('jpg', 'jpeg', $image->info['extension']);
@@ -264,7 +270,7 @@ function image_gd_save(stdClass $image, $destination) {
     return FALSE;
   }
   if ($extension == 'jpeg') {
-    return $function($image->resource, $destination, variable_get('image_jpeg_quality', 75));
+    $success = $function($image->resource, $destination, variable_get('image_jpeg_quality', 75));
   }
   else {
     // Always save PNG images with full transparency.
@@ -272,8 +278,13 @@ function image_gd_save(stdClass $image, $destination) {
       imagealphablending($image->resource, FALSE);
       imagesavealpha($image->resource, TRUE);
     }
-    return $function($image->resource, $destination);
+    $success = $function($image->resource, $destination);
+  }
+  // Move temporary local file to remote destination.
+  if (isset($permanent_destination) && $success) {
+    return (bool) file_unmanaged_move($destination, $permanent_destination, FILE_EXISTS_REPLACE);
   }
+  return $success;
 }
 
 /**
diff --git a/modules/system/region.tpl.php b/modules/system/region.tpl.php
index 8ff154910b95993f583219cc258cf4567dd78ab2..be8e25c6785efd130caa6346c38583f232d9691f 100644
--- a/modules/system/region.tpl.php
+++ b/modules/system/region.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: region.tpl.php,v 1.2 2010/08/23 09:09:23 dries Exp $
+// $Id: region.tpl.php,v 1.3 2010/09/23 17:53:09 dries Exp $
 
 /**
  * @file
@@ -27,7 +27,7 @@
  * @see template_process()
  */
 ?>
-<?php if($content): ?>
+<?php if ($content): ?>
   <div class="<?php print $classes; ?>">
     <?php print $content; ?>
   </div>
diff --git a/modules/system/system-behavior-rtl.css b/modules/system/system-behavior-rtl.css
deleted file mode 100644
index 1158f6e44d490ecc27b490e6ad9ece54f13ae38a..0000000000000000000000000000000000000000
--- a/modules/system/system-behavior-rtl.css
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $Id: system-behavior-rtl.css,v 1.4 2010/06/20 17:34:51 webchick Exp $ */
-
-/**
- * Autocomplete
- */
- /* Animated throbber */
-html.js input.form-autocomplete {
-  background-position: 0% 2px;
-}
-html.js input.throbbing {
-  background-position: 0% -18px;
-}
-
-/**
- * Collapsing fieldsets
- */
-html.js fieldset.collapsible .fieldset-legend {
-  padding-left: 0;
-  padding-right: 15px;
-  background-position: 98% 75%;
-}
-html.js fieldset.collapsed .fieldset-legend {
-  background-image: url(../../misc/menu-collapsed-rtl.png);
-  background-position: 98% 50%;
-}
-
-/**
- * Progress bar
- */
-.progress .percentage {
-  float: left;
-}
-.progress-disabled {
-  float: right;
-}
-.ajax-progress {
-  float: right;
-}
-.ajax-progress .throbber {
-  float: right;
-}
-
-/**
- * Password strength indicator
- */
-input.password-field {
-  margin-left: 10px;
-  margin-right: 0;
-}
-input.password-confirm {
-  margin-left: 10px;
-  margin-right: 0;
-}
-.password-strength-title {
-  float: right;
-}
-.password-parent {
-  float: right;
-}
-
-/**
- * Table drag and drop
- */
-.draggable a.tabledrag-handle {
-  float: right;
-  margin: -0.4em -0.5em -0.4em 0;
-  padding: 0.42em 0.5em 0.42em 1.5em;
-}
-div.indentation {
-  margin: -0.4em -0.4em -0.4em 0.2em;
-  padding: 0.42em 0.6em 0.42em 0;
-  float: right;
-}
-div.tree-child,
-div.tree-child-last {
-  background-position: -65px center;
-}
-.tabledrag-toggle-weight-wrapper {
-  text-align: left; /* RTL */
-}
-
-/**
- * Multiselect form
- */
-dl.multiselect dt,
-dl.multiselect dd {
-  float: right;
-  margin: 0 0 0 1em;
-}
diff --git a/modules/system/system-menus-rtl.css b/modules/system/system-menus-rtl.css
deleted file mode 100644
index f1449afc382e62970bf91abe6488cade63df2949..0000000000000000000000000000000000000000
--- a/modules/system/system-menus-rtl.css
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $Id: system-menus-rtl.css,v 1.3 2010/04/28 20:08:39 dries Exp $ */
-
-ul.menu {
-  text-align:right;
-}
-ul.menu li {
-  margin: 0 0.5em 0 0;
-}
-ul li.collapsed {
-  list-style-image: url(../../misc/menu-collapsed-rtl.png);
-}
-li.expanded,
-li.collapsed,
-li.leaf {
-  padding: 0.2em 0 0 0.5em;
-}
diff --git a/modules/system/system-menus.css b/modules/system/system-menus.css
deleted file mode 100644
index dd7a243df6872b129ba7aa82bc3625d72c1d57c7..0000000000000000000000000000000000000000
--- a/modules/system/system-menus.css
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id: system-menus.css,v 1.4 2010/05/18 11:56:59 dries Exp $ */
-
-ul.menu {
-  list-style: none;
-  border: none;
-  text-align:left; /* LTR */
-}
-ul.menu li {
-  margin: 0 0 0 0.5em; /* LTR */
-}
-ul li.expanded {
-  list-style-type: circle;
-  list-style-image: url(../../misc/menu-expanded.png);
-}
-ul li.collapsed {
-  list-style-type: disc;
-  list-style-image: url(../../misc/menu-collapsed.png); /* LTR */
-}
-ul li.leaf {
-  list-style-type: square;
-  list-style-image: url(../../misc/menu-leaf.png);
-}
-li.expanded,
-li.collapsed,
-li.leaf {
-  padding: 0.2em 0.5em 0 0; /* LTR */
-  margin: 0;
-}
-li a.active {
-  color: #000;
-}
-td.menu-disabled {
-  background: #ccc;
-}
-ul.links {
-  margin: 0;
-  padding: 0;
-}
-ul.links.inline {
-  display: inline;
-}
-ul.links li {
-  display: inline;
-  list-style-type: none;
-  padding: 0 0.5em;
-}
-.block ul {
-  margin: 0;
-  padding: 0 0 0.25em 1em; /* LTR */
-}
diff --git a/modules/system/system-rtl.css b/modules/system/system-rtl.css
deleted file mode 100644
index 6d6df78ab85a973423ac769512b5ee7ef9d1a399..0000000000000000000000000000000000000000
--- a/modules/system/system-rtl.css
+++ /dev/null
@@ -1,74 +0,0 @@
-/* $Id: system-rtl.css,v 1.19 2010/01/07 07:41:46 webchick Exp $ */
-
-th {
-  text-align: right;
-  padding-right: 0;
-  padding-left: 1em;
-}
-
-thead th {
-  text-align: right;
-  padding-left: 1em;
-  padding-right: 0.5em;
-}
-
-.item-list .icon {
-  float: left;
-  padding-left: 0;
-  padding-right: 0.25em;
-  clear: left;
-}
-.item-list ul li {
-  margin: 0 1.5em 0.25em 0;
-}
-
-.more-link {
-  text-align: left;
-}
-.more-help-link {
-  text-align: left;
-}
-.more-help-link a {
-  padding: 1px 20px 1px 0;
-  background-position: 100% 50%;
-}
-
-.block ul {
-  padding: 0 1em 0.25em 0;
-}
-
-ul.primary {
-  padding: 0 1em 0 0;
-}
-ul.primary li a {
-  margin-right: 5px;
-  margin-left: 0.5em;
-}
-ul.secondary li {
-  display: inline;
-  padding: 0 1em;
-  border-right: none;
-  border-left: 1px solid #ccc;
-}
-
-.system-themes-list-enabled .theme-selector .screenshot,
-.system-themes-list-enabled .theme-selector .no-screenshot {
-  float: right;
-  margin: 0 0 0 20px;
-}
-.system-themes-list-disabled .theme-selector {
-  float: right;
-  padding: 20px 0 20px 20px;
-}
-.theme-selector .operations li {
-  float: right;
-  border-right: none;
-  border-left: 1px solid #cdcdcd;
-}
-.theme-selector .operations li.last {
-  padding: 0 0.7em 0 0;
-  border-left: none;
-}
-.theme-selector .operations li.first {
-  padding: 0 0 0 0.7em;
-}
diff --git a/modules/system/system.admin-rtl.css b/modules/system/system.admin-rtl.css
new file mode 100644
index 0000000000000000000000000000000000000000..dcda9bc426ba8806ae3846df800e7a7111a3db7e
--- /dev/null
+++ b/modules/system/system.admin-rtl.css
@@ -0,0 +1,87 @@
+/* $Id: system.admin-rtl.css,v 1.2 2010/09/25 02:28:14 dries Exp $ */
+
+/**
+ * @file
+ * RTL styles for administration pages.
+ */
+
+/**
+ * Administration blocks.
+ */
+div.admin-panel .body {
+  padding: 0 8px 2px 4px;
+}
+div.admin .left {
+  float: right;
+  margin-left: 0;
+  margin-right: 1em;
+}
+div.admin .right {
+  float: left;
+  margin-left: 1em;
+  margin-right: 0;
+}
+div.admin .expert-link {
+  margin-right: 0;
+  margin-left: 1em;
+  padding-right: 0;
+  padding-left: 4px;
+  text-align: left;
+}
+
+/**
+ * Status report.
+ */
+table.system-status-report th,
+table.system-status-report tr.merge-up td {
+  padding-right: 30px;
+}
+table.system-status-report th {
+  background-position: 95% 50%;
+}
+
+/**
+ * Appearance page.
+ */
+table.screenshot {
+  margin-left: 1em;
+}
+.system-themes-list-enabled .theme-selector .screenshot,
+.system-themes-list-enabled .theme-selector .no-screenshot {
+  float: right;
+  margin: 0 0 0 20px;
+}
+.system-themes-list-disabled .theme-selector {
+  float: right;
+  padding: 20px 0 20px 20px;
+}
+.theme-selector .operations li {
+  border-right: none;
+  border-left: 1px solid #cdcdcd;
+  float: right;
+}
+.theme-selector .operations li.last {
+  border-left: none;
+  padding: 0 0.7em 0 0;
+}
+.theme-selector .operations li.first {
+  padding: 0 0 0 0.7em;
+}
+
+/**
+ * Exposed filters.
+ */
+.exposed-filters .filters {
+  float: right;
+  margin-left: 1em;
+  margin-right: 0;
+}
+.exposed-filters .form-item label {
+  float: right;
+}
+/* Current filters */
+.exposed-filters .additional-filters {
+  float: right;
+  margin-left: 1em;
+  margin-right: 0;
+}
diff --git a/modules/system/system.admin.css b/modules/system/system.admin.css
new file mode 100644
index 0000000000000000000000000000000000000000..ca922e2a7b38630d49d6f57d91c1123c41b897b6
--- /dev/null
+++ b/modules/system/system.admin.css
@@ -0,0 +1,264 @@
+/* $Id: system.admin.css,v 1.2 2010/09/25 02:28:14 dries Exp $ */
+
+/**
+ * @file
+ * Styles for administration pages.
+ */
+
+/**
+ * Administration blocks.
+ */
+div.admin-panel {
+  margin: 0;
+  padding: 5px 5px 15px 5px;
+}
+div.admin-panel .description {
+  margin: 0 0 3px;
+  padding: 2px 0 3px 0;
+}
+div.admin-panel .body {
+  padding: 0 4px 2px 8px; /* LTR */
+}
+div.admin {
+  padding-top: 15px;
+}
+div.admin .left {
+  float: left; /* LTR */
+  width: 47%;
+  margin-left: 1em; /* LTR */
+}
+div.admin .right {
+  float: right; /* LTR */
+  width: 47%;
+  margin-right: 1em; /* LTR */
+}
+div.admin .expert-link {
+  text-align: right; /* LTR */
+  margin-right: 1em; /* LTR */
+  padding-right: 4px; /* LTR */
+}
+
+/**
+ * Markup generated by theme_system_compact_link().
+ */
+.compact-link {
+  margin: 0 0 0.5em 0;
+}
+
+/**
+ * Modules page.
+ */
+#system-modules div.incompatible {
+  font-weight: bold;
+}
+div.admin-requirements,
+div.admin-required {
+  font-size: 0.9em;
+  color: #444;
+}
+span.admin-disabled {
+  color: #800;
+}
+span.admin-enabled {
+  color: #080;
+}
+span.admin-missing {
+  color: #f00;
+}
+a.module-link {
+  display: block;
+  padding: 1px 0 1px 20px; /* LTR */
+  white-space: nowrap;
+}
+a.module-link-help {
+  background: url(../../misc/help.png) 0 50% no-repeat; /* LTR */
+}
+a.module-link-permissions {
+  background: url(../../misc/permissions.png) 0 50% no-repeat; /* LTR */
+}
+a.module-link-configure {
+  background: url(../../misc/configure.png) 0 50% no-repeat; /* LTR */
+}
+.module-help {
+  margin-left: 1em; /* LTR */
+  float: right; /* LTR */
+}
+
+/**
+ * Status report.
+ */
+table.system-status-report th {
+  border-bottom: 1px solid #ccc;
+}
+table.system-status-report th,
+table.system-status-report tr.merge-up td {
+  padding-left: 30px; /* LTR */
+}
+table.system-status-report th {
+  background-repeat: no-repeat;
+  background-position: 5px 50%; /* LTR */
+  padding-top: 6px;
+  padding-bottom: 6px;
+}
+table.system-status-report tr.error th {
+  background-image: url(../../misc/watchdog-error.png);
+}
+table.system-status-report tr.warning th {
+  background-image: url(../../misc/watchdog-warning.png);
+}
+table.system-status-report tr.ok th {
+  background-image: url(../../misc/watchdog-ok.png);
+}
+tr.merge-down,
+tr.merge-down td,
+tr.merge-down th {
+  border-bottom-width: 0 !important;
+}
+tr.merge-up,
+tr.merge-up td,
+tr.merge-up th {
+  border-top-width: 0 !important;
+}
+
+/**
+ * Theme settings.
+ */
+.theme-settings-left {
+  float: left;
+  width: 49%;
+}
+.theme-settings-right {
+  float: right;
+  width: 49%;
+}
+.theme-settings-bottom {
+  clear: both;
+}
+
+/**
+ * Appearance page.
+ */
+table.screenshot {
+  margin-right: 1em; /* LTR */
+}
+.theme-info h2 {
+  margin-bottom: 0;
+}
+.theme-info p {
+  margin-top: 0;
+}
+.system-themes-list {
+  margin-bottom: 20px;
+}
+.system-themes-list-disabled {
+  border-top: 1px solid #cdcdcd;
+  padding-top: 20px;
+}
+.system-themes-list h2 {
+  margin: 0;
+}
+.theme-selector {
+  padding-top: 20px;
+}
+.theme-selector .screenshot,
+.theme-selector .no-screenshot {
+  border: 1px solid #e0e0d8;
+  padding: 2px;
+  vertical-align: bottom;
+  width: 294px;
+  height: 219px;
+  line-height: 219px;
+  text-align: center;
+}
+.theme-default .screenshot {
+  border: 1px solid #aaa;
+}
+.system-themes-list-enabled .theme-selector .screenshot,
+.system-themes-list-enabled .theme-selector .no-screenshot {
+  float: left; /* LTR */
+  margin: 0 20px 0 0; /* LTR */
+}
+.system-themes-list-disabled .theme-selector .screenshot,
+.system-themes-list-disabled .theme-selector .no-screenshot {
+  width: 194px;
+  height: 144px;
+  line-height: 144px;
+}
+.theme-selector h3 {
+  font-weight: normal;
+}
+.theme-default h3 {
+  font-weight: bold;
+}
+.system-themes-list-enabled .theme-selector h3 {
+  margin-top: 0;
+}
+.system-themes-list-disabled .theme-selector {
+  width: 300px;
+  float: left; /* LTR */
+  padding: 20px 20px 20px 0; /* LTR */
+}
+.system-themes-list-enabled .theme-info {
+  max-width: 940px;
+}
+.system-themes-list-disabled .theme-info {
+  min-height: 170px;
+}
+.theme-selector .incompatible {
+  margin-top: 10px;
+  font-weight: bold;
+}
+.theme-selector .operations {
+  margin: 10px 0 0 0;
+  padding: 0;
+}
+.theme-selector .operations li {
+  float: left; /* LTR */
+  margin: 0;
+  padding: 0 0.7em;
+  list-style-type: none;
+  border-right: 1px solid #cdcdcd;  /* LTR */
+}
+.theme-selector .operations li.last {
+  padding: 0 0 0 0.7em; /* LTR */
+  border-right: none; /* LTR */
+}
+.theme-selector .operations li.first {
+  padding: 0 0.7em 0 0; /* LTR */
+}
+#system-themes-admin-form {
+  clear: left;
+}
+
+/**
+ * Exposed filters.
+ */
+.exposed-filters .filters {
+  float: left; /* LTR */
+  margin-right: 1em; /* LTR */
+  width: 25em; /* IE6 */
+}
+.exposed-filters .form-item {
+  margin: 0 0 0.1em 0;
+  padding: 0;
+}
+.exposed-filters .form-item label {
+  float: left; /* LTR */
+  font-weight: normal;
+  width: 10em;
+}
+.exposed-filters .form-select {
+  width: 14em;
+}
+/* Current filters */
+.exposed-filters .current-filters {
+  margin-bottom: 1em;
+}
+.exposed-filters .current-filters .placeholder {
+  font-style: normal;
+  font-weight: bold;
+}
+.exposed-filters .additional-filters {
+  float: left; /* LTR */
+  margin-right: 1em; /* LTR */
+}
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index 3d421f295c3cf8fb286c62a427071dec11be7f95..611081c3031154c7a128216dea2ce6677a6a98a1 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -1,75 +1,11 @@
 <?php
-// $Id: system.admin.inc,v 1.304 2010/09/15 04:31:02 webchick Exp $
+// $Id: system.admin.inc,v 1.317 2010/10/07 03:26:41 webchick Exp $
 
 /**
  * @file
  * Admin page callbacks for the system module.
  */
 
-/**
- * Menu callback; Provide the administration overview page.
- */
-function system_main_admin_page($arg = NULL) {
-  // Only continue if provided arguments are expected. This function serves
-  // as the callback for the top-level admin/ page, so any unexpected arguments
-  // are likely the result of someone typing in the URL of an administrative
-  // page that doesn't actually exist; for example, admin/some/random/page.
-  if (isset($arg) && substr($arg, 0, 3) != 'by-') {
-    return MENU_NOT_FOUND;
-  }
-
-  // Check for status report errors.
-  if (system_status(TRUE) && user_access('administer site configuration')) {
-    drupal_set_message(t('One or more problems were detected with your Drupal installation. Check the <a href="@status">status report</a> for more information.', array('@status' => url('admin/reports/status'))), 'error');
-  }
-  $blocks = array();
-  if ($admin = db_query("SELECT menu_name, mlid FROM {menu_links} WHERE link_path = 'admin' AND module = 'system'")->fetchAssoc()) {
-    $result = db_query("
-      SELECT m.*, ml.*
-      FROM {menu_links} ml
-      INNER JOIN {menu_router} m ON ml.router_path = m.path
-      WHERE ml.link_path != 'admin/help' AND menu_name = :menu_name AND ml.plid = :mlid AND hidden = 0", $admin, array('fetch' => PDO::FETCH_ASSOC));
-    foreach ($result as $item) {
-      _menu_link_translate($item);
-      if (!$item['access']) {
-        continue;
-      }
-      // The link 'description' either derived from the hook_menu 'description'
-      // or entered by the user via menu module is saved as the title attribute.
-      if (!empty($item['localized_options']['attributes']['title'])) {
-        $item['description'] = $item['localized_options']['attributes']['title'];
-      }
-      $block = $item;
-      $block['content'] = '';
-      $block['show'] = FALSE;
-      if ($item['block_callback'] && function_exists($item['block_callback'])) {
-        $function = $item['block_callback'];
-        $block['content'] .= $function();
-      }
-      $content = system_admin_menu_block($item);
-      if ((isset($item['page_callback']) && !in_array($item['page_callback'], array('system_admin_menu_block_page', 'system_admin_config_page', 'system_settings_overview'))) || count($content)) {
-        // Only show blocks for items which are not containers, or those which
-        // are containers and do have items we can show.
-        $block['show'] = TRUE;
-        $block['title'] = l($item['title'], $item['href'], $item['localized_options']);
-        if (!empty($content)) {
-          $block['content'] .= theme('admin_block_content', array('content' => $content));
-        }
-      }
-      // Prepare for sorting as in function _menu_tree_check_access().
-      // The weight is offset so it is always positive, with a uniform 5-digits.
-      $blocks[(50000 + $item['weight']) . ' ' . $item['title'] . ' ' . $item['mlid']] = $block;
-    }
-  }
-  if ($blocks) {
-    ksort($blocks);
-    return theme('admin_page', array('blocks' => $blocks));
-  }
-  else {
-    return t('You do not have any administrative items.');
-  }
-}
-
 /**
  * Menu callback; Provide the administration overview page.
  */
@@ -90,10 +26,11 @@ function system_admin_config_page() {
       if (!$item['access']) {
         continue;
       }
-      // The link 'description' either derived from the hook_menu 'description'
-      // or entered by the user via menu module is saved as the title attribute.
+      // The link description, either derived from 'description' in hook_menu()
+      // or customized via menu module is used as title attribute.
       if (!empty($item['localized_options']['attributes']['title'])) {
         $item['description'] = $item['localized_options']['attributes']['title'];
+        unset($item['localized_options']['attributes']['title']);
       }
       $block = $item;
       $block['content'] = '';
@@ -142,9 +79,9 @@ function system_admin_menu_block_page() {
 }
 
 /**
- * Menu callback; prints a listing of admin tasks for each installed module.
+ * Menu callback; prints a listing of admin tasks, organized by module.
  */
-function system_admin_by_module() {
+function system_admin_index() {
   $module_info = system_get_info('module');
   foreach ($module_info as $module => $info) {
     $module_info[$module] = new stdClass();
@@ -152,30 +89,24 @@ function system_admin_by_module() {
   }
   uasort($module_info, 'system_sort_modules_by_info_name');
   $menu_items = array();
-  $help_arg = module_exists('help') ? drupal_help_arg() : FALSE;
 
   foreach ($module_info as $module => $info) {
-    if ($module == 'help') {
-      continue;
-    }
-
-    $admin_tasks = system_get_module_admin_tasks($module);
-
     // Only display a section if there are any available tasks.
-    if (count($admin_tasks)) {
-
-      // Check for help links.
-      if ($help_arg && module_invoke($module, 'help', "admin/help#$module", $help_arg)) {
-        $admin_tasks[100] = l(t('Get help'), "admin/help/$module");
+    if ($admin_tasks = system_get_module_admin_tasks($module, $info->info)) {
+      // Sort links by title.
+      uasort($admin_tasks, 'system_sort_by_title');
+      // Move 'Configure permissions' links to the bottom of each section.
+      $permission_key = "admin/people/permissions#module-$module";
+      if (isset($admin_tasks[$permission_key])) {
+        $permission_task = $admin_tasks[$permission_key];
+        unset($admin_tasks[$permission_key]);
+        $admin_tasks[$permission_key] = $permission_task;
       }
 
-      // Sort.
-      ksort($admin_tasks);
-
       $menu_items[$info->info['name']] = array($info->info['description'], $admin_tasks);
     }
   }
-  return theme('system_admin_by_module', array('menu_items' => $menu_items));
+  return theme('system_admin_index', array('menu_items' => $menu_items));
 }
 
 /**
@@ -639,7 +570,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     }
 
     // Restore the original current theme.
-    if (!is_null($default_theme)) {
+    if (isset($default_theme)) {
       $GLOBALS['theme_key'] = $default_theme;
     }
     else {
@@ -926,8 +857,6 @@ function system_modules($form, $form_state = array()) {
       }
     }
 
-    // Mark dependents disabled so the user cannot remove required modules.
-    $dependents = array();
     // If this module is required by other modules, list those, and then make it
     // impossible to disable this one.
     foreach ($module->required_by as $required_by => $v) {
@@ -977,6 +906,19 @@ function system_modules($form, $form_state = array()) {
   return $form;
 }
 
+/**
+ * Array sorting callback; sorts elements by 'title' key.
+ */
+function system_sort_by_title($a, $b) {
+  if (!isset($b['title'])) {
+    return -1;
+  }
+  if (!isset($a['title'])) {
+    return 1;
+  }
+  return strcasecmp($a['title'], $b['title']);
+}
+
 /**
  * Array sorting callback; sorts modules or themes by their name.
  */
@@ -1031,7 +973,7 @@ function _system_modules_build_row($info, $extra) {
   $status_long = '';
 
   // Check the core compatibility.
-  if (!isset($info['core']) || $info['core'] != DRUPAL_CORE_COMPATIBILITY || empty($info['files'])) {
+  if (!isset($info['core']) || $info['core'] != DRUPAL_CORE_COMPATIBILITY) {
     $compatible = FALSE;
     $status_short .= t('Incompatible with this version of Drupal core. ');
     $status_long .= t('This version is not compatible with Drupal !core_version and should be replaced.', array('!core_version' => DRUPAL_CORE_COMPATIBILITY));
@@ -1041,6 +983,7 @@ function _system_modules_build_row($info, $extra) {
   if (version_compare(phpversion(), $info['php']) < 0) {
     $compatible = FALSE;
     $status_short .= t('Incompatible with this version of PHP');
+    $php_required = $info['php'];
     if (substr_count($info['php'], '.') < 2) {
       $php_required .= '.*';
     }
@@ -1061,7 +1004,7 @@ function _system_modules_build_row($info, $extra) {
   }
   else {
     $form['enable'] = array(
-      '#markup' =>  theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => t('incompatible'), 'title' => $status_short)),
+      '#markup' =>  theme('image', array('path' => 'misc/watchdog-error.png', 'alt' => $status_short, 'title' => $status_short)),
     );
     $form['description']['#markup'] .= theme('system_modules_incompatible', array('message' => $status_long));
   }
@@ -1224,6 +1167,7 @@ function system_modules_submit($form, &$form_state) {
     if ($module['enabled']) {
       if (drupal_get_installed_schema_version($name) == SCHEMA_UNINSTALLED) {
         $actions['install'][] = $name;
+        $actions['enable'][] = $name;
       }
       elseif (!module_exists($name)) {
         $actions['enable'][] = $name;
@@ -1239,37 +1183,27 @@ function system_modules_submit($form, &$form_state) {
   $pre_install_list = module_list();
   unset($form_state['storage']);
 
+  // Reverse the 'enable' list, to order dependencies before dependents.
+  krsort($actions['enable']);
+
   // Installs, enables, and disables modules.
-  module_enable($actions['enable']);
-  module_disable($actions['disable']);
-  module_enable($actions['install']);
+  module_enable($actions['enable'], FALSE);
+  module_disable($actions['disable'], FALSE);
 
-  // Gets module list after install process, displays message if there are changes.
+  // Gets module list after install process, flushes caches and displays a
+  // message if there are changes.
   $post_install_list = module_list(TRUE);
   if ($pre_install_list != $post_install_list) {
+    drupal_flush_all_caches();
     drupal_set_message(t('The configuration options have been saved.'));
   }
 
-  // Clear all caches.
-  registry_rebuild();
-  system_rebuild_theme_data();
-  drupal_theme_rebuild();
-  node_types_rebuild();
-  menu_rebuild();
-  cache_clear_all('schema', 'cache');
-  entity_info_cache_clear();
-  drupal_clear_css_cache();
-  drupal_clear_js_cache();
-
   $form_state['redirect'] = 'admin/modules';
 
   // Notify locale module about module changes, so translations can be
   // imported. This might start a batch, and only return to the redirect
   // path after that.
   module_invoke('locale', 'system_update', $actions['install']);
-
-  // Synchronize to catch any actions that were added or removed.
-  actions_synchronize();
 }
 
 /**
@@ -1745,7 +1679,7 @@ function system_performance_settings() {
   $is_writable = is_dir($directory) && is_writable($directory);
   $disabled = !$is_writable;
   $disabled_message = '';
-  if(!$is_writable) {
+  if (!$is_writable) {
     $disabled_message = ' ' . t('<strong class="error">Set up the <a href="!file-system">public files directory</a> to make these optimizations available.</strong>', array('!file-system' => url('admin/config/media/file-system')));
   }
 
@@ -1839,7 +1773,7 @@ function system_file_system_settings() {
   );
   // Any visible, writeable wrapper can potentially be used for the files
   // directory, including a remote file system that integrates with a CDN.
-  foreach(file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
+  foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
     $options[$scheme] = check_plain($info['description']);
   }
 
@@ -1936,8 +1870,6 @@ function system_rss_feeds_settings() {
 function system_regional_settings() {
   include_once DRUPAL_ROOT . '/includes/locale.inc';
   $countries = country_get_list();
-  // Add a 'No default country' option to the start of the list.
-  $countries = array_merge(array('' => t('No default country')), $countries);
 
   // Date settings:
   $zones = system_time_zones();
@@ -1950,6 +1882,7 @@ function system_regional_settings() {
   $form['locale']['site_default_country'] = array(
     '#type' => 'select',
     '#title' => t('Default country'),
+    '#empty_value' => '',
     '#default_value' => variable_get('site_default_country', ''),
     '#options' => $countries,
     '#attributes' => array('class' => array('country-detect')),
@@ -2387,43 +2320,36 @@ function system_batch_page() {
  *
  * @param $variables
  *   An associative array containing:
- *   - block: An array containing information about the block. It should include
- *     a 'title', a 'description' and a formatted 'content'.
+ *   - block: An array containing information about the block:
+ *     - show: A Boolean whether to output the block. Defaults to FALSE.
+ *     - title: The block's title.
+ *     - content: (optional) Formatted content for the block.
+ *     - description: (optional) Description of the block. Only output if
+ *       'content' is not set.
  *
  * @ingroup themeable
  */
 function theme_admin_block($variables) {
   $block = $variables['block'];
+  $output = '';
 
   // Don't display the block if it has no content to display.
   if (empty($block['show'])) {
-    return '';
+    return $output;
   }
 
-  if (empty($block['content'])) {
-    $output = <<< EOT
-    <div class="admin-panel">
-      <h3>
-        $block[title]
-      </h3>
-      <div class="description">
-        $block[description]
-      </div>
-    </div>
-EOT;
+  $output .= '<div class="admin-panel">';
+  if (!empty($block['title'])) {
+    $output .= '<h3>' . $block['title'] . '</h3>';
+  }
+  if (!empty($block['content'])) {
+    $output .= '<div class="body">' . $block['content'] . '</div>';
   }
   else {
-    $output = <<< EOT
-    <div class="admin-panel">
-      <h3>
-        $block[title]
-      </h3>
-     <div class="body">
-       $block[content]
-      </div>
-    </div>
-EOT;
+    $output .= '<div class="description">' . $block['description'] . '</div>';
   }
+  $output .= '</div>';
+
   return $output;
 }
 
@@ -2432,30 +2358,28 @@ EOT;
  *
  * @param $variables
  *   An associative array containing:
- *   - content: An array containing information about the block. It should
- *     include a 'title', a 'description' and a formatted 'content'.
+ *   - content: An array containing information about the block. Each element
+ *     of the array represents an administrative menu item, and must at least
+ *     contain the keys 'title', 'href', and 'localized_options', which are
+ *     passed to l(). A 'description' key may also be provided.
  *
  * @ingroup themeable
  */
 function theme_admin_block_content($variables) {
   $content = $variables['content'];
+  $output = '';
 
-  if (!$content) {
-    return '';
-  }
-
-  if (system_admin_compact_mode()) {
-    $output = '<ul class="menu">';
-    foreach ($content as $item) {
-      $output .= '<li class="leaf">' . l($item['title'], $item['href'], $item['localized_options']) . '</li>';
+  if (!empty($content)) {
+    $class = 'admin-list';
+    if ($compact = system_admin_compact_mode()) {
+      $class .= ' compact';
     }
-    $output .= '</ul>';
-  }
-  else {
-    $output = '<dl class="admin-list">';
+    $output .= '<dl class="' . $class . '">';
     foreach ($content as $item) {
       $output .= '<dt>' . l($item['title'], $item['href'], $item['localized_options']) . '</dt>';
-      $output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
+      if (!$compact && isset($item['description'])) {
+        $output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
+      }
     }
     $output .= '</dl>';
   }
@@ -2514,11 +2438,10 @@ function theme_admin_page($variables) {
  *
  * @ingroup themeable
  */
-function theme_system_admin_by_module($variables) {
+function theme_system_admin_index($variables) {
   $menu_items = $variables['menu_items'];
 
   $stripe = 0;
-  $output = '';
   $container = array('left' => '', 'right' => '');
   $flip = array('left' => 'right', 'right' => 'left');
   $position = 'left';
@@ -2531,7 +2454,7 @@ function theme_system_admin_by_module($variables) {
     if (count($items)) {
       $block = array();
       $block['title'] = $module;
-      $block['content'] = theme('item_list', array('items' => $items));
+      $block['content'] = theme('admin_block_content', array('content' => $items));
       $block['description'] = t($description);
       $block['show'] = TRUE;
 
@@ -2547,6 +2470,7 @@ function theme_system_admin_by_module($variables) {
   }
 
   $output = '<div class="admin clearfix">';
+  $output .= theme('system_compact_link');
   foreach ($container as $id => $data) {
     $output .= '<div class="' . $id . ' clearfix">';
     $output .= $data;
@@ -2719,7 +2643,7 @@ function theme_system_themes_page($variables) {
     // Start new theme group.
     $output .= '<div class="system-themes-list system-themes-list-'. $state .' clearfix"><h2>'. $title .'</h2>';
 
-    foreach($theme_groups[$state] as $theme) {
+    foreach ($theme_groups[$state] as $theme) {
 
       // Theme the screenshot.
       $screenshot = $theme->screenshot ? theme('image', $theme->screenshot) : '<div class="no-screenshot">' . t('no screenshot') . '</div>';
@@ -2941,7 +2865,7 @@ function system_actions_manage() {
   actions_synchronize();
   $actions = actions_list();
   $actions_map = actions_actions_map($actions);
-  $options = array(t('Choose an advanced action'));
+  $options = array();
   $unconfigurable = array();
 
   foreach ($actions_map as $key => $array) {
@@ -2977,7 +2901,7 @@ function system_actions_manage() {
   }
 
   if ($row) {
-    $pager = theme('pager', array('tags' => NULL));
+    $pager = theme('pager');
     if (!empty($pager)) {
       $row[] = array(array('data' => $pager, 'colspan' => '3'));
     }
@@ -3013,9 +2937,7 @@ function system_actions_manage_form($form, &$form_state, $options = array()) {
   );
   $form['parent']['action'] = array(
     '#type' => 'select',
-    '#default_value' => '',
     '#options' => $options,
-    '#description' => '',
   );
   $form['parent']['actions'] = array('#type' => 'actions');
   $form['parent']['actions']['submit'] = array(
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index d8450db604bbcea8efe3c59759c90ea5451e72f1..cd4cf3f4f62a51c331d10c285461c79fcdef01c8 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: system.api.php,v 1.193 2010/09/11 14:35:13 dries Exp $
+// $Id: system.api.php,v 1.197 2010/10/02 01:22:41 dries Exp $
 
 /**
  * @file
@@ -1199,6 +1199,53 @@ function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) {
   );
 }
 
+/**
+ * Alter links in the active trail before it is rendered as the breadcrumb.
+ *
+ * This hook is invoked by menu_get_active_breadcrumb() and allows alteration
+ * of the breadcrumb links for the current page, which may be preferred instead
+ * of setting a custom breadcrumb via drupal_set_breadcrumb().
+ *
+ * Implementations should take into account that menu_get_active_breadcrumb()
+ * subsequently performs the following adjustments to the active trail *after*
+ * this hook has been invoked:
+ * - The last link in $active_trail is removed, if its 'href' is identical to
+ *   the 'href' of $item. This happens, because the breadcrumb normally does
+ *   not contain a link to the current page.
+ * - The (second to) last link in $active_trail is removed, if the current $item
+ *   is a MENU_DEFAULT_LOCAL_TASK. This happens in order to do not show a link
+ *   to the current page, when being on the path for the default local task;
+ *   e.g. when being on the path node/%/view, the breadcrumb should not contain
+ *   a link to node/%.
+ *
+ * Each link in the active trail must contain:
+ * - title: The localized title of the link.
+ * - href: The system path to link to.
+ * - localized_options: An array of options to pass to url().
+ *
+ * @param $active_trail
+ *   An array containing breadcrumb links for the current page.
+ * @param $item
+ *   The menu router item of the current page.
+ *
+ * @see drupal_set_breadcrumb()
+ * @see menu_get_active_breadcrumb()
+ * @see menu_get_active_trail()
+ * @see menu_set_active_trail()
+ */
+function hook_menu_breadcrumb_alter(&$active_trail, $item) {
+  // Always display a link to the current page by duplicating the last link in
+  // the active trail. This means that menu_get_active_breadcrumb() will remove
+  // the last link (for the current page), but since it is added once more here,
+  // it will appear.
+  if (!drupal_is_front_page()) {
+    $end = end($active_trail);
+    if ($item['href'] == $end['href']) {
+      $active_trail[] = $end;
+    }
+  }
+}
+
 /**
  * Alter contextual links before they are rendered.
  *
@@ -1907,37 +1954,33 @@ function hook_xmlrpc() {
 }
 
 /**
- * Alter the definition of XML-RPC methods before they are called.
- *
- * This hook lets at module modify the callback definition for already
- * declared XML-RPC methods, when they are being invoked by a client.
+ * Alters the definition of XML-RPC methods before they are called.
  *
- * This hook is invoked by xmlrpc.php. The method definitions are
- * passed in by reference. Each element of the $methods array is one
- * callback definition returned by a module from hook_xmlrpc. Additional
- * methods may be added, or existing items altered.
+ * This hook allows modules to modify the callback definition of declared
+ * XML-RPC methods, right before they are invoked by a client. Methods may be
+ * added, or existing methods may be altered.
  *
- * Modules implementing this hook must take care of the fact that
- * hook_xmlrpc allows two distinct and incompatible formats for callback
- * definition, so module must be prepared to handle either format for
- * each callback being altered.
+ * Note that hook_xmlrpc() supports two distinct and incompatible formats to
+ * define a callback, so care must be taken when altering other methods.
  *
  * @param $methods
- *   Associative array of method callback definitions returned from
- *   hook_xmlrpc.
+ *   An asssociative array of method callback definitions, as returned from
+ *   hook_xmlrpc() implementations.
  *
  * @see hook_xmlrpc()
+ * @see xmlrpc_server()
  */
 function hook_xmlrpc_alter(&$methods) {
-
-  // Direct update for methods defined the simple way
+  // Directly change a simple method.
   $methods['drupal.login'] = 'mymodule_login';
 
-  // Lookup update for methods defined the complex way
+  // Alter complex definitions.
   foreach ($methods as $key => &$method) {
+    // Skip simple method definitions.
     if (!is_int($key)) {
       continue;
     }
+    // Perform the wanted manipulation.
     if ($method[0] == 'drupal.site.ping') {
       $method[1] = 'mymodule_directory_ping';
     }
@@ -2586,9 +2629,11 @@ function hook_requirements($phase) {
  * details on schema definition structures.
  *
  * @return
- * A schema definition structure array. For each element of the
- * array, the key is a table name and the value is a table structure
- * definition.
+ *   A schema definition structure array. For each element of the
+ *   array, the key is a table name and the value is a table structure
+ *   definition.
+ *
+ * @ingroup schemaapi
  */
 function hook_schema() {
   $schema['node'] = array(
@@ -3247,7 +3292,7 @@ function hook_drupal_goto_alter(&$path, &$options, &$http_response_code) {
  *   array will be the most likely target for changes.
  */
 function hook_html_head_alter(&$head_elements) {
-  foreach($head_elements as $key => $element) {
+  foreach ($head_elements as $key => $element) {
     if (isset($element['#attributes']['rel']) && $element['#attributes']['rel'] == 'canonical') {
       // I want a custom canonical url.
       $head_elements[$key]['#attributes']['href'] = mymodule_canonical_url();
@@ -3615,7 +3660,7 @@ function hook_page_delivery_callback_alter(&$callback) {
  */
 function hook_system_themes_page_alter(&$theme_groups) {
   foreach ($theme_groups as $state => &$group) {
-    foreach($theme_groups[$state] as &$theme) {
+    foreach ($theme_groups[$state] as &$theme) {
       // Add a foo link to each list of theme operations.
       $theme->operations[] = l(t('Foo'), 'admin/appearance/foo', array('query' => array('theme' => $theme->name)));
     }
diff --git a/modules/system/system.base-rtl.css b/modules/system/system.base-rtl.css
new file mode 100644
index 0000000000000000000000000000000000000000..79e13d970553a08a2c092f3bedc8c1d13b0b400f
--- /dev/null
+++ b/modules/system/system.base-rtl.css
@@ -0,0 +1,55 @@
+/* $Id: system.base-rtl.css,v 1.3 2010/09/27 03:56:14 webchick Exp $ */
+
+/**
+ * @file
+ * Generic theme-independent base styles.
+ */
+
+/**
+ * Autocomplete.
+ */
+/* Animated throbber */
+html.js input.form-autocomplete {
+  background-position: 0% 2px;
+}
+html.js input.throbbing {
+  background-position: 0% -18px;
+}
+
+/**
+ * Progress bar.
+ */
+.progress .percentage {
+  float: left;
+}
+.progress-disabled {
+  float: right;
+}
+.ajax-progress {
+  float: right;
+}
+.ajax-progress .throbber {
+  float: right;
+}
+
+/**
+ * TableDrag behavior.
+ */
+.draggable a.tabledrag-handle {
+  float: right;
+  margin: -0.4em -0.5em -0.4em 0;
+  padding: 0.42em 0.5em 0.42em 1.5em;
+}
+div.indentation {
+  float: right;
+  margin: -0.4em -0.4em -0.4em 0.2em;
+  padding: 0.42em 0.6em 0.42em 0;
+}
+div.tree-child,
+div.tree-child-last {
+  background-position: -65px center;
+}
+.tabledrag-toggle-weight-wrapper {
+  text-align: left;
+}
+
diff --git a/modules/system/system-behavior.css b/modules/system/system.base.css
similarity index 61%
rename from modules/system/system-behavior.css
rename to modules/system/system.base.css
index 72799d499b1479af01b767687bf305baf012a4b3..65924bcae4096002aa1f83e4da18fa335f96e7f7 100644
--- a/modules/system/system-behavior.css
+++ b/modules/system/system.base.css
@@ -1,43 +1,48 @@
-/* $Id: system-behavior.css,v 1.13 2010/08/09 16:58:15 webchick Exp $ */
+/* $Id: system.base.css,v 1.3 2010/09/25 02:28:14 dries Exp $ */
 
 /**
- * Autocomplete
+ * @file
+ * Generic theme-independent base styles.
+ */
+
+/**
+ * Autocomplete.
+ *
+ * @see autocomplete.js
  */
 /* Suggestion list */
 #autocomplete {
-  position: absolute;
   border: 1px solid;
   overflow: hidden;
+  position: absolute;
   z-index: 100;
 }
 #autocomplete ul {
-  margin: 0;
-  padding: 0;
   list-style: none;
   list-style-image: none;
+  margin: 0;
+  padding: 0;
 }
 #autocomplete li {
   background: #fff;
   color: #000;
-  white-space: pre;
   cursor: default;
-}
-#autocomplete li.selected {
-  background: #0072b9;
-  color: #fff;
+  white-space: pre;
 }
 /* Animated throbber */
 html.js input.form-autocomplete {
   background-image: url(../../misc/throbber.gif);
-  background-repeat: no-repeat;
   background-position: 100% 2px; /* LTR */
+  background-repeat: no-repeat;
 }
 html.js input.throbbing {
   background-position: 100% -18px; /* LTR */
 }
 
 /**
- * Collapsing fieldsets
+ * Collapsible fieldsets.
+ *
+ * @see collapse.js
  */
 html.js fieldset.collapsed {
   border-bottom-width: 0;
@@ -54,42 +59,33 @@ fieldset.collapsible {
 fieldset.collapsible .fieldset-legend {
   display: block;
 }
-html.js fieldset.collapsible .fieldset-legend {
-  padding-left: 15px; /* LTR */
-  background: url(../../misc/menu-expanded.png) 5px 65% no-repeat; /* LTR */
-}
-html.js fieldset.collapsed .fieldset-legend {
-  background-image: url(../../misc/menu-collapsed.png); /* LTR */
-  background-position: 5px 50%; /* LTR */
-}
-.fieldset-legend span.summary {
-  font-size: 0.9em;
-  color: #999;
-  margin-left: 0.5em;
-}
 
 /**
- * Resizable textareas
+ * Resizable textareas.
+ *
+ * @see textarea.js
  */
 .form-textarea-wrapper textarea {
+  display: block;
   margin: 0;
   width: 100%;
-  display: block;
   -webkit-box-sizing: border-box;
   -moz-box-sizing: border-box;
   box-sizing: border-box;
 }
 .resizable-textarea .grippie {
-  height: 9px;
-  overflow: hidden;
   background: #eee url(../../misc/grippie.png) no-repeat center 2px;
   border: 1px solid #ddd;
   border-top-width: 0;
   cursor: s-resize;
+  height: 9px;
+  overflow: hidden;
 }
 
 /**
- * Table drag and drop
+ * TableDrag behavior.
+ *
+ * @see tabledrag.js
  */
 body.drag {
   cursor: move;
@@ -106,20 +102,20 @@ a.tabledrag-handle:hover {
   text-decoration: none;
 }
 a.tabledrag-handle .handle {
-  margin-top: 4px;
+  background: url(../../misc/draggable.png) no-repeat 0 0;
   height: 13px;
+  margin-top: 4px;
   width: 13px;
-  background: url(../../misc/draggable.png) no-repeat 0 0;
 }
 a.tabledrag-handle-hover .handle {
   background-position: 0 -20px;
 }
 div.indentation {
-  width: 20px;
+  float: left; /* LTR */
   height: 1.7em;
   margin: -0.4em 0.2em -0.4em -0.4em; /* LTR */
   padding: 0.42em 0 0.42em 0.6em; /* LTR */
-  float: left; /* LTR */
+  width: 20px;
 }
 div.tree-child {
   background: url(../../misc/tree.png) no-repeat 11px center; /* LTR */
@@ -133,29 +129,29 @@ div.tree-child-horizontal {
 .tabledrag-toggle-weight-wrapper {
   text-align: right; /* LTR */
 }
-.tabledrag-toggle-weight {
-  font-size: 0.9em;
-}
-body div.tabledrag-changed-warning {
-  margin-bottom: 0.5em;
-}
 
 /**
- * Progress bar
+ * TableHeader behavior.
+ *
+ * @see tableheader.js
  */
-.progress {
-  font-weight: bold;
+table.sticky-header {
+  background-color: #fff;
+  margin-top: 0;
 }
+
+/**
+ * Progress behavior.
+ *
+ * @see progress.js
+ */
+/* Bar */
 .progress .bar {
-  border-radius: 3px;
-  -moz-border-radius: 3px;
-  -webkit-border-radius: 3px;
-  background: #ccc;
-  border: 1px solid #666;
-  margin: 0 0.2em;
+  background-color: #fff;
+  border: 1px solid;
 }
 .progress .filled {
-  background: #0072b9 url(../../misc/progress.gif);
+  background-color: #000;
   height: 1.5em;
   width: 5px;
 }
@@ -165,15 +161,16 @@ body div.tabledrag-changed-warning {
 .progress-disabled {
   float: left; /* LTR */
 }
+/* Throbber */
 .ajax-progress {
   float: left; /* LTR */
 }
 .ajax-progress .throbber {
-  width: 15px;
-  height: 15px;
-  margin: 2px;
   background: transparent url(../../misc/throbber.gif) no-repeat 0px -18px;
   float: left; /* LTR */
+  height: 15px;
+  margin: 2px;
+  width: 15px;
 }
 tr .ajax-progress .throbber {
   margin: 0 2px;
@@ -183,87 +180,7 @@ tr .ajax-progress .throbber {
 }
 
 /**
- * Multiselect form
- */
-dl.multiselect dd,
-dl.multiselect dd .form-item,
-dl.multiselect dd select {
-  font-family: inherit;
-  font-size: inherit;
-  width: 14em;
-}
-dl.multiselect dt,
-dl.multiselect dd {
-  float: left; /* LTR */
-  line-height: 1.75em;
-  padding: 0;
-  margin: 0 1em 0 0; /* LTR */
-}
-dl.multiselect .form-item {
-  height: 1.75em;
-  margin: 0;
-}
-
-/**
- * Password strength indicator
- */
-.password-strength {
-  width: 17em;
-  float: right;  /* LTR */
-  margin-top: 1.4em;
-}
-.password-strength-title {
-  display: inline;
-}
-.password-strength-text {
-  float: right; /* LTR */
-  font-weight: bold;
-}
-.password-indicator {
-  background-color: #C4C4C4;
-  height: 0.3em;
-  width: 100%;
-}
-.password-indicator div {
-  height: 100%;
-  width: 0%;
-  background-color: #47C965;
-}
-input.password-confirm,
-input.password-field {
-  width: 16em;
-  margin-bottom: 0.4em;
-}
-div.password-confirm {
-  display: inline;
-  padding-left: 1em;
-}
-div.form-item div.password-suggestions {
-  padding: 0.2em 0.5em;
-  margin: 0.7em 0;
-  width: 38.5em;
-  border: 1px solid #B4B4B4;
-}
-div.password-suggestions ul {
-  margin-bottom: 0;
-}
-.password-parent {
-  margin: 0;
-  width: 34.3em;
-}
-
-/**
- * Password confirmation checker
- */
-.confirm-parent {
-  margin: 0;
-}
-div.password-confirm {
-  visibility: hidden;
-}
-
-/**
- * Inline items (need to override above)
+ * Inline items.
  */
 .container-inline div,
 .container-inline label {
@@ -274,6 +191,9 @@ div.password-confirm {
   display: block;
 }
 
+/**
+ * Prevent text wrapping.
+ */
 .nowrap {
   white-space: nowrap;
 }
@@ -303,13 +223,43 @@ html.js .js-hide {
  *
  * Used for information required for screen-reader users to understand and use
  * the site where visual display is undesirable. Information provided in this
- * manner should be kept concise, to avoid unnecessary burden on the user. Must
- * not be used for focusable elements (such as links and form elements) as this
- * causes issues for keyboard only or voice recognition users. "!important" is
- * used to prevent unintentional overrides.
+ * manner should be kept concise, to avoid unnecessary burden on the user.
+ * "!important" is used to prevent unintentional overrides.
  */
 .element-invisible {
   position: absolute !important;
   clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
   clip: rect(1px, 1px, 1px, 1px);
 }
+
+/**
+ * The .element-focusable class extends the .element-invisible class to allow
+ * the element to be focusable when navigated to via the keyboard.
+ */
+.element-invisible.element-focusable:active,
+.element-invisible.element-focusable:focus {
+  position: static !important;
+  clip: auto;
+}
+
+/**
+ * Markup free clearing.
+ *
+ * @see http://perishablepress.com/press/2009/12/06/new-clearfix-hack
+ */
+.clearfix:after {
+  content: ".";
+  display: block;
+  height: 0;
+  clear: both;
+  visibility: hidden;
+}
+/* IE6 */
+* html .clearfix {
+  height: 1%;
+}
+/* IE7 */
+*:first-child + html .clearfix {
+  min-height: 1%;
+}
+
diff --git a/modules/system/system.css b/modules/system/system.css
deleted file mode 100644
index a04e6d63d784c0ab33775f5f39df5a698888e212..0000000000000000000000000000000000000000
--- a/modules/system/system.css
+++ /dev/null
@@ -1,416 +0,0 @@
-/* $Id: system.css,v 1.78 2010/08/02 11:22:22 dries Exp $ */
-
-/*
-** HTML elements
-*/
-fieldset {
-  margin-bottom: 1em;
-  padding: .5em;
-}
-form {
-  margin: 0;
-  padding: 0;
-}
-hr {
-  height: 1px;
-  border: 1px solid gray;
-}
-img {
-  border: 0;
-}
-table {
-  border-collapse: collapse;
-}
-th {
-  text-align: left; /* LTR */
-  padding-right: 1em; /* LTR */
-  border-bottom: 3px solid #ccc;
-}
-th.active img {
-  display: inline;
-}
-tr.even,
-tr.odd {
-  background-color: #eee;
-  border-bottom: 1px solid #ccc;
-  padding: 0.1em 0.6em;
-}
-tr.drag {
-  background-color: #fffff0;
-}
-tr.drag-previous {
-  background-color: #ffd;
-}
-td.active {
-  background-color: #ddd;
-}
-td.checkbox,
-th.checkbox {
-  text-align: center;
-}
-tbody {
-  border-top: 1px solid #ccc;
-}
-tbody th {
-  border-bottom: 1px solid #ccc;
-}
-thead th {
-  text-align: left; /* LTR */
-  padding-right: 1em; /* LTR */
-  border-bottom: 3px solid #ccc;
-}
-
-/*
-** Other common styles
-*/
-.breadcrumb {
-  padding-bottom: .5em
-}
-.item-list .icon {
-  color: #555;
-  float: right; /* LTR */
-  padding-left: 0.25em; /* LTR */
-  clear: right; /* LTR */
-}
-.item-list .title {
-  font-weight: bold;
-}
-.item-list ul {
-  margin: 0 0 0.75em 0;
-  padding: 0;
-}
-.item-list ul li {
-  margin: 0 0 0.25em 1.5em; /* LTR */
-  padding: 0;
-  list-style: disc;
-}
-.form-item {
-  margin-top: 1em;
-  margin-bottom: 1em;
-}
-tr.odd .form-item,
-tr.even .form-item {
-  margin-top: 0;
-  margin-bottom: 0;
-  white-space: nowrap;
-}
-tr.merge-down,
-tr.merge-down td,
-tr.merge-down th {
-  border-bottom-width: 0 !important;
-}
-tr.merge-up,
-tr.merge-up td,
-tr.merge-up th {
-  border-top-width: 0 !important;
-}
-.form-item input.error,
-.form-item textarea.error,
-.form-item select.error {
-  border: 2px solid red;
-}
-.form-item .description {
-  font-size: 0.85em;
-}
-.form-item label {
-  display: block;
-  font-weight: bold;
-}
-.form-item label.option {
-  display: inline;
-  font-weight: normal;
-}
-.form-checkboxes,
-.form-radios {
-  margin: 1em 0;
-}
-.form-checkboxes .form-item,
-.form-radios .form-item {
-  margin-top: 0.4em;
-  margin-bottom: 0.4em;
-}
-.form-type-radio .description,
-.form-type-checkbox .description {
-  margin-left: 2.4em;
-}
-input.form-checkbox,
-input.form-radio {
-  vertical-align: middle;
-}
-.marker,
-.form-required {
-  color: #f00;
-}
-.more-help-link {
-  text-align: right; /* LTR */
-}
-.more-help-link a,
-a.module-link {
-  padding: 1px 0 1px 20px; /* LTR */
-}
-a.module-link {
-  display: block;
-  white-space: nowrap;
-}
-.more-help-link a,
-a.module-link-help {
-  background: url(../../misc/help.png) 0 50% no-repeat; /* LTR */
-}
-a.module-link-permissions {
-  background: url(../../misc/permissions.png) 0 50% no-repeat; /* LTR */
-}
-a.module-link-configure {
-  background: url(../../misc/configure.png) 0 50% no-repeat; /* LTR */
-}
-.more-link {
-  text-align: right; /* LTR */
-}
-.module-help {
-  margin-left: 1em; /* LTR */
-  float: right; /* LTR */
-}
-.item-list .pager {
-  clear: both;
-  text-align: center;
-}
-.item-list .pager li {
-  background-image:none;
-  display:inline;
-  list-style-type:none;
-  padding: 0.5em;
-}
-.pager-current {
-  font-weight:bold;
-}
-.tips {
-  margin-top: 0;
-  margin-bottom: 0;
-  padding-top: 0;
-  padding-bottom: 0;
-  font-size: 0.9em;
-}
-.compact-link {
-  margin: 0 0 0.5em 0;
-}
-
-/*
-** Tab navigation
-*/
-ul.primary {
-  border-collapse: collapse;
-  padding: 0 0 0 1em; /* LTR */
-  white-space: nowrap;
-  list-style: none;
-  margin: 5px;
-  height: auto;
-  line-height: normal;
-  border-bottom: 1px solid #bbb;
-}
-ul.primary li {
-  display: inline;
-}
-ul.primary li a {
-  background-color: #ddd;
-  border-color: #bbb;
-  border-width: 1px;
-  border-style: solid solid none solid;
-  height: auto;
-  margin-right: 0.5em; /* LTR */
-  padding: 0 1em;
-  text-decoration: none;
-}
-ul.primary li.active a {
-  background-color: #fff;
-  border: 1px solid #bbb;
-  border-bottom: #fff 1px solid;
-}
-ul.primary li a:hover {
-  background-color: #eee;
-  border-color: #ccc;
-  border-bottom-color: #eee;
-}
-ul.secondary {
-  border-bottom: 1px solid #bbb;
-  padding: 0.5em 1em;
-  margin: 5px;
-}
-ul.secondary li {
-  display: inline;
-  padding: 0 1em;
-  border-right: 1px solid #ccc; /* LTR */
-}
-ul.secondary a {
-  padding: 0;
-  text-decoration: none;
-}
-ul.secondary a.active {
-  border-bottom: 4px solid #999;
-}
-
-/*
-** To be used with tableselect.js
-*/
-tr.selected td {
-  background: #ffc;
-}
-
-/*
-** To be used with displace.js
-*/
-.displace-top,
-.displace-bottom {
-  position: relative;
-  width: 100%;
-}
-.displace-processed .displace-top,
-.displace-processed .displace-bottom {
-  position: fixed;
-  width: auto;
-  left: 0;
-  right: 0;
-}
-.displace-unsupported .displace-top,
-.displace-unsupported .displace-bottom {
-  position: absolute;
-}
-
-/*
-** To be used with displace.js
-*/
-.displace-top,
-.displace-bottom {
-  position: relative;
-  width: 100%;
-}
-.displace-processed .displace-top,
-.displace-processed .displace-bottom {
-  position: fixed;
-  width: auto;
-  left: 0;
-  right: 0;
-}
-.displace-unsupported .displace-top,
-.displace-unsupported .displace-bottom {
-  position: absolute;
-}
-
-/*
-** Floating header for tableheader.js
-*/
-table.sticky-header {
-  margin-top: 0;
-  background: #fff;
-}
-
-/*
-** Styles for the system modules page (admin/modules)
-*/
-#system-modules div.incompatible {
-  font-weight: bold;
-}
-
-/*
-** Styles for the system themes page (admin/appearance)
-*/
-.system-themes-list {
-  margin-bottom: 20px;
-}
-.system-themes-list-disabled {
-  border-top: 1px solid #cdcdcd;
-  padding-top: 20px;
-}
-.system-themes-list h2 {
-  margin: 0;
-}
-.theme-selector {
-  padding-top: 20px;
-}
-.theme-selector .screenshot,
-.theme-selector .no-screenshot {
-  border: 1px solid #e0e0d8;
-  padding: 2px;
-  vertical-align: bottom;
-  width: 294px;
-  height: 219px;
-  line-height: 219px;
-  text-align: center;
-}
-.theme-default .screenshot {
-  border: 1px solid #aaa;
-}
-.system-themes-list-enabled .theme-selector .screenshot,
-.system-themes-list-enabled .theme-selector .no-screenshot {
-  float: left; /* LTR */
-  margin: 0 20px 0 0; /* LTR */
-}
-.system-themes-list-disabled .theme-selector .screenshot,
-.system-themes-list-disabled .theme-selector .no-screenshot {
-  width: 194px;
-  height: 144px;
-  line-height: 144px;
-}
-.theme-selector h3 {
-  font-weight: normal;
-}
-.theme-default h3 {
-  font-weight: bold;
-}
-.system-themes-list-enabled .theme-selector h3 {
-  margin-top: 0;
-}
-.system-themes-list-disabled .theme-selector {
-  width: 300px;
-  float: left; /* LTR */
-  padding: 20px 20px 20px 0; /* LTR */
-}
-.system-themes-list-enabled .theme-info {
-  max-width: 940px;
-}
-.system-themes-list-disabled .theme-info {
-  min-height: 170px;
-}
-.theme-selector .incompatible {
-  margin-top: 10px;
-  font-weight: bold;
-}
-.theme-selector .operations {
-  margin: 10px 0 0 0;
-  padding: 0;
-}
-.theme-selector .operations li {
-  float: left; /* LTR */
-  margin: 0;
-  padding: 0 0.7em;
-  list-style-type: none;
-  border-right: 1px solid #cdcdcd;  /* LTR */
-}
-.theme-selector .operations li.last {
-  padding: 0 0 0 0.7em; /* LTR */
-  border-right: none; /* LTR */
-}
-.theme-selector .operations li.first {
-  padding: 0 0.7em 0 0; /* LTR */
-}
-#system-themes-admin-form {
-  clear: left;
-}
-
-/*
-** Markup free clearing
-** Details: http://perishablepress.com/press/2009/12/06/new-clearfix-hack
-*/
-.clearfix:after {
-  content: ".";
-  display: block;
-  height: 0;
-  clear: both;
-  visibility: hidden;
-}
-/* IE6 */
-* html .clearfix {
-  height: 1%;
-}
-/* IE7 */
-*:first-child + html .clearfix {
-  min-height: 1%;
-}
diff --git a/modules/system/system.info b/modules/system/system.info
index b24fa6d114eea9bd2fc9a594b3fbd8db0d3532ff..f1d33538d61f4bd6c71465d25caebc204bcfd04e 100644
--- a/modules/system/system.info
+++ b/modules/system/system.info
@@ -18,8 +18,8 @@ files[] = system.mail.inc
 required = TRUE
 configure = admin/config/system
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/system/system.install b/modules/system/system.install
index d124d6dd62d4933d2a325335686a1abffc8cf033..e3ceaef2d9db35203bbf72648d1ef0c919647e89 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: system.install,v 1.506 2010/09/13 05:50:09 webchick Exp $
+// $Id: system.install,v 1.515 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -128,10 +128,7 @@ function system_requirements($phase) {
       '@system_requirements' => 'http://drupal.org/requirements',
     ));
 
-    $description .= theme('item_list',  array(
-      'type' => 'ul',
-      'items' => $missing_extensions,
-    ));
+    $description .= theme('item_list', array('items' => $missing_extensions));
 
     $requirements['php_extensions']['value'] = $t('Disabled');
     $requirements['php_extensions']['severity'] = REQUIREMENT_ERROR;
@@ -1566,7 +1563,7 @@ function system_schema() {
         'default' => 0,
       ),
       'info' => array(
-        'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, dependents, and php.",
+        'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, and php.",
         'type' => 'blob',
         'not null' => FALSE,
       ),
@@ -1813,7 +1810,7 @@ function system_update_7004(&$sandbox) {
       '0' => 'active',
       '1' => 'new',
     ),
-    'locale' => array('0' => 'language-switcher'),
+    'locale' => array('0' => LANGUAGE_TYPE_INTERFACE),
     'node' => array('0' => 'syndicate'),
     'poll' => array('0' => 'recent'),
     'profile' => array('0' => 'author-information'),
@@ -1863,14 +1860,6 @@ function system_update_7005() {
   variable_del('throttle_probability_limiter');
 }
 
-/**
- * Registry tables and drop the file key of the menu router, since it is no
- * longer needed.
- */
-function system_update_7006() {
-  // Update moved to update_fix_d7_requirements().
-}
-
 /**
  * Convert to new method of storing permissions.
  *
@@ -1897,14 +1886,6 @@ function system_update_7007() {
   return implode(', ', $messages);
 }
 
-/**
- * Use the poll_choice primary key to record votes in poll_votes rather than
- * the choice order. Rename chorder to weight.
- */
-function system_update_7008() {
-  // Moved to poll_update_7001().
-}
-
 /**
  * Rename the variable for primary links.
  */
@@ -1916,13 +1897,6 @@ function system_update_7009() {
   }
 }
 
-/**
- * Moved to system_update_6048().
- */
-function system_update_7010() {
-  return '';
-}
-
 /**
  * Split the 'bypass node access' permission from 'administer nodes'.
  */
@@ -1944,8 +1918,6 @@ function system_update_7011() {
   $insert->execute();
 }
 
-// system_update_7012() moved to block_update_7002().
-
 /**
  * Convert default time zone offset to default time zone name.
  */
@@ -1998,12 +1970,6 @@ function system_update_7013() {
   variable_del('date_temporary_timezone');
 }
 
-/**
- * Drop the bootstrap column from the {system} table. This was reverted.
- */
-function system_update_7014() {
-}
-
 /**
  * Change the user logout path.
  */
@@ -2055,13 +2021,15 @@ function system_update_7016() {
  * Change the theme setting 'toggle_node_info' into a per content type variable.
  */
 function system_update_7017() {
-  $types = node_type_get_types();
-  if (count($types)) {
-    foreach ($types as $type) {
-      $node_info = theme_get_setting('toggle_node_info_' . $type->type);
-      if ($node_info !== NULL) {
-        variable_set('node_submitted_' . $type->type, $node_info);
-      }
+  // Get the global theme settings.
+  $settings = variable_get('theme_settings', array());
+  // Get the settings of the default theme.
+  $settings = array_merge($settings, variable_get('theme_' . variable_get('theme_default', 'garland') . '_settings', array()));
+
+  $types = _update_7000_node_get_types();
+  foreach ($types as $type) {
+    if (isset($settings['toggle_node_info_' . $type->type])) {
+      variable_set('node_submitted_' . $type->type, $settings['toggle_node_info_' . $type->type]);
     }
   }
 
@@ -2126,8 +2094,6 @@ function system_update_7027() {
   module_enable($module_list, FALSE);
 }
 
-// system_update_7028() moved to taxonomy_update_7001().
-
 /**
  * Add new 'view own unpublished content' permission for authenticated users.
  * Preserves legacy behavior from Drupal 6.x.
@@ -2141,14 +2107,6 @@ function system_update_7029() {
     ->execute();
 }
 
-/**
- * Removed in favour of Drupal 6 backport.
- *
- * @see system_update_6052()
- */
-function system_update_7031() {
-}
-
 /**
 * Alter field hostname to identifier in the {flood} table.
  */
@@ -2260,13 +2218,6 @@ function system_update_7034() {
   db_create_table('file_managed', $schema['file_managed']);
 }
 
-/**
- * Migrate upload module files to the new {file_managed} table.
- */
-function system_update_7035() {
-  // Update merged into system_update_7059().
-}
-
 /**
  * Split the 'access site in maintenance mode' permission from 'administer site configuration'.
  */
@@ -2291,36 +2242,6 @@ function system_update_7036() {
   variable_del('site_offline_message');
 }
 
-/**
- * Rename action description to label.
- */
-function system_update_7037() {
-  db_change_field('actions', 'description', 'label', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '0'));
-}
-
-/**
- * Adds fields to the {menu_router} table to allow custom themes to be set per
- * page.
- */
-function system_update_7039() {
-  // Moved to update_fix_d7_requirements().
-}
-
-/**
- * Create new date format tables.
- */
-function system_update_7040() {
-  // Moved to update_fix_d7_requirements().
-}
-
-/**
- * Adds 'delivery_callback' field to the {menu_router} table to allow a custom
- * function to be used for final page rendering and sending to browser.
- */
-function system_update_7041() {
-  // Moved to update_fix_d7_requirements().
-}
-
 /**
  * Upgrade the {url_alias} table and create a cache bin for path aliases.
  */
@@ -2343,13 +2264,6 @@ function system_update_7042() {
   db_add_index('url_alias', 'alias_language_pid', array('alias', 'language', 'pid'));
 }
 
-/**
- * Add a 'context' field to {menu_router} to control contextual placement of local tasks.
- */
-function system_update_7043() {
-  // Moved to update_fix_d7_requirements().
-}
-
 /**
  * Drop the actions_aid table.
  */
@@ -2588,7 +2502,7 @@ function system_update_7055() {
   db_change_field('sessions', 'session', 'session', $spec);
 
   $spec = array(
-    'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, dependents, and php.",
+    'description' => "A serialized array containing information from the module's .info file; keys can include name, description, package, version, core, dependencies, and php.",
     'type' => 'blob',
     'not null' => FALSE,
   );
@@ -2669,132 +2583,179 @@ function system_update_7059() {
 }
 
 /**
- * Migrate upload.module to file.module.
+ * Create fields in preparation for migrating upload.module to file.module.
  */
-function system_update_7060(&$sandbox) {
+function system_update_7060() {
   if (!db_table_exists('upload')) {
     return;
   }
 
-  if (!isset($sandbox['progress'])) {
-    // Initialize batch update information.
-    $sandbox['progress'] = 0;
-    $sandbox['last_vid_processed'] = -1;
-    $sandbox['max'] = db_query("SELECT COUNT(DISTINCT u.vid) FROM {upload} u")->fetchField();
+  if (!db_query_range('SELECT 1 FROM {upload}', 0, 1)->fetchField()) {
+    // There is nothing to migrate. Delete variables and the empty table. There
+    // is no need to create fields that are not going to be used.
+    foreach (_update_7000_node_get_types() as $node_type) {
+      variable_del('upload_' . $node_type->type);
+    }
+    db_drop_table('upload');
+    return;
+  }
 
-    // Check which node types have upload.module attachments enabled.
-    $context['types'] = array();
-    foreach (node_type_get_types() as $node_type => $node_info) {
-      if (variable_get('upload_' . $node_type, 1)) {
-        $context['types'][$node_type] = $node_type;
-      }
-      variable_del('upload_' . $node_type);
+  // Check which node types have upload.module attachments enabled.
+  $context['types'] = array();
+  foreach (_update_7000_node_get_types() as $node_type) {
+    if (variable_get('upload_' . $node_type->type, 0)) {
+      $context['types'][$node_type->type] = $node_type->type;
     }
+  }
 
-    // The {upload} table will be deleted when this update is complete so we
-    // want to be careful to migrate all the data, even for node types that
-    // may have had attachments disabled after files were uploaded. Look for
-    // any other node types referenced by the upload records and add those to
-    // the list. The admin can always remove the field later.
-    $results = db_query('SELECT DISTINCT type FROM {node} n INNER JOIN {upload} u ON n.vid = u.vid');
-    foreach ($results as $row) {
-      if (!isset($context['types'][$row->type])) {
-        drupal_set_message(t('The content type %rowtype had uploads disabled but contained uploaded file data. Uploads have been re-enabled to migrate the existing data. You may delete the "File attachments" field in the %rowtype type if this data is not necessary.', array('%rowtype' => $row->type)));
-        $context['types'][$row->type] = $row->type;
-      }
+  // The {upload} table will be deleted when this update is complete so we
+  // want to be careful to migrate all the data, even for node types that
+  // may have had attachments disabled after files were uploaded. Look for
+  // any other node types referenced by the upload records and add those to
+  // the list. The admin can always remove the field later.
+  $results = db_query('SELECT DISTINCT type FROM {node} n INNER JOIN {node_revision} nr ON n.nid = nr.nid INNER JOIN {upload} u ON nr.vid = u.vid');
+  foreach ($results as $row) {
+    if (!isset($context['types'][$row->type])) {
+      drupal_set_message(t('The content type %rowtype had uploads disabled but contained uploaded file data. Uploads have been re-enabled to migrate the existing data. You may delete the "File attachments" field in the %rowtype type if this data is not necessary.', array('%rowtype' => $row->type)));
+      $context['types'][$row->type] = $row->type;
     }
+  }
+
+  // Create a single "upload" field on all the content types that have uploads
+  // enabled, then add an instance to each enabled type.
+  if (count($context['types']) > 0) {
+    module_enable(array('file'));
+    $field = array(
+      'field_name' => 'upload',
+      'type' => 'file',
+      'module' => 'file',
+      'locked' => FALSE,
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'translatable' => FALSE,
+      'settings' => array(
+        'display_field' => 1,
+        'display_default' => variable_get('upload_list_default', 1),
+        'uri_scheme' => file_default_scheme(),
+        'default_file' => 0,
+      ),
+    );
 
-    // Create a single "field_upload" field on all the content types that have
-    // uploads enabled, then add an instance to each enabled type.
-    if (count($context['types']) > 0) {
-      module_enable(array('file'));
-      module_load_include('inc', 'field', 'field.crud');
-
-      $field = array(
-        'field_name' => 'file',
-        'type' => 'file',
-        'locked' => FALSE,
-        'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-        'translatable' => FALSE,
+    $upload_size = variable_get('upload_uploadsize_default', 1);
+    $instance = array(
+      'field_name' => 'upload',
+      'entity_type' => 'node',
+      'bundle' => NULL,
+      'label' => 'File attachments',
+      'required' => 0,
+      'description' => '',
+      'widget' => array(
+        'weight' => '1',
         'settings' => array(
-          'display_field' => 1,
-          'display_default' => variable_get('upload_list_default', 1),
-          'uri_scheme' => file_default_scheme(),
-          'default_file' => 0,
+          'progress_indicator' => 'throbber',
         ),
-      );
-
-      $upload_size = variable_get('upload_uploadsize_default', 1);
-      $instance = array(
-        'field_name' => 'file',
-        'entity_type' => 'node',
-        'bundle' => NULL,
-        'label' => 'File attachments',
-        'widget_type' => 'file_generic',
-        'required' => 0,
-        'description' => '',
-        'widget' => array(
-          'weight' => '1',
-          'settings' => array(
-            'progress_indicator' => 'throbber',
-          ),
-          'type' => 'file_generic',
+        'type' => 'file_generic',
+      ),
+      'settings' => array(
+        'max_filesize' => $upload_size ? ($upload_size . ' MB') : '',
+        'file_extensions' => variable_get('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
+        'file_directory' => '',
+        'description_field' => 1,
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'hidden',
+          'type' => 'file_table',
+          'settings' => array(),
+          'weight' => 0,
+          'module' => 'file',
         ),
-        'settings' => array(
-          'max_filesize' => $upload_size ? ($upload_size . ' MB') : '',
-          'file_extensions' => variable_get('upload_extensions_default', 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
-          'file_directory' => '',
-          'description_field' => 1,
+        'full' => array(
+          'label' => 'hidden',
+          'type' => 'file_table',
+          'settings' => array(),
+          'weight' => 0,
+          'module' => 'file',
         ),
-        'display' => array(
-          'full' => array(
-            'label' => 'hidden',
-            'type' => 'file_table',
-            'settings' => array(),
-            'weight' => 0,
-            'module' => 'file',
-          ),
-          'teaser' => array(
-            'label' => 'hidden',
-            'type' => 'hidden',
-            'settings' => array(),
-            'weight' => 0,
-            'module' => NULL,
-          ),
-          'rss' => array(
-            'label' => 'hidden',
-            'type' => 'file_table',
-            'settings' => array(),
-            'weight' => 0,
-            'module' => 'file',
-          ),
+        'teaser' => array(
+          'label' => 'hidden',
+          'type' => 'hidden',
+          'settings' => array(),
+          'weight' => 0,
+          'module' => NULL,
         ),
-      );
+        'rss' => array(
+          'label' => 'hidden',
+          'type' => 'file_table',
+          'settings' => array(),
+          'weight' => 0,
+          'module' => 'file',
+        ),
+      ),
+    );
 
-      // Create the field. Save the field id for the data insertion later on.
-      $field = field_create_field($field);
-      $sandbox['field_id'] = $field['id'];
+    // Create the field.
+    _update_7000_field_create_field($field);
 
-      // Create the instances.
-      foreach ($context['types'] as $bundle) {
-        $instance['bundle'] = $bundle;
-        field_create_instance($instance);
-      }
-    }
-    else {
-      // No uploads or content types with uploads enabled.
-      db_drop_table('upload');
-      // We're done: return without specifying a #progress.
-      return;
+    // Create the instances.
+    foreach ($context['types'] as $bundle) {
+      $instance['bundle'] = $bundle;
+      _update_7000_field_create_instance($field, $instance);
+      // Now that the instance is created, we can safely delete any legacy
+      // node type information.
+      variable_del('upload_' . $bundle);
     }
   }
+  else {
+    // No uploads or content types with uploads enabled.
+    db_drop_table('upload');
+  }
+}
+
+/**
+ * Migrate upload.module data to the newly created file field.
+ */
+function system_update_7061(&$sandbox) {
+  if (!db_table_exists('upload')) {
+    return;
+  }
+
+  if (!isset($sandbox['progress'])) {
+    // Retrieve a list of node revisions that have uploaded files attached.
+    // DISTINCT queries are expensive, especially when paged, so we store the
+    // data in its own table for the duration of the update.
+    $table = array(
+      'description' => t('Stores temporary data for system_update_7061.'),
+      'fields' => array('vid' => array('type' => 'int')),
+      'primary key' => array('vid'),
+    );
+    db_create_table('system_update_7061', $table);
+    $query = db_select('upload', 'u');
+    $query->distinct();
+    $query->addField('u','vid');
+    db_insert('system_update_7061')
+      ->from($query)
+      ->execute();
+
+    // Initialize batch update information.
+    $sandbox['progress'] = 0;
+    $sandbox['last_vid_processed'] = -1;
+    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {system_update_7061}")->fetchField();
+  }
+
+  $node_revisions = array();
+
+  // Determine vids for this batch.
+  // Process all files attached to a given revision during the same batch.
+  $limit = 100;
+  $vids = db_query_range('SELECT vid FROM {system_update_7061} WHERE vid > :lastvid ORDER BY vid', 0, $limit, array(':lastvid' => $sandbox['last_vid_processed']))
+    ->fetchCol();
 
-  // Migrate a batch of files from the upload table to the appropriate field.
-  $limit = 500;
-  $result = db_query_range('SELECT DISTINCT u.fid, u.vid, u.list, u.description, n.nid, n.type FROM {upload} u INNER JOIN {node_revision} nr ON u.vid = nr.vid INNER JOIN {node} n ON n.nid = nr.nid WHERE u.vid > :lastvid ORDER BY u.vid, u.weight', 0, $limit, array(':lastvid' => $sandbox['last_vid_processed']));
+  // Retrieve information on all the files attached to these revisions.
+  $result = db_query('SELECT u.fid, u.vid, u.list, u.description, n.nid, n.type, u.weight FROM {upload} u INNER JOIN {node_revision} nr ON u.vid = nr.vid INNER JOIN {node} n ON n.nid = nr.nid WHERE u.vid IN (:vids) ORDER BY u.vid, u.weight, u.fid', array(':vids' => $vids));
   foreach ($result as $record) {
-    // Note that we still reference the old files table here, since upload will
-    // not know about the new FID in the new file_managed table.
+    // For each uploaded file, retrieve the corresponding data from the old
+    // files table (since upload doesn't know about the new entry in the
+    // file_managed table).
     $file = db_select('files', 'f')
       ->fields('f', array('fid', 'uid', 'filename', 'filepath', 'filemime', 'filesize', 'status', 'timestamp'))
       ->condition('f.fid', $record->fid)
@@ -2804,35 +2765,30 @@ function system_update_7060(&$sandbox) {
       continue;
     }
 
+    // Add in the file information from the upload table.
     $file['description'] = $record->description;
     $file['display'] = $record->list;
 
+    // Create one record for each revision that contains all the uploaded files.
     $node_revisions[$record->vid]['nid'] = $record->nid;
     $node_revisions[$record->vid]['vid'] = $record->vid;
     $node_revisions[$record->vid]['type'] = $record->type;
     $node_revisions[$record->vid]['file'][LANGUAGE_NONE][] = $file;
   }
 
-  // To make sure we process an entire node all at once, toss the last node
-  // revision (which might be partial) unless it's the last one.
-  if ((count($node_revisions) > 1) && ($result->rowCount() == $limit)) {
-    array_pop($node_revisions);
-  }
-  else {
-    $finished = TRUE;
-  }
-
+  // Now that we know which files belong to which revisions, update the files'
+  // database entries, and save a reference to each file in the upload field on
+  // their node revisions.
   $basename = variable_get('file_directory_path', conf_path() . '/files');
   $scheme = file_default_scheme() . '://';
   foreach ($node_revisions as $vid => $revision) {
-    // We will convert filepaths to uri using the default scheme
-    // and stripping off the existing file directory path.
-    $fids = array();
     foreach ($revision['file'][LANGUAGE_NONE] as $delta => $file) {
-      // Insert into the file_managed table.
+      // We will convert filepaths to uri using the default scheme
+      // and stripping off the existing file directory path.
       $file['uri'] = $scheme . str_replace($basename, '', $file['filepath']);
       $file['uri'] = file_stream_wrapper_uri_normalize($file['uri']);
       unset($file['filepath']);
+      // Insert into the file_managed table.
       // Each fid should only be stored once in file_managed.
       db_merge('file_managed')
         ->key(array(
@@ -2849,26 +2805,34 @@ function system_update_7060(&$sandbox) {
         ))
         ->execute();
 
-      // Update the node field with the file URI.
-      $revision['file'][LANGUAGE_NONE][$delta] = $file;
-
       // Add the usage entry for the file.
       $file = (object) $file;
       file_usage_add($file, 'file', 'node', $revision['nid']);
+
+      // Update the node revision's upload file field with the file data.
+      $revision['file'][LANGUAGE_NONE][$delta] = array('fid' => $file->fid, 'display' => $file->display, 'description' => $file->description);
     }
 
-    // Insert the revision's files into the field_upload table.
+    // Write the revision's upload field data into the field_upload tables.
     $node = (object) $revision;
-    field_sql_storage_field_storage_write('node', $node, FIELD_STORAGE_INSERT, array($sandbox['field_id']));
+    _update_7000_field_sql_storage_write('node', $node->type, $node->nid, $node->vid, 'upload', $node->file);
 
     // Update our progress information for the batch update.
     $sandbox['progress']++;
     $sandbox['last_vid_processed'] = $vid;
   }
 
+  // If less than limit node revisions were processed, the update process is
+  // finished.
+  if (count($node_revisions) < $limit) {
+    $finished = TRUE;
+  }
+
+
   // If there's no max value then there's nothing to update and we're finished.
   if (empty($sandbox['max']) || isset($finished)) {
     db_drop_table('upload');
+    db_drop_table('system_update_7061');
     return t('Upload module has been migrated to File module.');
   }
   else {
@@ -2880,7 +2844,7 @@ function system_update_7060(&$sandbox) {
 /**
  * Replace 'system_list' index with 'bootstrap' index on {system}.
  */
-function system_update_7061() {
+function system_update_7062() {
   db_drop_index('system', 'bootstrap');
   db_drop_index('system', 'system_list');
   db_add_index('system', 'system_list', array('status', 'bootstrap', 'type', 'weight', 'name'));
diff --git a/modules/system/maintenance.css b/modules/system/system.maintenance.css
similarity index 85%
rename from modules/system/maintenance.css
rename to modules/system/system.maintenance.css
index 22801e3da96338db171ef12b2b50b3fe696c36ce..2bfbbb6bc97c46421c8b4001abfd76309f087b6b 100644
--- a/modules/system/maintenance.css
+++ b/modules/system/system.maintenance.css
@@ -1,6 +1,8 @@
-/* $Id: maintenance.css,v 1.3 2010/01/07 07:41:46 webchick Exp $ */
+/* $Id: system.maintenance.css,v 1.1 2010/09/19 18:35:42 dries Exp $ */
 
-/* Update styles */
+/**
+ * Update styles
+ */
 #update-results {
   margin-top: 3em;
   padding: 0.25em;
@@ -22,7 +24,9 @@
   color: #b63300;
 }
 
-/* authorize.php styles */
+/**
+ * Authorize.php styles
+ */
 .connection-settings-update-filetransfer-default-wrapper {
   float: left;
 }
diff --git a/modules/system/system.menus-rtl.css b/modules/system/system.menus-rtl.css
new file mode 100644
index 0000000000000000000000000000000000000000..d3d3260e9165cd7c42fb92ec5b251cc2a606c5f2
--- /dev/null
+++ b/modules/system/system.menus-rtl.css
@@ -0,0 +1,38 @@
+/* $Id: system.menus-rtl.css,v 1.2 2010/09/25 02:28:14 dries Exp $ */
+
+/**
+ * @file
+ * RTL styles for menus and navigation markup.
+ */
+
+ul.menu {
+  text-align:right;
+}
+ul.menu li {
+  margin: 0 0.5em 0 0;
+}
+ul li.collapsed {
+  list-style-image: url(../../misc/menu-collapsed-rtl.png);
+}
+li.expanded,
+li.collapsed,
+li.leaf {
+  padding: 0.2em 0 0 0.5em;
+}
+
+/**
+ * Markup generated by theme_menu_local_tasks().
+ */
+ul.primary {
+  padding: 0 1em 0 0;
+}
+ul.primary li a {
+  margin-right: 5px;
+  margin-left: 0.5em;
+}
+ul.secondary li {
+  border-left: 1px solid #ccc;
+  border-right: none;
+  display: inline;
+  padding: 0 1em;
+}
diff --git a/modules/system/system.menus.css b/modules/system/system.menus.css
new file mode 100644
index 0000000000000000000000000000000000000000..98e8036642b46d1345020705ff84c5e1d3d6e888
--- /dev/null
+++ b/modules/system/system.menus.css
@@ -0,0 +1,119 @@
+/* $Id: system.menus.css,v 1.2 2010/09/25 02:28:14 dries Exp $ */
+
+/**
+ * @file
+ * Styles for menus and navigation markup.
+ */
+
+/**
+ * Markup generated by theme_menu_tree().
+ */
+ul.menu {
+  border: none;
+  list-style: none;
+  text-align: left; /* LTR */
+}
+ul.menu li {
+  margin: 0 0 0 0.5em; /* LTR */
+}
+ul li.expanded {
+  list-style-image: url(../../misc/menu-expanded.png);
+  list-style-type: circle;
+}
+ul li.collapsed {
+  list-style-image: url(../../misc/menu-collapsed.png); /* LTR */
+  list-style-type: disc;
+}
+ul li.leaf {
+  list-style-image: url(../../misc/menu-leaf.png);
+  list-style-type: square;
+}
+li.expanded,
+li.collapsed,
+li.leaf {
+  padding: 0.2em 0.5em 0 0; /* LTR */
+  margin: 0;
+}
+li a.active {
+  color: #000;
+}
+td.menu-disabled {
+  background: #ccc;
+}
+
+/**
+ * Markup generated by theme_links().
+ */
+ul.links {
+  margin: 0;
+  padding: 0;
+}
+ul.links.inline {
+  display: inline;
+}
+ul.links li {
+  display: inline;
+  list-style-type: none;
+  padding: 0 0.5em;
+}
+
+/**
+ * Markup generated by theme_breadcrumb().
+ */
+.breadcrumb {
+  padding-bottom: 0.5em;
+}
+
+/**
+ * Markup generated by theme_menu_local_tasks().
+ */
+ul.primary {
+  border-bottom: 1px solid #bbb;
+  border-collapse: collapse;
+  height: auto;
+  line-height: normal;
+  list-style: none;
+  margin: 5px;
+  padding: 0 0 0 1em; /* LTR */
+  white-space: nowrap;
+}
+ul.primary li {
+  display: inline;
+}
+ul.primary li a {
+  background-color: #ddd;
+  border-color: #bbb;
+  border-style: solid solid none solid;
+  border-width: 1px;
+  height: auto;
+  margin-right: 0.5em; /* LTR */
+  padding: 0 1em;
+  text-decoration: none;
+}
+ul.primary li.active a {
+  background-color: #fff;
+  border: 1px solid #bbb;
+  border-bottom: 1px solid #fff;
+}
+ul.primary li a:hover {
+  background-color: #eee;
+  border-color: #ccc;
+  border-bottom-color: #eee;
+}
+ul.secondary {
+  border-bottom: 1px solid #bbb;
+  padding: 0.5em 1em;
+  margin: 5px;
+}
+ul.secondary li {
+  border-right: 1px solid #ccc; /* LTR */
+  display: inline;
+  padding: 0 1em;
+}
+ul.secondary a {
+  padding: 0;
+  text-decoration: none;
+}
+ul.secondary a.active {
+  border-bottom: 4px solid #999;
+}
diff --git a/modules/system/system-messages.css b/modules/system/system.messages.css
similarity index 88%
rename from modules/system/system-messages.css
rename to modules/system/system.messages.css
index b1a1406ee4ff013fae0974c20653536dc6c9f72f..e14e3b23f12fe529181e74fd84f6d119ee510f77 100644
--- a/modules/system/system-messages.css
+++ b/modules/system/system.messages.css
@@ -1,4 +1,9 @@
-/* $Id */
+/* $Id: system.messages.css,v 1.1 2010/09/19 18:35:42 dries Exp $ */
+
+/**
+ * @file
+ * Styles for system messages.
+ */
 
 div.messages {
   background-position: 8px 8px; /* LTR */
@@ -7,6 +12,7 @@ div.messages {
   margin: 6px 0;
   padding: 10px 10px 10px 50px; /* LTR */
 }
+
 div.status {
   background-image: url(../../misc/message-24-ok.png);
   border-color: #be7;
@@ -19,6 +25,7 @@ div.status,
 table tr.ok {
   background-color: #f8fff0;
 }
+
 div.warning {
   background-image: url(../../misc/message-24-warning.png);
   border-color: #ed5;
@@ -31,6 +38,7 @@ div.warning,
 table tr.warning {
   background-color: #fffce5;
 }
+
 div.error {
   background-image: url(../../misc/message-24-error.png);
   border-color: #ed541d;
@@ -46,6 +54,7 @@ table tr.error {
 div.error p.error {
   color: #333;
 }
+
 div.messages ul {
   margin: 0 0 0 1em; /* LTR */
   padding: 0;
diff --git a/modules/system/system.module b/modules/system/system.module
index ce489a5cf2e353c005bf2d169d5afdf7e7001acd..78774d1d67f884d8fff75491f5ead6882bc06db0 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: system.module,v 1.960 2010/09/11 06:03:12 webchick Exp $
+// $Id: system.module,v 1.976 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @file
@@ -87,7 +87,7 @@ function system_help($path, $arg) {
       $output .= '<dd>' . t('Actions are individual tasks that the system can do, such as unpublishing a piece of content or banning a user. Modules, such as the <a href="@trigger-help">Trigger module</a>, can fire these actions when certain system events happen; for example, when a new post is added or when a user logs in. Modules may also provide additional actions. Visit the <a href="@actions">Actions page</a> to configure actions.', array('@trigger-help' => url('admin/help/trigger'), '@actions' => url('admin/config/system/actions'))) . '</dd>';
       $output .= '</dl>';
       return $output;
-    case 'admin/by-module':
+    case 'admin/index':
       return '<p>' . t('This page shows you all available administration tasks for each module.') . '</p>';
     case 'admin/appearance':
       $output = '<p>' . t('Set and configure the default theme for your website.  Alternative <a href="@themes">themes</a> are available.', array('@themes' => 'http://drupal.org/project/themes')) . '</p>';
@@ -184,7 +184,7 @@ function system_theme() {
       'variables' => array('content' => NULL),
       'file' => 'system.admin.inc',
     ),
-    'system_admin_by_module' => array(
+    'system_admin_index' => array(
       'variables' => array('menu_items' => NULL),
       'file' => 'system.admin.inc',
     ),
@@ -399,9 +399,8 @@ function system_element_info() {
   );
   $types['select'] = array(
     '#input' => TRUE,
-    '#size' => 0,
     '#multiple' => FALSE,
-    '#process' => array('ajax_process_form'),
+    '#process' => array('form_process_select', 'ajax_process_form'),
     '#theme' => 'select',
     '#theme_wrappers' => array('form_element'),
   );
@@ -510,6 +509,7 @@ function system_menu() {
     'page callback' => 'ajax_form_callback',
     'delivery callback' => 'ajax_deliver',
     'access callback' => TRUE,
+    'theme callback' => 'ajax_base_page_theme',
     'type' => MENU_CALLBACK,
     'file path' => 'includes',
     'file' => 'form.inc',
@@ -522,9 +522,9 @@ function system_menu() {
     'file' => 'system.admin.inc',
   );
   $items['admin'] = array(
-    'title' => 'Administer',
+    'title' => 'Administration',
     'access arguments' => array('access administration pages'),
-    'page callback' => 'system_main_admin_page',
+    'page callback' => 'system_admin_menu_block_page',
     'weight' => 9,
     'menu_name' => 'management',
     'theme callback' => 'variable_get',
@@ -538,17 +538,14 @@ function system_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
-  $items['admin/by-task'] = array(
-    'title' => 'By task',
-    'page callback' => 'system_main_admin_page',
-    'access arguments' => array('access administration pages'),
+  $items['admin/tasks'] = array(
+    'title' => 'Tasks',
     'type' => MENU_DEFAULT_LOCAL_TASK,
-    'file' => 'system.admin.inc',
     'weight' => -20,
   );
-  $items['admin/by-module'] = array(
-    'title' => 'By module',
-    'page callback' => 'system_admin_by_module',
+  $items['admin/index'] = array(
+    'title' => 'Index',
+    'page callback' => 'system_admin_index',
     'access arguments' => array('access administration pages'),
     'type' => MENU_LOCAL_TASK,
     'weight' => -18,
@@ -568,7 +565,7 @@ function system_menu() {
   // Appearance.
   $items['admin/appearance'] = array(
     'title' => 'Appearance',
-    'description' => 'Select and configure your themes',
+    'description' => 'Select and configure your themes.',
     'page callback' => 'system_themes_page',
     'access arguments' => array('administer themes'),
     'position' => 'left',
@@ -634,7 +631,7 @@ function system_menu() {
   // Modules.
   $items['admin/modules'] = array(
     'title' => 'Modules',
-    'description' => 'Enable or disable modules',
+    'description' => 'Enable or disable modules.',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_modules'),
     'access arguments' => array('administer modules'),
@@ -648,7 +645,7 @@ function system_menu() {
   $items['admin/modules/list/confirm'] = array(
     'title' => 'List',
     'access arguments' => array('administer modules'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
   );
   $items['admin/modules/uninstall'] = array(
     'title' => 'Uninstall',
@@ -661,14 +658,14 @@ function system_menu() {
   $items['admin/modules/uninstall/confirm'] = array(
     'title' => 'Uninstall',
     'access arguments' => array('administer modules'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'system.admin.inc',
   );
 
   // Configuration.
   $items['admin/config'] = array(
     'title' => 'Configuration',
-    'description' => 'Administer settings',
+    'description' => 'Administer settings.',
     'page callback' => 'system_admin_config_page',
     'access arguments' => array('access administration pages'),
     'file' => 'system.admin.inc',
@@ -688,7 +685,6 @@ function system_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_ip_blocking_delete', 5),
     'access arguments' => array('block IP addresses'),
-    'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
 
@@ -829,7 +825,6 @@ function system_menu() {
   $items['admin/config/regional/date-time/types/%/delete'] = array(
     'title' => 'Delete date type',
     'description' => 'Allow users to delete a configured date type.',
-    'type' => MENU_CALLBACK,
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_delete_date_format_type_form', 5),
     'access arguments' => array('administer site configuration'),
@@ -857,7 +852,6 @@ function system_menu() {
   $items['admin/config/regional/date-time/formats/%/edit'] = array(
     'title' => 'Edit date format',
     'description' => 'Allow users to edit a configured date format.',
-    'type' => MENU_CALLBACK,
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_configure_date_formats_form', 5),
     'access arguments' => array('administer site configuration'),
@@ -866,7 +860,6 @@ function system_menu() {
   $items['admin/config/regional/date-time/formats/%/delete'] = array(
     'title' => 'Delete date format',
     'description' => 'Allow users to delete a configured date format.',
-    'type' => MENU_CALLBACK,
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_date_delete_format_form', 5),
     'access arguments' => array('administer site configuration'),
@@ -874,9 +867,9 @@ function system_menu() {
   );
   $items['admin/config/regional/date-time/formats/lookup'] = array(
     'title' => 'Date and time lookup',
-    'type' => MENU_CALLBACK,
     'page callback' => 'system_date_time_lookup',
     'access arguments' => array('administer site configuration'),
+    'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
 
@@ -938,7 +931,7 @@ function system_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_actions_configure'),
     'access arguments' => array('administer actions'),
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'system.admin.inc',
   );
   $items['admin/config/system/actions/delete/%actions'] = array(
@@ -947,7 +940,6 @@ function system_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('system_actions_delete_form', 5),
     'access arguments' => array('administer actions'),
-    'type' => MENU_CALLBACK,
     'file' => 'system.admin.inc',
   );
   $items['admin/config/system/actions/orphan'] = array(
@@ -1007,7 +999,7 @@ function system_menu() {
   // Reports.
   $items['admin/reports'] = array(
     'title' => 'Reports',
-    'description' => 'View reports, updates, and errors',
+    'description' => 'View reports, updates, and errors.',
     'page callback' => 'system_admin_menu_block_page',
     'access arguments' => array('access site reports'),
     'weight' => 5,
@@ -1074,9 +1066,8 @@ function system_library() {
     'website' => 'http://jquery.com',
     'version' => '1.4.2',
     'js' => array(
-      'misc/jquery.js' => array('weight' => JS_LIBRARY - 20),
+      'misc/jquery.js' => array('group' => JS_LIBRARY, 'weight' => -20),
     ),
-    'preprocess' => TRUE,
   );
 
   // jQuery Once.
@@ -1085,9 +1076,8 @@ function system_library() {
     'website' => 'http://plugins.jquery.com/project/once',
     'version' => '1.2',
     'js' => array(
-      'misc/jquery.once.js' => array('weight' => JS_LIBRARY - 19),
+      'misc/jquery.once.js' => array('group' => JS_LIBRARY, 'weight' => -19),
     ),
-    'preprocess' => TRUE,
   );
 
   // jQuery Form Plugin.
@@ -1152,7 +1142,7 @@ function system_library() {
     'website' => 'http://jqueryui.com',
     'version' => '1.8',
     'js' => array(
-      'misc/ui/jquery.ui.core.min.js' => array('weight' => JS_LIBRARY - 11),
+      'misc/ui/jquery.ui.core.min.js' => array('group' => JS_LIBRARY, 'weight' => -11),
     ),
     'css' => array(
       'misc/ui/jquery.ui.core.css' => array(),
@@ -1369,7 +1359,7 @@ function system_library() {
     'website' => 'http://docs.jquery.com/UI/Widget',
     'version' => '1.8',
     'js' => array(
-      'misc/ui/jquery.ui.widget.min.js' => array('weight' => JS_LIBRARY - 10),
+      'misc/ui/jquery.ui.widget.min.js' => array('group' => JS_LIBRARY, 'weight' => -10),
     ),
     'dependencies' => array(
       array('system', 'ui'),
@@ -1380,7 +1370,7 @@ function system_library() {
     'website' => 'http://jqueryui.com/demos/effect/',
     'version' => '1.8',
     'js' => array(
-      'misc/ui/jquery.effects.core.min.js' => array('weight' => JS_LIBRARY - 9),
+      'misc/ui/jquery.effects.core.min.js' => array('group' => JS_LIBRARY, 'weight' => -9),
     ),
   );
   $libraries['effects.blind'] = array(
@@ -1730,7 +1720,7 @@ function system_filetransfer_backends() {
   $backends = array();
 
   // This is the default, will be available on most systems.
-  if (function_exists('ftp_connect') || ini_get('allow_url_fopen')) {
+  if (function_exists('ftp_connect')) {
     $backends['ftp'] = array(
       'title' => t('FTP'),
       'class' => 'FileTransferFTP',
@@ -1829,14 +1819,15 @@ function _system_filetransfer_backend_form_common() {
  */
 function system_init() {
   $path = drupal_get_path('module', 'system');
-  // Add the CSS for this module.
+  // Add the CSS for this module. These aren't in system.info, because they
+  // need to be in the CSS_SYSTEM group rather than the CSS_DEFAULT group.
+  drupal_add_css($path . '/system.base.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
   if (arg(0) == 'admin' || (variable_get('node_admin_theme', '0') && arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit' || arg(2) == 'delete'))) {
-    drupal_add_css($path . '/admin.css', array('weight' => CSS_SYSTEM));
+    drupal_add_css($path . '/system.admin.css', array('group' => CSS_SYSTEM));
   }
-  drupal_add_css($path . '/system.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
-  drupal_add_css($path . '/system-behavior.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
-  drupal_add_css($path . '/system-menus.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
-  drupal_add_css($path . '/system-messages.css', array('weight' => CSS_SYSTEM, 'preprocess' => TRUE));
+  drupal_add_css($path . '/system.menus.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
+  drupal_add_css($path . '/system.messages.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
+  drupal_add_css($path . '/system.theme.css', array('group' => CSS_SYSTEM, 'every_page' => TRUE));
 
   // Ignore slave database servers for this request.
   //
@@ -1872,13 +1863,13 @@ function system_add_module_assets() {
     if (!empty($info['stylesheets'])) {
       foreach ($info['stylesheets'] as $media => $stylesheets) {
         foreach ($stylesheets as $stylesheet) {
-          drupal_add_css($stylesheet, array('media' => $media, 'preprocess' => TRUE));
+          drupal_add_css($stylesheet, array('every_page' => TRUE, 'media' => $media));
         }
       }
     }
     if (!empty($info['scripts'])) {
       foreach ($info['scripts'] as $script) {
-        drupal_add_js($script, array('preprocess' => TRUE));
+        drupal_add_js($script, array('every_page' => TRUE));
       }
     }
   }
@@ -2031,6 +2022,14 @@ function system_preprocess_block(&$variables) {
  */
 function system_admin_menu_block($item) {
   $cache = &drupal_static(__FUNCTION__, array());
+  // If we are calling this function for a menu item that corresponds to a
+  // local task (for example, admin/tasks), then we want to retrieve the
+  // parent item's child links, not this item's (since this item won't have
+  // any).
+  if ($item['tab_root'] != $item['path']) {
+    $item = menu_get_item($item['tab_root_href']);
+  }
+
   if (!isset($item['mlid'])) {
     $item += db_query("SELECT mlid, menu_name FROM {menu_links} ml WHERE ml.router_path = :path AND module = 'system'", array(':path' => $item['path']))->fetchAssoc();
   }
@@ -2040,62 +2039,41 @@ function system_admin_menu_block($item) {
   }
 
   $content = array();
-  $default_task = NULL;
-  $has_subitems = FALSE;
-  $result = db_query("
-    SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.delivery_callback, m.title, m.title_callback, m.title_arguments, m.theme_callback, m.theme_arguments, m.type, m.description, m.path, m.weight as router_weight, ml.*
-    FROM {menu_router} m
-    LEFT JOIN {menu_links} ml ON m.path = ml.router_path
-    WHERE (ml.plid = :plid AND ml.menu_name = :name AND hidden = 0) OR (m.tab_parent = :path AND m.type IN (:local_task, :default_task))", array(':plid' => $item['mlid'], ':name' => $item['menu_name'], ':path' => $item['path'], ':local_task' => MENU_LOCAL_TASK, ':default_task' => MENU_DEFAULT_LOCAL_TASK), array('fetch' => PDO::FETCH_ASSOC));
-  foreach ($result as $link) {
-    if (!isset($link['link_path'])) {
-      // If this was not an actual link, fake the tab as a menu link, so we
-      // don't need to special case it beyond this point.
-      $link['link_title'] = $link['title'];
-      $link['link_path'] = $link['path'];
-      $link['options'] = 'a:0:{}';
-      $link['weight'] = $link['router_weight'];
-    }
-    else {
-      // We found a non-tab subitem, remember that.
-      $has_subitems = TRUE;
-    }
+  $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
+  $query->join('menu_router', 'm', 'm.path = ml.router_path');
+  $query
+    ->fields('ml')
+    // Weight should be taken from {menu_links}, not {menu_router}.
+    ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), array('weight')))
+    ->condition('ml.plid', $item['mlid'])
+    ->condition('ml.menu_name', $item['menu_name'])
+    ->condition('ml.hidden', 0);
+
+  foreach ($query->execute() as $link) {
     _menu_link_translate($link);
-    if (!$link['access']) {
-      continue;
-    }
-
-    // The link 'description' — either derived from the hook_menu 'description' or
-    // entered by the user via menu module — is saved as the title attribute.
-    // The title attribute is then unset to reduce redundancy in admin pages
-    // for screen readers.
-    if (!empty($link['localized_options']['attributes']['title'])) {
-      $link['description'] = $link['localized_options']['attributes']['title'];
-      unset($link['localized_options']['attributes']['title']);
-    }
-
-    // Prepare for sorting as in function _menu_tree_check_access().
-    // The weight is offset so it is always positive, with a uniform 5-digits.
-    $key = (50000 + $link['weight']) . ' ' . drupal_strtolower($link['title']) . ' ' . $link['mlid'];
-    $content[$key] = $link;
-    if ($link['type'] == MENU_DEFAULT_LOCAL_TASK) {
-      $default_task = $key;
+    if ($link['access']) {
+      // The link description, either derived from 'description' in
+      // hook_menu() or customized via menu module is used as title attribute.
+      if (!empty($link['localized_options']['attributes']['title'])) {
+        $link['description'] = $link['localized_options']['attributes']['title'];
+        unset($link['localized_options']['attributes']['title']);
+      }
+      // Prepare for sorting as in function _menu_tree_check_access().
+      // The weight is offset so it is always positive, with a uniform 5-digits.
+      $key = (50000 + $link['weight']) . ' ' . drupal_strtolower($link['title']) . ' ' . $link['mlid'];
+      $content[$key] = $link;
     }
   }
-  if ($has_subitems) {
-    // If we've had at least one non-tab subitem, remove the link for the
-    // default task, since that is already broken down to subitems.
-    unset($content[$default_task]);
-  }
   ksort($content);
   $cache[$item['mlid']] = $content;
   return $content;
 }
 
 /**
- * Checks the existence of the directory specified in $form_element. This
- * function is called from the system_settings form to check both core file
- * directories (file_public_path, file_private_path, file_temporary_path).
+ * Checks the existence of the directory specified in $form_element.
+ *
+ * This function is called from the system_settings form to check all core
+ * file directories (file_public_path, file_private_path, file_temporary_path).
  *
  * @param $form_element
  *   The form element containing the name of the directory to check.
@@ -2214,7 +2192,7 @@ function system_update_files_database(&$files, $type) {
 
   // All remaining files are not in the system table, so we need to add them.
   $query = db_insert('system')->fields(array('filename', 'name', 'type', 'owner', 'info'));
-  foreach($files as &$file) {
+  foreach ($files as &$file) {
     if (isset($file->exists)) {
       unset($file->exists);
     }
@@ -2301,7 +2279,6 @@ function _system_rebuild_module_data() {
   // Set defaults for module info.
   $defaults = array(
     'dependencies' => array(),
-    'dependents' => array(),
     'description' => '',
     'package' => 'Other',
     'version' => NULL,
@@ -2621,23 +2598,21 @@ function system_find_base_themes($themes, $key, $used_keys = array()) {
  *   An array of regions in the form $region['name'] = 'description'.
  */
 function system_region_list($theme_key, $show = REGIONS_ALL) {
-  $list = &drupal_static(__FUNCTION__, array());
+  $themes = list_themes();
+  if (!isset($themes[$theme_key])) {
+    return array();
+  }
 
-  if (empty($list[$theme_key][$show])) {
-    $themes = list_themes();
-    if (!isset($themes[$theme_key])) {
-      $list[$theme_key][$show] = array();
-      return $list[$theme_key][$show];
-    }
-    $info = $themes[$theme_key]->info;
-    // If requested, suppress hidden regions. See block_admin_display_form().
-    foreach ($info['regions'] as $name => $label) {
-      if ($show == REGIONS_ALL || !isset($info['regions_hidden']) || !in_array($name, $info['regions_hidden'])) {
-        $list[$theme_key][$show][$name] = $label;
-      }
+  $list = array();
+  $info = $themes[$theme_key]->info;
+  // If requested, suppress hidden regions. See block_admin_display_form().
+  foreach ($info['regions'] as $name => $label) {
+    if ($show == REGIONS_ALL || !isset($info['regions_hidden']) || !in_array($name, $info['regions_hidden'])) {
+      $list[$name] = $label;
     }
   }
-  return $list[$theme_key][$show];
+
+  return $list;
 }
 
 /**
@@ -2782,7 +2757,6 @@ function confirm_form($form, $question, $path, $description = NULL, $yes = NULL,
   else {
     $options = array('path' => $path);
   }
-  $cancel = l($no ? $no : t('Cancel'), $options['path'], $options);
 
   drupal_set_title($question, PASS_THROUGH);
 
@@ -2790,12 +2764,17 @@ function confirm_form($form, $question, $path, $description = NULL, $yes = NULL,
   $form['description'] = array('#markup' => $description);
   $form[$name] = array('#type' => 'hidden', '#value' => 1);
 
-  $form['actions'] = array(
-    '#type' => 'actions',
-    '#attributes' => array('class' => array('container-inline')),
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => $yes ? $yes : t('Confirm'),
+  );
+  $form['actions']['cancel'] = array(
+    '#type' => 'link',
+    '#title' => $no ? $no : t('Cancel'),
+    '#href' => $options['path'],
+    '#options' => $options,
   );
-  $form['actions']['submit'] = array('#type' => 'submit', '#value' => $yes ? $yes : t('Confirm'));
-  $form['actions']['cancel'] = array('#markup' => $cancel);
   // By default, render the form using theme_confirm_form().
   if (!isset($form['#theme'])) {
     $form['#theme'] = 'confirm_form';
@@ -2831,38 +2810,61 @@ function system_admin_compact_page($mode = 'off') {
  *
  * @param $module
  *   Module name.
+ * @param $info
+ *   The module's information, as provided by system_get_info().
+ *
  * @return
  *   An array of task links.
  */
-function system_get_module_admin_tasks($module) {
-  $items = &drupal_static(__FUNCTION__, array());
-
-  if (empty($items)) {
-    $result = db_query("
-       SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.delivery_callback, m.title, m.title_callback, m.title_arguments, m.theme_callback, m.theme_arguments, m.type, ml.*
-       FROM {menu_links} ml INNER JOIN {menu_router} m ON ml.router_path = m.path WHERE ml.link_path LIKE 'admin/%' AND hidden >= 0 AND module = 'system' AND m.number_parts > 2", array(), array('fetch' => PDO::FETCH_ASSOC));
-    foreach ($result as $item) {
-      _menu_link_translate($item);
-      if ($item['access']) {
-        $items[$item['router_path']] = $item;
+function system_get_module_admin_tasks($module, $info) {
+  $links = &drupal_static(__FUNCTION__);
+
+  if (!isset($links)) {
+    $links = array();
+    $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
+    $query->join('menu_router', 'm', 'm.path = ml.router_path');
+    $query
+      ->fields('ml')
+      // Weight should be taken from {menu_links}, not {menu_router}.
+      ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), array('weight')))
+      ->condition('ml.link_path', 'admin/%', 'LIKE')
+      ->condition('ml.hidden', 0, '>=')
+      ->condition('ml.module', 'system')
+      ->condition('m.number_parts', 1, '>')
+      ->condition('m.page_callback', 'system_admin_menu_block_page', '!=');
+    foreach ($query->execute() as $link) {
+      _menu_link_translate($link);
+      if ($link['access']) {
+        $links[$link['router_path']] = $link;
       }
     }
   }
 
-  $admin_access = user_access('administer permissions');
   $admin_tasks = array();
-  $admin_task_count = 0;
-  // Check for permissions.
-  if (in_array($module, module_implements('permission')) && $admin_access) {
-    $admin_tasks[-1] = l(t('Configure permissions'), 'admin/people/permissions', array('fragment' => 'module-' . $module));
+  if ($menu = module_invoke($module, 'menu')) {
+    foreach ($menu as $path => $item) {
+      if (isset($links[$path])) {
+        $task = $links[$path];
+        // The link description, either derived from 'description' in
+        // hook_menu() or customized via menu module is used as title attribute.
+        if (!empty($task['localized_options']['attributes']['title'])) {
+          $task['description'] = $task['localized_options']['attributes']['title'];
+          unset($task['localized_options']['attributes']['title']);
+        }
+        $admin_tasks[$path] = $task;
+      }
+    }
   }
 
-  // Check for menu items that are admin links.
-  if (in_array($module, module_implements('menu')) && $menu = module_invoke($module, 'menu')) {
-    foreach (array_keys($menu) as $path) {
-      if (isset($items[$path])) {
-        $admin_tasks[$items[$path]['title'] . $admin_task_count ++] = l($items[$path]['title'], $path);
-      }
+  // Append link for permissions.
+  if (module_hook($module, 'permission')) {
+    $item = menu_get_item('admin/people/permissions');
+    if (!empty($item['access'])) {
+      $item['link_path'] = $item['href'];
+      $item['title'] = t('Configure @module permissions', array('@module' => $info['name']));
+      unset($item['description']);
+      $item['localized_options']['fragment'] = 'module-' . $module;
+      $admin_tasks["admin/people/permissions#module-$module"] = $item;
     }
   }
 
@@ -3769,6 +3771,35 @@ function theme_system_settings_form($variables) {
   return drupal_render_children($variables['form']);
 }
 
+/**
+ * Returns HTML for an exposed filter form.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - form: An associative array containing the structure of the form.
+ *
+ * @return
+ *   A string containing an HTML-formatted form.
+ *
+ * @ingroup themeable
+ */
+function theme_exposed_filters($variables) {
+  $form = $variables['form'];
+  $output = '';
+
+  if (isset($form['current'])) {
+    $items = array();
+    foreach (element_children($form['current']) as $key) {
+      $items[] = drupal_render($form['current'][$key]);
+    }
+    $output .= theme('item_list', array('items' => $items, 'attributes' => array('class' => array('clearfix', 'current-filters'))));
+  }
+
+  $output .= drupal_render_children($form);
+
+  return '<div class="exposed-filters">' . $output . '</div>';
+}
+
 /**
  * Implements hook_admin_paths().
  */
diff --git a/modules/system/system.test b/modules/system/system.test
index 3cc68d67ed56bbafb4064ed81f27c056f131ec7d..a4ded7e780737e193911a17fddfddfe825b7878b 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: system.test,v 1.142 2010/09/11 21:14:32 webchick Exp $
+// $Id: system.test,v 1.146 2010/10/05 00:22:24 webchick Exp $
 
 /**
  * Helper class for module test cases.
@@ -318,6 +318,35 @@ class ModuleDependencyTestCase extends ModuleTestCase {
     $this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
     $this->assertModules(array('taxonomy', 'forum'), TRUE);
   }
+
+  /**
+   * Tests that module dependencies are enabled in the correct order via the
+   * UI. Dependencies should be enabled before their dependents.
+   */
+  function testModuleEnableOrder() {
+    module_enable(array('module_test'), FALSE);
+    $this->resetAll();
+    $this->assertModules(array('module_test'), TRUE);
+    variable_set('dependency_test', 'dependency');
+    // module_test creates a dependency chain: forum depends on poll, which
+    // depends on php. The correct enable order is, php, poll, forum.
+    $expected_order = array('php', 'poll', 'forum');
+
+    // Enable the modules through the UI, verifying that the dependency chain
+    // is correct.
+    $edit = array();
+    $edit['modules[Core][forum][enable]'] = 'forum';
+    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+    $this->assertModules(array('forum'), FALSE);
+    $this->assertText(t('You must enable the Poll, PHP filter modules to install Forum.'), t('Dependency chain created.'));
+    $edit['modules[Core][poll][enable]'] = 'poll';
+    $edit['modules[Core][php][enable]'] = 'php';
+    $this->drupalPost('admin/modules', $edit, t('Save configuration'));
+    $this->assertModules(array('forum', 'poll', 'php'), TRUE);
+
+    // Check the actual order which is saved by module_test_modules_enabled().
+    $this->assertIdentical(variable_get('test_module_enable_order', FALSE), $expected_order, t('Modules enabled in the correct order.'));
+  }
 }
 
 /**
@@ -653,8 +682,7 @@ class AccessDeniedTestCase extends DrupalWebTestCase {
     parent::setUp();
 
     // Create an administrative user.
-    $this->admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer blocks'));
-    $this->drupalLogin($this->admin_user);
+    $this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer site configuration', 'administer blocks'));
   }
 
   function testAccessDenied() {
@@ -662,6 +690,7 @@ class AccessDeniedTestCase extends DrupalWebTestCase {
     $this->assertText(t('Access denied'), t('Found the default 403 page'));
     $this->assertResponse(403);
 
+    $this->drupalLogin($this->admin_user);
     $edit = array(
       'title' => $this->randomName(10),
       'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(100)))),
@@ -671,6 +700,7 @@ class AccessDeniedTestCase extends DrupalWebTestCase {
     // Use a custom 403 page.
     $this->drupalPost('admin/config/system/site-information', array('site_403' => 'node/' . $node->nid), t('Save configuration'));
 
+    $this->drupalLogout();
     $this->drupalGet('admin');
     $this->assertText($node->title, t('Found the custom 403 page'));
 
@@ -1665,6 +1695,73 @@ array_space[a b] = Value';
   }
 }
 
+/**
+ * Tests the effectiveness of hook_system_info_alter().
+ */
+class SystemInfoAlterTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'System info alter',
+      'description' => 'Tests the effectiveness of hook_system_info_alter().',
+      'group' => 'System',
+    );
+  }
+
+  /**
+   * Tests that {system}.info is rebuilt after a module that implements
+   * hook_system_info_alter() is enabled. Also tests if core *_list() functions
+   * return freshly altered info.
+   */
+  function testSystemInfoAlter() {
+    // Enable our test module. Flush all caches, which we assert is the only
+    // thing necessary to use the rebuilt {system}.info.
+    module_enable(array('module_test'), FALSE);
+    drupal_flush_all_caches();
+    $this->assertTrue(module_exists('module_test'), t('Test module is enabled.'));
+
+    $info = $this->getSystemInfo('seven', 'theme');
+    $this->assertTrue(isset($info['regions']['test_region']), t('Altered theme info was added to {system}.info.'));
+    $seven_regions = system_region_list('seven');
+    $this->assertTrue(isset($seven_regions['test_region']), t('Altered theme info was returned by system_region_list().'));
+    $system_list_themes = system_list('theme');
+    $info = $system_list_themes['seven']->info;
+    $this->assertTrue(isset($info['regions']['test_region']), t('Altered theme info was returned by system_list().'));
+    $list_themes = list_themes();
+    $this->assertTrue(isset($list_themes['seven']->info['regions']['test_region']), t('Altered theme info was returned by list_themes().'));
+
+    // Disable the module and verify that {system}.info is rebuilt without it.
+    module_disable(array('module_test'), FALSE);
+    drupal_flush_all_caches();
+    $this->assertFalse(module_exists('module_test'), t('Test module is disabled.'));
+
+    $info = $this->getSystemInfo('seven', 'theme');
+    $this->assertFalse(isset($info['regions']['test_region']), t('Altered theme info was removed from {system}.info.'));
+    $seven_regions = system_region_list('seven');
+    $this->assertFalse(isset($seven_regions['test_region']), t('Altered theme info was not returned by system_region_list().'));
+    $system_list_themes = system_list('theme');
+    $info = $system_list_themes['seven']->info;
+    $this->assertFalse(isset($info['regions']['test_region']), t('Altered theme info was not returned by system_list().'));
+    $list_themes = list_themes();
+    $this->assertFalse(isset($list_themes['seven']->info['regions']['test_region']), t('Altered theme info was not returned by list_themes().'));
+  }
+
+  /**
+   * Returns the info array as it is stored in {system}.
+   *
+   * @param $name
+   *   The name of the record in {system}.
+   * @param $type
+   *   The type of record in {system}.
+   *
+   * @return
+   *   Array of info, or FALSE if the record is not found.
+   */
+  function getSystemInfo($name, $type) {
+    $raw_info = db_query("SELECT info FROM {system} WHERE name = :name AND type = :type", array(':name' => $name, ':type' => $type))->fetchField();
+    return $raw_info ? unserialize($raw_info) : FALSE;
+  }
+}
+
 /**
  * Tests for the update system functionality.
  */
@@ -1847,21 +1944,96 @@ class ShutdownFunctionsTest extends DrupalWebTestCase {
 }
 
 /**
- * Functional tests compact mode.
+ * Tests administrative overview pages.
  */
-class CompactModeTest extends DrupalWebTestCase {
+class SystemAdminTestCase extends DrupalWebTestCase {
   public static function getInfo() {
     return array(
-      'name' => 'Compact mode',
-      'description' => 'Tests compact mode functionality.',
+      'name' => 'Administrative pages',
+      'description' => 'Tests output on administrative pages and compact mode functionality.',
       'group' => 'System',
     );
   }
 
   function setUp() {
-    parent::setUp();
-    $admin_user = $this->drupalCreateUser(array('access administration pages'));
-    $this->drupalLogin($admin_user);
+    // testAdminPages() requires Locale module.
+    parent::setUp(array('locale'));
+
+    // Create an administrator with all permissions, as well as a regular user
+    // who can only access administration pages and perform some Locale module
+    // administrative tasks, but not all of them.
+    $this->admin_user = $this->drupalCreateUser(array_keys(module_invoke_all('permission')));
+    $this->web_user = $this->drupalCreateUser(array(
+      'access administration pages',
+      'translate interface',
+    ));
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Tests output on administrative listing pages.
+   */
+  function testAdminPages() {
+    // Go to Administration.
+    $this->drupalGet('admin');
+
+    // Verify that all visible, top-level administration links are listed on
+    // the main administration page.
+    foreach (menu_get_router() as $path => $item) {
+      if (strpos($path, 'admin/') === 0 && ($item['type'] & MENU_VISIBLE_IN_TREE) && $item['_number_parts'] == 2) {
+        $this->assertLink($item['title']);
+        $this->assertLinkByHref($path);
+        $this->assertText($item['description']);
+      }
+    }
+
+    // For each administrative listing page on which the Locale module appears,
+    // verify that there are links to the module's primary configuration pages,
+    // but no links to its individual sub-configuration pages. Also verify that
+    // a user with access to only some Locale module administration pages only
+    // sees links to the pages they have access to.
+    $admin_list_pages = array(
+      'admin/index',
+      'admin/config',
+      'admin/config/regional',
+    );
+
+    foreach ($admin_list_pages as $page) {
+      // For the administrator, verify that there are links to Locale's primary
+      // configuration pages, but no links to individual sub-configuration
+      // pages.
+      $this->drupalLogin($this->admin_user);
+      $this->drupalGet($page);
+      $this->assertLinkByHref('admin/config');
+      $this->assertLinkByHref('admin/config/regional/settings');
+      $this->assertLinkByHref('admin/config/regional/date-time');
+      $this->assertLinkByHref('admin/config/regional/language');
+      $this->assertNoLinkByHref('admin/config/regional/language/configure/session');
+      $this->assertNoLinkByHref('admin/config/regional/language/configure/url');
+      $this->assertLinkByHref('admin/config/regional/translate');
+      // On admin/index only, the administrator should also see a "Configure
+      // permissions" link for the Locale module.
+      if ($page == 'admin/index') {
+        $this->assertLinkByHref("admin/people/permissions#module-locale");
+      }
+
+      // For a less privileged user, verify that there are no links to Locale's
+      // primary configuration pages, but a link to the translate page exists.
+      $this->drupalLogin($this->web_user);
+      $this->drupalGet($page);
+      $this->assertLinkByHref('admin/config');
+      $this->assertNoLinkByHref('admin/config/regional/settings');
+      $this->assertNoLinkByHref('admin/config/regional/date-time');
+      $this->assertNoLinkByHref('admin/config/regional/language');
+      $this->assertNoLinkByHref('admin/config/regional/language/configure/session');
+      $this->assertNoLinkByHref('admin/config/regional/language/configure/url');
+      $this->assertLinkByHref('admin/config/regional/translate');
+      // This user cannot configure permissions, so even on admin/index should
+      // not see a "Configure permissions" link for the Locale module.
+      if ($page == 'admin/index') {
+        $this->assertNoLinkByHref("admin/people/permissions#module-locale");
+      }
+    }
   }
 
   /**
diff --git a/modules/system/system.theme-rtl.css b/modules/system/system.theme-rtl.css
new file mode 100644
index 0000000000000000000000000000000000000000..3c2794f50337adde93362650f3d5e4eaecbe84da
--- /dev/null
+++ b/modules/system/system.theme-rtl.css
@@ -0,0 +1,54 @@
+/* $Id: system.theme-rtl.css,v 1.2 2010/09/25 02:28:14 dries Exp $ */
+
+/**
+ * @file
+ * RTL styles for common markup.
+ */
+
+/**
+ * HTML elements.
+ */
+th {
+  text-align: right;
+  padding-left: 1em;
+  padding-right: 0;
+}
+
+/**
+ * Markup generated by theme_item_list().
+ */
+.item-list ul li {
+  margin: 0 1.5em 0.25em 0;
+}
+
+/**
+ * Markup generated by theme_more_link().
+ */
+.more-link {
+  text-align: left;
+}
+
+/**
+ * Markup generated by theme_more_help_link().
+ */
+.more-help-link {
+  text-align: left;
+}
+.more-help-link a {
+  background-position: 100% 50%;
+  padding: 1px 20px 1px 0;
+}
+
+/**
+ * Collapsible fieldsets.
+ */
+html.js fieldset.collapsible .fieldset-legend {
+  background-position: 98% 75%;
+  padding-left: 0;
+  padding-right: 15px;
+}
+html.js fieldset.collapsed .fieldset-legend {
+  background-image: url(../../misc/menu-collapsed-rtl.png);
+  background-position: 98% 50%;
+}
+
diff --git a/modules/system/system.theme.css b/modules/system/system.theme.css
new file mode 100644
index 0000000000000000000000000000000000000000..09f249c8fe6d5369c1ba3bfc91130d82a46b84fc
--- /dev/null
+++ b/modules/system/system.theme.css
@@ -0,0 +1,240 @@
+/* $Id: system.theme.css,v 1.3 2010/09/27 01:12:45 dries Exp $ */
+
+/**
+ * @file
+ * Basic styling for common markup.
+ */
+
+/**
+ * HTML elements.
+ */
+fieldset {
+  margin-bottom: 1em;
+  padding: 0.5em;
+}
+form {
+  margin: 0;
+  padding: 0;
+}
+hr {
+  border: 1px solid gray;
+  height: 1px;
+}
+img {
+  border: 0;
+}
+table {
+  border-collapse: collapse;
+}
+th {
+  border-bottom: 3px solid #ccc;
+  padding-right: 1em; /* LTR */
+  text-align: left; /* LTR */
+}
+tbody {
+  border-top: 1px solid #ccc;
+}
+tr.even,
+tr.odd {
+  background-color: #eee;
+  border-bottom: 1px solid #ccc;
+  padding: 0.1em 0.6em;
+}
+
+/**
+ * Markup generated by theme_tablesort_indicator().
+ */
+th.active img {
+  display: inline;
+}
+td.active {
+  background-color: #ddd;
+}
+
+/**
+ * Markup generated by theme_item_list().
+ */
+.item-list .title {
+  font-weight: bold;
+}
+.item-list ul {
+  margin: 0 0 0.75em 0;
+  padding: 0;
+}
+.item-list ul li {
+  margin: 0 0 0.25em 1.5em; /* LTR */
+  padding: 0;
+}
+
+/**
+ * Markup generated by Form API.
+ */
+.form-item,
+.form-actions {
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+tr.odd .form-item,
+tr.even .form-item {
+  margin-top: 0;
+  margin-bottom: 0;
+  white-space: nowrap;
+}
+.form-item .description {
+  font-size: 0.85em;
+}
+label {
+  display: block;
+  font-weight: bold;
+}
+label.option {
+  display: inline;
+  font-weight: normal;
+}
+.form-checkboxes .form-item,
+.form-radios .form-item {
+  margin-top: 0.4em;
+  margin-bottom: 0.4em;
+}
+.form-type-radio .description,
+.form-type-checkbox .description {
+  margin-left: 2.4em;
+}
+input.form-checkbox,
+input.form-radio {
+  vertical-align: middle;
+}
+.marker,
+.form-required {
+  color: #f00;
+}
+.form-item input.error,
+.form-item textarea.error,
+.form-item select.error {
+  border: 2px solid red;
+}
+
+/**
+ * Inline items.
+ */
+.container-inline .form-actions,
+.container-inline.form-actions {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+/**
+ * Markup generated by theme_more_link().
+ */
+.more-link {
+  text-align: right; /* LTR */
+}
+
+/**
+ * Markup generated by theme_more_help_link().
+ */
+.more-help-link {
+  text-align: right; /* LTR */
+}
+.more-help-link a {
+  background: url(../../misc/help.png) 0 50% no-repeat; /* LTR */
+  padding: 1px 0 1px 20px; /* LTR */
+}
+
+/**
+ * Markup generated by theme_pager().
+ */
+.item-list .pager {
+  clear: both;
+  text-align: center;
+}
+.item-list .pager li {
+  background-image: none;
+  display: inline;
+  list-style-type: none;
+  padding: 0.5em;
+}
+.pager-current {
+  font-weight: bold;
+}
+
+/**
+ * Autocomplete.
+ *
+ * @see autocomplete.js
+ */
+/* Suggestion list */
+#autocomplete li.selected {
+  background: #0072b9;
+  color: #fff;
+}
+
+/**
+ * Collapsible fieldsets.
+ *
+ * @see collapse.js
+ */
+html.js fieldset.collapsible .fieldset-legend {
+  background: url(../../misc/menu-expanded.png) 5px 65% no-repeat; /* LTR */
+  padding-left: 15px; /* LTR */
+}
+html.js fieldset.collapsed .fieldset-legend {
+  background-image: url(../../misc/menu-collapsed.png); /* LTR */
+  background-position: 5px 50%; /* LTR */
+}
+.fieldset-legend span.summary {
+  color: #999;
+  font-size: 0.9em;
+  margin-left: 0.5em;
+}
+
+/**
+ * TableDrag behavior.
+ *
+ * @see tabledrag.js
+ */
+tr.drag {
+  background-color: #fffff0;
+}
+tr.drag-previous {
+  background-color: #ffd;
+}
+.tabledrag-toggle-weight {
+  font-size: 0.9em;
+}
+body div.tabledrag-changed-warning {
+  margin-bottom: 0.5em;
+}
+
+/**
+ * TableSelect behavior.
+ *
+ * @see tableselect.js
+*/
+tr.selected td {
+  background: #ffc;
+}
+td.checkbox,
+th.checkbox {
+  text-align: center;
+}
+
+/**
+ * Progress bar.
+ *
+ * @see progress.js
+ */
+.progress {
+  font-weight: bold;
+}
+.progress .bar {
+  background: #ccc;
+  border-color: #666;
+  margin: 0 0.2em;
+  -moz-border-radius: 3px;
+  -webkit-border-radius: 3px;
+  border-radius: 3px;
+}
+.progress .filled {
+  background: #0072b9 url(../../misc/progress.gif);
+}
diff --git a/modules/taxonomy/taxonomy.admin.inc b/modules/taxonomy/taxonomy.admin.inc
index 1193b69bb6d5aa8bf09cfbafd5b66b79dbb90525..a509c9a19947362993d2277f4570769fa2e8c0da 100644
--- a/modules/taxonomy/taxonomy.admin.inc
+++ b/modules/taxonomy/taxonomy.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: taxonomy.admin.inc,v 1.107 2010/07/31 13:01:50 webchick Exp $
+// $Id: taxonomy.admin.inc,v 1.111 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -627,13 +627,13 @@ function theme_taxonomy_overview_terms($variables) {
   }
 
   if (empty($rows)) {
-    $rows[] = array(array('data' => $form['#empty_text'], 'colspan' => '2'));
+    $rows[] = array(array('data' => $form['#empty_text'], 'colspan' => '3'));
   }
 
   $header = array(t('Name'), t('Weight'), t('Operations'));
   $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'taxonomy')));
   $output .= drupal_render_children($form);
-  $output .= theme('pager', array('tags' => NULL));
+  $output .= theme('pager');
 
   return $output;
 }
@@ -656,7 +656,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary =
     $defaults = array(
       'name' => '',
       'description' => '',
-      'format' => filter_default_format(),
+      'format' => NULL,
       'vocabulary_machine_name' => isset($vocabulary) ? $vocabulary->machine_name : NULL,
       'tid' => NULL,
       'weight' => 0,
@@ -868,8 +868,6 @@ function taxonomy_form_term_submit($form, &$form_state) {
 
   $form_state['values']['tid'] = $term->tid;
   $form_state['tid'] = $term->tid;
-  // Do not rebuild here. The term is saved by now and the form should clear.
-  $form_state['rebuild'] = FALSE;
 }
 
 /**
diff --git a/modules/taxonomy/taxonomy.info b/modules/taxonomy/taxonomy.info
index 51a6625704509564d216317921ac3a58767f1038..cb37bc727ab2e39cd1a1ab600b666c7366585ffc 100644
--- a/modules/taxonomy/taxonomy.info
+++ b/modules/taxonomy/taxonomy.info
@@ -12,8 +12,8 @@ files[] = taxonomy.test
 files[] = taxonomy.tokens.inc
 configure = admin/structure/taxonomy
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/taxonomy/taxonomy.install b/modules/taxonomy/taxonomy.install
index 3be5829f7d901cc07ef9b718a021f164d73d3ad0..f111ab7afe94f31ec5deee48fa2d9945a19db8ba 100644
--- a/modules/taxonomy/taxonomy.install
+++ b/modules/taxonomy/taxonomy.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: taxonomy.install,v 1.46 2010/09/05 17:00:04 webchick Exp $
+// $Id: taxonomy.install,v 1.51 2010/10/06 21:53:41 webchick Exp $
 
 /**
  * @file
@@ -52,9 +52,8 @@ function taxonomy_schema() {
       ),
       'format' => array(
         'type' => 'int',
-        'size' => 'small',
-        'not null' => TRUE,
-        'default' => 0,
+        'unsigned' => TRUE,
+        'not null' => FALSE,
         'description' => 'The {filter_format}.format of the description.',
       ),
       'weight' => array(
@@ -263,6 +262,17 @@ function taxonomy_update_dependencies() {
   return $dependencies;
 }
 
+/**
+ * Utility function: get the list of vocabularies directly from the database.
+ *
+ * This function is valid for a database schema version 7002.
+ *
+ * @ingroup update-api-6.x-to-7.x
+ */
+function _update_7002_taxonomy_get_vocabularies() {
+  return db_query('SELECT v.* FROM {taxonomy_vocabulary} v ORDER BY v.weight, v.name')->fetchAllAssoc('vid', PDO::FETCH_OBJ);
+}
+
 /**
  * Rename taxonomy tables.
  */
@@ -299,7 +309,6 @@ function taxonomy_update_7002() {
       ->fields(array('machine_name' => $machine_name))
       ->condition('vid', $vid)
       ->execute();
-    field_attach_create_bundle('taxonomy_term', $machine_name);
   }
 
   // The machine_name unique key can only be added after we ensure the
@@ -392,19 +401,20 @@ function taxonomy_update_7004() {
     $field_name = 'taxonomy_' . $vocabulary->machine_name;
     $field = array(
       'field_name' => $field_name,
+      'module' => 'taxonomy',
       'type' => 'taxonomy_term_reference',
       'cardinality' => $vocabulary->multiple || $vocabulary->tags ? FIELD_CARDINALITY_UNLIMITED : 1,
       'settings' => array(
         'required' => $vocabulary->required ? TRUE : FALSE,
         'allowed_values' => array(
           array(
-            'vid' => $vocabulary->vid,
+            'vocabulary' => $vocabulary->machine_name,
             'parent' => 0,
           ),
         ),
       ),
     );
-    field_create_field($field);
+    _update_7000_field_create_field($field);
 
     foreach ($vocabulary->nodes as $bundle) {
       $instance = array(
@@ -412,10 +422,9 @@ function taxonomy_update_7004() {
         'field_name' => $field_name,
         'bundle' => $bundle,
         'entity_type' => 'node',
+        'settings' => array(),
         'description' => $vocabulary->help,
-        'widget' => array(
-          'type' => $vocabulary->tags ? 'taxonomy_autocomplete' : 'select',
-        ),
+        'widget' => array(),
         'display' => array(
           'default' => array(
             'type' => 'taxonomy_term_reference_link',
@@ -427,7 +436,24 @@ function taxonomy_update_7004() {
           ),
         ),
       );
-      field_create_instance($instance);
+      if ($vocabulary->tags) {
+        $instance['widget'] = array(
+          'type' => 'taxonomy_autocomplete',
+          'module' => 'taxonomy',
+          'settings' => array(
+            'size' => 60,
+            'autocomplete_path' => 'taxonomy/autocomplete',
+          ),
+        );
+      }
+      else {
+        $instance['widget'] = array(
+          'type' => 'select',
+          'module' => 'options',
+          'settings' => array(),
+        );
+      }
+      _update_7000_field_create_instance($field, $instance);
     }
   }
 
@@ -438,9 +464,9 @@ function taxonomy_update_7004() {
 
   // Allowed values for this extra vocabs field is every vocabulary.
   $allowed_values = array();
-  foreach (taxonomy_get_vocabularies() as $vocabulary) {
+  foreach (_update_7002_taxonomy_get_vocabularies() as $vocabulary) {
     $allowed_values[] = array(
-      'vid' => $vocabulary->vid,
+      'vocabulary' => $vocabulary->machine_name,
       'parent' => 0,
     );
   }
@@ -448,6 +474,7 @@ function taxonomy_update_7004() {
   $field_name = 'taxonomyextra';
   $field = array(
     'field_name' => $field_name,
+    'module' => 'taxonomy',
     'type' => 'taxonomy_term_reference',
     'cardinality' => FIELD_CARDINALITY_UNLIMITED,
     'settings' => array(
@@ -455,17 +482,20 @@ function taxonomy_update_7004() {
       'allowed_values' => $allowed_values,
     ),
   );
-  field_create_field($field);
+  _update_7000_field_create_field($field);
 
-  foreach (node_type_get_types() as $bundle) {
+  foreach (_update_7000_node_get_types() as $bundle) {
     $instance = array(
       'label' => 'Taxonomy upgrade extras',
       'field_name' => $field_name,
-      'bundle' => $bundle->type,
       'entity_type' => 'node',
+      'bundle' => $bundle->type,
+      'settings' => array(),
       'description' => 'Debris left over after upgrade from Drupal 6',
       'widget' => array(
         'type' => 'taxonomy_autocomplete',
+        'module' => 'taxonomy',
+        'settings' => array(),
       ),
       'display' => array(
         'default' => array(
@@ -478,7 +508,7 @@ function taxonomy_update_7004() {
         ),
       ),
     );
-    field_create_instance($instance);
+    _update_7000_field_create_instance($field, $instance);
   }
 
   $fields = array('help', 'multiple', 'required', 'tags');
@@ -528,7 +558,7 @@ function taxonomy_update_7005(&$sandbox) {
   // provides the delta value for each term reference data insert. The
   // deltas are reset for each new revision.
 
-  $field_info = field_info_fields();
+  $field_info = _update_7000_field_read_fields();
 
   // This is a multi-pass update. On the first call we need to initialize some
   // variables.
@@ -536,8 +566,11 @@ function taxonomy_update_7005(&$sandbox) {
     $sandbox['last'] = 0;
     $sandbox['count'] = 0;
 
-    $query = db_select('taxonomy_term_node', 't');
-    $sandbox['total'] = $query->countQuery()->execute()->fetchField();
+    // Run the same joins as the query that is used later to retrieve the
+    // term_node data, this ensures that bad records in that table - for
+    // tids which aren't in taxonomy_term_data or nids which aren't in {node}
+    // are not included in the count.
+    $sandbox['total'] = db_query('SELECT COUNT(*) FROM {taxonomy_term_data} td INNER JOIN {taxonomy_term_node} tn ON td.tid = tn.tid INNER JOIN {node} n ON tn.nid = n.nid LEFT JOIN {node} n2 ON tn.vid = n2.vid')->fetchField();
 
     // Use an inline version of Drupal 6 taxonomy_get_vocabularies() here since
     // we can no longer rely on $vocabulary->nodes from the API function.
@@ -614,8 +647,11 @@ function taxonomy_update_7005(&$sandbox) {
         // use the previous deltas to calculate the next delta.
         if ($record->vid == $values[2]) {
 
-          // see field_default_validate().
-          if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ($deltas[$field_name] + 1) >= $field['cardinality']) {
+          // For limited cardinality fields, the delta must not be allowed to
+          // exceed the cardinality during the update. So ensure that the
+          // delta about to be inserted is within this limit.
+          // @see field_default_validate().
+          if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ($deltas[$field_name] + 1) > $field['cardinality']) {
 
             // For excess values of a single-term vocabulary, switch over to
             // the overflow field.
@@ -635,8 +671,9 @@ function taxonomy_update_7005(&$sandbox) {
 
       // Table and column found in the field's storage details. During upgrades,
       // it's always SQL.
-      $table = key($field['storage']['details']['sql'][FIELD_LOAD_REVISION]);
-      $value_column = $field['storage']['details']['sql'][FIELD_LOAD_REVISION][$table]['tid'];
+      $table_name = "field_data_{$field_name}";
+      $revision_name = "field_revision_{$field_name}";
+      $value_column = $field_name . '_tid';
 
       // Column names and values in field storage are the same for current and
       // revision.
@@ -644,12 +681,11 @@ function taxonomy_update_7005(&$sandbox) {
       $values = array($etid, $record->nid, $record->vid, $record->type, LANGUAGE_NONE, $deltas[$field_name]++, $record->tid);
 
       // Insert rows into the revision table.
-      db_insert($table)->fields($columns)->values($values)->execute();
+      db_insert($revision_name)->fields($columns)->values($values)->execute();
 
       // is_current column is a node ID if this revision is also current.
       if ($record->is_current) {
-        $table = key($field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
-        db_insert($table)->fields($columns)->values($values)->execute();
+        db_insert($table_name)->fields($columns)->values($values)->execute();
 
         // Update the {taxonomy_index} table.
         db_insert('taxonomy_index')
@@ -680,20 +716,20 @@ function taxonomy_update_7005(&$sandbox) {
 
     // Determine necessity of taxonomyextras field.
     $field = $field_info['taxonomyextra'];
-    $table = key($field['storage']['details']['sql'][FIELD_LOAD_REVISION]);
-    $node_types = db_select($table)->distinct()->fields($table, array('bundle'))
+    $revision_name = 'field_revision_' . $field['field_name'];
+    $node_types = db_select($revision_name)->distinct()->fields($revision_name, array('bundle'))
       ->execute()->fetchCol();
 
     if (empty($node_types)) {
       // Delete the overflow field if there are no rows in the revision table.
-      field_delete_field('taxonomyextra');
+      _update_7000_field_delete_field('taxonomyextra');
     }
     else {
       // Remove instances which are not actually used.
-      $bundles = array_diff($field['bundles']['node'], $node_types);
+      $bundles = db_query('SELECT bundle FROM {field_config_instance} WHERE field_name = :field_name', array(':field_name' => 'taxonomyextra'))->fetchCol();
+      $bundles = array_diff($bundles, $node_types);
       foreach ($bundles as $bundle) {
-        $instance = field_info_instance('node', 'taxonomyextra', $bundle);
-        field_delete_instance($instance);
+        _update_7000_field_delete_instance('taxonomyextra', 'node', $bundle);
       }
     }
   }
@@ -705,9 +741,8 @@ function taxonomy_update_7005(&$sandbox) {
 function taxonomy_update_7006() {
   db_add_field('taxonomy_term_data', 'format', array(
     'type' => 'int',
-    'size' => 'small',
-    'not null' => TRUE,
-    'default' => 0,
+    'unsigned' => TRUE,
+    'not null' => FALSE,
     'description' => 'The {filter_format}.format of the description.',
   ));
 }
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index d220848fd1742f8ac521e3c62938d95f270c34c0..de8ed2d88f95b95ad73d7f4df9e3f7ec75e26932 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: taxonomy.module,v 1.605 2010/09/11 06:03:12 webchick Exp $
+// $Id: taxonomy.module,v 1.609 2010/10/03 01:15:33 dries Exp $
 
 /**
  * @file
@@ -287,7 +287,6 @@ function taxonomy_menu() {
     'page callback' => 'taxonomy_term_page',
     'page arguments' => array(2),
     'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
     'file' => 'taxonomy.pages.inc',
   );
   $items['taxonomy/term/%taxonomy_term/view'] = array(
@@ -600,11 +599,18 @@ function taxonomy_term_delete($tid) {
  *   A term object.
  * @param $view_mode
  *   View mode, e.g. 'full', 'teaser'...
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  *
  * @return
  *   An array as expected by drupal_render().
  */
-function taxonomy_term_view($term, $view_mode = 'full') {
+function taxonomy_term_view($term, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   field_attach_prepare_view('taxonomy_term', array($term->tid => $term), $view_mode);
   entity_prepare_view('taxonomy_term', array($term->tid => $term));
 
@@ -612,9 +618,10 @@ function taxonomy_term_view($term, $view_mode = 'full') {
     '#theme' => 'taxonomy_term',
     '#term' => $term,
     '#view_mode' => $view_mode,
+    '#language' => $langcode,
   );
 
-  $build += field_attach_view('taxonomy_term', $term, $view_mode);
+  $build += field_attach_view('taxonomy_term', $term, $view_mode, $langcode);
 
   $build['description'] = array(
     '#markup' => check_markup($term->description, $term->format, '', TRUE),
@@ -842,7 +849,7 @@ function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) {
     }
   }
 
-  $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
+  $max_depth = (!isset($max_depth)) ? count($children[$vid]) : $max_depth;
   $tree = array();
   if ($max_depth > $depth && !empty($children[$vid][$parent])) {
     foreach ($children[$vid][$parent] as $child) {
@@ -1039,7 +1046,7 @@ function taxonomy_implode_tags($tags, $vid = NULL) {
   $typed_tags = array();
   foreach ($tags as $tag) {
     // Extract terms belonging to the vocabulary in question.
-    if (is_null($vid) || $tag->vid == $vid) {
+    if (!isset($vid) || $tag->vid == $vid) {
       // Make sure we have a completed loaded taxonomy term.
       if (isset($tag->name)) {
         // Commas and quotes in tag names are special cases, so encode 'em.
@@ -1059,7 +1066,7 @@ function taxonomy_implode_tags($tags, $vid = NULL) {
  *
  * Field settings:
  * - allowed_values: a list array of one or more vocabulary trees:
- *   - vid: a vocabulary ID.
+ *   - vocabulary: a vocabulary machine name.
  *   - parent: a term ID of a term whose children are allowed. This should be
  *     '0' if all terms in a vocabulary are allowed. The allowed values do not
  *     include the parent term.
@@ -1075,7 +1082,7 @@ function taxonomy_field_info() {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => '0',
+            'vocabulary' => '',
             'parent' => '0',
           ),
         ),
@@ -1149,8 +1156,8 @@ function taxonomy_field_validate($entity_type, $entity, $field, $instance, $lang
         $validate = FALSE;
         foreach ($field['settings']['allowed_values'] as $settings) {
           // If no parent is specified, check if the term is in the vocabulary.
-          if (isset($settings['vid']) && empty($settings['parent'])) {
-            if ($settings['vid'] == $terms[$item['tid']]->vid) {
+          if (isset($settings['vocabulary']) && empty($settings['parent'])) {
+            if ($settings['vocabulary'] == $terms[$item['tid']]->vocabulary_machine_name) {
               $validate = TRUE;
               break;
             }
@@ -1259,10 +1266,11 @@ function taxonomy_field_formatter_view($entity_type, $entity, $field, $instance,
 function taxonomy_allowed_values($field) {
   $options = array();
   foreach ($field['settings']['allowed_values'] as $tree) {
-    $terms = taxonomy_get_tree($tree['vid'], $tree['parent']);
-    if ($terms) {
-      foreach ($terms as $term) {
-        $options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
+    if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
+      if ($terms = taxonomy_get_tree($vocabulary->vid, $tree['parent'])) {
+        foreach ($terms as $term) {
+          $options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
+        }
       }
     }
   }
@@ -1361,9 +1369,11 @@ function taxonomy_autocomplete_validate($element, &$form_state) {
   if ($tags = $element['#value']) {
     // Collect candidate vocabularies.
     $field = $form_state['field'][$element['#field_name']][$element['#language']]['field'];
-    $vids = array();
+    $vocabularies = array();
     foreach ($field['settings']['allowed_values'] as $tree) {
-      $vids[] = $tree['vid'];
+      if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
+        $vocabularies[$vocabulary->vid] = $vocabulary;
+      }
     }
 
     // Translate term names into actual terms.
@@ -1371,14 +1381,14 @@ function taxonomy_autocomplete_validate($element, &$form_state) {
     foreach ($typed_terms as $typed_term) {
       // See if the term exists in the chosen vocabulary and return the tid;
       // otherwise, create a new 'autocreate' term for insert/update.
-      if ($possibilities = taxonomy_term_load_multiple(array(), array('name' => trim($typed_term), 'vid' => $vids))) {
+      if ($possibilities = taxonomy_term_load_multiple(array(), array('name' => trim($typed_term), 'vid' => array_keys($vocabularies)))) {
         $term = array_pop($possibilities);
       }
       else {
-        $vocabulary = taxonomy_vocabulary_load($vids[0]);
+        $vocabulary = reset($vocabularies);
         $term = array(
           'tid' => 'autocreate',
-          'vid' => $vids[0],
+          'vid' => $vocabulary->vid,
           'name' => $typed_term,
           'vocabulary_machine_name' => $vocabulary->machine_name,
         );
@@ -1404,17 +1414,17 @@ function taxonomy_field_settings_form($field, $instance, $has_data) {
   $vocabularies = taxonomy_get_vocabularies();
   $options = array();
   foreach ($vocabularies as $vocabulary) {
-    $options[$vocabulary->vid] = $vocabulary->name;
+    $options[$vocabulary->machine_name] = $vocabulary->name;
   }
   $form['allowed_values'] = array(
     '#tree' => TRUE,
   );
 
   foreach ($field['settings']['allowed_values'] as $delta => $tree) {
-    $form['allowed_values'][$delta]['vid'] = array(
+    $form['allowed_values'][$delta]['vocabulary'] = array(
       '#type' => 'select',
       '#title' => t('Vocabulary'),
-      '#default_value' => $tree['vid'],
+      '#default_value' => $tree['vocabulary'],
       '#options' => $options,
       '#required' => TRUE,
       '#description' => t('The vocabulary which supplies the options for this field.'),
diff --git a/modules/taxonomy/taxonomy.pages.inc b/modules/taxonomy/taxonomy.pages.inc
index 43509ed2a04bf27ed3f6e56e435c736624312305..f15ef27c919e0534dc689be0e0f5cb368af898be 100644
--- a/modules/taxonomy/taxonomy.pages.inc
+++ b/modules/taxonomy/taxonomy.pages.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: taxonomy.pages.inc,v 1.53 2010/08/22 13:53:37 dries Exp $
+// $Id: taxonomy.pages.inc,v 1.55 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -19,6 +19,8 @@ function taxonomy_term_page($term) {
   $current = (object) array(
     'tid' => $term->tid,
   );
+  // @todo This overrides any other possible breadcrumb and is a pure hard-coded
+  //   presumption. Make this behavior configurable per vocabulary or term.
   $breadcrumb = array();
   while ($parents = taxonomy_get_parents($current->tid)) {
     $current = array_shift($parents);
@@ -43,7 +45,7 @@ function taxonomy_term_page($term) {
     $nodes = node_load_multiple($nids);
     $build += node_view_multiple($nodes);
     $build['pager'] = array(
-      '#markup' => theme('pager', array('tags' => NULL)),
+      '#markup' => theme('pager'),
       '#weight' => 5,
      );
   }
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index 5e961047dc991a1e33a6bf5e9db7c44a18f9aad7..f530c6f0f0228037ad3509bfaa386e2352c701a4 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: taxonomy.test,v 1.90 2010/08/22 15:45:03 dries Exp $
+// $Id: taxonomy.test,v 1.93 2010/10/01 01:37:13 webchick Exp $
 
 /**
  * @file
@@ -34,6 +34,8 @@ class TaxonomyWebTestCase extends DrupalWebTestCase {
     $term = new stdClass();
     $term->name = $this->randomName();
     $term->description = $this->randomName();
+    // Use the first available text format.
+    $term->format = db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField();
     $term->vid = $vocabulary->vid;
     taxonomy_term_save($term);
     return $term;
@@ -377,7 +379,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => $this->vocabulary->vid,
+            'vocabulary' => $this->vocabulary->machine_name,
             'parent' => 0,
           ),
         ),
@@ -557,7 +559,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
     // the first edit link found on the listing page is to our term.
     $this->clickLink(t('edit'));
 
-    $this->assertText($edit['name'], t('The randomly generated term name is present.'));
+    $this->assertRaw($edit['name'], t('The randomly generated term name is present.'));
     $this->assertText($edit['description[value]'], t('The randomly generated term description is present.'));
 
     $edit = array(
@@ -843,7 +845,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => $this->vocabulary->vid,
+            'vocabulary' => $this->vocabulary->machine_name,
             'parent' => '0',
           ),
         ),
@@ -903,7 +905,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => $this->vocabulary->vid,
+            'vocabulary' => $this->vocabulary->machine_name,
             'parent' => '0',
           ),
         ),
@@ -939,7 +941,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
       "{$this->field_name}[$langcode]" => array($term->tid),
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
@@ -979,7 +981,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {
       'settings' => array(
         'allowed_values' => array(
           array(
-            'vid' => $this->vocabulary->vid,
+            'vocabulary' => $this->vocabulary->machine_name,
             'parent' => 0,
           ),
         ),
diff --git a/modules/toolbar/toolbar.info b/modules/toolbar/toolbar.info
index 4f86211c0a6077f560b347a7caad86d9e5b8e83e..c03f9aa336e96f3d7bf4323db4ae6d31d5b54094 100644
--- a/modules/toolbar/toolbar.info
+++ b/modules/toolbar/toolbar.info
@@ -6,8 +6,8 @@ package = Core
 version = VERSION
 files[] = toolbar.module
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/toolbar/toolbar.module b/modules/toolbar/toolbar.module
index 9f5cd30e344da7e2091400d85f0fb68672a677d8..930996e0cabe5dd1ec3f2e0f46808a58358174ce 100644
--- a/modules/toolbar/toolbar.module
+++ b/modules/toolbar/toolbar.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: toolbar.module,v 1.43 2010/07/02 02:22:26 dries Exp $
+// $Id: toolbar.module,v 1.46 2010/10/05 19:59:10 dries Exp $
 
 /**
  * @file
@@ -188,7 +188,7 @@ function toolbar_view() {
     '#attached'=> array(
       'js' => array(
         $module_path . '/toolbar.js',
-        array('data' => 'misc/jquery.cookie.js', 'weight' => JS_LIBRARY + 2),
+        array('data' => 'misc/jquery.cookie.js', 'group' => JS_LIBRARY, 'weight' => 2),
         array(
           'data' => array('tableHeaderOffset' => 'Drupal.toolbar.height'),
           'type' => 'setting'
@@ -202,12 +202,11 @@ function toolbar_view() {
 
   // Retrieve the admin menu from the database.
   $links = toolbar_menu_navigation_links(toolbar_get_menu_tree());
-  $system_menus = menu_list_system_menus();
   $build['toolbar_menu'] = array(
     '#theme' => 'links__toolbar_menu',
     '#links' => $links,
     '#attributes' => array('id' => 'toolbar-menu'),
-    '#heading' => array('text' => t($system_menus['management']), 'level' => 'h2', 'class' => 'element-invisible'),
+    '#heading' => array('text' => t('Administrative toolbar'), 'level' => 'h2', 'class' => 'element-invisible'),
   );
 
   // Add logout & user account links or login link.
diff --git a/modules/tracker/tracker.info b/modules/tracker/tracker.info
index 8ed689039e268c36ffdc9fa7834f61e1fc35d20e..c94334f0cf073ec05706a9c700a4175692b5cd87 100644
--- a/modules/tracker/tracker.info
+++ b/modules/tracker/tracker.info
@@ -9,8 +9,8 @@ files[] = tracker.module
 files[] = tracker.pages.inc
 files[] = tracker.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/tracker/tracker.test b/modules/tracker/tracker.test
index 8eeb86c91f8e55d8672f97a6b393bbd12631ce8e..3518cc50e9273545424db72b476344d2bd99f7ad 100644
--- a/modules/tracker/tracker.test
+++ b/modules/tracker/tracker.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: tracker.test,v 1.20 2010/08/05 23:53:39 webchick Exp $
+// $Id: tracker.test,v 1.21 2010/10/05 06:17:29 webchick Exp $
 
 class TrackerTest extends DrupalWebTestCase {
   protected $user;
@@ -17,7 +17,7 @@ class TrackerTest extends DrupalWebTestCase {
   function setUp() {
     parent::setUp('comment', 'tracker');
 
-    $permissions = array('access comments', 'create page content', 'post comments', 'post comments without approval');
+    $permissions = array('access comments', 'create page content', 'post comments', 'skip comment approval');
     $this->user = $this->drupalCreateUser($permissions);
     $this->other_user = $this->drupalCreateUser($permissions);
 
diff --git a/modules/translation/translation.info b/modules/translation/translation.info
index 2efa3bc933af2d66cc6d5cf47e05999c39053836..0a76075c1dea9ae92333c2d8cf99f8299e3b5663 100644
--- a/modules/translation/translation.info
+++ b/modules/translation/translation.info
@@ -9,8 +9,8 @@ files[] = translation.module
 files[] = translation.pages.inc
 files[] = translation.test
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/trigger/tests/trigger_test.info b/modules/trigger/tests/trigger_test.info
index b3e4ad817d2ed28cce1c543c486348bd7eb2e702..a1e228163d169e93504273d263f49e082f132888 100644
--- a/modules/trigger/tests/trigger_test.info
+++ b/modules/trigger/tests/trigger_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = trigger_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/trigger/trigger.admin.inc b/modules/trigger/trigger.admin.inc
index b156a3e71d1991b0a54a780d1db2509a4f5cd10d..88143201cc11bed4ec5ba4ae2779162d465b7c24 100644
--- a/modules/trigger/trigger.admin.inc
+++ b/modules/trigger/trigger.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: trigger.admin.inc,v 1.27 2010/08/22 11:04:09 dries Exp $
+// $Id: trigger.admin.inc,v 1.28 2010/09/24 21:36:22 dries Exp $
 
 /**
  * @file
@@ -177,7 +177,6 @@ function trigger_assign_form($form, $form_state, $module, $hook, $label) {
   );
   // List possible actions that may be assigned.
   if (count($options) != 0) {
-    array_unshift($options, t('Choose an action'));
     $form[$hook]['parent']['aid'] = array(
       '#type' => 'select',
       '#options' => $options,
diff --git a/modules/trigger/trigger.info b/modules/trigger/trigger.info
index 7881d0e0965e7114e10d8d6596a84a442e198b31..72ef21e5cda585aef816a37153a806bae617f635 100644
--- a/modules/trigger/trigger.info
+++ b/modules/trigger/trigger.info
@@ -10,8 +10,8 @@ files[] = trigger.install
 files[] = trigger.test
 configure = admin/structure/trigger
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/trigger/trigger.module b/modules/trigger/trigger.module
index 808bb90f6488d65e2d3ce512a996d264e17cc03f..d684fac41c0003d2853e75fae228375e3003e307 100644
--- a/modules/trigger/trigger.module
+++ b/modules/trigger/trigger.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: trigger.module,v 1.64 2010/07/10 01:44:28 dries Exp $
+// $Id: trigger.module,v 1.65 2010/09/24 00:37:44 dries Exp $
 
 /**
  * @file
@@ -80,7 +80,6 @@ function trigger_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('trigger_unassign'),
     'access arguments' => array('administer actions'),
-    'type' => MENU_CALLBACK,
     'file' => 'trigger.admin.inc',
   );
 
diff --git a/modules/trigger/trigger.test b/modules/trigger/trigger.test
index b579127a6665b685a6c0d5b4ee3b625f493e7be6..d3307d618f173b51eb5889b0c013a13f159eaaa7 100644
--- a/modules/trigger/trigger.test
+++ b/modules/trigger/trigger.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: trigger.test,v 1.36 2010/08/05 23:53:39 webchick Exp $
+// $Id: trigger.test,v 1.37 2010/10/05 06:17:29 webchick Exp $
 
 /**
  * Provides common helper methods.
@@ -495,7 +495,7 @@ class TriggerUserActionTestCase extends TriggerActionTestCase {
    * Tests user action assignment and execution.
    */
   function testUserActionAssignmentExecution() {
-    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments'));
+    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'skip comment approval', 'edit own comments'));
     $this->drupalLogin($test_user);
 
     $triggers = array('comment_presave', 'comment_insert', 'comment_update');
@@ -517,7 +517,7 @@ class TriggerUserActionTestCase extends TriggerActionTestCase {
     // the comment is updated.
     user_save($account, array('status' => TRUE));
 
-    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments'));
+    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'skip comment approval', 'edit own comments'));
     $this->drupalLogin($test_user);
 
     // Our original comment will have been comment 1.
@@ -526,7 +526,7 @@ class TriggerUserActionTestCase extends TriggerActionTestCase {
     $this->assertTrue($comment_author_account->status == 0, t('Comment author account (uid=@uid) is blocked after update to comment', array('@uid' => $comment_author_uid)));
 
     // Verify that the comment was updated.
-    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'post comments without approval', 'edit own comments'));
+    $test_user = $this->drupalCreateUser(array('administer actions', 'create article content', 'access comments', 'administer comments', 'skip comment approval', 'edit own comments'));
     $this->drupalLogin($test_user);
 
     $this->drupalGet("node/$node->nid");
@@ -627,7 +627,7 @@ class TriggerOtherTestCase extends TriggerWebTestCase {
     variable_set($action_id, FALSE);
 
     // Create a node and add a comment to it.
-    $web_user = $this->drupalCreateUser(array('create article content', 'access content', 'post comments without approval', 'post comments'));
+    $web_user = $this->drupalCreateUser(array('create article content', 'access content', 'skip comment approval', 'post comments'));
     $this->drupalLogin($web_user);
     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
     $edit = array();
diff --git a/modules/update/tests/aaa_update_test.info b/modules/update/tests/aaa_update_test.info
index e2668c7c13183065329ccb421e11d35d18222769..7f2d54483cc42e624d501b18c4eb288198d423c9 100644
--- a/modules/update/tests/aaa_update_test.info
+++ b/modules/update/tests/aaa_update_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = aaa_update_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/update/tests/bbb_update_test.info b/modules/update/tests/bbb_update_test.info
index 6b36719edf273b1245ce155867796e0a6ad17502..6c2fdabefa8b65bb0509c85b2357ca45393ce72e 100644
--- a/modules/update/tests/bbb_update_test.info
+++ b/modules/update/tests/bbb_update_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = bbb_update_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/update/tests/ccc_update_test.info b/modules/update/tests/ccc_update_test.info
index 65ea06ae0901af2e5fa91faf3860d69b76973681..b6d978b1a7347a7c0048461881d0f31d4f46f11b 100644
--- a/modules/update/tests/ccc_update_test.info
+++ b/modules/update/tests/ccc_update_test.info
@@ -6,8 +6,8 @@ core = 7.x
 files[] = ccc_update_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/update/tests/update_test.info b/modules/update/tests/update_test.info
index c7445a8b6e7343d049775f4f3837058c48f1a9ab..ab7b0594aefd2c4de3a51621d04df9484666621b 100644
--- a/modules/update/tests/update_test.info
+++ b/modules/update/tests/update_test.info
@@ -7,8 +7,8 @@ core = 7.x
 files[] = update_test.module
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/update/tests/update_test.module b/modules/update/tests/update_test.module
index 42b6cef0807e2983afe1fee0ac7a5ae1ac81fc96..1ab30b0f785d87a19eb0ce32bc3f2b50e1fd8501 100644
--- a/modules/update/tests/update_test.module
+++ b/modules/update/tests/update_test.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: update_test.module,v 1.4 2009/12/04 16:49:47 dries Exp $
+// $Id: update_test.module,v 1.6 2010/10/05 02:17:44 dries Exp $
 
 /**
  * Implements hook_menu().
@@ -39,6 +39,32 @@ function update_test_system_info_alter(&$info, $file) {
   }
 }
 
+/**
+ * Implements hook_update_status_alter().
+ *
+ * This checks the 'update_test_update_status' variable and sees if we need to
+ * alter the update status for the given project based on the setting. The
+ * setting is expected to be a nested associative array. If the key '#all' is
+ * defined, its subarray will include .info keys and values for all modules
+ * and themes on the system. Otherwise, the settings array is keyed by the
+ * module or theme short name and the subarrays contain settings just for that
+ * module or theme.
+ */
+function update_test_update_status_alter(&$projects) {
+  $setting = variable_get('update_test_update_status', array());
+  if (!empty($setting)) {
+    foreach ($projects as $project_name => &$project) {
+      foreach (array('#all', $project_name) as $id) {
+        if (!empty($setting[$id])) {
+          foreach ($setting[$id] as $key => $value) {
+            $project[$key] = $value;
+          }
+        }
+      }
+    }
+  }
+}
+
 /**
  * Page callback, prints mock XML for the update module.
  *
@@ -73,3 +99,16 @@ function update_test_mock_page($project_name) {
   $path = drupal_get_path('module', 'update_test');
   readfile("$path/$project_name.$availability_scenario.xml");
 }
+
+/**
+ * Implement hook_archiver_info().
+ */
+function update_test_archiver_info() {
+  return array(
+    'update_test_archiver' => array(
+      // This is bogus, we only care about the extensions for now.
+      'class' => 'ArchiverUpdateTest',
+      'extensions' => array('update-test-extension'),
+    ),
+  );
+}
diff --git a/modules/update/update.compare.inc b/modules/update/update.compare.inc
index 5fb0334d25148d1a1d213eff454998d0cf4b17bb..1efb6979c802e7da982942241ee92772d76c02da 100644
--- a/modules/update/update.compare.inc
+++ b/modules/update/update.compare.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.compare.inc,v 1.40 2010/01/30 07:59:26 dries Exp $
+// $Id: update.compare.inc,v 1.41 2010/10/04 07:26:25 webchick Exp $
 
 /**
  * @file
@@ -738,10 +738,20 @@ function update_calculate_project_update_status($project, &$project_data, $avail
 function update_project_cache($cid) {
   $projects = array();
 
-  // On certain paths, we should clear the cache and recompute the projects or
+  // On certain paths, we should clear the cache and recompute the projects for
   // update status of the site to avoid presenting stale information.
   $q = $_GET['q'];
-  $paths = array('admin/modules', 'admin/appearance', 'admin/reports', 'admin/reports/updates', 'admin/reports/status', 'admin/reports/updates/check');
+  $paths = array(
+    'admin/modules',
+    'admin/modules/update',
+    'admin/appearance',
+    'admin/appearance/update',
+    'admin/reports',
+    'admin/reports/updates',
+    'admin/reports/updates/update',
+    'admin/reports/status',
+    'admin/reports/updates/check',
+  );
   if (in_array($q, $paths)) {
     _update_cache_clear($cid);
   }
diff --git a/modules/update/update.info b/modules/update/update.info
index fab0777c8f4783c47996c091a03d452bbfcbcf61..d9a81efbde12562fa273dea711f7bb8ec30ce16b 100644
--- a/modules/update/update.info
+++ b/modules/update/update.info
@@ -15,8 +15,8 @@ files[] = update.settings.inc
 files[] = update.test
 configure = admin/reports/updates/settings
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/update/update.install b/modules/update/update.install
index 00d659be0c67331afc885f3b313ae1f98b90deb5..176973d5d04345152d17ad93483639fdde5777e1 100644
--- a/modules/update/update.install
+++ b/modules/update/update.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.install,v 1.19 2010/06/25 17:47:22 dries Exp $
+// $Id: update.install,v 1.20 2010/10/03 22:44:48 dries Exp $
 
 /**
  * @file
@@ -71,7 +71,7 @@ function update_schema() {
  * Implements hook_install().
  */
 function update_install() {
-  $queue = DrupalQueue::get('update_fetch_tasks');
+  $queue = DrupalQueue::get('update_fetch_tasks', TRUE);
   $queue->createQueue();
 }
 
diff --git a/modules/update/update.module b/modules/update/update.module
index 746ec24a5ff5454191145dd52ed40a2fdf5d83ef..c4063b89ff2c5d6c5dad3416b173184fb433ec39 100644
--- a/modules/update/update.module
+++ b/modules/update/update.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.module,v 1.67 2010/05/18 18:26:30 dries Exp $
+// $Id: update.module,v 1.70 2010/10/06 13:36:30 dries Exp $
 
 /**
  * @file
@@ -79,34 +79,6 @@ function update_help($path, $arg) {
     case 'admin/reports/updates':
       return '<p>' . t('Here you can find information about available updates for your installed modules and themes. Note that each module or theme is part of a "project", which may or may not have the same name, and might include multiple modules or themes within it.') . '</p>';
 
-    case 'admin/appearance':
-    case 'admin/modules':
-      module_load_install('update');
-      $status = update_requirements('runtime');
-      foreach (array('core', 'contrib') as $report_type) {
-        $type = 'update_' . $report_type;
-        if (isset($status[$type]['severity'])) {
-          if ($status[$type]['severity'] == REQUIREMENT_ERROR) {
-            drupal_set_message($status[$type]['description'], 'error');
-          }
-          elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) {
-            drupal_set_message($status[$type]['description'], 'warning');
-          }
-        }
-      }
-
-    case 'admin/appearance/update':
-    case 'admin/appearance/install':
-    case 'admin/modules/update':
-    case 'admin/modules/install':
-    case 'admin/reports/updates/update':
-    case 'admin/reports/updates/install':
-    case 'admin/reports/updates/settings':
-    case 'admin/reports/status':
-    case 'admin/update/ready':
-      // These pages don't need additional nagging.
-      break;
-
     case 'admin/help#update':
       $output = '';
       $output .= '<h3>' . t('About') . '</h3>';
@@ -128,23 +100,60 @@ function update_help($path, $arg) {
       }
       $output .= '</dl>';
       return $output;
+  }
+}
 
-    default:
-      // Otherwise, if we're on *any* admin page and there's a security
-      // update missing, print an error message about it.
-      if (arg(0) == 'admin' && strpos($path, '#') === FALSE
-          && user_access('administer site configuration')) {
-        module_load_install('update');
-        $status = update_requirements('runtime');
-        foreach (array('core', 'contrib') as $report_type) {
-          $type = 'update_' . $report_type;
-          if (isset($status[$type])
-              && isset($status[$type]['reason'])
-              && $status[$type]['reason'] === UPDATE_NOT_SECURE) {
+/**
+ * Implements hook_init().
+ */
+function update_init() {
+  if (arg(0) == 'admin' && user_access('administer site configuration')) {
+    switch ($_GET['q']) {
+      // These pages don't need additional nagging.
+      case 'admin/appearance/update':
+      case 'admin/appearance/install':
+      case 'admin/modules/update':
+      case 'admin/modules/install':
+      case 'admin/reports/updates':
+      case 'admin/reports/updates/update':
+      case 'admin/reports/updates/install':
+      case 'admin/reports/updates/settings':
+      case 'admin/reports/status':
+      case 'admin/update/ready':
+        return;
+
+      // If we are on the appearance or modules list, display a detailed report
+      // of the update status.
+      case 'admin/appearance':
+      case 'admin/modules':
+        $verbose = TRUE;
+        break;
+
+    }
+    module_load_install('update');
+    $status = update_requirements('runtime');
+    foreach (array('core', 'contrib') as $report_type) {
+      $type = 'update_' . $report_type;
+      if (!empty($verbose)) {
+        if (isset($status[$type]['severity'])) {
+          if ($status[$type]['severity'] == REQUIREMENT_ERROR) {
             drupal_set_message($status[$type]['description'], 'error');
           }
+          elseif ($status[$type]['severity'] == REQUIREMENT_WARNING) {
+            drupal_set_message($status[$type]['description'], 'warning');
+          }
+        }
+      }
+      // Otherwise, if we're on *any* admin page and there's a security
+      // update missing, print an error message about it.
+      else {
+        if (isset($status[$type])
+            && isset($status[$type]['reason'])
+            && $status[$type]['reason'] === UPDATE_NOT_SECURE) {
+          drupal_set_message($status[$type]['description'], 'error');
         }
       }
+    }
   }
 }
 
@@ -217,9 +226,10 @@ function update_menu() {
     );
   }
   // Customize the titles of the action links depending on where they appear.
-  $items['admin/reports/updates/install']['title'] = 'Install new module or theme';
-  $items['admin/modules/install']['title'] = 'Install new module';
-  $items['admin/appearance/install']['title'] = 'Install new theme';
+  // We use += array() to let the translation extractor find these menu titles.
+  $items['admin/reports/updates/install'] += array('title' => 'Install new module or theme');
+  $items['admin/modules/install'] += array('title' => 'Install new module');
+  $items['admin/appearance/install'] += array('title' => 'Install new theme');
 
   // Menu callback used for the confirmation page after all the releases
   // have been downloaded, asking you to backup before installing updates.
diff --git a/modules/update/update.report.inc b/modules/update/update.report.inc
index 7344de442e35f75956f8afd78b238e57538bddac..1208350379f19d8e3226304dc420b3fef7f50cf0 100644
--- a/modules/update/update.report.inc
+++ b/modules/update/update.report.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.report.inc,v 1.32 2010/08/17 13:50:52 dries Exp $
+// $Id: update.report.inc,v 1.33 2010/10/03 22:43:16 dries Exp $
 
 /**
  * @file
@@ -23,7 +23,7 @@ function update_status() {
 /**
  * Returns HTML for the project status report.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - data: An array of data about each project's status.
  *
@@ -104,8 +104,9 @@ function theme_update_report($variables) {
     }
     $row .= "</div>\n";
 
-    $row .= "<div class=\"versions\">\n";
-
+    $versions_inner = '';
+    $security_class = array();
+    $version_class = array();
     if (isset($project['recommended'])) {
       if ($project['status'] != UPDATE_CURRENT || $project['existing_version'] !== $project['recommended']) {
 
@@ -114,10 +115,10 @@ function theme_update_report($variables) {
         // recommending, give it the same CSS class as if it was recommended,
         // but don't print out a separate "Recommended" line for this project.
         if (!empty($project['security updates']) && count($project['security updates']) == 1 && $project['security updates'][0]['version'] === $project['recommended']) {
-          $security_class = ' version-recommended version-recommended-strong';
+          $security_class[] = 'version-recommended';
+          $security_class[] = 'version-recommended-strong';
         }
         else {
-          $security_class = array();
           $version_class[] = 'version-recommended';
           // Apply an extra class if we're displaying both a recommended
           // version and anything else for an extra visual hint.
@@ -132,36 +133,38 @@ function theme_update_report($variables) {
               ) {
             $version_class[] = 'version-recommended-strong';
           }
-          $row .= theme('update_version', array('version' => $project['releases'][$project['recommended']], 'tag' => t('Recommended version:'), 'class' => $version_class));
+          $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['recommended']], 'tag' => t('Recommended version:'), 'class' => $version_class));
         }
 
         // Now, print any security updates.
         if (!empty($project['security updates'])) {
+          $security_class[] = 'version-security';
           foreach ($project['security updates'] as $security_update) {
-            $row .= theme('update_version', array('version' => $security_update, 'tag' => t('Security update:'), 'class' => 'version-security' . $security_class));
+            $versions_inner .= theme('update_version', array('version' => $security_update, 'tag' => t('Security update:'), 'class' => $security_class));
           }
         }
       }
 
       if ($project['recommended'] !== $project['latest_version']) {
-        $row .= theme('update_version', array('version' => $project['releases'][$project['latest_version']], 'tag' => t('Latest version:'), 'class' => array('version-latest')));
+        $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['latest_version']], 'tag' => t('Latest version:'), 'class' => array('version-latest')));
       }
       if ($project['install_type'] == 'dev'
           && $project['status'] != UPDATE_CURRENT
           && isset($project['dev_version'])
           && $project['recommended'] !== $project['dev_version']) {
-        $row .= theme('update_version', array('version' => $project['releases'][$project['dev_version']], 'tag' => t('Development version:'), 'class' => array('version-latest')));
+        $versions_inner .= theme('update_version', array('version' => $project['releases'][$project['dev_version']], 'tag' => t('Development version:'), 'class' => array('version-latest')));
       }
     }
 
     if (isset($project['also'])) {
       foreach ($project['also'] as $also) {
-        $row .= theme('update_version', array('version' => $project['releases'][$also], 'tag' => t('Also available:'), 'class' => array('version-also-available')));
+        $versions_inner .= theme('update_version', array('version' => $project['releases'][$also], 'tag' => t('Also available:'), 'class' => array('version-also-available')));
       }
     }
 
-    $row .= "</div>\n"; // versions div.
-
+    if (!empty($versions_inner)) {
+      $row .= "<div class=\"versions\">\n" . $versions_inner . "</div>\n";
+    }
     $row .= "<div class=\"info\">\n";
     if (!empty($project['extra'])) {
       $row .= '<div class="extra">' . "\n";
@@ -250,7 +253,7 @@ function theme_update_report($variables) {
 /**
  * Returns HTML for a label to display for a project's update status.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - status: The integer code for a project's current update status.
  *
@@ -279,7 +282,7 @@ function theme_update_status_label($variables) {
 /**
  * Returns HTML for the version display of a project.
  *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - version: An array of data about the latest released version, containing:
  *     - version: The version number.
@@ -294,7 +297,7 @@ function theme_update_status_label($variables) {
 function theme_update_version($variables) {
   $version = $variables['version'];
   $tag = $variables['tag'];
-  $class = $variables['class'];
+  $class = implode(' ', $variables['class']);
 
   $output = '';
   $output .= '<table class="version ' . $class . '">';
diff --git a/modules/update/update.test b/modules/update/update.test
index e2a3bf2849513480da9ff46735f7203d6c60d7f6..8f87c3431f4b44dbddac0f5213da00ad087e80af 100644
--- a/modules/update/update.test
+++ b/modules/update/update.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.test,v 1.16 2010/08/05 23:53:39 webchick Exp $
+// $Id: update.test,v 1.19 2010/10/06 13:36:30 dries Exp $
 
 /**
  * @file
@@ -181,6 +181,24 @@ class UpdateCoreTestCase extends UpdateTestHelper {
     $this->assertText(t('Checked available update data for one project.'));
     $this->assertNoText(t('There are updates available for your version of Drupal.'));
     $this->assertText(t('There is a security update available for your version of Drupal.'));
+
+    // Make sure admin/appearance warns you you're missing a security update.
+    $this->drupalGet('admin/appearance');
+    $this->assertNoText(t('There are updates available for your version of Drupal.'));
+    $this->assertText(t('There is a security update available for your version of Drupal.'));
+
+    // Make sure duplicate messages don't appear on Update status pages.
+    $this->drupalGet('admin/reports/status');
+    // We're expecting "There is a security update..." inside the status report
+    // itself, but the drupal_set_message() appears as an li so we can prefix
+    // with that and search for the raw HTML.
+    $this->assertNoRaw('<li>' . t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/reports/updates');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/reports/updates/settings');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
   }
 
   protected function setSystemInfo7_0() {
@@ -491,6 +509,67 @@ class UpdateTestContribCase extends UpdateTestHelper {
     $this->assertRaw(l(t('CCC Update test'), 'http://example.com/project/ccc_update_test'), t('Link to bbb_update_test project appears.'));
   }
 
+  /**
+   * Check that hook_update_status_alter() works to change a status.
+   *
+   * We provide the same external data as if aaa_update_test 7.x-1.0 were
+   * installed and that was the latest release. Then we use
+   * hook_update_status_alter() to try to mark this as missing a security
+   * update, then assert if we see the appropriate warnings on the right
+   * pages.
+   */
+  function testHookUpdateStatusAlter() {
+    variable_set('allow_authorize_operations', TRUE);
+    $update_admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer software updates'));
+    $this->drupalLogin($update_admin_user);
+
+    $system_info = array(
+      '#all' => array(
+        'version' => '7.0',
+      ),
+      'aaa_update_test' => array(
+        'project' => 'aaa_update_test',
+        'version' => '7.x-1.0',
+        'hidden' => FALSE,
+      ),
+    );
+    variable_set('update_test_system_info', $system_info);
+    $update_status = array(
+      'aaa_update_test' => array(
+        'status' => UPDATE_NOT_SECURE,
+      ),
+    );
+    variable_set('update_test_update_status', $update_status);
+    $this->refreshUpdateStatus(
+      array(
+        'drupal' => '0',
+        'aaa_update_test' => '1_0',
+      )
+    );
+    $this->drupalGet('admin/reports/updates');
+    $this->assertRaw('<h3>' . t('Modules') . '</h3>');
+    $this->assertText(t('Security update required!'));
+    $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), t('Link to aaa_update_test project appears.'));
+
+    // Visit the reports page again without the altering and make sure the
+    // status is back to normal.
+    variable_set('update_test_update_status', array());
+    $this->drupalGet('admin/reports/updates');
+    $this->assertRaw('<h3>' . t('Modules') . '</h3>');
+    $this->assertNoText(t('Security update required!'));
+    $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), t('Link to aaa_update_test project appears.'));
+
+    // Turn the altering back on and visit the Update manager UI.
+    variable_set('update_test_update_status', $update_status);
+    $this->drupalGet('admin/modules/update');
+    $this->assertText(t('Security update'));
+
+    // Turn the altering back off and visit the Update manager UI.
+    variable_set('update_test_update_status', array());
+    $this->drupalGet('admin/modules/update');
+    $this->assertNoText(t('Security update'));
+  }
+
 }
 
 class UpdateTestUploadCase extends UpdateTestHelper {
@@ -503,7 +582,7 @@ class UpdateTestUploadCase extends UpdateTestHelper {
   }
 
   public function setUp() {
-    parent::setUp('update');
+    parent::setUp('update', 'update_test');
     variable_set('allow_authorize_operations', TRUE);
     $admin_user = $this->drupalCreateUser(array('administer software updates', 'administer site configuration'));
     $this->drupalLogin($admin_user);
@@ -532,5 +611,56 @@ class UpdateTestUploadCase extends UpdateTestHelper {
     $this->drupalPost('admin/modules/install', $edit, t('Install'));
     $this->assertText(t('@module_name is already installed.', array('@module_name' => 'AAA Update test')), 'Existing module was extracted and not reinstalled.');
   }
-}
 
+  /**
+   * Ensure that archiver extensions are properly merged in the UI.
+   */
+  function testFileNameExtensionMerging() {
+    $this->drupalGet('admin/modules/install');    
+    // Make sure the bogus extension supported by update_test.module is there.
+    $this->assertPattern('/archive extensions are supported:.*update-test-extension/', t("Found 'update-test-extension' extension"));
+    // Make sure it didn't clobber the first option from core.
+    $this->assertPattern('/archive extensions are supported:.*zip/', t("Found 'zip' extension"));
+  }
+
+  /**
+   * Check the messages on Update manager pages when missing a security update.
+   */
+  function testUpdateManagerCoreSecurityUpdateMessages() {
+    $setting = array(
+      '#all' => array(
+        'version' => '7.0',
+      ),
+    );
+    variable_set('update_test_system_info', $setting);
+    variable_set('update_fetch_url', url('update-test', array('absolute' => TRUE)));
+    variable_set('update_test_xml_map', array('drupal' => '2-sec'));
+    // Initialize the update status.
+    $this->drupalGet('admin/reports/updates');
+
+    // Now, make sure none of the Update manager pages have duplicate messages
+    // about core missing a security update.
+
+    $this->drupalGet('admin/modules/install');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/modules/update');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/appearance/install');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/appearance/update');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/reports/updates/install');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/reports/updates/update');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+
+    $this->drupalGet('admin/update/ready');
+    $this->assertNoText(t('There is a security update available for your version of Drupal.'));
+  }
+
+}
diff --git a/modules/user/user-rtl.css b/modules/user/user-rtl.css
index 6373a869e8fcaec1cca0b692444888d4d31e8094..b589171b304d75eb9cabbcf6e17b816147deceb8 100644
--- a/modules/user/user-rtl.css
+++ b/modules/user/user-rtl.css
@@ -1,21 +1,29 @@
-/* $Id: user-rtl.css,v 1.7 2010/01/03 21:01:04 webchick Exp $ */
+/* $Id: user-rtl.css,v 1.9 2010/09/19 18:10:42 dries Exp $ */
 
 #permissions td.permission {
   padding-left: 0;
   padding-right: 1.5em;
 }
 
-#user-filter-form dl.multiselect dd .form-item label {
+/**
+ * Password strength indicator.
+ */
+input.password-field {
+  margin-left: 10px;
+  margin-right: 0;
+}
+input.password-confirm {
+  margin-left: 10px;
+  margin-right: 0;
+}
+.password-strength-title {
   float: right;
 }
-
-#user-admin-buttons {
+.password-parent {
   float: right;
-  margin-left: 0;
-  margin-right: 0.5em;
-  clear: left;
 }
 
+/* Generated by user.module but used by profile.module: */
 .profile .user-picture {
   float: left;
   margin: 0 0 1em 1em;
diff --git a/modules/user/user.admin.inc b/modules/user/user.admin.inc
index 06bfe2fc98ef51b7a72d5eff38105e568ff103ff..35a5717beb8ecbac2fd2c5bcc554a789835b345f 100644
--- a/modules/user/user.admin.inc
+++ b/modules/user/user.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: user.admin.inc,v 1.117 2010/09/01 20:08:17 dries Exp $
+// $Id: user.admin.inc,v 1.119 2010/10/06 13:38:40 dries Exp $
 
 /**
  * @file
@@ -40,7 +40,7 @@ function user_filter_form() {
   $form['filters'] = array(
     '#type' => 'fieldset',
     '#title' => t('Show only users where'),
-    '#theme' => 'user_filters',
+    '#theme' => 'exposed_filters__user',
   );
   foreach ($session as $filter) {
     list($type, $value) = $filter;
@@ -53,18 +53,26 @@ function user_filter_form() {
     else {
       $value = $filters[$type]['options'][$value];
     }
-    $params = array('%property' => $filters[$type]['title'] , '%value' => $value);
+    $t_args = array('%property' => $filters[$type]['title'], '%value' => $value);
     if ($i++) {
-      $form['filters']['current'][] = array('#markup' => t('<em>and</em> where <strong>%property</strong> is <strong>%value</strong>', $params));
+      $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args));
     }
     else {
-      $form['filters']['current'][] = array('#markup' => t('<strong>%property</strong> is <strong>%value</strong>', $params));
+      $form['filters']['current'][] = array('#markup' => t('%property is %value', $t_args));
     }
   }
 
+  $form['filters']['status'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('clearfix')),
+    '#prefix' => ($i ? '<div class="additional-filters">' . t('and where') . '</div>' : ''),
+  );
+  $form['filters']['status']['filters'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('filters')),
+  );
   foreach ($filters as $key => $filter) {
-    $names[$key] = $filter['title'];
-    $form['filters']['status'][$key] = array(
+    $form['filters']['status']['filters'][$key] = array(
       '#type' => 'select',
       '#options' => $filter['options'],
       '#title' => $filter['title'],
@@ -72,21 +80,20 @@ function user_filter_form() {
     );
   }
 
-  $form['filters']['actions'] = array(
+  $form['filters']['status']['actions'] = array(
     '#type' => 'actions',
-    '#id' => 'user-admin-buttons',
     '#attributes' => array('class' => array('container-inline')),
   );
-  $form['filters']['actions']['submit'] = array(
+  $form['filters']['status']['actions']['submit'] = array(
     '#type' => 'submit',
     '#value' => (count($session) ? t('Refine') : t('Filter')),
   );
   if (count($session)) {
-    $form['filters']['actions']['undo'] = array(
+    $form['filters']['status']['actions']['undo'] = array(
       '#type' => 'submit',
       '#value' => t('Undo'),
     );
-    $form['filters']['actions']['reset'] = array(
+    $form['filters']['status']['actions']['reset'] = array(
       '#type' => 'submit',
       '#value' => t('Reset'),
     );
@@ -214,7 +221,7 @@ function user_admin_account() {
     '#options' => $options,
     '#empty' => t('No people available.'),
   );
-  $form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
+  $form['pager'] = array('#markup' => theme('pager'));
 
   return $form;
 }
@@ -1017,41 +1024,3 @@ function user_admin_role_delete_confirm_submit($form, &$form_state) {
   $form_state['redirect'] = 'admin/people/permissions/roles';
 }
 
-/**
- * Returns HTML for the user administration filter selector.
- *
- * @param $variables
- *   An associative array containing:
- *   - form: A render element representing the form.
- *
- * @ingroup themeable
- */
-function theme_user_filters($variables) {
-  $form = $variables['form'];
-
-  $output = '<ul class="clearfix">';
-  if (!empty($form['current'])) {
-    foreach (element_children($form['current']) as $key) {
-      $output .= '<li>' . drupal_render($form['current'][$key]) . '</li>';
-    }
-  }
-  $output .= '</ul>';
-
-  $output .= '<div class="clearfix">';
-
-  $output .= '<dl class="multiselect">' . (!empty($form['current']) ? '<dt><em>' . t('and') . '</em> ' . t('where') . '</dt>' : '');
-
-  $output .= '<dd>';
-
-  foreach (element_children($form['status']) as $key) {
-    $output .= drupal_render($form['status'][$key]);
-  }
-  $output .= '</dd>';
-
-  $output .= '</dl>';
-  $output .= drupal_render($form['actions']);
-
-  $output .= '</div>';
-
-  return $output;
-}
diff --git a/modules/user/user.api.php b/modules/user/user.api.php
index 064ece011818be1a9f24ed44fe000af4c9f0d723..f2b7d390c3a8f103d3df6a55aa860307489ce556 100644
--- a/modules/user/user.api.php
+++ b/modules/user/user.api.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: user.api.php,v 1.23 2010/03/31 13:56:59 dries Exp $
+// $Id: user.api.php,v 1.24 2010/10/03 01:15:34 dries Exp $
 
 /**
  * @file
@@ -314,8 +314,10 @@ function hook_user_logout($account) {
  *   The user object on which the operation is being performed.
  * @param $view_mode
  *   View mode, e.g. 'full'.
+ * @param $langcode
+ *   The language code used for rendering.
  */
-function hook_user_view($account, $view_mode) {
+function hook_user_view($account, $view_mode, $langcode) {
   if (user_access('create blog content', $account)) {
     $account->content['summary']['blog'] =  array(
       '#type' => 'user_profile_item',
diff --git a/modules/user/user.css b/modules/user/user.css
index ecf6870a1e0bfbac58804e7d778ae6608e295dc3..85829f7e39153305df07858bccd4dacf8db8c386 100644
--- a/modules/user/user.css
+++ b/modules/user/user.css
@@ -1,4 +1,4 @@
-/* $Id: user.css,v 1.21 2010/04/28 20:08:39 dries Exp $ */
+/* $Id: user.css,v 1.23 2010/09/19 18:10:42 dries Exp $ */
 
 #permissions td.module {
   font-weight: bold;
@@ -10,22 +10,6 @@
 #permissions tr.even .form-item {
   white-space: normal;
 }
-/* Override the default multiselect layout in system-behavior.css. */
-#user-filter-form dl.multiselect dd,
-dl.multiselect dd .form-item {
-  width: 20em; /* 6em label + 14em select */
-}
-#user-filter-form dl.multiselect dd .form-item label {
-  display: block;
-  float: left; /* LTR */
-  width: 6em;
-  font-weight: normal;
-}
-#user-admin-buttons {
-  float: left; /* LTR */
-  margin-left: 0.5em; /* LTR */
-  clear: right; /* LTR */
-}
 #user-admin-settings fieldset .fieldset-description {
   font-size: 0.85em;
   padding-bottom: .5em;
@@ -43,6 +27,64 @@ dl.multiselect dd .form-item {
   margin-right: 1em;
 }
 
+/**
+ * Password strength indicator.
+ */
+.password-strength {
+  width: 17em;
+  float: right;  /* LTR */
+  margin-top: 1.4em;
+}
+.password-strength-title {
+  display: inline;
+}
+.password-strength-text {
+  float: right; /* LTR */
+  font-weight: bold;
+}
+.password-indicator {
+  background-color: #C4C4C4;
+  height: 0.3em;
+  width: 100%;
+}
+.password-indicator div {
+  height: 100%;
+  width: 0%;
+  background-color: #47C965;
+}
+input.password-confirm,
+input.password-field {
+  width: 16em;
+  margin-bottom: 0.4em;
+}
+div.password-confirm {
+  display: inline;
+  padding-left: 1em;
+}
+div.form-item div.password-suggestions {
+  padding: 0.2em 0.5em;
+  margin: 0.7em 0;
+  width: 38.5em;
+  border: 1px solid #B4B4B4;
+}
+div.password-suggestions ul {
+  margin-bottom: 0;
+}
+.password-parent {
+  margin: 0;
+  width: 34.3em;
+}
+
+/**
+ * Password confirmation checker.
+ */
+.confirm-parent {
+  margin: 0;
+}
+div.password-confirm {
+  visibility: hidden;
+}
+
 /* Generated by user.module but used by profile.module: */
 .profile {
   clear: both;
diff --git a/modules/user/user.info b/modules/user/user.info
index a6ec491e5392734684c389da2b21d624edfd404d..8115e10e2cf2b0599e06b5270c234c933297de76 100644
--- a/modules/user/user.info
+++ b/modules/user/user.info
@@ -14,8 +14,8 @@ required = TRUE
 configure = admin/config/people
 stylesheets[all][] = user.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/modules/user/user.install b/modules/user/user.install
index 7b40e90141fd540a60449da34ac7a070986c68ec..217081162f09b26d9935e601f9ace73a3ba0980f 100644
--- a/modules/user/user.install
+++ b/modules/user/user.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: user.install,v 1.63 2010/09/13 05:50:09 webchick Exp $
+// $Id: user.install,v 1.67 2010/10/05 06:17:29 webchick Exp $
 
 /**
  * @file
@@ -168,9 +168,8 @@ function user_schema() {
       ),
       'signature_format' => array(
         'type' => 'int',
-        'size' => 'small',
-        'not null' => TRUE,
-        'default' => 0,
+        'unsigned' => TRUE,
+        'not null' => FALSE,
         'description' => 'The {filter_format}.format of the signature.',
       ),
       'created' => array(
@@ -346,8 +345,9 @@ function user_update_dependencies() {
   $dependencies['system'][7000] = array(
     'user' => 7008,
   );
-  // user_update_7006 relies on filter_update_7002.
-  // TODO: move user_update_7006 down below in the upgrade process.
+  // Both user_update_7006() and user_update_7010() need to query the list of
+  // existing text formats and therefore must run after filter_update_7003().
+  // @todo: move user_update_7006 down below in the upgrade process.
   $dependencies['user'][7006] = array(
     'filter' => 7003,
   );
@@ -547,13 +547,6 @@ function user_update_7003() {
   }
 }
 
-/**
- * Moved to user_update_7012().
- */
-function user_update_7004() {
-  // This doesn't affect any subsequent user updates.
-}
-
 /**
  * Changes the users table to allow longer e-mail addresses.
  */
@@ -640,17 +633,51 @@ function user_update_7009() {
  * Update the {user}.signature_format column.
  */
 function user_update_7010() {
-  // It was previously possible for a value of "0" to be stored in database
-  // tables to indicate that a particular piece of text should be filtered
-  // using the default text format.
+  // Update the database column to allow NULL values.
+  db_change_field('users', 'signature_format', 'signature_format', array(
+    'type' => 'int',
+    'unsigned' => TRUE,
+    'not null' => FALSE,
+    'description' => 'The {filter_format}.format of the signature.',
+  ));
+
+  // Replace the signature format with NULL if the signature is empty and does
+  // not already have a stored text format.
+  //
+  // In Drupal 6, "0" (the former FILTER_FORMAT_DEFAULT constant) could be used
+  // to indicate this situation, but in Drupal 7, only NULL is supported. This
+  // update therefore preserves the ability of user accounts which were never
+  // given a signature (for example, if the site did not have user signatures
+  // enabled, or if the user never edited their account information) to not
+  // have a particular text format assumed for them the first time the
+  // signature is edited.
+  db_update('users')
+    ->fields(array('signature_format' => NULL))
+    ->condition('signature', '')
+    ->condition('signature_format', 0)
+    ->execute();
+
+  // There are a number of situations in which a Drupal 6 site could store
+  // content with a nonexistent text format. This includes text formats that
+  // had later been deleted, or non-empty content stored with a value of "0"
+  // (the former FILTER_FORMAT_DEFAULT constant). Drupal 6 would filter this
+  // content using whatever the site-wide default text format was at the moment
+  // the text was being displayed.
+  //
+  // In Drupal 7, this behavior is no longer supported, and all content must be
+  // stored with an explicit text format (or it will not be displayed when it
+  // is filtered). Therefore, to preserve the behavior of the site after the
+  // upgrade, we must replace all instances described above with the current
+  // value of the (old) site-wide default format at the moment of the upgrade.
+  $existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
   $default_format = variable_get('filter_default_format', 1);
   db_update('users')
     ->fields(array('signature_format' => $default_format))
-    ->condition('signature_format', 0)
+    ->isNotNull('signature_format')
+    ->condition('signature_format', $existing_formats, 'NOT IN')
     ->execute();
 }
 
-
 /**
  * Updates email templates to use new tokens.
  *
@@ -796,6 +823,20 @@ function user_update_7013(&$sandbox) {
   $sandbox['#finished'] = empty($sandbox['max']) || ($sandbox['progress'] / $sandbox['max']);
 }
 
+/**
+ * Rename the 'post comments without approval' permission.
+ *
+ * In Drupal 7, this permission has been renamed to 'skip comment approval'.
+ */
+function user_update_7014() {
+  db_update('role_permission')
+        ->fields(array('permission' => 'skip comment approval'))
+        ->condition('permission', 'post comments without approval')
+        ->execute();
+
+  return t("Renamed the 'post comments without approval' permission to 'skip comment approval'.");
+}
+
 /**
  * @} End of "defgroup user-updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
diff --git a/modules/user/user.module b/modules/user/user.module
index 2e84c6e169867906e65a436b36ae603a9c96c501..c78f3edd5c57aa7e36835091ba391be4c06bb8c7 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: user.module,v 1.1200 2010/09/11 06:03:12 webchick Exp $
+// $Id: user.module,v 1.1206 2010/10/04 14:54:10 webchick Exp $
 
 /**
  * @file
@@ -122,10 +122,6 @@ function user_theme() {
       'render element' => 'form',
       'file' => 'user.admin.inc',
     ),
-    'user_filters' => array(
-      'render element' => 'form',
-      'file' => 'user.admin.inc',
-    ),
     'user_permission_description' => array(
       'variables' => array('permission_item' => NULL, 'hide' => NULL),
       'file' => 'user.admin.inc',
@@ -1414,10 +1410,10 @@ function template_preprocess_user_picture(&$variables) {
     if (isset($filepath)) {
       $alt = t("@user's picture", array('@user' => format_username($account)));
       if (module_exists('image') && $style = variable_get('user_picture_style', '')) {
-        $variables['user_picture'] = theme('image_style', array('style_name' => $style, 'path' => $filepath, 'alt' => $alt, 'title' => $alt, 'attributes' => array(), 'getsize' => FALSE));
+        $variables['user_picture'] = theme('image_style', array('style_name' => $style, 'path' => $filepath, 'alt' => $alt, 'title' => $alt));
       }
       else {
-        $variables['user_picture'] = theme('image', array('path' => $filepath, 'alt' => $alt, 'title' => $alt, 'attributes' => array(), 'getsize' => FALSE));
+        $variables['user_picture'] = theme('image', array('path' => $filepath, 'alt' => $alt, 'title' => $alt));
       }
       if (!empty($account->uid) && user_access('access user profiles')) {
         $attributes = array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE);
@@ -1526,7 +1522,12 @@ function user_menu() {
     'title' => 'User account',
     'page callback' => 'user_page',
     'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
+    // Edge-case: No menu links should be auto-generated for this and below
+    // items, which makes it a MENU_CALLBACK. However, this item's title is
+    // expected to appear on user login, register, and password pages, so we
+    // need to use MENU_VISIBLE_IN_BREADCRUMB to make
+    // menu_get_active_breadcrumb() account for it.
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'user.pages.inc',
   );
 
@@ -1573,7 +1574,7 @@ function user_menu() {
   // User listing pages.
   $items['admin/people'] = array(
     'title' => 'People',
-    'description' => 'Manage user accounts, roles, and permissions',
+    'description' => 'Manage user accounts, roles, and permissions.',
     'page callback' => 'user_admin',
     'page arguments' => array('list'),
     'access arguments' => array('administer users'),
@@ -1621,7 +1622,6 @@ function user_menu() {
     'page arguments' => array('user_admin_role', 5),
     'access callback' => 'user_role_edit_access',
     'access arguments' => array(5),
-    'type' => MENU_CALLBACK,
   );
   $items['admin/people/permissions/roles/delete/%user_role'] = array(
     'title' => 'Delete role',
@@ -1629,7 +1629,6 @@ function user_menu() {
     'page arguments' => array('user_admin_role_delete_confirm', 5),
     'access callback' => 'user_role_edit_access',
     'access arguments' => array(5),
-    'type' => MENU_CALLBACK,
     'file' => 'user.admin.inc',
   );
 
@@ -1692,7 +1691,6 @@ function user_menu() {
     'page arguments' => array('user_cancel_confirm_form', 1),
     'access callback' => 'user_cancel_access',
     'access arguments' => array(1),
-    'type' => MENU_CALLBACK,
     'file' => 'user.pages.inc',
   );
 
@@ -1702,7 +1700,6 @@ function user_menu() {
     'page arguments' => array(1, 4, 5),
     'access callback' => 'user_cancel_access',
     'access arguments' => array(1),
-    'type' => MENU_CALLBACK,
     'file' => 'user.pages.inc',
   );
 
@@ -2392,13 +2389,20 @@ function user_view_page($uid) {
  *   A user object.
  * @param $view_mode
  *   View mode, e.g. 'full'.
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  *
  * @return
  *   An array as expected by drupal_render().
  */
-function user_view($account, $view_mode = 'full') {
+function user_view($account, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Retrieve all profile fields and attach to $account->content.
-  user_build_content($account, $view_mode);
+  user_build_content($account, $view_mode, $langcode);
 
   $build = $account->content;
   // We don't need duplicate rendering info in account->content.
@@ -2408,6 +2412,7 @@ function user_view($account, $view_mode = 'full') {
     '#theme' => 'user_profile',
     '#account' => $account,
     '#view_mode' => $view_mode,
+    '#language' => $langcode,
   );
 
   // Allow modules to modify the structured user.
@@ -2423,18 +2428,25 @@ function user_view($account, $view_mode = 'full') {
  *   A user object.
  * @param $view_mode
  *   View mode, e.g. 'full'.
+ * @param $langcode
+ *   (optional) A language code to use for rendering. Defaults to the global
+ *   content language of the current request.
  */
-function user_build_content($account, $view_mode = 'full') {
+function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
+  if (!isset($langcode)) {
+    $langcode = $GLOBALS['language_content']->language;
+  }
+
   // Remove previously built content, if exists.
   $account->content = array();
 
   // Build fields content.
   field_attach_prepare_view('user', array($account->uid => $account), $view_mode);
   entity_prepare_view('user', array($account->uid => $account));
-  $account->content += field_attach_view('user', $account, $view_mode);
+  $account->content += field_attach_view('user', $account, $view_mode, $langcode);
 
   // Populate $account->content with a render() array.
-  module_invoke_all('user_view', $account, $view_mode);
+  module_invoke_all('user_view', $account, $view_mode, $langcode);
 }
 
 /**
@@ -3601,16 +3613,6 @@ function user_modules_uninstalled($modules) {
      ->execute();
 }
 
-/**
- * Implements hook_filter_format_delete().
- */
-function user_filter_format_delete($format, $fallback) {
-  db_update('users')
-    ->fields(array('signature_format' => $fallback->format))
-    ->condition('signature_format', $format->format)
-    ->execute();
-}
-
 /**
  * Helper function to rewrite the destination to avoid redirecting to login page after login.
  *
diff --git a/modules/user/user.test b/modules/user/user.test
index d89dac1d4bb45adbb42e9425b9f287c24b8c6044..c673b31321eacb832b77c6572ca0a310dbd04e1b 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -1,5 +1,5 @@
 <?php
-// $Id: user.test,v 1.101 2010/08/27 11:28:45 webchick Exp $
+// $Id: user.test,v 1.102 2010/10/05 06:17:29 webchick Exp $
 
 class UserRegistrationTestCase extends DrupalWebTestCase {
   public static function getInfo() {
@@ -571,7 +571,7 @@ class UserCancelTestCase extends DrupalWebTestCase {
     variable_set('user_cancel_method', 'user_cancel_delete');
 
     // Create a user.
-    $account = $this->drupalCreateUser(array('cancel account', 'post comments', 'post comments without approval'));
+    $account = $this->drupalCreateUser(array('cancel account', 'post comments', 'skip comment approval'));
     $this->drupalLogin($account);
     // Load real user object.
     $account = user_load($account->uid, TRUE);
diff --git a/profiles/minimal/minimal.info b/profiles/minimal/minimal.info
index 740efaee8da49dc6463bdd7a126c9252be32540e..5d964888729247dc5b93ab790a7dc87a400243bf 100644
--- a/profiles/minimal/minimal.info
+++ b/profiles/minimal/minimal.info
@@ -7,8 +7,8 @@ dependencies[] = block
 dependencies[] = dblog
 files[] = minimal.profile
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/profiles/minimal/translations/README.txt b/profiles/minimal/translations/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d5cf750159a1695b718a58ef2e2b279a28bf6b61
--- /dev/null
+++ b/profiles/minimal/translations/README.txt
@@ -0,0 +1,4 @@
+// $Id: README.txt,v 1.1 2010/09/22 01:49:17 webchick Exp $
+
+This directory should be used to place downloaded translations
+for installing Drupal core.
diff --git a/profiles/standard/standard.info b/profiles/standard/standard.info
index 3624742c617ebc69e3790447e7886d6c3a72a7c8..f5d6d1d05454cb295b0890e99cd634b1414804b5 100644
--- a/profiles/standard/standard.info
+++ b/profiles/standard/standard.info
@@ -23,8 +23,8 @@ dependencies[] = file
 dependencies[] = rdf
 files[] = standard.profile
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/profiles/standard/standard.install b/profiles/standard/standard.install
index a93b6b3bdd2bf5759baff9f52278ece817acd4d1..681fbdd34ec655851160aa7e7b3938aa79bbbf58 100644
--- a/profiles/standard/standard.install
+++ b/profiles/standard/standard.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: standard.install,v 1.23 2010/09/07 18:01:32 webchick Exp $
+// $Id: standard.install,v 1.26 2010/10/05 06:17:29 webchick Exp $
 
 /**
  * Implements hook_install().
@@ -297,7 +297,7 @@ function standard_install() {
     'settings' => array(
       'allowed_values' => array(
         array(
-          'vid' => $vocabulary->vid,
+          'vocabulary' => $vocabulary->machine_name,
           'parent' => 0,
         ),
       ),
@@ -313,7 +313,7 @@ function standard_install() {
     'description' => $vocabulary->help,
     'widget' => array(
       'type' => 'taxonomy_autocomplete',
-      'weight' => 4,
+      'weight' => -4,
     ),
     'display' => array(
       'default' => array(
@@ -401,7 +401,7 @@ function standard_install() {
   // Enable default permissions for system roles.
   $filtered_html_permission = filter_permission_name($filtered_html_format);
   user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'access comments', $filtered_html_permission));
-  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval', $filtered_html_permission));
+  user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'skip comment approval', $filtered_html_permission));
 
   // Create a default role for site administrators, with all available permissions assigned.
   $admin_role = new stdClass();
diff --git a/profiles/standard/translations/README.txt b/profiles/standard/translations/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d5cf750159a1695b718a58ef2e2b279a28bf6b61
--- /dev/null
+++ b/profiles/standard/translations/README.txt
@@ -0,0 +1,4 @@
+// $Id: README.txt,v 1.1 2010/09/22 01:49:17 webchick Exp $
+
+This directory should be used to place downloaded translations
+for installing Drupal core.
diff --git a/profiles/testing/testing.info b/profiles/testing/testing.info
index e0948bcb276a815f565b99b2ae452f5796418feb..c601cea8ab7e5f5f61c51d7976ecad0e81ef1c57 100644
--- a/profiles/testing/testing.info
+++ b/profiles/testing/testing.info
@@ -5,8 +5,8 @@ version = VERSION
 core = 7.x
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/profiles/unl_profile/unl_profile.install b/profiles/unl_profile/unl_profile.install
index 470d5ae1a85427ad5ecebb17f2d33aa60f1a5760..372523ea2ad8dae41a990007a828ad77fc80b00b 100644
--- a/profiles/unl_profile/unl_profile.install
+++ b/profiles/unl_profile/unl_profile.install
@@ -124,7 +124,9 @@ EOF;
 UNL is an equal opportunity employer with a comprehensive plan for diversity. Find out more: <a href="https://employment.unl.edu/" target="_blank" title="Employment at UNL">employment.unl.edu</a><br />
 EOF;
     
+
     // Enable some standard blocks.
+    
     db_insert('block')
         ->fields(array('module', 'delta', 'theme', 'status', 'weight', 'region', 'pages', 'cache'))
         ->values(array(
@@ -169,31 +171,40 @@ EOF;
         ))
         ->execute();
     
+    
+    // Get the default filter_format from the parent database.
+    $parent_site_database_settings = unl_profile_get_default_site_db_settings();
+    $parent_site_prefix = $parent_site_database_settings['default']['default']['prefix'];
+    $results = db_query("SELECT * FROM {$parent_site_prefix}filter_format WHERE status=1 ORDER BY weight LIMIT 1");
+    foreach ($results as $result) {
+      $format = $result->format;
+    }
+    
     db_insert('block_custom')
         ->fields(array('bid', 'body', 'info', 'format'))
         ->values(array(
             'bid'    => 101,
             'body'   => $block_contents['contactinfo'],
             'info'   => 'Contact Info',
-            'format' => 3
+            'format' => $format,
         ))
         ->values(array(
             'bid'    => 102,
             'body'   => $block_contents['leftcollinks'],
             'info'   => 'Related Links',
-            'format' => 3
+            'format' => $format,
         ))
         ->values(array(
             'bid'    => 103,
             'body'   => $block_contents['optionalfooter'],
             'info'   => 'Optional Footer',
-            'format' => 3
+            'format' => $format,
         ))
         ->values(array(
             'bid'    => 104,
             'body'   => $block_contents['footercontent'],
             'info'   => 'Footer Content',
-            'format' => 3
+            'format' => $format,
         ))
         ->execute();
     
@@ -206,30 +217,40 @@ EOF;
 
     // Update the settings file to use shared database tables (unless this is the default site)
     if (conf_path() != 'sites/default') {
-        $shared_prefix = unl_profile_get_default_site_db_prefix();
+        $parent_site_database_settings = unl_profile_get_default_site_db_settings();
+    
         $new_prefix = $GLOBALS['databases']['default']['default']['prefix'];
+        $shared_prefix = $parent_site_database_settings['default']['default']['prefix'];
+        $new_prefixes = array(
+          // Localized tables, prefixed with site name
+          'default'       => $new_prefix,
+
+          // shared tables across all sites
+          'authmap'       => $shared_prefix,
+          'filter'        => $shared_prefix,
+          'filter_format' => $shared_prefix,
+          'role'          => $shared_prefix,
+          'sessions'      => $shared_prefix,
+          'users'         => $shared_prefix,
+          'users_roles'   => $shared_prefix,
+          'wysiwyg'       => $shared_prefix,
+        );
+        
         $settings['databases'] = array(
-            'value'    => $GLOBALS['databases'],
+            'value'    => $parent_site_database_settings,
             'required' => TRUE
         );
-        $settings['databases']['value']['default']['default']['prefix'] = array(
-
-            // Localized tables, prefixed with site name
-            'default'       => $new_prefix,
-
-            // shared tables across all sites
-            'authmap'       => $shared_prefix,
-            'filter'        => $shared_prefix,
-            'filter_format' => $shared_prefix,
-            'role'          => $shared_prefix,
-            'sessions'      => $shared_prefix,
-            'users'         => $shared_prefix,
-            'users_roles'   => $shared_prefix,
-            'wysiwyg'       => $shared_prefix
-        );
+        
+        foreach ($settings['databases']['value'] as &$database) {
+          $database['default']['prefix'] = $new_prefixes;
+          foreach ($database['slave'] as &$slave_database) {
+            $slave_database['prefix'] = $new_prefixes;
+          }
+        }
+        
         $settings['drupal_hash_salt'] = array(
-            'value'    => 'FOOBAR' . $GLOBALS['drupal_hash_salt'],
-            'required' => TRUE,
+          'value'    => 'FOOBAR' . $GLOBALS['drupal_hash_salt'],
+          'required' => TRUE,
         );
         
         $settings_dir = DRUPAL_ROOT . DIRECTORY_SEPARATOR . conf_path();
@@ -263,12 +284,12 @@ EOF;
 /**
  * Load the default site's config file and return the db_prefix value from it.
  */
-function unl_profile_get_default_site_db_prefix()
+function unl_profile_get_default_site_db_settings()
 {
     $default_site_settings_file = DRUPAL_ROOT . '/sites/default/settings.php';
     require $default_site_settings_file;
     
-    return $databases['default']['default']['prefix'];
+    return $databases;
 }
 
 function unl_profile_add_shortcut($title, $path)
diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh
index 748fbbe5bb1dc3ad59a561f622015731e8ba5ed9..55fe830b18044bf26a3bb4c42444d175fcd78654 100755
--- a/scripts/run-tests.sh
+++ b/scripts/run-tests.sh
@@ -1,5 +1,5 @@
 <?php
-// $Id: run-tests.sh,v 1.40 2010/01/15 10:51:02 dries Exp $
+// $Id: run-tests.sh,v 1.42 2010/09/28 02:30:32 dries Exp $
 /**
  * @file
  * This script runs Drupal tests from command line.
@@ -41,7 +41,7 @@ if ($args['clean']) {
 
   // Get the status messages and print them.
   $messages = array_pop(drupal_get_messages('status'));
-  foreach($messages as $text) {
+  foreach ($messages as $text) {
     echo " - " . $text . "\n";
   }
   exit;
@@ -302,7 +302,7 @@ function simpletest_script_init($server_software) {
 function simpletest_script_execute_batch() {
   global $args;
 
-  if (is_null($args['test-id'])) {
+  if (!isset($args['test-id'])) {
     simpletest_script_print_error("--execute-batch should not be called interactively.");
     exit;
   }
@@ -431,7 +431,7 @@ function simpletest_script_get_test_list() {
       // Check for valid group names and get all valid classes in group.
       foreach ($args['test_names'] as $group_name) {
         if (isset($groups[$group_name])) {
-          foreach($groups[$group_name] as $class_name => $info) {
+          foreach ($groups[$group_name] as $class_name => $info) {
             $test_list[] = $class_name;
           }
         }
diff --git a/sites/all/modules/imce/README.txt b/sites/all/modules/imce/README.txt
index 76fbf2bbdfd01c0599eb532090df8d1bbfc32aae..acdd5af711c649ba199d2947700ff96781fe237f 100644
--- a/sites/all/modules/imce/README.txt
+++ b/sites/all/modules/imce/README.txt
@@ -1,4 +1,4 @@
-// $Id: README.txt,v 1.17 2010/06/19 15:12:34 ufku Exp $
+// $Id: README.txt,v 1.18 2010/10/06 04:42:57 ufku Exp $
 
 IMCE
 http://drupal.org/project/imce
@@ -68,8 +68,8 @@ Install http://drupal.org/project/imce_wysiwyg bridge module and enable IMCE as
 BUEditor:
 IMCE is integrated in image and link dialogs.
 
-FCKeditor(without WYSIWYG): 
-Fckeditor profile->File browser settings->IMCE integration
+(F)CKeditor(without WYSIWYG): 
+(F)ckeditor profile->File browser settings->IMCE integration
 
 If your application is not one of the above, please keep reading in order to learn how to integrate IMCE.
 
diff --git a/sites/all/modules/imce/css/imce-content.css b/sites/all/modules/imce/css/imce-content.css
index 42543596b25eaaad926fbb44bb7b7aa25b80720f..6aae3e5b02ddeac829c716f84dfba305cd9b8505 100644
--- a/sites/all/modules/imce/css/imce-content.css
+++ b/sites/all/modules/imce/css/imce-content.css
@@ -1,4 +1,4 @@
-/* $Id: imce-content.css,v 1.5 2010/05/15 13:31:16 ufku Exp $ */
+/* $Id: imce-content.css,v 1.9 2010/10/09 05:47:47 ufku Exp $ */
 
 /*Body*/
 body.imce {
@@ -32,7 +32,7 @@ body.imce {
 #imce-content label.option {
   font-weight: normal;
 }
-#imce-content input.form-text, #imce-content input[type=text], #imce-content input.form-file, #imce-content input[type=file], #imce-content select {
+#imce-content input.form-text, #imce-content input[type=text], #imce-content input.form-file, #imce-content input[type=file], #imce-content select, #imce-content textarea {
   border: 1px inset #aaa;
   padding: 2px;
   background-color: #fff;
@@ -44,6 +44,9 @@ body.imce {
   padding: 2px 6px 2px 20px;
   margin: 2px 0;
   background: #e8e8d8 url(submit.png) no-repeat 2px 50%;
+  -moz-border-radius: 0;
+  -webkit-border-radius: 0;
+  border-radius: 0;
 }
 #imce-content [disabled], #imce-content .disabled {
   color: #999;
@@ -56,6 +59,9 @@ body.imce {
 #imce-content .form-item {
   margin: 4px 0;
 }
+#imce-content .form-item .description {
+  font-size: 0.9em;
+}
 #imce-content strong, #imce-content h4 {
   font-weight: bold;
 }
@@ -269,7 +275,7 @@ body.imce {
   position: relative;
 }
 #op-close-link {
-  display: inline-block;
+  display: none;
   position: absolute;
   z-index: 3;
   top: 2px;
@@ -277,7 +283,6 @@ body.imce {
   width: 16px;
   height: 16px;
   background: url(close.png) no-repeat 50% 50%;
-  visibility: hidden;
 }
 #ops-list {
 }
@@ -321,6 +326,25 @@ body.imce {
 #op-item-sendto a {
   background-image: url(sendto.png);
 }
+#op-item-help a {
+  background-image: url(help.png);
+}
+#op-item-changeview a {
+  background-image: url(view-box.png);
+}
+.box-view #op-item-changeview a {
+  background-image: url(view-list.png);
+}
+#op-item-help a, #op-item-changeview a {
+  white-space: nowrap;
+  overflow: hidden;
+  width: 1px;
+  padding: 5px 0 5px 25px;
+  background-position: 5px 50%;
+}
+#op-item-help, #op-item-changeview {
+  float: right !important;
+}
 
 /*resizers*/
 #imce-content .y-resizer {
@@ -338,41 +362,13 @@ body.imce {
   border-right: 1px solid #e0e3e5;
 }
 
-/*Help box*/
-#help-box {
-  position: absolute;
-  z-index: 9;
-  right: 0;
-  background: url(help.png) no-repeat 100% 0;
-  max-width: 500px;
-}
-#help-box-title {
-  cursor: help;
-}
-#help-box-title span {
-  display: inline-block;
-  width: 16px;
-  height: 16px;
-  overflow: hidden;
-  visibility: hidden;
-}
-#help-box-content {
-  display: none;
-  padding: 10px;
-  border: 2px solid #344454;
-  background-color: #f5f5f5;
-}
-#help-box:hover #help-box-content, #help-box-content.hover {
-  display: block;
-}
-
 /*Message box*/
 #message-box {
   display: none;
   position: absolute;
   width: 60%;
   left: 20%;
-  top: 40%;
+  top: 32%;
   z-index: 10;
   padding: 5px;
   background-color: #fff;
@@ -409,7 +405,7 @@ body.imce {
 #file-preview {
   text-align: center;
 }
-.imce-hide, .js #forms-wrapper {
+.imce-hide, .js #forms-wrapper, #help-box {
   display: none;
 }
 
@@ -426,4 +422,35 @@ body.imce {
 }
 .ie-7 #ops-list a span {
   cursor: pointer;
+}
+.ie-7 #file-list-wrapper {
+  display: inline-block; /* Gives hasLayout */
+}
+
+/* File list in box view */
+.box-view #file-list tr {
+  display: block;
+  float: left;
+  border: 1px solid #ccf;
+  margin: 10px;
+}
+.box-view #file-list td {
+  border: 0;
+}
+.box-view #file-list td.name {
+  min-width: 0;
+  padding: 5px;
+  text-align: center;
+  vertical-align: middle;
+}
+.box-view #file-list td.name img {
+  margin: 0;
+}
+.box-view #file-list td.name span {
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+}
+.box-view #file-list td.size, .box-view #file-list td.date, .box-view #file-list td.width, .box-view #file-list td.height {
+  display: none;
 }
\ No newline at end of file
diff --git a/sites/all/modules/imce/imce.info b/sites/all/modules/imce/imce.info
index b032cc4b3c4b13f5fbc190ece3cb93fd13e6d82e..c939de2d14f13d38c5fb7bfd0cd618a07221f46f 100644
--- a/sites/all/modules/imce/imce.info
+++ b/sites/all/modules/imce/imce.info
@@ -9,9 +9,9 @@ files[] = "imce.module"
 files[] = "inc/imce.admin.inc"
 files[] = "inc/imce.page.inc"
 
-; Information added by drupal.org packaging script on 2010-06-21
-version = "7.x-1.0-alpha3"
+; Information added by drupal.org packaging script on 2010-10-09
+version = "7.x-1.0-beta1"
 core = "7.x"
 project = "imce"
-datestamp = "1277145015"
+datestamp = "1286606462"
 
diff --git a/sites/all/modules/imce/imce.install b/sites/all/modules/imce/imce.install
index 3a0cfcc85e4635d958bd0675b42bfc59fdcfdf1c..a5552b3d57c08a8c68444b9d1cb8805b84276a82 100644
--- a/sites/all/modules/imce/imce.install
+++ b/sites/all/modules/imce/imce.install
@@ -1,5 +1,5 @@
 <?php
-// $Id: imce.install,v 1.7 2010/06/02 08:27:00 ufku Exp $
+// $Id: imce.install,v 1.8 2010/08/30 04:06:25 ufku Exp $
 
 /**
  * @file
@@ -22,6 +22,7 @@ function imce_uninstall() {
   variable_del('imce_profiles');
   variable_del('imce_roles_profiles');
   variable_del('imce_settings_textarea');
+  variable_del('imce_settings_absurls');
   variable_del('imce_settings_replace');
   variable_del('imce_settings_thumb_method');
   variable_del('imce_settings_disable_private');
@@ -30,34 +31,11 @@ function imce_uninstall() {
   variable_del('imce_custom_scan');
 }
 
-/**
- * Implements hook_schema().
- */
-function imce_schema() {
-  $schema['imce_files'] = array(
-    'description' => 'Stores files created by IMCE.',
-    'fields' => array(
-      'fid' => array(
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'The {file_managed}.fid that belongs to IMCE.',
-      ),
-    ),
-    'primary key' => array('fid'),
-    'foreign keys' => array(
-      'fid' => array('file_managed' => 'fid'),
-    ),
-  );
-  return $schema;
-}
-
 /**
  * Updates from 6.x to 7.x.
  */
 function imce_update_7000() {
-  //update role-profile assignments
+  // Update role-profile assignments
   $roles_profiles = variable_get('imce_roles_profiles', array());
   if (!empty($roles_profiles)) {
     $scheme = variable_get('file_default_scheme', 'public');
@@ -67,7 +45,7 @@ function imce_update_7000() {
     }
     variable_set('imce_roles_profiles', $roles_profiles);
   }
-  //update textarea ids
+  // Update textarea ids
   $ids = str_replace(' ', '', variable_get('imce_settings_textarea', ''));
   if ($ids != '') {
     $ids = explode(',', $ids);
@@ -76,4 +54,28 @@ function imce_update_7000() {
     }
     variable_set('imce_settings_textarea', implode(', ', $ids));
   }
+}
+
+/**
+ * Removes {imce_files} in favor of {file_usage}.
+ */
+function imce_update_7001(&$sandbox) {
+  if (!db_table_exists('imce_files')) {
+    return;
+  }
+  if (!isset($sandbox['progress'])) {
+    $sandbox['progress'] = 0;
+    $sandbox['last_fid_processed'] = -1;
+    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {imce_files}")->fetchField();
+  }
+  $limit = 500;
+  $result = db_query_range('SELECT i.fid FROM {imce_files} i INNER JOIN {file_managed} f ON i.fid = f.fid WHERE i.fid > :fid ORDER BY i.fid', 0, $limit, array(':fid' => $sandbox['last_fid_processed']))->fetchAll();
+  foreach ($result as $file) {
+    file_usage_add($file, 'imce', 'file', $file->fid);
+    $sandbox['progress']++;
+    $sandbox['last_fid_processed'] = $file->fid;
+  }
+  if ($sandbox['#finished'] = empty($sandbox['max']) || ($sandbox['progress'] / $sandbox['max'])) {
+    db_drop_table('imce_files');
+  }
 }
\ No newline at end of file
diff --git a/sites/all/modules/imce/imce.module b/sites/all/modules/imce/imce.module
index 6b6cb01dfefc24c2db45212d5569897ccd7f06ff..1632e94d1c4f8dbdc49bd1a04bc8a184c7467b27 100644
--- a/sites/all/modules/imce/imce.module
+++ b/sites/all/modules/imce/imce.module
@@ -1,5 +1,5 @@
 <?php
-// $Id: imce.module,v 1.34 2010/06/02 08:31:10 ufku Exp $
+// $Id: imce.module,v 1.36 2010/10/09 05:48:35 ufku Exp $
 
 /**
  * @file
@@ -40,7 +40,7 @@ function imce_menu() {
     'title' => 'Add new profile',
     'page callback' => 'imce_profile_operations',
     'access arguments' => $access,
-    'type' => MENU_CALLBACK,
+    'type' => MENU_VISIBLE_IN_BREADCRUMB,
     'file' => 'inc/imce.admin.inc',
   );
   return $items;
@@ -104,26 +104,6 @@ function imce_file_download($uri) {
   }
 }
 
-/**
- * Implements hook_file_delete().
- */
-function imce_file_delete($file) {
-  db_delete('imce_files')->condition('fid', $file->fid)->execute();
-}
-
-/**
- * Implements of hook_file_references().
- */
-function imce_file_references($file) {
-  //do not report reference count on internal file deletion
-  if (isset($file->imce_noref) && $file->imce_noref) {
-    return;
-  }
-  if (db_query('SELECT 1 FROM {imce_files} WHERE fid = :fid', array(':fid' => $file->fid))->fetchField()) {
-    return array('imce' => 1);
-  }
-}
-
 /**
  * Implements hook_element_info().
  */
diff --git a/sites/all/modules/imce/inc/imce.admin.inc b/sites/all/modules/imce/inc/imce.admin.inc
index 7d1d4a30273f5ef3657af95a04b3166419972443..420ee39616b34fc1384a64c5946f418edb91c42e 100644
--- a/sites/all/modules/imce/inc/imce.admin.inc
+++ b/sites/all/modules/imce/inc/imce.admin.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: imce.admin.inc,v 1.5 2010/06/02 08:31:10 ufku Exp $
+// $Id: imce.admin.inc,v 1.7 2010/10/09 05:49:37 ufku Exp $
 
 /**
  * @file
@@ -59,18 +59,12 @@ function imce_admin_form($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
   );
-  $form['common']['disable_private'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Disable serving of private files'),
-    '#default_value' => variable_get('imce_settings_disable_private', 1),
-    '#description' => t('IMCE serves all files under private files directory without applying any access restrictions. This allows anonymous access to any file(/system/files/filename) unless there is a module restricting access to the files. Here you can switch this behavior.'),
-  );
   $form['common']['textarea'] = array(
     '#type' => 'textfield',
     '#title' => t('Enable inline image/file insertion into plain textareas'),
     '#default_value' => variable_get('imce_settings_textarea', ''),
     '#maxlength' => NULL,
-    '#description' => t('If you don\'t use any WYSIWYG editor, this feature will allow you to add your images or files as <strong>html code into any plain textarea</strong>. Enter <strong>comma separated textarea IDs</strong> under which you want to enable a link to IMCE. The * character is a wildcard. Hint: ID of Body fields in most node types starts with edit-body.'),
+    '#description' => t('If you don\'t use any WYSIWYG editor, this feature will allow you to add your images or files as <strong>html code into any plain textarea</strong>. Enter <strong>comma separated textarea IDs</strong> under which you want to enable a link to IMCE. The * character is a wildcard. Hint: ID of Body fields in most node types starts with edit-body*.'),
   );
   $form['common']['absurls'] = array(
     '#type' => 'checkbox',
@@ -97,6 +91,12 @@ function imce_admin_form($form, &$form_state) {
       'scale_and_crop' => t('First scale then crop the image to fit the thumbnail dimensions.')
     ),
   );
+  $form['common']['disable_private'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Disable serving of private files'),
+    '#default_value' => variable_get('imce_settings_disable_private', 1),
+    '#description' => t('IMCE serves all files under private files directory without applying any access restrictions. This allows anonymous access to any file(/system/files/filename) unless there is a module restricting access to the files. Here you can disable this feature.'),
+  );
 
   $form['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
   $form['#theme'] = 'imce_admin';
@@ -480,6 +480,7 @@ function imce_role_form($role, $weight = TRUE, $core = TRUE) {
       '#type' => 'select',
       '#options' => imce_profile_options(),
       '#default_value' => $role[$scheme . '_pid'],
+      '#empty_value' => 0,
     );
   }
   return $form;
@@ -517,7 +518,7 @@ function imce_profile_delete_submit($form, &$form_state) {
  * Profile options.
  */
 function imce_profile_options() {
-  $options = array(t('none'));
+  $options = array();
   foreach (variable_get('imce_profiles', array()) as $pid => $profile) {
     $options[$pid] = $profile['name'];
   }
@@ -668,4 +669,4 @@ function imce_rolesort($r1, $r2) {
 }
 
 //Include core profile functions.
-module_load_include('inc', 'imce', 'inc/imce.core.profiles');
\ No newline at end of file
+include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'imce') . '/inc/imce.core.profiles.inc';
\ No newline at end of file
diff --git a/sites/all/modules/imce/inc/imce.page.inc b/sites/all/modules/imce/inc/imce.page.inc
index c16ca5a6966fff8f325fce6c73d03718e004aa89..d517ab993fd4eb0a4d3e1d42c32944e6e0e61f75 100644
--- a/sites/all/modules/imce/inc/imce.page.inc
+++ b/sites/all/modules/imce/inc/imce.page.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: imce.page.inc,v 1.9 2010/06/19 15:13:35 ufku Exp $
+// $Id: imce.page.inc,v 1.10 2010/08/30 04:06:25 ufku Exp $
 
 /**
  * @file
@@ -403,22 +403,26 @@ function imce_delete_filepath($uri) {
   $file = file_load_multiple(array(), array('uri' => $uri));
   $file = reset($file);
 
-  //file exists in database
+  // File exists in database
   if ($file) {
-    //prevent imce returning ref count
-    $file->imce_noref = TRUE;
-    $result = file_delete($file);
-    //deletion blocked by an other module.
-    if (is_array($result)) {
+    $usage = file_usage_list($file);
+    $is_imce = isset($usage['imce']);
+    unset($usage['imce']);
+    // File is in use by an other module.
+    if (!empty($usage)) {
       drupal_set_message(t('%filename is in use by another application.', array('%filename' => $file->filename)), 'error');
       return FALSE;
     }
-    //general failure
-    if (!$result) {
+    // Force delete file. Prevent running file_usage_list() second time.
+    if (!file_delete($file, TRUE)) {
       return FALSE;
     }
+    // Remove imce usage
+    if ($is_imce) {
+      file_usage_delete($file, 'imce');
+    }
   }
-  //not in db. probably loaded via ftp.
+  // Not in db. Probably loaded via ftp.
   elseif (!file_unmanaged_delete($uri)) {
     return FALSE;
   }
@@ -1080,7 +1084,7 @@ function theme_imce_user_page($variables) {
  * Registers the file as an IMCE file.
  */
 function imce_file_register($file) {
-  if (!db_query('SELECT 1 FROM {imce_files} WHERE fid = :fid', array(':fid' => $file->fid))->fetchField()) {
-    return @db_insert('imce_files')->fields(array('fid' => $file->fid))->execute();
+  if (!db_query("SELECT 1 FROM {file_usage} WHERE module = 'imce' AND fid = :fid", array(':fid' => $file->fid))->fetchField()) {
+    file_usage_add($file, 'imce', 'file', $file->fid);
   }
 }
\ No newline at end of file
diff --git a/sites/all/modules/imce/js/imce.js b/sites/all/modules/imce/js/imce.js
index 87211864218d24b4e170bfdd9002f30b1bc7baf3..9331291ea4cedcc5d48bdc42280ebf56f7fd7069 100644
--- a/sites/all/modules/imce/js/imce.js
+++ b/sites/all/modules/imce/js/imce.js
@@ -1,4 +1,4 @@
-// $Id: imce.js,v 1.23 2010/06/19 15:14:20 ufku Exp $
+// $Id: imce.js,v 1.26 2010/10/06 04:42:57 ufku Exp $
 
 (function($) {
 //Global container.
@@ -10,8 +10,9 @@ hooks: {load: [], list: [], navigate: [], cache: []},
 initiate: function() {
   imce.conf = Drupal.settings.imce || {};
   if (imce.conf.error != false) return;
-  imce.FLW = imce.el('file-list-wrapper');
-  imce.SBW = imce.el('sub-browse-wrapper');
+  imce.FLW = imce.el('file-list-wrapper'), imce.SBW = imce.el('sub-browse-wrapper');
+  imce.NW = imce.el('navigation-wrapper'), imce.BW = imce.el('browse-wrapper');
+  imce.PW = imce.el('preview-wrapper'), imce.FW = imce.el('forms-wrapper');
   imce.updateUI();
   imce.prepareMsgs();//process initial status messages
   imce.initiateTree();//build directory tree
@@ -81,6 +82,7 @@ dirCollapsible: function (branch) {
     if (branch.ul) {
       $(branch.ul).toggle();
       $(branch.li).toggleClass('expanded');
+      $.browser.msie && $('#navigation-header').css('top', imce.NW.scrollTop);
     }
     else if (branch.clkbl){
       $(branch.a).click();
@@ -285,15 +287,16 @@ refreshOps: function() {
 opAdd: function (op) {
   var oplist = imce.el('ops-list'), opcons = imce.el('op-contents');
   var name = op.name || ('op-'+ $(oplist).children('li').size());
-  var Op = imce.ops[name] = {title: op.title || 'Untitled'};
+  var title = op.title || 'Untitled';
+  var Op = imce.ops[name] = {title: title};
   if (op.content) {
     Op.div = imce.newEl('div');
     $(Op.div).attr({id: 'op-content-'+ name, 'class': 'op-content'}).appendTo(opcons).append(op.content);
   }
   Op.a = imce.newEl('a');
   Op.li = imce.newEl('li');
-  $(Op.a).attr({href: '#', 'name': name}).html('<span>' + op.title +'</span>').click(imce.opClickEvent);
-  $(Op.li).attr('id', 'op-item-'+ op.name).append(Op.a).appendTo(oplist);
+  $(Op.a).attr({href: '#', name: name, title: title}).html('<span>' + title +'</span>').click(imce.opClickEvent);
+  $(Op.li).attr('id', 'op-item-'+ name).append(Op.a).appendTo(oplist);
   Op.func = op.func || imce.opVoid;
   return Op;
 },
@@ -316,12 +319,12 @@ opClick: function(name) {
   if (Op.div) {
     if (oldop) {
       var toggle = oldop == name;
-      imce.opShrink(oldop, toggle ? 'slideUp' : 'hide');
+      imce.opShrink(oldop, toggle ? 'fadeOut' : 'hide');
       if (toggle) return false;
     }
     var left = Op.li.offsetLeft;
     var $opcon = $('#op-contents').css({left: 0});
-    $(Op.div).slideDown('normal', function() {
+    $(Op.div).fadeIn('normal', function() {
       setTimeout(function() {
         if (imce.vars.op) {
           var $inputs = $('input', imce.ops[imce.vars.op].div);
@@ -334,7 +337,7 @@ opClick: function(name) {
     var diff = left + $opcon.width() - $('#imce-content').width();
     $opcon.css({left: diff > 0 ? left - diff : left});
     $(Op.li).addClass('active');
-    $(imce.opCloseLink).css('visibility', 'visible');
+    $(imce.opCloseLink).fadeIn(300);
     imce.vars.op = name;
   }
   Op.func(true);
@@ -366,7 +369,7 @@ opShrink: function(name, effect) {
   var Op = imce.ops[name];
   $(Op.div).stop(true, true)[effect || 'hide']();
   $(Op.li).removeClass('active');
-  $(imce.opCloseLink).css('visibility', 'hidden');
+  $(imce.opCloseLink).hide();
   Op.func(false);
   imce.vars.op = null;
 },
@@ -424,7 +427,7 @@ navUpdate: function(data, dir) {
 navCache: function (dir, newdir) {
   var C = imce.cache[dir] = {'dir': dir, files: imce.el('file-list'), dirsize: imce.el('dir-size').innerHTML, perm: $.extend({}, imce.conf.perm)};
   C.files.id = 'cached-list-'+ dir;
-  imce.el('forms-wrapper').appendChild(C.files);
+  imce.FW.appendChild(C.files);
   imce.invoke('cache', C, newdir);
 },
 
@@ -565,7 +568,9 @@ setMessage: function (msg, type) {
     $box.css({opacity: 0, display: 'block'}).html(msg);
     $box.dequeue();
   });
-  $box.fadeTo(600, 1).fadeTo(1000, 1).fadeOut(400);
+  var q = $box.queue().length;
+  q = q < 2 ? 1 : q < 3 ? 0.8 : q < 4 ? 0.7 : 0.4;//adjust speed with respect to queue length
+  $box.fadeTo(600 * q, 1).fadeTo(1000 * q, 1).fadeOut(400 * q);
   $(logs).append(msg);
   return false;
 },
@@ -687,7 +692,7 @@ highlight: function (fid) {
 },
 //process a row
 processRow: function (row) {
-  row.cells[0].innerHTML = imce.decode(row.id);
+  row.cells[0].innerHTML = '<span>' + imce.decode(row.id) + '</span>';
   row.onmousedown = function(e) {
     var e = e||window.event;
     imce.fileClick(this, e.ctrlKey, e.shiftKey);
@@ -740,7 +745,7 @@ updateUI: function() {
   var host = location.host;
   var baseurl = location.protocol + '//' + host;
   if (furl.charAt(furl.length - 1) != '/') {
-    furl += '/';
+    furl = imce.conf.furl = furl + '/';
   }
   imce.conf.modfix = imce.conf.clean && furl.indexOf(host + '/system/') > -1;
   if (absurls && !isabs) {
@@ -750,7 +755,7 @@ updateUI: function() {
     imce.conf.furl = furl.substr(baseurl.length);
   }
   //convert button elements to input elements.
-  imce.convertButtons(imce.el('forms-wrapper'));
+  imce.convertButtons(imce.FW);
   //ops-list
   $('#ops-list').removeClass('tabs secondary').addClass('clear-block clearfix');
   imce.opCloseLink = $(imce.newEl('a')).attr({id: 'op-close-link', href: '#', title: Drupal.t('Close')}).click(function() {
@@ -759,7 +764,7 @@ updateUI: function() {
   }).appendTo('#op-contents')[0];
   //navigation-header
   if (!$('#navigation-header').size()) {
-    $('#navigation-wrapper > .navigation-text').attr('id', 'navigation-header').wrapInner('<span></span>');
+    $(imce.NW).children('.navigation-text').attr('id', 'navigation-header').wrapInner('<span></span>');
   }
   //log
   $('#log-prv-wrapper').before($('#log-prv-wrapper > #preview-wrapper')).remove();
@@ -767,29 +772,22 @@ updateUI: function() {
   //content resizer
   $('#content-resizer').remove();
   //message-box
-  imce.msgBox = imce.el('message-box') || $('<div id="message-box"></div>').prependTo('#imce-content')[0];
-  //help box & ie fix
+  imce.msgBox = imce.el('message-box') || $(imce.newEl('div')).attr('id', 'message-box').prependTo('#imce-content')[0];
+  //create help tab
   var $hbox = $('#help-box');
   $hbox.is('a') && $hbox.replaceWith($(imce.newEl('div')).attr('id', 'help-box').append($hbox.children()));
-  var $htitle = $('#help-box-title');
-  if ($.browser.msie) {
-    $('html').addClass('ie');
-    if (parseFloat($.browser.version) < 8) {
-      var $hcontent = $('#help-box-content');
-      $hcontent.add($htitle).hover(function() {
-        $hcontent.addClass('hover');
-      }, function() {
-        $hcontent.removeClass('hover');
-      });
-      $('html').addClass('ie-7');
-    }
-  }
-  !$htitle.children('span').size() && $htitle.wrapInner('<span></span>');
+  imce.hooks.load.push(function() {
+    imce.opAdd({name: 'help', title: $('#help-box-title').remove().text(), content: $('#help-box').show()});
+  });
+  //add ie classes
+  $.browser.msie && $('html').addClass('ie') && parseFloat($.browser.version) < 8 && $('html').addClass('ie-7');
+  // enable box view for file list
+  imce.vars.boxW && imce.boxView();
   //scrolling file list
   imce.syncScroll(imce.SBW, '#file-header-wrapper');
   imce.syncScroll(imce.SBW, '#dir-stat', true);
   //scrolling directory tree
-  imce.syncScroll('#navigation-wrapper', '#navigation-header');
+  imce.syncScroll(imce.NW, '#navigation-header');
 }
 };
 
diff --git a/sites/all/modules/imce/js/imce_extras.js b/sites/all/modules/imce/js/imce_extras.js
index a06ad3426bc8203e847c44edcfd8d10a5c36df82..4f736e5f7f2d4da0a050610374ba1f5e4374811d 100644
--- a/sites/all/modules/imce/js/imce_extras.js
+++ b/sites/all/modules/imce/js/imce_extras.js
@@ -1,14 +1,10 @@
-// $Id: imce_extras.js,v 1.6 2010/06/05 08:04:41 ufku Exp $
+// $Id: imce_extras.js,v 1.9 2010/10/06 04:42:57 ufku Exp $
 //This pack implemets: keyboard shortcuts, file sorting, resize bars, and inline thumbnail preview.
 
 (function($) {
 
-//add onload hook. unshift to make sure it runs first after imce loads.
-imce.hooks.load.unshift(function () {
-  imce.NW = imce.el('navigation-wrapper');
-  imce.BW = imce.el('browse-wrapper');
-  imce.PW = imce.el('preview-wrapper');
-  //add scale calculator for resizing.
+// add scale calculator for resizing.
+imce.hooks.load.push(function () {
   $('#edit-width, #edit-height').focus(function () {
     var fid, r, w, isW, val;
     if (fid = imce.vars.prvfid) {
@@ -19,7 +15,7 @@ imce.hooks.load.unshift(function () {
   });
 });
 
-/**************** SHORTCUTS ********************/
+// Shortcuts
 var F = null;
 imce.initiateShortcuts = function () {
   $(imce.NW).attr('tabindex', '0').keydown(function (e) {
@@ -97,8 +93,6 @@ $.each({k46: 'delete', k82: 'resize', k84: 'thumb', k85: 'upload'}, function (k,
   };
 });
 
-/**************** SORTING ********************/
-
 //prepare column sorting
 imce.initiateSorting = function() {
   //add cache hook. cache the old directory's sort settings before the new one replaces it.
@@ -154,14 +148,12 @@ imce.sortStrDsc = function(a, b) {return imce.sortStrAsc(b, a);};
 imce.sortNumAsc = function(a, b) {return a-b;};
 imce.sortNumDsc = function(a, b) {return b-a};
 
-/**************** RESIZE-BARS  ********************/
-
 //set resizers for resizable areas and recall previous dimensions
 imce.initiateResizeBars = function () {
-  imce.setResizer('navigation-resizer', 'X', 'navigation-wrapper', null, 1, function(p1, p2, m) {
+  imce.setResizer('#navigation-resizer', 'X', imce.NW, null, 1, function(p1, p2, m) {
     p1 != p2 && imce.cookie('imcenww', p2);
   });
-  imce.setResizer('browse-resizer', 'Y', 'browse-wrapper', 'preview-wrapper', 50, function(p1, p2, m) {
+  imce.setResizer('#browse-resizer', 'Y', imce.BW, imce.PW, 50, function(p1, p2, m) {
     p1 != p2 && imce.cookie('imcebwh', p2);
   });
   imce.recallDimensions();
@@ -171,8 +163,8 @@ imce.initiateResizeBars = function () {
 imce.setResizer = function (resizer, axis, area1, area2, Min, callback) {
   var opt = axis == 'X' ? {pos: 'pageX', func: 'width'} : {pos: 'pageY', func: 'height'};
   var Min = Min || 0;
-  var $area1 = $(imce.el(area1)), $area2 = area2 ? $(imce.el(area2)) : null, $doc = $(document);
-  $(imce.el(resizer)).mousedown(function(e) {
+  var $area1 = $(area1), $area2 = area2 ? $(area2) : null, $doc = $(document);
+  $(resizer).mousedown(function(e) {
     var pos = e[opt.pos];
     var end = start = $area1[opt.func]();
     var Max = $area2 ? start + $area2[opt.func]() : 1200;
@@ -238,12 +230,12 @@ imce.cookie = function (name, value) {
 imce.thumbRow = function (row) {
   var w = row.cells[2].innerHTML * 1;
   if (!w) return;
-  var h = row.cells[3].innerHTML*1;
+  var h = row.cells[3].innerHTML * 1;
   if (imce.vars.tMaxW < w || imce.vars.tMaxH < h) {
-    if (!imce.vars.prvstyle) return;
+    if (!imce.vars.prvstyle || imce.conf.dir.indexOf('styles') == 0) return;
     var img = new Image();
     img.src = imce.imagestyleURL(imce.getURL(row.id), imce.vars.prvstyle);
-    img.className = 'imagestyle imagestyle-' + imce.vars.prvstyle;
+    img.className = 'imagestyle-' + imce.vars.prvstyle;
   }
   else {
     var prvH = h, prvW = w;
@@ -267,7 +259,32 @@ imce.thumbRow = function (row) {
 //convert a file URL returned by imce.getURL() to an image style(imagecache preset) URL
 imce.imagestyleURL = function (url, stylename) {
   var len = imce.conf.furl.length - 1;
-  return url.substr(0, len) + '/styles/' + stylename + url.substr(len);
+  return url.substr(0, len) + '/styles/' + stylename + '/' + imce.conf.scheme + url.substr(len);
+};
+
+// replace table view with box view for file list
+imce.boxView = function () {
+  var w = imce.vars.boxW, h = imce.vars.boxH;
+  if (!w || !h || $.browser.msie && parseFloat($.browser.version) < 8) return;
+  var $body = $(document.body);
+  var toggle = function() {
+    $body.toggleClass('box-view');
+    // refresh dom. required by all except FF.
+    !$.browser.mozilla && $('#file-list').appendTo(imce.FW).appendTo(imce.FLW);
+  };
+  $body.append('<style type="text/css">.box-view #file-list td.name {width: ' + w + 'px;height: ' + h + 'px;} .box-view #file-list td.name span {width: ' + w + 'px;word-wrap: normal;text-overflow: ellipsis;}</style>');
+  imce.hooks.load.push(function() {
+    toggle();
+    imce.SBW.scrollTop = 0;
+    imce.opAdd({name: 'changeview', title: Drupal.t('Change view'), func: toggle});
+  });
+  imce.hooks.list.push(imce.boxViewRow);
+};
+
+// process a row for box view. include all data in box title.
+imce.boxViewRow = function (row) {
+  var s = ' | ', w = row.cells[2].innerHTML * 1, dim = w ? s + w + 'x' + row.cells[3].innerHTML * 1 : '';
+  row.cells[0].title = imce.decode(row.id) + s + row.cells[1].innerHTML + (dim) + s + row.cells[4].innerHTML;
 };
 
 })(jQuery);
\ No newline at end of file
diff --git a/sites/all/modules/imce/js/imce_set_app.js b/sites/all/modules/imce/js/imce_set_app.js
index f910cc57e9a74a9d96c630364781ceff2f80e97d..7dfea4c3a863b35c7f427fdd5636854f50b6656f 100644
--- a/sites/all/modules/imce/js/imce_set_app.js
+++ b/sites/all/modules/imce/js/imce_set_app.js
@@ -1,4 +1,4 @@
-// $Id: imce_set_app.js,v 1.6 2010/06/02 08:28:47 ufku Exp $
+// $Id: imce_set_app.js,v 1.8 2010/08/29 03:46:54 ufku Exp $
 /*
  * IMCE Integration by URL
  * Ex-1: http://example.com/imce?app=XEditor|url@urlFieldId|width@widthFieldId|height@heightFieldId
@@ -82,7 +82,7 @@ var isFunc = function(str, scope) {
   var obj = scope || appWindow;
   var parts = str.split('.'), len = parts.length;
   for (var i = 0; i < len && (obj = obj[parts[i]]); i++);
-  return i == len && $.isFunction(obj) ? obj : false;
+  return obj && i == len && (typeof obj == 'function' || typeof obj != 'string' && !obj.nodeName && obj.constructor != Array && /^[\s[]?function/.test(obj.toString())) ? obj : false;
 }
 
 })(jQuery);
\ No newline at end of file
diff --git a/sites/all/modules/imce/tpl/imce-content.tpl.php b/sites/all/modules/imce/tpl/imce-content.tpl.php
index 00a1c51d37731398e8e545337c1532255997f568..8b3bece7b354e422ea59174ab8717be9727f322c 100644
--- a/sites/all/modules/imce/tpl/imce-content.tpl.php
+++ b/sites/all/modules/imce/tpl/imce-content.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: imce-content.tpl.php,v 1.11 2010/05/15 13:31:16 ufku Exp $
+// $Id: imce-content.tpl.php,v 1.12 2010/10/06 04:42:57 ufku Exp $
 $imce =& $imce_ref['imce'];//keep this line.
 ?>
 
@@ -17,6 +17,10 @@ $imce =& $imce_ref['imce'];//keep this line.
   imce.vars.prvH = 40; //maximum height of the thumbnail used in inline preview.
   //imce.vars.prvstyle = 'stylename'; //preview larger images inline using an image style(imagecache preset).
 
+  //enable box view for file list. set box dimensions = preview dimensions + 30 or more
+  //imce.vars.boxW = 100; //width of a file info box
+  //imce.vars.boxH = 100; //height of a file info box
+
   //imce.vars.previewImages = 0; //disable click previewing of images.
   //imce.vars.cache = 0; //disable directory caching. File lists will always refresh.
   //imce.vars.absurls = 1; //make IMCE return absolute file URLs to external applications.
diff --git a/sites/all/modules/unl/cron.php b/sites/all/modules/unl/cron.php
index d8d43c6bff537933e72305ea1ee297c1aae5da31..956b5436ae71c26dfa14e69486970a35b7337fcd 100644
--- a/sites/all/modules/unl/cron.php
+++ b/sites/all/modules/unl/cron.php
@@ -18,11 +18,18 @@ while ($row = $query->fetchAssoc()) {
    ->fields(array('installed' => 1))
    ->condition('site_id', $row['site_id'])
    ->execute();
-  unl_add_site($row['site_path'], $row['uri'], $row['clean_url'], $row['db_prefix']);
-  db_update('unl_sites')
-    ->fields(array('installed' => 2))
-    ->condition('site_id', $row['site_id'])
-    ->execute();
+  if (unl_add_site($row['site_path'], $row['uri'], $row['clean_url'], $row['db_prefix'], $row['site_id'])) {
+    db_update('unl_sites')
+      ->fields(array('installed' => 2))
+      ->condition('site_id', $row['site_id'])
+      ->execute();
+  }
+  else {
+    db_update('unl_sites')
+      ->fields(array('installed' => 5))
+      ->condition('site_id', $row['site_id'])
+      ->execute();
+  }
 }
 
 $query = db_query('SELECT * FROM {unl_sites} WHERE installed=3');
@@ -31,7 +38,7 @@ while ($row = $query->fetchAssoc()) {
     ->fields(array('installed' => 4))
     ->condition('site_id', $row['site_id'])
     ->execute();
-  if (unl_remove_site($row['site_path'], $row['uri'], $row['db_prefix'])) {
+  if (unl_remove_site($row['site_path'], $row['uri'], $row['db_prefix'], $row['site_id'])) {
     db_delete('unl_sites')
       ->condition('site_id', $row['site_id'])
       ->execute();
@@ -46,7 +53,7 @@ while ($row = $query->fetchAssoc()) {
 }
 
 
-function unl_add_site($site_path, $uri, $clean_url, $db_prefix) {
+function unl_add_site($site_path, $uri, $clean_url, $db_prefix, $site_id) {
   if (substr($site_path, 0, 1) == '/') {
     $site_path = substr($site_path, 1);
   }
@@ -54,10 +61,7 @@ function unl_add_site($site_path, $uri, $clean_url, $db_prefix) {
     $site_path = substr($site_path, 0, -1);
   }
   
-  $path_parts = parse_url($uri);
-  $sites_subdir = $path_parts['host'] . $path_parts['path'];
-  $sites_subdir = strtr($sites_subdir, array('/' => '.')); 
-  
+  $sites_subdir = _unl_get_sites_subdir($uri);
   
   $database = $GLOBALS['databases']['default']['default'];
   $db_url = $database['driver']
@@ -76,31 +80,29 @@ function unl_add_site($site_path, $uri, $clean_url, $db_prefix) {
   $db_url = escapeshellarg($db_url);
   $db_prefix = escapeshellarg($db_prefix);
   
-  $subdir = explode('/', $site_path);
-  $symlink_name = array_pop($subdir);
-  $subdir_levels = count($subdir);
-  $subdir = implode('/', $subdir);
+  $command = "$php_path sites/all/modules/drush/drush.php -y --uri=$uri site-install unl_profile --sites-subdir=$sites_subdir --db-url=$db_url --db-prefix=$db_prefix --clean-url=$clean_url";
+  shell_exec($command);
   
-  $symlink_target = array();
-  for ($i = 0; $i < $subdir_levels; $i++) {
-      $symlink_target[] = '..';
+  $stub_token = '  # %UNL_CREATION_TOOL_STUB%';
+  $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
+  $stub_pos = strpos($htaccess, $stub_token);
+  if ($stub_pos === FALSE) {
+    return FALSE;
   }
-  $symlink_target = implode('/', $symlink_target);
-  
-  if (!$symlink_target) {
-    $symlink_target = '.';
+  $new_htaccess = substr($htaccess, 0, $stub_pos)
+                . "  # %UNL_START_SITE_ID_$site_id%\n";
+  foreach (array('misc', 'modules', 'sites', 'themes') as $drupal_dir) {
+    $new_htaccess .=  "  RewriteRule $site_path/$drupal_dir/(.*) $drupal_dir/$1\n";
   }
+  $new_htaccess .= "  # %UNL_END_SITE_ID_$site_id%\n\n" 
+                 . $stub_token
+                 . substr($htaccess, $stub_pos + strlen($stub_token));
   
-  $command = "$php_path sites/all/modules/drush/drush.php -y --uri=$uri site-install unl_profile --sites-subdir=$sites_subdir --db-url=$db_url --db-prefix=$db_prefix --clean-url=$clean_url";
-  
-  if ($subdir) {
-    mkdir($subdir, 0755, TRUE);
-  }
-  symlink($symlink_target, DRUPAL_ROOT . '/' . $subdir . '/' . $symlink_name);
-  shell_exec($command);
+  file_put_contents(DRUPAL_ROOT . '/.htaccess', $new_htaccess);
+  return TRUE;
 }
 
-function unl_remove_site($site_path, $uri, $db_prefix) {
+function unl_remove_site($site_path, $uri, $db_prefix, $site_id) {
   $schema = drupal_get_schema();
   $tables = array_keys($schema);
   sort($tables);
@@ -109,10 +111,7 @@ function unl_remove_site($site_path, $uri, $db_prefix) {
   $db_prefix .= '_' . $database['prefix'];
   
   
-  $path_parts = parse_url($uri);
-  $sites_subdir = $path_parts['host'] . $path_parts['path'];
-  $sites_subdir = strtr($sites_subdir, array('/' => '.'));
-
+  $sites_subdir = _unl_get_sites_subdir($uri);
   $sites_subdir = DRUPAL_ROOT . '/sites/' . $sites_subdir;
   $sites_subdir = realpath($sites_subdir);
   
@@ -124,7 +123,7 @@ function unl_remove_site($site_path, $uri, $db_prefix) {
   if (strlen($sites_subdir) <= strlen(DRUPAL_ROOT . '/sites/')) {
     return FALSE;
   }
- 
+
   foreach ($tables as $table) {
     $table = $db_prefix . $table;
     try {
@@ -137,16 +136,35 @@ function unl_remove_site($site_path, $uri, $db_prefix) {
   shell_exec('chmod -R u+w ' . escapeshellarg($sites_subdir));
   shell_exec('rm -rf ' . escapeshellarg($sites_subdir));
   
+  // Remove the rewrite rules from .htaccess for this site.
+  $htaccess = file_get_contents(DRUPAL_ROOT . '/.htaccess');
+  $site_start_token = "\n  # %UNL_START_SITE_ID_$site_id%";
+  $site_end_token = "  # %UNL_END_SITE_ID_$site_id%\n";
   
-  $subdir = explode('/', $site_path);
-  $symlink_name = array_pop($subdir);
-  $subdir_levels = count($subdir);
-  $subdir = implode('/', $subdir);
-  unlink(DRUPAL_ROOT . '/' . $subdir . '/' . $symlink_name);
+  $start_pos = strpos($htaccess, $site_start_token);
+  $end_pos = strpos($htaccess, $site_end_token);
+  
+  if ($start_pos === FALSE || $end_pos === FALSE) {
+    return FALSE;
+  }
+  $new_htaccess = substr($htaccess, 0, $start_pos)
+                . substr($htaccess, $end_pos + strlen($site_end_token))
+                ;
+  file_put_contents(DRUPAL_ROOT . '/.htaccess', $new_htaccess);
   
   return TRUE;
 }
 
+function _unl_get_sites_subdir($uri) {
+  $path_parts = parse_url($uri);
+  if (substr($path_parts['host'], -7) == 'unl.edu') {
+    $path_parts['host'] = 'unl.edu';
+  }
+  $sites_subdir = $path_parts['host'] . $path_parts['path'];
+  $sites_subdir = strtr($sites_subdir, array('/' => '.')); 
+  
+  return $sites_subdir;
+}
 
 
 
diff --git a/sites/all/modules/unl/unl_migration.php b/sites/all/modules/unl/unl_migration.php
index 768d90d6131a7b2069f43a517fb95048e57561f2..aaf65715ff6c92b399de3b78e383109977c4206f 100644
--- a/sites/all/modules/unl/unl_migration.php
+++ b/sites/all/modules/unl/unl_migration.php
@@ -41,21 +41,18 @@ function unl_migration($form, &$form_state)
 
 function unl_migration_submit($form, &$form_state)
 {
-    Unl_Migration_Tool::migrate($form_state['values']['site_url'],
-                                $form_state['values']['frontier_path'],
-                                $form_state['values']['frontier_user'],
-                                $form_state['values']['frontier_pass']);
+    $migration = new Unl_Migration_Tool(
+      $form_state['values']['site_url'],
+      $form_state['values']['frontier_path'],
+      $form_state['values']['frontier_user'],
+      $form_state['values']['frontier_pass']
+    );
+    while (!$migration->migrate());
 }
 
 
 class Unl_Migration_Tool
 {
-    static public function migrate($baseUrl, $frontierPath, $frontierUser, $frontierPass)
-    {
-        $instance = new self($baseUrl, $frontierPath, $frontierUser, $frontierPass);
-        return $instance->_migrate();
-    }
-
     /**
      * base url to the site to migrate, eg: http://www.unl.edu/band/
      *
@@ -78,6 +75,7 @@ class Unl_Migration_Tool
     private $_siteMap            = array();
     private $_processedPages     = array();
     private $_content            = array();
+    private $_createdContent     = array();
     private $_lastModifications  = array();
     private $_hrefTransform      = array();
     private $_hrefTransformFiles = array();
@@ -87,7 +85,17 @@ class Unl_Migration_Tool
     private $_log                = array();
     private $_blocks             = array();
     
-    private function __construct($baseUrl, $frontierPath, $frontierUser, $frontierPass)
+    /**
+     * Keep track of the state of the migration progress so that we can resume later
+     * @var int
+     */
+    private $_state           = self::STATE_NONE;
+    const STATE_NONE             = 1;
+    const STATE_PROCESSING_PAGES = 2;
+    const STATE_CREATING_NODES   = 3;
+    const STATE_DONE             = 4;
+    
+    public function __construct($baseUrl, $frontierPath, $frontierUser, $frontierPass)
     {
         header('Content-type: text/plain');
 
@@ -108,52 +116,76 @@ class Unl_Migration_Tool
         $this->_frontierScan('/');
     }
     
-    private function _migrate()
+    public function migrate($time_limit = 1)
     {
+        $start_time = time();
         ini_set('memory_limit', -1);
+                
+        if ($this->_state == self::STATE_NONE) {
+            // Parse the menu
+            $this->_processMenu();
+            $this->_process_blocks();
+            $this->_state = self::STATE_PROCESSING_PAGES;
+        }
         
-        // Parse the menu
-        $this->_processMenu();
-        $this->_process_blocks();
-        
-        // Process all of the pages on the site
-        do {
-            set_time_limit(30);
-            
-            $pagesToProcess = $this->_getPagesToProcess();
-            foreach ($pagesToProcess as $pageToProcess) {
-                $this->_processPage($pageToProcess);
-            }
-            //if ($i++ == 2) break;
-        } while (count($pagesToProcess) > 0);
+        if ($this->_state == self::STATE_PROCESSING_PAGES) {
+            // Process all of the pages on the site (Takes a while)
+            do {
+                set_time_limit(30);
+                
+                $pagesToProcess = $this->_getPagesToProcess();
+                foreach ($pagesToProcess as $pageToProcess) {
+                    if (time() - $start_time > $time_limit) {
+                        return FALSE;
+                    }
+                    $this->_processPage($pageToProcess);
+                }
+            } while (count($pagesToProcess) > 0);
+         
         
-        // Fix any links to files that got moved to sites/<site>/files
-        foreach ($this->_hrefTransform as $path => &$transforms) {
-            if (array_key_exists('', $transforms)) {
-                unset($transforms['']);
-            }
-            foreach ($transforms as $oldPath => &$newPath) {
-                if (array_key_exists($newPath, $this->_hrefTransformFiles)) {
-                    $newPath = $this->_hrefTransformFiles[$newPath];
+            // Fix any links to files that got moved to sites/<site>/files
+            foreach ($this->_hrefTransform as $path => &$transforms) {
+                if (array_key_exists('', $transforms)) {
+                    unset($transforms['']);
+                }
+                foreach ($transforms as $oldPath => &$newPath) {
+                    if (array_key_exists($newPath, $this->_hrefTransformFiles)) {
+                        $newPath = $this->_hrefTransformFiles[$newPath];
+                    }
                 }
             }
+           
+            $this->_state = self::STATE_CREATING_NODES;
         }
         
-        // Update links and then create new page nodes.
-        foreach ($this->_content as $path => $content) {
-            set_time_limit(30);
+        if ($this->_state == self::STATE_CREATING_NODES) {
+            // Update links and then create new page nodes. (Takes a while)
+            foreach ($this->_content as $path => $content) {
+                if (in_array($path, $this->_createdContent)) {
+                    continue;
+                }
+                if (time() - $start_time > $time_limit) {
+                    return FALSE;
+                }
+                set_time_limit(30);
+                
+                $hrefTransform = $this->_hrefTransform[$path];
+                
+                if (is_array($hrefTransform)) {
+                    $content = strtr($content, $hrefTransform);
+                }
+                $pageTitle = $this->_pageTitles[$path];
+                $this->_createPage($pageTitle, $content, $path, '' == $path);
+                $this->_createdContent[] = $path;
+            }
             
-            $hrefTransform = $this->_hrefTransform[$path];
+            $this->_createMenu();
+            $this->_create_blocks();
             
-            if (is_array($hrefTransform)) {
-                $content = strtr($content, $hrefTransform);
-            }
-            $pageTitle = $this->_pageTitles[$path];
-            $this->_createPage($pageTitle, $content, $path, '' == $path);
+            $this->_state = self::STATE_DONE;
         }
         
-        $this->_createMenu();
-        $this->_create_blocks();
+        return TRUE;
     }
     
     private function _addSitePath($path)
diff --git a/sites/all/modules/unl/unl_site_creation.php b/sites/all/modules/unl/unl_site_creation.php
index 3155a0829d8194c51f29819dd5b81993509f899b..91986d22e142b3b389e87a5024460d8cb37eab88 100644
--- a/sites/all/modules/unl/unl_site_creation.php
+++ b/sites/all/modules/unl/unl_site_creation.php
@@ -180,8 +180,7 @@ function unl_site_remove($site_id) {
   }
   $uri = $uri[0];
 
-  $path_parts = parse_url($uri);
-  $sites_subdir = $path_parts['host'] . $path_parts['path'];
+  $sites_subdir = _unl_get_sites_subdir($uri);
   $sites_subdir = strtr($sites_subdir, array('/' => '.'));
   $sites_subdir = DRUPAL_ROOT . '/sites/' . $sites_subdir;
   $sites_subdir = realpath($sites_subdir);
@@ -206,6 +205,16 @@ function unl_site_remove($site_id) {
   drupal_set_message('The site has been scheduled for removal.');
 }
 
+function _unl_get_sites_subdir($uri) {
+  $path_parts = parse_url($uri);
+  if (substr($path_parts['host'], -7) == 'unl.edu') {
+    $path_parts['host'] = 'unl.edu';
+  }
+  $sites_subdir = $path_parts['host'] . $path_parts['path'];
+  $sites_subdir = strtr($sites_subdir, array('/' => '.')); 
+  
+  return $sites_subdir;
+}
 
 
 
diff --git a/themes/bartik/bartik.info b/themes/bartik/bartik.info
index 7885faa2a4ce15acbeb841a253bed876d129fbfe..2010fec6ed6a5336671f7a55346e14f101642a59 100644
--- a/themes/bartik/bartik.info
+++ b/themes/bartik/bartik.info
@@ -36,8 +36,8 @@ regions[footer] = Footer
 settings[shortcut_module_link] = 0
 
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/bartik/color/color.inc b/themes/bartik/color/color.inc
index f71c9f44e7f6d18b10e0238880fb13fa3e650c4e..a94c13a95a0f55c4e8fef2bc9a2c47d32dd6c58e 100644
--- a/themes/bartik/color/color.inc
+++ b/themes/bartik/color/color.inc
@@ -1,5 +1,5 @@
 <?php
-// $Id: color.inc,v 1.3 2010/08/18 00:28:08 dries Exp $
+// $Id: color.inc,v 1.6 2010/09/28 02:29:27 dries Exp $
 
 // Put the logo path into JavaScript for the live preview.
 drupal_add_js(array('color' => array('logo' => theme_get_setting('logo', 'bartik'))), 'setting');
@@ -23,14 +23,14 @@ $info = array(
       'title' => t('Blue Lagoon (default)'),
       'colors' => array(
         'bg' => '#ffffff',
-        'link' => '#288cc9',
+        'link' => '#0071B3',
         'top' => '#0779bf',
         'bottom' => '#48a9e4',
         'text' => '#3b3b3b',
         'sidebar' => '#f6f6f2',
         'sidebarborders' => '#f9f9f9',
         'footer' => '#292929',
-        'titleslogan' => '#ffffff',
+        'titleslogan' => '#fffeff',
       ),
     ),
     'firehouse' => array(
@@ -124,7 +124,6 @@ $info = array(
   'blend_target' => '#ffffff',
 
   // Preview files.
-  'preview_image' => 'color/preview.png',
   'preview_css' => 'color/preview.css',
   'preview_js' => 'color/preview.js',
   'preview_html' => 'color/preview.html',
diff --git a/themes/bartik/css/colors.css b/themes/bartik/css/colors.css
index 911d8caed4fff8f1d0fdb0235763d6999ffefa97..31c742d7734883f9d4d9e7376fdf106eec60163f 100644
--- a/themes/bartik/css/colors.css
+++ b/themes/bartik/css/colors.css
@@ -1,4 +1,4 @@
-/* $Id: colors.css,v 1.5 2010/09/09 15:27:08 webchick Exp $ */
+/* $Id: colors.css,v 1.7 2010/10/05 01:48:11 dries Exp $ */
 
 /* ---------- Color Module Styles ----------- */
 
@@ -12,7 +12,8 @@ body.overlay {
   background-color: #ffffff;
   color: #3b3b3b;
 }
-#main-menu ul.links li.active-trail a {
+#main-menu-links li a.active,
+#main-menu-links li.active-trail a {
   background: #ffffff;
 }
 .tabs ul.primary li a.active {
@@ -28,7 +29,7 @@ body.overlay {
   background-image: -moz-linear-gradient(-90deg, #0779bf, #48a9e4);
 }
 a {
-  color: #288CC9;
+  color: #0071B3;
 }
 a:hover,
 a:focus {
@@ -44,6 +45,9 @@ a:active {
 #footer-wrapper {
   background: #292929;
 }
+.region-header,
+.region-header a,
+.region-header li a.active,
 #header #name-and-slogan,
 #header #name-and-slogan a,
 #secondary-menu-links li a {
diff --git a/themes/bartik/css/ie-rtl.css b/themes/bartik/css/ie-rtl.css
index 85836bc0f6358da48c6660d676111834751dcba0..d2cc4ccf38278cba561b9a617cdd8d764d080e8d 100644
--- a/themes/bartik/css/ie-rtl.css
+++ b/themes/bartik/css/ie-rtl.css
@@ -1,8 +1,28 @@
-/* $Id: ie-rtl.css,v 1.2 2010/08/22 13:58:29 dries Exp $ */
+/* $Id: ie-rtl.css,v 1.3 2010/10/05 01:48:11 dries Exp $ */
 
 fieldset legend {
   left: 6px;
 }
-ul.action-links li a {
+ul.action-links li a,
+#user-login-form li.openid-link a,
+#user-login li.openid-link a {
+  zoom: 1;
+}
+.region-header .block,
+.region-header #block-user-login .form-item {
+  float: none;
+  display: inline;
+  vertical-align: top;
+}
+.region-header #block-user-login .item-list li {
+  float: none;
+}
+.region-header #block-user-login .item-list li.last {
+  padding-right: 0;
+}
+#user-login-form li.openid-link a,
+#user-login li.openid-link a {
+  background-position: right -3px;
+  padding-right: 20px;
   zoom: 1;
 }
diff --git a/themes/bartik/css/ie.css b/themes/bartik/css/ie.css
index 3972f451de84aef2c540ac77f83306ec2bf78a99..ff0e767be1c7a0032758776b75cb965717fa1fb8 100644
--- a/themes/bartik/css/ie.css
+++ b/themes/bartik/css/ie.css
@@ -1,11 +1,8 @@
-/* $Id: ie.css,v 1.3 2010/09/02 20:43:18 dries Exp $ */
+/* $Id: ie.css,v 1.6 2010/10/05 01:48:11 dries Exp $ */
 
 .block {
   zoom: 1;
 }
-input.form-text {
-  font-family: sans-serif;
-}
 #password-strength-text {
   margin-top: 0;
 }
@@ -13,9 +10,6 @@ fieldset legend {
   left: -8px;
   padding: 0;
 }
-.tabs ul.primary {
-  height: auto;
-}
 #footer-wrapper #footer .block {
   height: 100%;
 }
@@ -24,3 +18,15 @@ fieldset legend {
   text-transform: capitalize; /* Trigger text indent. */
   height: 26px;
 }
+.meta {
+  margin-bottom: 10px;
+}
+.region-header .form-required {
+  color: #eee;
+}
+#search-block-form input.form-submit:hover,
+#search-block-form input.form-submit:focus,
+#search-form input.form-submit:hover,
+#search-form input.form-submit:focus {
+  background-position: center -25px;
+}
diff --git a/themes/bartik/css/ie6.css b/themes/bartik/css/ie6.css
index 980f7ed5dd1c04c2dd553eee8f160f98845bcfcd..9fbc9ce9f5fbf20e99c4dab86523e9cf493778fe 100644
--- a/themes/bartik/css/ie6.css
+++ b/themes/bartik/css/ie6.css
@@ -1,4 +1,4 @@
-/* $Id: ie6.css,v 1.2 2010/09/02 20:43:18 dries Exp $ */
+/* $Id: ie6.css,v 1.4 2010/10/05 01:48:11 dries Exp $ */
 
 #content {
   overflow: hidden;
@@ -6,9 +6,18 @@
 .form-item-search-block-form {
   width: 50%;
 }
-.tabs ul.primary {
+.tabs ul.primary,
+.region-header .block-menu li a {
   zoom: 1;
 }
 #block-search-form .form-item-search-block-form input {
   width: 67%;
 }
+.node-sticky {
+  background: transparent;
+  border: none;
+  padding: 0 0 15px;
+}
+.node-teaser {
+  border-bottom: 1px solid #d3d7d9;
+}
diff --git a/themes/bartik/css/layout-rtl.css b/themes/bartik/css/layout-rtl.css
index 6c31f87bf5221f27cd0100f86e410ea1acabb5b7..6e9c934e92cadd00a8348dbe02f3d122013606b8 100644
--- a/themes/bartik/css/layout-rtl.css
+++ b/themes/bartik/css/layout-rtl.css
@@ -1,4 +1,4 @@
-/* $Id: layout-rtl.css,v 1.3 2010/09/09 15:27:08 webchick Exp $ */
+/* $Id: layout-rtl.css,v 1.4 2010/10/05 01:48:11 dries Exp $ */
 
 /* ---------- Basic Layout RTL Styles ----------- */
 
@@ -13,6 +13,9 @@
 .region-footer-fourthcolumn {
   float: right;
 }
+.region-header {
+  float: left;
+}
 #secondary-menu {
   left: 0;
   right: auto;
diff --git a/themes/bartik/css/layout.css b/themes/bartik/css/layout.css
index 4e5e8351807ee3fb69e6bb5e81cbf2ae206bf04a..e3150f5308d5e134bcb3d38a531248553b9e3366 100644
--- a/themes/bartik/css/layout.css
+++ b/themes/bartik/css/layout.css
@@ -1,4 +1,4 @@
-/* $Id: layout.css,v 1.3 2010/09/09 15:27:08 webchick Exp $ */
+/* $Id: layout.css,v 1.4 2010/10/05 01:48:11 dries Exp $ */
 
 /* ---------- Basic Layout Styles ----------- */
 
@@ -16,9 +16,19 @@
 #header div.section {
   position: relative;
 }
+.region-header {
+  float: right; /* LTR */
+  margin: 0 5px 10px;
+}
+.with-secondary-menu .region-header {
+  margin-top: 3em;
+}
+.without-secondary-menu .region-header {
+  margin-top: 15px;
+}
 #secondary-menu {
   position: absolute;
-  right: 0;
+  right: 0; /* LTR */
   top: 0;
   width: 480px;
 }
diff --git a/themes/bartik/css/maintenance-page.css b/themes/bartik/css/maintenance-page.css
index f0aa0a7c679eb50c13af985b5f90fd7d7bf2861b..4b3b5fe914d7a702542f8880bfc9fdd083e96646 100644
--- a/themes/bartik/css/maintenance-page.css
+++ b/themes/bartik/css/maintenance-page.css
@@ -1,4 +1,4 @@
-/* $Id: maintenance-page.css,v 1.4 2010/09/09 15:27:08 webchick Exp $ */
+/* $Id: maintenance-page.css,v 1.5 2010/10/01 07:05:22 webchick Exp $ */
 
 body.maintenance-page {
   background-color: #fff;
@@ -37,16 +37,16 @@ body.maintenance-page {
   background-color: #fff;
   background-image: none;
 }
-.maintenance-page #header #name-and-slogan {
+.maintenance-page #name-and-slogan {
   margin-bottom: 50px;
   margin-left: 0;
   padding-top: 20px;
   font-size: 90%;
 }
-.maintenance-page #header #name-and-slogan,
-.maintenance-page #header #name-and-slogan a,
-.maintenance-page #header #name-and-slogan a:hover,
-.maintenance-page #header #name-and-slogan a:hover {
+.maintenance-page #name-and-slogan,
+.maintenance-page #name-and-slogan a,
+.maintenance-page #name-and-slogan a:hover,
+.maintenance-page #name-and-slogan a:hover {
   color: #777;
 }
 .maintenance-page  h1#page-title {
diff --git a/themes/bartik/css/style-rtl.css b/themes/bartik/css/style-rtl.css
index ca8f9c467d1b45dd6418e0b8dd85de3423ea2903..a31c9f23fd269d4f826d0c59b24193890a8e8de4 100644
--- a/themes/bartik/css/style-rtl.css
+++ b/themes/bartik/css/style-rtl.css
@@ -1,4 +1,4 @@
-/* $Id: style-rtl.css,v 1.7 2010/09/09 15:27:08 webchick Exp $ */
+/* $Id: style-rtl.css,v 1.11 2010/10/05 01:48:11 dries Exp $ */
 
 /* ------------------ Reset Styles ------------------ */
 
@@ -30,58 +30,38 @@ blockquote:after {
 ul.tips {
   padding: 0 1.25em 0 0;
 }
+.block ul {
+  padding: 0 1em 0.25em 0;
+}
 
 /* ------------------ Header ------------------ */
 
-#header #logo {
-  float: right;
-  padding: 15px 0 15px 30px;
+#logo {
+  padding: 15px 10px 15px 30px;
 }
-/* Menus when in the header region. */
-#header div.block-menu,
-#header div#block-system-main-menu {
+#logo,
+#name-and-slogan,
+.region-header .block,
+.region-header #block-user-login .form-item,
+.region-header #block-user-login .item-list li {
   float: right;
 }
-#header .block-menu li a,
-#header #block-system-main-menu li a {
-  float: right;
-  border-left: 1px solid #555;
-  border-right: none;
-}
-#header .block-menu li.first a,
-#header #block-system-main-menu li.first a {
-  padding-right: 0;
-  padding-left: 12px;
+.region-header .form-text {
+  margin-left: 2px;
+  margin-right: 0;
 }
-#header .block-menu li.last a,
-#header #block-system-main-menu li.last a {
+.region-header #block-user-login .item-list li.last {
   padding-left: 0;
-  padding-right: 12px;
-  border-left: none;
-}
-#header #block-search-form {
-  float: left;
+  padding-right: 0.5em;
 }
-#header #block-user-login {
-  left: 2%;
-  right: auto;
-  float: left;
-}
-#header #block-user-login .form-text {
-  margin-left: 5px;
-}
-#header #block-user-login .item-list ul li {
-  margin: 0 15px 0 5px;
-}
-#header #block-user-login .userbox {
-  margin-right: 10px;
+.region-header #block-user-login ul.openid-links li.last {
+  padding-right: 0;
 }
-
-/* --------------- Main Menu ------------ */
-
-#main-menu ul.links li.first {
-  padding-right: 2px;
+.region-header #user-login-form li.openid-link a,
+.region-header #user-login li.openid-link a {
+  background-position: right -3px;
   padding-left: 0;
+  padding-right: 20px;
 }
 
 /* --------------- Secondary Menu ------------ */
@@ -92,44 +72,44 @@ ul.tips {
 
 /* ----------------- Content ------------------ */
 
-#block-system-main .submitted .user-picture img {
+.submitted .user-picture img {
   float: right;
   margin-left: 5px;
   margin-right: 0;
 }
-#block-system-main div.field-name-taxonomy-tags div.field-label,
-#block-system-main div.field-name-taxonomy-tags div.field-items,
-#block-system-main div.field-name-taxonomy-tags div.field-item {
+.field-type-taxonomy-term-reference .field-label,
+.field-type-taxonomy-term-reference .field-items,
+.field-type-taxonomy-term-reference .field-item {
   float: right;
   padding-left: 10px;
   padding-right: 0;
 }
-#block-system-main .link-wrapper {
+.link-wrapper {
   margin-right: 236px;
   margin-left: 0;
 }
 
 /* ----------------- Comments ----------------- */
 
-#comment-wrapper div.user-picture img {
+.comment .user-picture img {
   margin-right: 0;
 }
-#comments .attribution {
+.comment .attribution {
   float: right;
 }
-#comments .comment-arrow {
+.comment .comment-arrow {
   background: url(../images/comment-arrow-rtl.png);
   margin-right: -45px;
 }
-#comments .comment-text {
+.comment .comment-text {
   margin-right: 140px;
   margin-left: 0;
 }
-#comments .indented {
+.comment .indented {
   margin-right: 40px;
   margin-left: 0;
 }
-#comments ul.links li {
+.comment ul.links li {
   padding: 0 0 0.5em;
 }
 
@@ -161,11 +141,8 @@ a.button {
 #search-form input#edit-keys,
 #block-search-form .form-item-search-block-form input {
   float: right;
-}
-#search-block-form input.form-submit,
-#search-form input.form-submit {
-  margin-left: 0;
-  margin-right: 5px;
+  margin-left: 5px;
+  margin-right: 0;
 }
 
 /* ------------------ Footer ------------------ */
@@ -236,15 +213,15 @@ html.js input.throbbing {
 }
 
 /* Comment form */
-#comment-form .form-type-textfield label,
-#comment-form .form-type-item label {
+.comment-form .form-type-textfield label,
+.comment-form .form-type-item label {
   float: right;
 }
-#comment-form .form-type-textfield input,
-#comment-form .form-item .username {
+.comment-form .form-type-textfield input,
+.comment-form .form-item .username {
   float: left;
 }
-#comment-form .form-item .description {
+.comment-form .form-item .description {
   float: left;
 }
 
diff --git a/themes/bartik/css/style.css b/themes/bartik/css/style.css
index 3cd9df8344710e4cccd0b589f09ab6267fad0e50..e46383e187c9ce23139433c3b74533d2a6032924 100644
--- a/themes/bartik/css/style.css
+++ b/themes/bartik/css/style.css
@@ -1,12 +1,12 @@
-/* $Id: style.css,v 1.13 2010/09/10 17:56:20 webchick Exp $ */
+/* $Id: style.css,v 1.22 2010/10/05 01:48:11 dries Exp $ */
 
 /* ---------- Overall Specifications ---------- */
 
 body,
 #preview {
   background-color: #fff;
-  line-height: 1.4em;
-  font-size: 0.8em;
+  line-height: 1.5;
+  font-size: 87.5%;
   word-wrap: break-word;
   margin: 0;
   padding: 0;
@@ -39,12 +39,12 @@ h6,
 }
 h1,
 #preview h1 {
-  font-size: 140%;
+  font-size: 1.357em;
   color: #000;
 }
 h2,
-#preview h1 {
-  font-size: 120%;
+#preview h2 {
+  font-size: 1.143em;
 }
 p,
 #preview p {
@@ -132,9 +132,12 @@ a.feed-icon {
 
 table {
   border-spacing: 0;
-  font-size: 0.85em;
   width: 100%;
   margin: 10px 0;
+  font-size: 0.857em;
+}
+table table {
+  font-size: 1em;
 }
 #footer-wrapper table {
   font-size: 1em;
@@ -167,12 +170,13 @@ tr,
 tr.even {
   background-color: #efefef;
 }
-#block-system-main table ul.links {
-  font-size: 1em;
+table ul.links {
   margin: 0;
   padding: 0;
+  font-size: 1em;
+}
 }
-#block-system-main table ul.links li {
+table ul.links li {
   padding: 0 1em 0 0;
 }
 
@@ -180,10 +184,19 @@ tr.even {
 
 .block ul {
   margin: 0;
+  padding: 0 0 0.25em 1em; /* LTR */
+}
+.contextual-links-wrapper {
+  font-size: small !important;
+}
+ul.contextual-links {
+  font-size: 0.923em;
+}
+.contextual-links-wrapper a {
+  text-shadow: 0 0 0 !important;
 }
-ul.contextual-links,
 .item-list .pager {
-  font-size: 90%;
+  font-size: 0.929em;
 }
 ul.menu li {
   margin: 0;
@@ -202,7 +215,6 @@ ul.tips {
 }
 
 /* ------------------ Header ------------------ */
-
 #skip-link {
   left: 50%;
   margin-left: -5.25em;
@@ -243,156 +255,191 @@ ul.tips {
   position: static;
   width: auto;
 }
-#header,
-#preview #preview-header {
-  color: #fff;
-}
-#header a,
-#preview #preview-header a {
-  color: #fff;
-}
-#header #logo,
+#logo,
 #preview #preview-header #preview-logo {
   float: left; /* LTR */
-  padding: 15px 30px 15px 0; /* LTR */
+  padding: 15px 30px 15px 10px; /* LTR */
 }
-#header #name-and-slogan,
+#name-and-slogan {
+  float: left; /* LTR */
+}
+#name-and-slogan,
 #preview #preview-header #preview-name-and-slogan {
-  padding-top: 38px;
+  padding-top: 34px;
   margin-bottom: 30px;
-  margin-left: 15px;
 }
-#header #site-name,
+#site-name,
 #preview #preview-header #preview-site-name {
-  font-size: 200%;
+  font-size: 1.821em;
   color: #686868;
+  line-height: 1;
 }
-#header h1#site-name,
+h1#site-name,
 #preview #preview-header h1#preview-site-name {
   margin: 0;
 }
-#header #site-name a,
+#site-name a,
 #preview-header #preview-site-name a {
   font-weight: normal;
 }
-#header #site-slogan {
+#site-slogan {
+  font-size: 0.929em;
   margin-top: 7px;
-  font-size: 100%;
   word-spacing: 0.1em;
   font-style: italic;
 }
-/* Menus when in the header region. */
-#header .block-menu {
-  height: 1.1em;
-  margin: 10px 0;
-  font-size: 120%;
+/* Region header blocks. */
+.region-header .block {
+  font-size: 0.857em;
   float: left; /* LTR */
-  width: 75%;
+  margin: 0 10px;
+  padding: 0;
 }
-#header .block ul, /* Any menu block in the header region. */
-#header .block li {
-  list-style: none;
+.region-header .block .content {
   margin: 0;
   padding: 0;
 }
-#header .block-menu li a {
-  float: left; /* LTR */
-  padding: 0 12px;
-  display: block;
-  border-right: 1px solid #555; /* LTR */
+.region-header .block ul {
+  margin: 0;
+  padding: 0;
 }
-#header .block-menu li.first a {
-  padding-left: 0; /* LTR */
+.region-header .block li {
+  list-style: none;
+  list-style-image: none;
+  padding: 0;
 }
-#header .block-menu li.last a {
-  padding-right: 0; /* LTR */
-  border-right: none; /* LTR */
+.region-header .form-text {
+  background: #fefefe;
+  background: rgba(255, 255, 255, 0.7);
+  border-color: #ccc;
+  border-color: rgba(255, 255, 255, 0.3);
+  margin-right: 2px; /* LTR */
+  width: 120px;
+}
+.region-header .form-text:hover,
+.region-header .form-text:focus,
+.region-header .form-text:active {
+  background: #fff;
+  background: rgba(255, 255, 255, 0.8);
 }
-#header #block-search-form { /* Search block in the Header region. */
-  float: right; /* LTR */
-  width: 24%;
-  margin: 8px 0;
+.region-header .form-required {
+  color: #eee;
+  color: rgba(255, 255, 255, 0.7);
+}
+/* Region header block menus. */
+.region-header .block-menu {
+  border: 1px solid;
+  border-color: #eee;
+  border-color: rgba(255, 255, 255, 0.2);
+  padding: 0;
+  width: 208px;
 }
-#header #block-user-login { /* Login block in the Header region. */
+.region-header .block-menu li a {
   display: block;
-  position: absolute;
-  top: 0;
-  right: 2%; /* LTR */
-  background: #464748;
-  color: #fff;
-  float: right; /* LTR */
-  font-size: 13px;
-  padding: 4px 10px 5px;
-  text-transform: uppercase;
-  font-size: 80%;
+  border-bottom: 1px solid;
+  border-bottom-color: #eee;
+  border-bottom-color: rgba(255, 255, 255, 0.2);
+  padding: 3px 7px;
+}
+.region-header .block-menu li a:hover,
+.region-header .block-menu li a:focus,
+.region-header .block-menu li a:active {
+  text-decoration: none;
+  background: rgba(255, 255, 255, 0.15)
 }
-#header #block-user-login a {
-  color: #fff;
-  font-size: 90%;
+.region-header .block-menu li.last a {
+  border-bottom: 0;
 }
-#header #block-user-login .form-item label {
-  display: inline;
-  font-weight: normal;
+/* User Login block in the header region */
+.region-header #block-user-login {
+  width: auto;
 }
-#header #block-user-login .form-item {
-  display: inline;
-  font-weight: normal;
+.region-header #block-user-login .content {
+  margin-top: 2px;
 }
-#header #block-user-login .form-text {
-  margin-right: 5px; /* LTR */
+.region-header #block-user-login .form-item {
+  float: left; /* LTR */
+  margin: 0;
+  padding: 0;
 }
-#header #block-user-login .form-item label .form-required {
-  display: none;
+.region-header #block-user-login div.item-list,
+.region-header #block-user-login div.description {
+  font-size: 0.916em;
+  margin: 0;
 }
-#header #block-user-login div.item-list,
-#header #block-user-login .item-list ul {
-  display: inline;
+.region-header #block-user-login div.item-list {
+  clear: both;
 }
-#header #block-user-login .item-list ul li {
+.region-header #block-user-login div.description {
   display: inline;
-  margin: 0 5px 0 15px; /* LTR */
 }
-#header #block-user-login div.item-list {
-  margin-top: 5px;
-  font-style: italic;
-  font-size: 130%;
-  text-transform: none;
+.region-header #block-user-login .item-list ul {
+  padding: 0;
+  line-height: 1;
 }
-#header #block-user-login .userbox {
-  margin-left: 10px; /* LTR */
+.region-header #block-user-login .item-list li {
+  list-style: none;
+  float: left; /* LTR */
+  padding: 3px 0 1px;
 }
-#header #block-user-login input.form-submit {
-  color: #fff;
-  background: #929599;
-  border: 1px solid #73767c;
-  padding: 1px;
-  text-transform: uppercase;
-  margin-top: 1px;
-  position: relative;
-  display: inline;
+.region-header #block-user-login .item-list li.last {
+  padding-left: 0.5em; /* LTR */
 }
-#header #block-user-login #user-login-form div.item-list { /* Hide create new account + email replacement password links. */
-  display: none;
+.region-header #block-user-login ul.openid-links li.last {
+  padding-left: 0; /* LTR */
+}
+.region-header #user-login-form li.openid-link a,
+.region-header #user-login li.openid-link a {
+  padding-left: 20px; /* LTR */
+}
+.region-header #block-user-login .form-actions {
+  margin: 4px 0 0;
+  padding: 0;
+  clear: both
+}
+.region-header #block-user-login input.form-submit {
+  border: 1px solid;
+  border-color: #ccc;
+  border-color: rgba(255, 255, 255, 0.5);
+  background: #eee;
+  background: rgba(255, 255, 255, 0.7);
+  margin: 4px 0;
+  padding: 3px 8px;
+}
+.region-header #block-user-login input.form-submit:hover,
+.region-header #block-user-login input.form-submit:focus {
+  background: #fff;
+  background: rgba(255, 255, 255, 0.9);
+}
+/* Search block in region header. */
+.region-header #block-search-form {
+  width: 208px;
+}
+.region-header #block-search-form .form-text {
+  width: 154px;
+}
+/* Language switcher block in region header. */
+#block-locale-language ul li {
+  display: inline;
+  padding: 0 0.5em;
 }
 
 /* --------------- Main Menu ------------ */
 
 #main-menu {
-  padding: 0 15px;
+  padding: 0 15px 3px;
   clear: both;
 }
-#main-menu a {
+#main-menu-links a {
   color: #d9d9d9;
   padding: 0.6em 1em 0.4em;
 }
-#main-menu ul {
+#main-menu-links {
+  font-size: 0.929em;
   padding: 2px 0;
+  padding: 0;
 }
-#main-menu ul.links {
-  font-size: 105%;
-  padding: 0.6em 0.6em 4px;
-}
-#main-menu ul.links li a {
+#main-menu-links a {
   color: #333;
   background: #ccc;
   background: rgba(255, 255, 255, 0.7);
@@ -406,36 +453,35 @@ ul.tips {
   -webkit-border-top-right-radius: 8px;
   border-top-right-radius: 8px;
 }
-#main-menu ul.links li a:hover,
-#main-menu ul.links li a:focus {
+#main-menu-links a:hover,
+#main-menu-links a:focus {
   background: #fff;
   background: rgba(255, 255, 255, 0.95);
 }
-#main-menu ul.links li a:active {
+#main-menu-links a:active {
   background: #b3b3b3;
   background: rgba(255, 255, 255, 1);
 }
-#main-menu ul.links li.active-trail a {
+#main-menu-links li a.active {
   border-bottom: none;
 }
-.featured #main-menu ul.links li.active-trail a {
+.featured #main-menu-links li a.active,
+.featured #main-menu-links li.active-trail a {
   background: #f0f0f0;
   background: rgba(240, 240, 240, 1.0);
 }
-#main-menu ul.links li {
+#main-menu-links li {
   display: inline;
   list-style-type: none;
   padding: 0.6em 0 0.4em;
 }
-#main-menu ul.links li.first {
-  padding-left: 2px; /* LTR */
-}
 
 /* --------------- Secondary Menu ------------ */
 
 #secondary-menu-links {
   float: right; /* LTR */
-  margin: 10px;
+  font-size: 0.929em;
+  margin: 10px 10px 0;
 }
 #secondary-menu-links a:hover,
 #secondary-menu-links a:focus {
@@ -454,15 +500,19 @@ ul.tips {
 
 #featured {
   text-align: center;
-  font-size: 180%;
+  font-size: 1.643em;
   font-weight: normal;
-  line-height: 1.4em;
-  padding: 50px 0 45px;
+  line-height: 1.4;
+  padding: 20px 0 45px;
   margin: 0;
   background: #f0f0f0;
   border-bottom: 1px solid #e7e7e7;
   text-shadow: 1px 1px #fff;
 }
+#featured h2 {
+  font-size: 1.174em;
+  line-height: 1;
+}
 #featured p {
   margin: 0;
   padding: 0;
@@ -471,126 +521,128 @@ ul.tips {
 /* ----------------- Content ------------------ */
 
 .content {
-  margin-top: 1em;
+  margin-top: 10px;
 }
-#block-system-main,
 #preview #preview-block-system-main {
-  font-size: 115%;
-  line-height: 1.5em;
-}
-body.page-admin-appearance-settings-bartik #block-system-main {
-  font-size: 100%;
+  line-height: 1.5;
 }
 h1#page-title,
 #preview h1#preview-page-title {
-  font-size: 220%;
-  line-height: 1.2em;
+  font-size: 2em;
+  line-height: 1;
 }
-#block-system-main h2,
+#content h2,
 #preview #preview-block-system-main h2 {
   margin-bottom: 2px;
-  font-size: 137%;
-  line-height: 1.4em;
+  font-size: 1.429em;
+  line-height: 1.4;
+}
+.node .content {
+  font-size: 1.071em;
+}
+.node-teaser .content {
+  font-size: 1em;
 }
-#block-system-main .node-teaser h2 a {
+.node-teaser h2 a {
   color: #181818;
 }
-#block-system-main .node-teaser {
+.node-teaser {
   border-bottom: 1px solid #d3d7d9;
   margin-bottom: 30px;
   padding-bottom: 15px;
 }
-#block-system-main .node-teaser .content {
-  font-size: 92%;
-  line-height: 1.65em;
+.node-teaser.node-sticky {
+  background: #f9f9f9;
+  background: rgba(0, 0, 0, 0.024);
+  border: 1px solid #d3d7d9;
+  padding: 0 15px 15px;
+}
+.node-teaser .content {
   color: #3b3b3b;
   clear: none;
+  line-height: 1.6;
 }
-#block-system-main .meta {
-  font-size: 80%;
+.meta {
+  font-size: 0.857em;
   color: #68696b;
   margin-bottom: -5px;
 }
-* html #block-system-main .meta {
-  margin-bottom: 10px;
-}
-*:first-child+html #block-system-main .meta {
-  margin-bottom: 10px;
-}
-#block-system-main .submitted .user-picture img {
+.submitted .user-picture img {
   float: left; /* LTR */
   height: 20px;
   margin: 1px 5px 0 0; /* LTR */
 }
-#block-system-main div.field-type-taxonomy-term-reference div.field-label,
-#block-system-main div.field-type-taxonomy-term-reference div.field-items,
-#block-system-main div.field-type-taxonomy-term-reference div.field-item {
+.field-type-taxonomy-term-reference .field-label,
+.field-type-taxonomy-term-reference .field-items,
+.field-type-taxonomy-term-reference .field-item {
   display: inline;
   float: left; /* LTR */
   padding-right: 10px; /* LTR */
   font-weight: normal;
 }
-#block-system-main div.field-name-field-tags div.field-label {
-  font-size: 86%;
+.field-type-taxonomy-term-reference div.field-label {
+  font-size: 0.857em;
   color: #68696b;
 }
-#block-system-main div.field-name-field-tags div.field-items,
-#block-system-main div.field-name-field-tags div.field-item {
-  font-size: 95%;
+.field-type-taxonomy-term-reference .field-items,
+.field-type-taxonomy-term-reference .field-item {
+  font-size: 0.929em;
 }
-#block-system-main div.field-name-field-tags a:hover,
-#block-system-main div.field-name-field-tags a:focus {
+.field-type-taxonomy-term-reference a:hover,
+.field-type-taxonomy-term-reference a:focus {
   text-decoration: underline;
 }
-#block-system-main .link-wrapper {
+.link-wrapper {
   text-align: right;
 }
-#block-system-main ul.links {
-  color: #68696b;
-  font-size: 80%;
-}
-#block-system-main .field-type-image img,
-#block-system-main .user-picture img {
+.field-type-image img,
+.user-picture img {
   margin: 0 0 1em;
 }
+ul.links {
+  color: #68696b;
+  font-size: 0.821em;
+}
 
 /* ----------------- Comments ----------------- */
 
-#comment-wrapper {
-  border-top: 1px solid #d3d7d9;
-  padding-top: 15px;
-}
-#comments h2.title {
+.comment h2.title {
   margin-bottom: 1em;
 }
-#comments div.user-picture img {
+.comment div.user-picture img {
   margin-left: 0; /* LTR */
 }
-#comments .comment {
+.comment {
   margin-bottom: 20px;
   position: relative;
 }
-#comments .attribution {
+.comment .attribution {
+  padding-top: 20px;
   float: left; /* LTR */
   width: 110px;
 }
-#comments .attribution img {
+.comment .attribution img {
   margin: 0;
   border: 1px solid #d3d7d9;
 }
-#comments .submitted p {
+.comment .submitted p {
   margin: 4px 0;
-  font-size: 110%;
-  line-height: 1.2em;
+  font-size: 1.071em;
+  line-height: 1.2;
 }
-#comments .submitted .comment-time {
-  font-size: 70%;
+.comment .submitted .comment-time {
+  font-size: 0.786em;
   color: #68696b;
 }
-#comments .content {
-  font-size: 90%;
+.comment .submitted .comment-permalink {
+  font-size: 0.786em;
+  text-transform: lowercase;
+}
+.comment .content {
+  font-size: 0.929em;
+  line-height: 1.6;
 }
-#comments .comment-arrow {
+.comment .comment-arrow {
   background: url(../images/comment-arrow.png); /* LTR */
   height: 40px;
   width: 20px;
@@ -598,27 +650,29 @@ h1#page-title,
   margin-top: 10px;
   position: absolute;
 }
-#comments .comment-text {
+.comment .comment-text {
   margin-left: 140px; /* LTR */
   padding: 10px 25px;
   border: 1px solid #d3d7d9;
 }
-#comments .indented {
+.comment .indented {
   margin-left: 40px; /* LTR */
 }
-#comments ul.links {
+.comment ul.links {
   padding: 0 0 0.25em 0;
 }
-#comments ul.links li {
+.comment ul.links li {
   padding: 0 0.5em 0 0; /* LTR */
 }
 
 /* ------------------ Sidebar ----------------- */
-
+.sidebar .section {
+  padding-top: 10px;
+}
 .sidebar .block {
   border: 1px solid;
   padding: 15px 20px;
-  margin: 20px 0;
+  margin: 0 0 20px;
 }
 .sidebar h2,
 #preview .sidebar h2 {
@@ -626,6 +680,12 @@ h1#page-title,
   border-bottom: 1px solid #d6d6d6;
   padding-bottom: 5px;
   text-shadow: 0 1px 0 #fff;
+  font-size: 1.071em;
+  line-height: 1.2;
+}
+.sidebar .block .content {
+  font-size: 0.914em;
+  line-height: 1.4;
 }
 .sidebar tbody {
   border: none;
@@ -644,16 +704,17 @@ h1#page-title,
 }
 #triptych h2 {
   color: #000;
-  font-size: 194%;
-  margin-bottom: .8em;
+  font-size: 1.714em;
+  margin-bottom: 0.8em;
   text-shadow: 0px 1px 0 #fff;
   text-align: center;
-  line-height: 1.2em;
+  line-height: 1;
 }
 #triptych .block {
   margin-bottom: 2em;
   padding-bottom: 2em;
   border-bottom: 1px solid #dfdfdf;
+  line-height: 1.3;
 }
 #triptych .block.last {
   border-bottom: none;
@@ -695,7 +756,7 @@ h1#page-title,
 #footer-wrapper {
   color: #c0c0c0;
   color: rgba(255,255,255,0.65);  
-  font-size: 90%;
+  font-size: 0.857em;
 }
 #footer-wrapper a {
   color: #fcfcfc;
@@ -730,7 +791,7 @@ h1#page-title,
 #footer-columns h2 {
   border-bottom: 1px solid #555;
   border-color: rgba(255,255,255,0.15);  
-  font-size: 104%;
+  font-size: 1em;
   margin-bottom: 0;
   padding-bottom: 3px;
   text-transform: uppercase;
@@ -755,7 +816,7 @@ h1#page-title,
   display: block;
   border-bottom: 1px solid #555;
   border-color: rgba(255,255,255,0.15);  
-  line-height: 1.2em;
+  line-height: 1.2;
   padding: 0.8em 2px 0.8em 20px; /* LTR */
   text-indent: -15px;
 }
@@ -766,7 +827,6 @@ h1#page-title,
   text-decoration: none;
 }
 #footer {
-  font-size: 92%;
   letter-spacing: 0.2px;
   margin-top: 30px;
   border-top: 1px solid #555;
@@ -832,8 +892,9 @@ h1#page-title,
   color: #000;
   background-color: #ededed;
   height: 1.8em;
-  line-height: 1.8em;
+  line-height: 1.9;
   display: block;
+  font-size: 0.929em;
   float: left; /* not LTR */
   padding: 0 10px 3px;
   margin: 0;
@@ -903,7 +964,7 @@ div.messages {
 /* -------------- Breadcrumbs   -------------- */
 
 .breadcrumb {
-  font-size:92%;
+  font-size: 0.929em;
 }
 
 /* -------------- User Profile   -------------- */
@@ -945,7 +1006,7 @@ a.button {
   border-right-color: #d2d2d2;
   color: #3a3a3a;
   cursor: pointer;
-  font-size: 90%;
+  font-size: 0.929em;
   font-weight: normal;
   text-align: center;
   margin-bottom: 1em;
@@ -1011,7 +1072,7 @@ fieldset legend {
   height: 2em;
   left: -1px; /* LTR */
   font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
-  line-height: 2em;
+  line-height: 2;
   padding: 0;
   position: absolute;
   text-indent: 10px;
@@ -1048,6 +1109,13 @@ input {
   margin: 2px 0;
   padding: 4px;
 }
+input,
+textarea {
+  font-size: 0.929em;
+}
+textarea {
+  line-height: 1.5;
+}
 textarea.form-textarea,
 select.form-select {
   padding: 4px;
@@ -1069,17 +1137,22 @@ input.form-submit:focus {
   margin-top: 2px;
 }
 .form-item label {
-  font-size: 90%;
-}
-.form-radio {
-  margin-right: 4px;
+  font-size: 0.929em;
 }
 fieldset .description {
   margin-top: 5px;
-  line-height: 1.4em;
+  line-height: 1.4;
   color: #3c3c3c;
   font-style: italic;
 }
+.form-type-radio label,
+.form-type-checkbox label {
+  margin-left: 4px;
+}
+.form-type-radio .description,
+.form-type-checkbox .description {
+  margin-left: 2px;
+}
 .form-actions {
   padding-top: 10px;
 }
@@ -1093,16 +1166,16 @@ html.js input.throbbing {
 }
 
 /* Comment form */
-#comment-form .form-item {
+.comment-form .form-item {
   overflow: hidden;
   margin-bottom: .8em;
 }
-#comment-form .form-type-textfield label,
-#comment-form .form-type-item label {
+.comment-form .form-type-textfield label,
+.comment-form .form-type-item label {
   float: left; /* LTR */
 }
-#comment-form .form-type-textfield input,
-#comment-form .form-item .username {
+.comment-form .form-type-textfield input,
+.comment-form .form-item .username {
   float: right; /* LTR */
   width: 75%;
   -khtml-border-radius: 4px;
@@ -1110,13 +1183,13 @@ html.js input.throbbing {
   -webkit-border-radius: 4px;
   border-radius: 4px;
 }
-#comment-form .form-item .description {
-  font-size: .75em;
-  line-height: 1em;
+.comment-form .form-item .description {
+  font-size: 0.786em;
+  line-height: 1;
   float: right; /* LTR */
   width: 76%;
 }
-#comment-form .form-textarea {
+.comment-form .form-textarea {
   -khtml-border-radius-topleft: 4px;
   -khtml-border-radius-topright: 4px;
   -webkit-border-top-left-radius: 4px;
@@ -1126,13 +1199,13 @@ html.js input.throbbing {
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
 }
-#comment-form fieldset.filter-wrapper .fieldset-wrapper,
-#comment-form .text-format-wrapper .form-item {
+.comment-form fieldset.filter-wrapper .fieldset-wrapper,
+.comment-form .text-format-wrapper .form-item {
   margin-top: 0;
   margin-bottom: 0;
 }
-#comment-form fieldset.filter-wrapper .tips {
-  font-size: .75em;
+.comment-form fieldset.filter-wrapper .tips {
+  font-size: 0.786em;
 }
 
 /* -------------- Other Overrides ------------- */
@@ -1150,6 +1223,12 @@ div.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane {
 #forum tr td.forum {
   padding-left: 35px;
 }
+#forum .name {
+  font-size: 1.083em;
+}
+#forum .description {
+  font-size: 1em;
+}
 
 /* --------------- Search Form ---------------- */
 
@@ -1162,18 +1241,29 @@ div.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane {
 #search-form input#edit-keys,
 #block-search-form .form-item-search-block-form input {
   float: left; /* LTR */
+  font-size: 1em;
+  height: 1.143em;
+  margin-right: 5px;
+  width: 9em;
 }
 #search-block-form input.form-submit,
 #search-form input.form-submit {
-  margin-left: 5px; /* LTR */
-  margin-right: 0; /* LTR */
+  margin-left: 0;
+  margin-right: 0;
   height: 25px;
   width: 34px;
   padding: 0;
   cursor: pointer;
   text-indent: -9999px;
-  border: 1px solid #ccc;
-  background: url(../images/search-button.png) no-repeat center center;
+  border-color: #e4e4e4 #d2d2d2 #b4b4b4;
+  background: url(../images/search-button.png) no-repeat center top;
+  overflow: hidden;
+}
+#search-block-form input.form-submit:hover,
+#search-block-form input.form-submit:focus,
+#search-form input.form-submit:hover,
+#search-form input.form-submit:focus {
+  background-position: center bottom;
 }
 #search-form .form-item-keys label {
   display: block;
@@ -1197,7 +1287,7 @@ div.add-or-remove-shortcuts {
 
 /* ---------- Admin-specific Theming ---------- */
 
-.page-admin #block-system-main img {
+.page-admin #content img {
   margin-right: 15px; /* LTR */
 }
 .page-admin-structure-block-demo .block-region {
@@ -1282,7 +1372,7 @@ div.admin-panel .description {
   margin: 0;
 }
 .poll .percent {
-  font-size: 86%;
+  font-size: 0.857em;
   font-style: italic;
   margin-bottom: 3em;
   margin-top: -3.2em;
@@ -1293,14 +1383,11 @@ div.admin-panel .description {
   clear: right;
 }
 .poll .total {
-  font-size: 95%;
+  font-size: 0.929em;
   font-style: italic;
   text-align: right; /* LTR */
   clear: both;
 }
-.poll .form-item label {
-  font-size: 100%;
-}
 .node .poll {
   margin: 1.8em 0 0;
 }
@@ -1355,7 +1442,7 @@ div.admin-panel .description {
   left: -20px; /* LTR */
 }
 .color-form #preview {
-  font-size: .85em;
+  font-size: 0.857em;
 }
 .overlay #preview #footer-wrapper {
   display: block;
diff --git a/themes/bartik/template.php b/themes/bartik/template.php
index f9bdaf70e2218e406a939970d979def5210a43f8..657c3057c0819f86d6e787f2d4c16610806db81a 100644
--- a/themes/bartik/template.php
+++ b/themes/bartik/template.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: template.php,v 1.5 2010/09/01 02:13:58 dries Exp $
+// $Id: template.php,v 1.7 2010/10/05 19:59:10 dries Exp $
 
 /**
  * Add body classes if certain regions have content.
@@ -23,8 +23,8 @@ function bartik_preprocess_html(&$variables) {
   }
 
   // Add conditional stylesheets for IE
-  drupal_add_css(path_to_theme() . '/css/ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 7', '!IE' => FALSE)));
-  drupal_add_css(path_to_theme() . '/css/ie6.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'IE 6', '!IE' => FALSE)));
+  drupal_add_css(path_to_theme() . '/css/ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
+  drupal_add_css(path_to_theme() . '/css/ie6.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'IE 6', '!IE' => FALSE), 'preprocess' => FALSE));
 }
 
 /**
@@ -103,9 +103,8 @@ function bartik_process_maintenance_page(&$variables) {
  * Override or insert variables into the block template.
  */
 function bartik_preprocess_block(&$variables) {
-  // In the header region, visually hide the title of any menu block or of the
-  // user login block, but leave it accessible.
-  if ($variables['block']->region == 'header' && ($variables['block']->module == 'user' && $variables['block']->delta == 'login' || in_array('block-menu', $variables['classes_array']))) {
+  // In the header region visually hide block titles.
+  if ($variables['block']->region == 'header') {
     $variables['title_attributes_array']['class'][] = 'element-invisible';
   }
 }
diff --git a/themes/bartik/templates/comment-wrapper.tpl.php b/themes/bartik/templates/comment-wrapper.tpl.php
index d4c391f1d8b6bb8bed6f9dd6d7257e30e5828bdc..09b8e1c17282834064cc297730f54eeb77bf5b31 100644
--- a/themes/bartik/templates/comment-wrapper.tpl.php
+++ b/themes/bartik/templates/comment-wrapper.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment-wrapper.tpl.php,v 1.1 2010/07/06 05:25:51 webchick Exp $
+// $Id: comment-wrapper.tpl.php,v 1.2 2010/09/25 02:05:51 dries Exp $
 
 /**
  * @file
@@ -36,19 +36,17 @@
  * @see theme_comment_wrapper()
  */
 ?>
-<div id="comments-wrapper">
-  <div id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
-    <?php if ($content['comments'] && $node->type != 'forum'): ?>
-      <?php print render($title_prefix); ?>
-      <h2 class="title"><?php print t('Comments'); ?></h2>
-      <?php print render($title_suffix); ?>
-    <?php endif; ?>
+<div id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
+  <?php if ($content['comments'] && $node->type != 'forum'): ?>
+    <?php print render($title_prefix); ?>
+    <h2 class="title"><?php print t('Comments'); ?></h2>
+    <?php print render($title_suffix); ?>
+  <?php endif; ?>
 
-    <?php print render($content['comments']); ?>
+  <?php print render($content['comments']); ?>
 
-    <?php if ($content['comment_form']): ?>
-      <h2 class="title comment-form"><?php print t('Add new comment'); ?></h2>
-      <?php print render($content['comment_form']); ?>
-    <?php endif; ?>
-  </div>
+  <?php if ($content['comment_form']): ?>
+    <h2 class="title comment-form"><?php print t('Add new comment'); ?></h2>
+    <?php print render($content['comment_form']); ?>
+  <?php endif; ?>
 </div>
diff --git a/themes/bartik/templates/comment.tpl.php b/themes/bartik/templates/comment.tpl.php
index 4b36aabcc4d7c5e4573e0e58c103064504b350d2..920bd3b814316481524d9a2330066b29dc3efb4f 100644
--- a/themes/bartik/templates/comment.tpl.php
+++ b/themes/bartik/templates/comment.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: comment.tpl.php,v 1.1 2010/07/06 05:25:51 webchick Exp $
+// $Id: comment.tpl.php,v 1.3 2010/09/24 01:36:30 webchick Exp $
 
 /**
  * @file
@@ -63,13 +63,15 @@
     <?php print $picture; ?>
 
     <div class="submitted">
-      <?php print $permalink; ?>
       <p class="commenter-name">
         <?php print $author; ?>
       </p>
       <p class="comment-time">
         <?php print $created; ?>
       </p>
+      <p class="comment-permalink">
+        <?php print $permalink; ?>
+      </p>
     </div>
   </div>
 
diff --git a/themes/bartik/templates/page.tpl.php b/themes/bartik/templates/page.tpl.php
index 83aa3026cb420cc64246d693df89e4e9725c0958..fe36f06dcff3b066d75e010e4f4076799a57fadd 100644
--- a/themes/bartik/templates/page.tpl.php
+++ b/themes/bartik/templates/page.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: page.tpl.php,v 1.5 2010/09/09 15:27:08 webchick Exp $
+// $Id: page.tpl.php,v 1.7 2010/10/05 01:48:11 dries Exp $
 
 /**
  * @file
@@ -87,7 +87,7 @@
 ?>
 <div id="page-wrapper"><div id="page">
 
-  <div id="header"><div class="section clearfix">
+  <div id="header" class="<?php print $secondary_menu ? 'with-secondary-menu': 'without-secondary-menu'; ?>"><div class="section clearfix">
 
     <?php if ($logo): ?>
       <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo">
@@ -166,9 +166,9 @@
   <?php endif; ?>
 
   <?php if ($page['featured']): ?>
-    <div id="featured" class="section clearfix">
+    <div id="featured"><div class="section clearfix">
       <?php print render($page['featured']); ?>
-    </div> <!-- /#featured -->
+    </div></div> <!-- /.section, /#featured -->
   <?php endif; ?>
 
   <div id="main-wrapper" class="clearfix"><div id="main" class="clearfix">
diff --git a/themes/garland/garland.info b/themes/garland/garland.info
index f84794ee2e20f72ad6b92b638460fa1ad8210e3b..14394c31e55ad657a455e4d872e7621c9ae8549b 100644
--- a/themes/garland/garland.info
+++ b/themes/garland/garland.info
@@ -9,8 +9,8 @@ stylesheets[all][] = style.css
 stylesheets[print][] = print.css
 settings[garland_width] = fluid
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/garland/page.tpl.php b/themes/garland/page.tpl.php
index 275b1364fd7dd80c3b30eb834283db97bfe1e77d..02d3e0e1c9b2501b105d0f8053ee4643c94fb1c7 100644
--- a/themes/garland/page.tpl.php
+++ b/themes/garland/page.tpl.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: page.tpl.php,v 1.46 2010/09/11 05:01:19 webchick Exp $
+// $Id: page.tpl.php,v 1.47 2010/09/16 19:47:45 dries Exp $
 ?>
   <?php print render($page['header']); ?>
 
@@ -47,8 +47,8 @@
             <h1<?php print $tabs ? ' class="with-tabs"' : '' ?>><?php print $title ?></h1>
           <?php endif; ?>
           <?php print render($title_suffix); ?>
-          <?php if ($tabs): ?><ul class="tabs primary"><?php print render($tabs) ?></ul></div><?php endif; ?>
-          <?php if ($tabs2): ?><ul class="tabs secondary"><?php print render($tabs2) ?></ul><?php endif; ?>
+          <?php if ($tabs): ?><h2 class="element-invisible"><?php print t('Primary tabs'); ?></h2><ul class="tabs primary"><?php print render($tabs) ?></ul></div><?php endif; ?>
+          <?php if ($tabs2): ?><h2 class="element-invisible"><?php print t('Secondary tabs'); ?></h2><ul class="tabs secondary"><?php print render($tabs2) ?></ul><?php endif; ?>
           <?php print $messages; ?>
           <?php print render($page['help']); ?>
           <?php if ($action_links): ?><ul class="action-links"><?php print render($action_links); ?></ul><?php endif; ?>
diff --git a/themes/garland/style-rtl.css b/themes/garland/style-rtl.css
index 657b8b45dd2b2d60fc1384e3a672ae6b0f6e5ed2..67d9030362b02921e321865ed1e4e852bc04a571 100644
--- a/themes/garland/style-rtl.css
+++ b/themes/garland/style-rtl.css
@@ -1,4 +1,4 @@
-/* $Id: style-rtl.css,v 1.22 2010/05/05 16:28:06 dries Exp $ */
+/* $Id: style-rtl.css,v 1.23 2010/09/27 01:12:45 dries Exp $ */
 
 html {
   direction: rtl;
@@ -77,7 +77,7 @@ dl dd {
 
 .form-button,
 .form-submit {
-  margin: 2em 0 1em 0.5em;
+  margin: 0 0 0 0.5em;
 }
 
 .region-header h2 {
diff --git a/themes/garland/style.css b/themes/garland/style.css
index 2355337b30408d9a821cef569dd3ec19606c5736..8b42a50ddad1af60da9fc4b4a717332b873b8b89 100644
--- a/themes/garland/style.css
+++ b/themes/garland/style.css
@@ -1,4 +1,4 @@
-/* $Id: style.css,v 1.85 2010/09/09 15:47:03 webchick Exp $ */
+/* $Id: style.css,v 1.86 2010/09/27 01:12:45 dries Exp $ */
 
 /**
  * Generic elements
@@ -301,22 +301,12 @@ span.form-required {
   margin-bottom: 2em;
 }
 
+.form-actions {
+  margin: 2em 0 1em;
+}
 .form-button,
 .form-submit {
-  margin: 2em 0.5em 1em 0; /* LTR */
-}
-
-#dblog-form-overview .form-submit,
-.confirmation .form-submit,
-.search-form .form-submit,
-.poll .form-submit,
-fieldset .form-button,
-fieldset .form-submit,
-.sidebar .form-button,
-.sidebar .form-submit,
-table .form-button,
-table .form-submit {
-  margin: 0;
+  margin: 0 0.5em 0 0; /* LTR */
 }
 
 /**
diff --git a/themes/garland/template.php b/themes/garland/template.php
index 37d76b65abab6bffaf7f9b57e57d86aa7ea00a06..6f33b339a1fe78b9595e1e1c294e8f386259f367 100644
--- a/themes/garland/template.php
+++ b/themes/garland/template.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: template.php,v 1.41 2010/07/30 02:47:28 dries Exp $
+// $Id: template.php,v 1.42 2010/10/05 19:59:10 dries Exp $
 
 /**
  * Return a themed breadcrumb trail.
@@ -42,7 +42,7 @@ function garland_preprocess_html(&$vars) {
     $vars['classes_array'][] = 'fluid-width';
   }
   // Add conditional CSS for IE6.
-  drupal_add_css(path_to_theme() . '/fix-ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE)));
+  drupal_add_css(path_to_theme() . '/fix-ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
 }
 
 /**
diff --git a/themes/seven/ie.css b/themes/seven/ie.css
index 39a17e088aea1e85498c70b90c3fa4d61275c226..74e56fa47962ed0ec3bfdd6119b548a43811b823 100644
--- a/themes/seven/ie.css
+++ b/themes/seven/ie.css
@@ -1,4 +1,4 @@
-/* $Id: ie.css,v 1.3 2010/04/12 17:33:35 webchick Exp $ */
+/* $Id: ie.css,v 1.4 2010/09/23 17:54:20 dries Exp $ */
 
 /* IE7 renders legends in nested fieldsets without a width. */
 fieldset legend {
@@ -10,3 +10,10 @@ fieldset .fieldset-legend {
   left: 0;
   top: 0;
 }
+
+/* IE renders monospace font too big. */
+code,
+pre,
+kbd {
+  font-size: 1em;
+}
diff --git a/themes/seven/ie6.css b/themes/seven/ie6.css
index 0e7d7483e40f18d9083e54585af12701ec104382..c3735ba5c9f09a7c4c9db87ecc9005836c33d631 100644
--- a/themes/seven/ie6.css
+++ b/themes/seven/ie6.css
@@ -1,4 +1,4 @@
-/* $Id: ie6.css,v 1.6 2010/04/28 20:08:39 dries Exp $ */
+/* $Id: ie6.css,v 1.7 2010/10/03 02:46:12 dries Exp $ */
 
 ul.menu li,
 ul.menu li a,
@@ -8,13 +8,11 @@ ul.links li a,
 #page {
   height: 1%;
 }
-#block-system-main ul.node-type-list li a,
 #block-system-main ul.admin-list li a {
   height: 1px;
   position: relative;
   display: block;
 }
-#block-system-main ul.node-type-list li div.description a,
 #block-system-main ul.admin-list li div.description a {
   display: inline;
 }
diff --git a/themes/seven/page.tpl.php b/themes/seven/page.tpl.php
index 4aa45fc97b2feb37fe90d1a22c788e80e3c2ab66..e337f5c39b4a0f6b788fbb480d20166a74007026 100644
--- a/themes/seven/page.tpl.php
+++ b/themes/seven/page.tpl.php
@@ -1,7 +1,6 @@
 <?php
-// $Id: page.tpl.php,v 1.12 2010/01/04 03:57:19 webchick Exp $
+// $Id: page.tpl.php,v 1.14 2010/10/05 00:29:14 dries Exp $
 ?>
-  <div class="element-invisible"><a id="main-content"></a></div>
   <div id="branding" class="clearfix">
     <?php print $breadcrumb; ?>
     <?php print render($title_prefix); ?>
@@ -9,13 +8,20 @@
       <h1 class="page-title"><?php print $title; ?></h1>
     <?php endif; ?>
     <?php print render($title_suffix); ?>
-    <?php if ($primary_local_tasks): ?><ul class="tabs primary"><?php print render($primary_local_tasks); ?></ul><?php endif; ?>
+    <?php if ($primary_local_tasks): ?>
+      <h2 class="element-invisible"><?php print t('Primary tabs'); ?></h2>
+      <ul class="tabs primary"><?php print render($primary_local_tasks); ?></ul>
+    <?php endif; ?>
   </div>
 
   <div id="page">
-    <?php if ($secondary_local_tasks): ?><ul class="tabs secondary"><?php print render($secondary_local_tasks); ?></ul><?php endif; ?>
+    <?php if ($secondary_local_tasks): ?>
+      <h2 class="element-invisible"><?php print t('Secondary tabs'); ?></h2>
+      <ul class="tabs secondary"><?php print render($secondary_local_tasks); ?></ul>
+    <?php endif; ?>
 
     <div id="content" class="clearfix">
+      <div class="element-invisible"><a id="main-content"></a></div>
       <?php if ($messages): ?>
         <div id="console" class="clearfix"><?php print $messages; ?></div>
       <?php endif; ?>
diff --git a/themes/seven/seven.info b/themes/seven/seven.info
index f0407743b12a92aad99bec5768c9cb404370bb7f..e30ee0652c125dac9c95ed6e85902d90cb74087a 100644
--- a/themes/seven/seven.info
+++ b/themes/seven/seven.info
@@ -15,8 +15,8 @@ regions[page_bottom] = Page bottom
 regions[sidebar_first] = First sidebar
 regions_hidden[] = sidebar_first
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/seven/style-rtl.css b/themes/seven/style-rtl.css
new file mode 100644
index 0000000000000000000000000000000000000000..f655bf717bc7b0f49026a912f5df4acc293fb8df
--- /dev/null
+++ b/themes/seven/style-rtl.css
@@ -0,0 +1,20 @@
+/* $Id: style-rtl.css,v 1.1 2010/09/19 18:35:42 dries Exp $ */
+
+/**
+ * Generic elements.
+ */
+ul,
+.block ul,
+.item-list ul,
+.item-list ul {
+  margin: 0.25em 1.5em 0.25em 0;
+}
+
+/* User login block */
+#user-login-form .openid-links {
+  margin-right: 0;
+}
+#user-login-form .openid-links .user-link {
+  margin-left: 0;
+  margin-right: 1.5em;
+}
diff --git a/themes/seven/style.css b/themes/seven/style.css
index d6d89aab1a27182fd7f49d578fb68cdadb476053..89c8d4c5bb390bca3d5e82f5beb059d96c0b251a 100644
--- a/themes/seven/style.css
+++ b/themes/seven/style.css
@@ -1,4 +1,4 @@
-/* $Id: style.css,v 1.69 2010/09/13 00:59:47 dries Exp $ */
+/* $Id: style.css,v 1.76 2010/10/05 21:03:17 webchick Exp $ */
 
 /**
  * Generic elements.
@@ -6,7 +6,7 @@
 body {
   color: #000;
   background: #fff;
-  font: 81.3%/1.538em normal Lucida Grande, Lucida Sans Unicode, sans-serif;
+  font: normal 81.3%/1.538em "Lucida Grande", "Lucida Sans Unicode", sans-serif;
 }
 a {
   color: #0074BD;
@@ -31,7 +31,7 @@ h3,
 h4,
 h5,
 h6 {
-  font-weight: bold;
+  font-weight: normal;
   margin: 10px 0;
 }
 h1 {
@@ -139,6 +139,10 @@ pre,
 kbd {
   font-size: 1.231em;
 }
+pre {
+  margin: 0.5em 0;
+  white-space: pre-wrap;
+}
 
 /**
  * Skip link.
@@ -375,7 +379,6 @@ ul.inline li {
 #secondary-links ul.links li a.active {
   background: #333;
 }
-ul.node-type-list li,
 ul.admin-list li {
   position: relative;
   padding-left: 30px;
@@ -394,23 +397,19 @@ ul.admin-list {
 }
 .admin-panel .item-list ul,
 ul.admin-list.compact {
-  margin-bottom: 8px;
+  margin: 8px 0;
 }
 .admin-panel .item-list li,
 ul.admin-list.compact li {
   border: none;
   background: none;
-  margin: 0.25em 0 0.25em 1.5em;
+  margin: 0 0 0.75em;
+  line-height: 1;
   padding: 0;
-  list-style-type: disc;
 }
 ul.admin-list li:last-child {
   border-bottom: none;
 }
-ul.node-type-list .label {
-  font-size: 1.154em;
-}
-ul.node-type-list li a,
 ul.admin-list li a {
   margin-left: -30px;
   padding: 0px 0 4px 30px;
@@ -420,12 +419,14 @@ ul.admin-list.compact li a {
   margin-left: 0;
   padding: 0;
 }
-ul.node-type-list li div.description a,
 ul.admin-list li div.description a {
   margin-left: 0px;
   padding: 0px;
   min-height: inherit;
 }
+div.submitted {
+  color: #898989;
+}
 
 /**
  * Tables.
@@ -1005,14 +1006,3 @@ table tbody tr.update-unsupported {
   background: #fffce5;
   border-bottom: 1px solid #ed5;
 }
-
-/* Vertical Tabs */
-div.vertical-tabs .vertical-tabs-list {
-  font-size: 1em;
-}
-div.vertical-tabs ul li.vertical-tab-button strong {
-  font-size: 0.923em;
-}
-div.vertical-tabs ul li.vertical-tab-button .summary {
-  font-size: 0.846em;
-}
diff --git a/themes/seven/template.php b/themes/seven/template.php
index 40862ff609e4e22afe46d6fb76c429edf2a2cf78..a6149d7e142f090144c6e4a0d7d8bec680f316be 100644
--- a/themes/seven/template.php
+++ b/themes/seven/template.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: template.php,v 1.20 2010/08/14 00:43:24 dries Exp $
+// $Id: template.php,v 1.24 2010/10/05 19:59:10 dries Exp $
 
 /**
  * Override or insert variables into the maintenance page template.
@@ -18,9 +18,9 @@ function seven_preprocess_maintenance_page(&$vars) {
  */
 function seven_preprocess_html(&$vars) {
   // Add conditional CSS for IE8 and below.
-  drupal_add_css(path_to_theme() . '/ie.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE)));
+  drupal_add_css(path_to_theme() . '/ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE), 'preprocess' => FALSE));
   // Add conditional CSS for IE6.
-  drupal_add_css(path_to_theme() . '/ie6.css', array('weight' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE)));
+  drupal_add_css(path_to_theme() . '/ie6.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lt IE 7', '!IE' => FALSE), 'preprocess' => FALSE));
 }
 
 /**
@@ -38,7 +38,7 @@ function seven_node_add_list($variables) {
   $content = $variables['content'];
   $output = '';
   if ($content) {
-    $output = '<ul class="node-type-list">';
+    $output = '<ul class="admin-list">';
     foreach ($content as $item) {
       $output .= '<li class="clearfix">';
       $output .= '<span class="label">' . l($item['title'], $item['href'], $item['localized_options']) . '</span>';
@@ -47,11 +47,14 @@ function seven_node_add_list($variables) {
     }
     $output .= '</ul>';
   }
+  else {
+    $output = '<p>' . t('You have not created any content types yet. Go to the <a href="@create-content">content type creation page</a> to add a new content type.', array('@create-content' => url('admin/structure/types/add'))) . '</p>';
+  }
   return $output;
 }
 
 /**
- * Override of theme_admin_block_content().
+ * Overrides theme_admin_block_content().
  *
  * Use unordered list markup in both compact and extended mode.
  */
@@ -63,7 +66,7 @@ function seven_admin_block_content($variables) {
     foreach ($content as $item) {
       $output .= '<li class="leaf">';
       $output .= l($item['title'], $item['href'], $item['localized_options']);
-      if (!system_admin_compact_mode()) {
+      if (isset($item['description']) && !system_admin_compact_mode()) {
         $output .= '<div class="description">' . filter_xss_admin($item['description']) . '</div>';
       }
       $output .= '</li>';
diff --git a/themes/seven/vertical-tabs.css b/themes/seven/vertical-tabs.css
index 8e2f5b83dc16609770b8edb69a6d268c491b2d17..55a50ee4cd342b8fb055aa7853af2f0414c65224 100644
--- a/themes/seven/vertical-tabs.css
+++ b/themes/seven/vertical-tabs.css
@@ -1,69 +1,75 @@
-/* $Id: vertical-tabs.css,v 1.6 2010/07/18 01:36:06 dries Exp $ */
+/* $Id: vertical-tabs.css,v 1.9 2010/10/06 13:42:18 dries Exp $ */
 
 /**
  * Override of misc/vertical-tabs.css.
  */
 div.vertical-tabs {
-  margin: 10px 0;
-  padding: 9px;
+  background: #fff url(images/fc.png) repeat-y 0 0;
   border: 1px solid #ccc;
-  background: #f8f8f8;
+  margin: 10px 0;
+  position: relative;
 }
-
 div.vertical-tabs fieldset {
   border: 0;
-  padding: 0 0 0 20px;
+  padding: 0;
+  margin: 0;
 }
-
 div.vertical-tabs .vertical-tabs-list {
-  line-height: 10px;
-  font-size: 0.875em;
-  width: 25%;
+  border-bottom: 1px solid #ccc;
   float: left;
-  list-style-type: none;
-  margin: 0;
+  font-size: 1em;
+  line-height: 1;
+  margin: 0 -100% -1px 0;
+  padding: 0;
+  width: 240px;
 }
-
 div.vertical-tabs ul li.vertical-tab-button {
-  list-style-type: none;
+  list-style: none;
+  list-style-image: none;
   margin: 0;
 }
-
 div.vertical-tabs ul li.vertical-tab-button a {
+  border-top: 1px solid #ccc;
   display: block;
-  border-right: 1px solid #ccc;
-  padding: 10px 9px 10px 10px;
-  border-top-left-radius: 5px;
-  border-bottom-left-radius: 5px;
-  -moz-border-radius-topleft: 5px;
-  -moz-border-radius-bottomleft: 5px;
-  -webkit-border-top-left-radius: 5px;
-  -webkit-border-bottom-left-radius: 5px;
+  padding: 10px;
+}
+div.vertical-tabs ul li.first a {
+  border-top: 0;
+}
+div.vertical-tabs ul li.vertical-tab-button strong {
+  font-size: 0.923em;
 }
-
 div.vertical-tabs ul li.vertical-tab-button .summary {
-  display: block;
-  font-size: 0.75em;
   color: #666;
+  display: block;
+  font-size: 0.846em;
   padding-top: 0.4em;
 }
-
-div.vertical-tabs ul li.vertical-tab-button a:hover {
-  background: #fff;
+div.vertical-tabs ul li.vertical-tab-button a:hover,
+div.vertical-tabs ul li.vertical-tab-button a:focus {
+  background: #d5d5d5;
   text-decoration: none;
 }
-
 div.vertical-tabs ul li.selected a,
-div.vertical-tabs ul li.selected a:hover {
-  background: #ddd;
+div.vertical-tabs ul li.selected a:hover,
+div.vertical-tabs ul li.selected a:focus,
+div.vertical-tabs ul li.selected a:active {
+  background: #fff;
+  border-right-color: #fff;
+  border-top: 1px solid #ccc;
+  outline: 0;
+}
+div.vertical-tabs ul li.first.selected a,
+div.vertical-tabs ul li.first.selected a:hover {
+  border-top: 0;
 }
-
 div.vertical-tabs .vertical-tabs-panes {
-  width: 72%;
-  padding: 0 1em 0 0;
-  float: right;
+  margin: 0 0 0 265px;
+  padding: 10px 15px 10px 0;
 }
-
 div.vertical-tabs .vertical-tabs-panes legend {
   display: none;
 }
+.vertical-tabs-pane .fieldset-wrapper > div:first-child {
+  padding-top: 5px;
+}
diff --git a/themes/stark/stark.info b/themes/stark/stark.info
index 3266e5265991226aecd5385bed1ffba7e4b7e1a9..39bbfe5382ea1eb48eba01c64e1ead7e04e500ba 100644
--- a/themes/stark/stark.info
+++ b/themes/stark/stark.info
@@ -7,8 +7,8 @@ core = 7.x
 engine = phptemplate
 stylesheets[all][] = layout.css
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/tests/test_theme/test_theme.info b/themes/tests/test_theme/test_theme.info
index 406be1035ca8f31fb79adf86828e1bcbd8bb0622..2007d7eef2870adb35853bc1879866d179defbf1 100644
--- a/themes/tests/test_theme/test_theme.info
+++ b/themes/tests/test_theme/test_theme.info
@@ -1,11 +1,24 @@
-; $Id: test_theme.info,v 1.1 2010/03/21 04:05:24 webchick Exp $
+; $Id: test_theme.info,v 1.2 2010/10/03 05:11:16 webchick Exp $
 name = Test theme
 description = Theme for testing the theme system
 core = 7.x
 engine = phptemplate
 hidden = TRUE
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+
+; Normally, themes may list CSS files like this, and if they exist in the theme
+; folder, then they get added to the page. If they have the same file name as a
+; module CSS file, then the theme's version overrides the module's version, so
+; that the module's version is not added to the page. Additionally, a theme may
+; have an entry like this one, without having the corresponding CSS file in the
+; theme's folder, and in this case, it just stops the module's version from
+; being loaded, and does not replace it with an alternate version. We have this
+; here in order for a test to ensure that this correctly prevents the module
+; version from being loaded, and that errors aren't caused by the lack of this
+; file within the theme folder.
+stylesheets[all][] = system.base.css
+
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/tests/update_test_basetheme/update_test_basetheme.info b/themes/tests/update_test_basetheme/update_test_basetheme.info
index b176671f7215a3bda55fe5c0c861d1eb2bec8bd2..175dd0ce4a175be34b204d2436c91fa38f09f8dc 100644
--- a/themes/tests/update_test_basetheme/update_test_basetheme.info
+++ b/themes/tests/update_test_basetheme/update_test_basetheme.info
@@ -5,8 +5,8 @@ core = 7.x
 engine = phptemplate
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/themes/tests/update_test_subtheme/update_test_subtheme.info b/themes/tests/update_test_subtheme/update_test_subtheme.info
index 6e3a7e3be05d814f62a7776ffe8d405c200acea7..6203b8df55d98e03ba13b23de6af865576c636b4 100644
--- a/themes/tests/update_test_subtheme/update_test_subtheme.info
+++ b/themes/tests/update_test_subtheme/update_test_subtheme.info
@@ -6,8 +6,8 @@ engine = phptemplate
 base theme = update_test_basetheme
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2010-09-16
-version = "7.0-alpha7"
+; Information added by drupal.org packaging script on 2010-10-07
+version = "7.0-beta1"
 project = "drupal"
-datestamp = "1284599761"
+datestamp = "1286422862"
 
diff --git a/update.php b/update.php
index 1554e05e194e04651074ae11a1a7e645e89b862a..588865f56889a22140fb126d8c32d1dce47a0437 100644
--- a/update.php
+++ b/update.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: update.php,v 1.323 2010/05/18 18:11:12 dries Exp $
+// $Id: update.php,v 1.325 2010/10/03 23:33:15 webchick Exp $
 
 /**
  * Root directory of Drupal installation.
@@ -330,12 +330,14 @@ ini_set('display_errors', FALSE);
 
 // We prepare a minimal bootstrap for the update requirements check to avoid
 // reaching the PHP memory limit.
+require_once DRUPAL_ROOT . '/includes/unl_bootstrap.inc';
 require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
 require_once DRUPAL_ROOT . '/includes/update.inc';
 require_once DRUPAL_ROOT . '/includes/common.inc';
 require_once DRUPAL_ROOT . '/includes/file.inc';
 require_once DRUPAL_ROOT . '/includes/entity.inc';
 require_once DRUPAL_ROOT . '/includes/unicode.inc';
+unl_bootstrap();
 update_prepare_d7_bootstrap();
 
 // Determine if the current user has access to run update.php.
diff --git a/xmlrpc.php b/xmlrpc.php
index 3d0b1452ac67b2615af9606cc18ab3b9f38ce6c9..32fe7ef188708fbbf2a3426b8f2503d537f71aa6 100644
--- a/xmlrpc.php
+++ b/xmlrpc.php
@@ -1,5 +1,5 @@
 <?php
-// $Id: xmlrpc.php,v 1.19 2009/12/13 13:06:45 dries Exp $
+// $Id: xmlrpc.php,v 1.20 2010/10/02 01:22:41 dries Exp $
 
 /**
  * @file
@@ -16,6 +16,4 @@ drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 include_once DRUPAL_ROOT . '/includes/xmlrpc.inc';
 include_once DRUPAL_ROOT . '/includes/xmlrpcs.inc';
 
-$services = module_invoke_all('xmlrpc');
-drupal_alter('xmlrpc', $services);
-xmlrpc_server($services);
+xmlrpc_server(module_invoke_all('xmlrpc'));