=== modified file 'includes/bootstrap.inc'
--- includes/bootstrap.inc	2009-01-31 16:50:56 +0000
+++ includes/bootstrap.inc	2009-02-07 16:18:44 +0000
@@ -28,13 +28,6 @@ define('CACHE_DISABLED', 0);
 define('CACHE_NORMAL', 1);
 
 /**
- * Indicates that page caching is using "aggressive" mode. This bypasses
- * loading any modules for additional speed, which may break functionality in
- * modules that expect to be run on each page load.
- */
-define('CACHE_AGGRESSIVE', 2);
-
-/**
  * Log message severity -- Emergency: system is unusable.
  *
  * @see watchdog()
@@ -104,10 +97,9 @@ define('WATCHDOG_DEBUG', 7);
 define('DRUPAL_BOOTSTRAP_CONFIGURATION', 0);
 
 /**
- * Second bootstrap phase: try to call a non-database cache
- * fetch routine.
+ * Second bootstrap phase: serve the page from cache if possible.
  */
-define('DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE', 1);
+define('DRUPAL_BOOTSTRAP_PAGE_CACHE', 1);
 
 /**
  * Third bootstrap phase: initialize database layer.
@@ -120,20 +112,19 @@ define('DRUPAL_BOOTSTRAP_DATABASE', 2);
 define('DRUPAL_BOOTSTRAP_ACCESS', 3);
 
 /**
- * Fifth bootstrap phase: initialize session handling.
+ * Fifth bootstrap phase: initialize the variable system.
  */
-define('DRUPAL_BOOTSTRAP_SESSION', 4);
+define('DRUPAL_BOOTSTRAP_VARIABLES', 4);
 
 /**
- * Sixth bootstrap phase: initialize the variable system.
+ * Sixth bootstrap phase: initialize session handling.
  */
-define('DRUPAL_BOOTSTRAP_VARIABLES', 5);
+define('DRUPAL_BOOTSTRAP_SESSION', 5);
 
 /**
- * Seventh bootstrap phase: load bootstrap.inc and module.inc, start
- * the variable system and try to serve a page from the cache.
+ * Seventh bootstrap phase: set up the page header.
  */
-define('DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE', 6);
+define('DRUPAL_BOOTSTRAP_PAGE_HEADER', 6);
 
 /**
  * Eighth bootstrap phase: find out language of the page.
@@ -694,11 +685,10 @@ function variable_del($name) {
  *   may not be cached (e.g. because it belongs to an authenticated user). If
  *   $retrieve is TRUE, only return either TRUE or FALSE.
  */
-function page_get_cache($retrieve) {
+function page_get_cache($retrieve = FALSE) {
   global $user, $base_root;
   static $ob_started = FALSE;
-
-  if ($user->uid || ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['REQUEST_METHOD'] != 'HEAD') || count(drupal_get_messages(NULL, FALSE))) {
+  if ((isset($_COOKIE[session_name()]) && $user->uid) || ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['REQUEST_METHOD'] != 'HEAD') || count(drupal_get_messages(NULL, FALSE))) {
     return FALSE;
   }
   if ($retrieve) {
@@ -1039,20 +1029,32 @@ function drupal_get_messages($type = NUL
  *
  * @param $ip string
  *   IP address to check.
+ * @param $database
+ *   Whether to check the database.
+ * @param $full
+ *   TRUE if you want to issue a 403 header and exit if the IP is denied.
  * @return bool
  *   TRUE if access is denied, FALSE if access is allowed.
  */
-function drupal_is_denied($ip) {
+function drupal_is_denied($ip, $database = TRUE, $full = FALSE) {
   // Because this function is called on every page request, we first check
   // for an array of IP addresses in settings.php before querying the
   // database.
   $blocked_ips = variable_get('blocked_ips');
+  $denied = FALSE;
   if (isset($blocked_ips) && is_array($blocked_ips)) {
-    return in_array($ip, $blocked_ips);
+    $denied = in_array($ip, $blocked_ips);
   }
-  else {
-    return (bool)db_query("SELECT 1 FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField();
+  elseif ($database) {
+    $denied = (bool)db_query("SELECT 1 FROM {blocked_ips} WHERE ip = :ip", array(':ip' => $ip))->fetchField();
+  }
+  // Deny access to blocked IP addresses - t() is not yet available.
+  if ($denied && $full) {
+    header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
+    print 'Sorry, ' . check_plain(ip_address()) . ' has been banned.';
+    exit();
   }
+  return $denied;
 }
 
 /**
@@ -1093,13 +1095,15 @@ function drupal_anonymous_user($session 
  *     DRUPAL_BOOTSTRAP_FULL: Drupal is fully loaded, validate and fix input data.
  */
 function drupal_bootstrap($phase = NULL) {
-  static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1;
+  static $phases = array(DRUPAL_BOOTSTRAP_CONFIGURATION, DRUPAL_BOOTSTRAP_PAGE_CACHE, DRUPAL_BOOTSTRAP_DATABASE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_VARIABLES, DRUPAL_BOOTSTRAP_PAGE_HEADER, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1;
 
   if (isset($phase)) {
     while ($phases && $phase > $completed_phase) {
       $current_phase = array_shift($phases);
       _drupal_bootstrap($current_phase);
-      $completed_phase = $current_phase;
+      if ($current_phase > $completed_phase) {
+        $completed_phase = $current_phase;
+      }
     }
   }
   return $completed_phase;
@@ -1129,16 +1133,35 @@ function _drupal_bootstrap($phase) {
       conf_init();
       break;
 
-    case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE:
+    case DRUPAL_BOOTSTRAP_PAGE_CACHE:
       // Allow specifying special cache handlers in settings.php, like
       // using memcached or files for storing cache information.
       require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');
-      // If the page_cache_fastpath is set to TRUE in settings.php and
-      // page_cache_fastpath (implemented in the special implementation of
-      // cache.inc) printed the page and indicated this with a returned TRUE
-      // then we are done.
-      if (variable_get('page_cache_fastpath', FALSE) && page_cache_fastpath()) {
-        exit;
+      // Allow cache mode to be set from settings.php as well.
+      $cache_mode = variable_get('cache', NULL);
+      if (isset($cache_mode)) {
+        // We have a cache mode override from settings.php, we check for denied
+        // addresses but only from settings.php.
+        drupal_is_denied(ip_address(), FALSE, TRUE);
+      }
+      else {
+        // We need to initialize the variable system. This will also load the
+        // database and check denied addresses.
+        drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
+      }
+      if ($cache_mode != CACHE_DISABLED && !isset($_COOKIE[session_name()])) {
+        $cache = page_get_cache(TRUE);
+        if (is_object($cache)) {
+          if (variable_get('page_cache_fire_hooks', TRUE)) {
+            require_once DRUPAL_ROOT . '/includes/module.inc';
+            module_invoke_all('boot');
+          }
+          drupal_page_cache_header($cache);
+          if (variable_get('page_cache_fire_hooks', TRUE)) {
+            module_invoke_all('exit');
+          }
+          exit;
+        }
       }
       break;
 
@@ -1152,12 +1175,12 @@ function _drupal_bootstrap($phase) {
       break;
 
     case DRUPAL_BOOTSTRAP_ACCESS:
-      // Deny access to blocked IP addresses - t() is not yet available.
-      if (drupal_is_denied(ip_address())) {
-        header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
-        print 'Sorry, ' . check_plain(ip_address()) . ' has been banned.';
-        exit();
-      }
+      // Check denied addresses, using the database if necessary.
+      drupal_is_denied(ip_address(), TRUE, TRUE);
+
+    case DRUPAL_BOOTSTRAP_VARIABLES:
+      // Initialize configuration variables, using values from settings.php if available.
+      $conf = variable_init(isset($conf) ? $conf : array());
       break;
 
     case DRUPAL_BOOTSTRAP_SESSION:
@@ -1175,42 +1198,16 @@ function _drupal_bootstrap($phase) {
       }
       break;
 
-    case DRUPAL_BOOTSTRAP_VARIABLES:
-      // Initialize configuration variables, using values from settings.php if available.
-      $conf = variable_init(isset($conf) ? $conf : array());
-      break;
-
-    case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE:
-      $cache_mode = variable_get('cache', CACHE_DISABLED);
-      // Get the page from the cache.
-      $cache = $cache_mode == CACHE_DISABLED ? FALSE : page_get_cache(TRUE);
-      // If the skipping of the bootstrap hooks is not enforced, call hook_boot.
-      if (!is_object($cache) || $cache_mode != CACHE_AGGRESSIVE) {
-        // Load module handling.
-        require_once DRUPAL_ROOT . '/includes/module.inc';
-        module_invoke_all('boot');
-      }
-      // If there is a cached page, display it.
-      if (is_object($cache)) {
-        // Destroy empty anonymous sessions.
-        if (drupal_session_is_started() && empty($_SESSION)) {
-          session_destroy();
-        }
-        drupal_page_cache_header($cache);
-        // If the skipping of the bootstrap hooks is not enforced, call hook_exit.
-        if ($cache_mode != CACHE_AGGRESSIVE) {
-          module_invoke_all('exit');
-        }
-        // We are done.
-        exit;
-      }
+    case DRUPAL_BOOTSTRAP_PAGE_HEADER:
       // Prepare for non-cached page workflow.
+      require_once DRUPAL_ROOT . '/includes/module.inc';
+      module_invoke_all('boot');
       drupal_page_header();
       // If the session has not already been started and output buffering is
       // not enabled, the session must be started now before the HTTP headers
       // are sent. If output buffering is enabled, the session may be started
       // at any time using drupal_session_start().
-      if ($cache === FALSE) {
+      if (page_get_cache() === FALSE) {
         drupal_session_start();
       }
       break;

=== modified file 'modules/system/system.admin.inc'
--- modules/system/system.admin.inc	2009-02-03 18:55:29 +0000
+++ modules/system/system.admin.inc	2009-02-07 15:45:30 +0000
@@ -1309,15 +1309,6 @@ function system_performance_settings() {
     $description .= '<p>' . t("When caching is enabled, anonymous user sessions are only saved to the database when needed, so the \"Who's online\" block does not display the number of anonymous users.") . '</p>';
   }
 
-  $problem_modules = array_unique(array_merge(module_implements('boot'), module_implements('exit')));
-  sort($problem_modules);
-
-  if (count($problem_modules) > 0) {
-    $description .= '<p>' . t('<strong class="error">The following enabled modules are incompatible with aggressive mode caching and will not function properly: %modules</strong>', array('%modules' => implode(', ', $problem_modules))) . '.</p>';
-  }
-  else {
-    $description .= '<p>' . t('<strong class="ok">Currently, all enabled modules are compatible with the aggressive caching policy.</strong> Please note, if you use aggressive caching and enable new modules, you will need to check this page again to ensure compatibility.') . '</p>';
-  }
   $form['page_cache'] = array(
     '#type' => 'fieldset',
     '#title' => t('Page cache'),
@@ -1328,7 +1319,7 @@ function system_performance_settings() {
     '#type' => 'radios',
     '#title' => t('Caching mode'),
     '#default_value' => variable_get('cache', CACHE_DISABLED),
-    '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended for production sites, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
+    '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended for production sites, no side effects)')),
     '#description' => $description
   );
 

=== modified file 'sites/default/default.settings.php'
--- sites/default/default.settings.php	2008-12-23 19:59:17 +0000
+++ sites/default/default.settings.php	2009-02-07 16:13:59 +0000
@@ -46,7 +46,7 @@
 /**
  * Database settings:
  *
- * The $databases array specifies the database connection or 
+ * The $databases array specifies the database connection or
  * connections that Drupal may use.  Drupal is able to connect
  * to multiple databases, including multiple types of databases,
  * during the same request.
@@ -63,7 +63,7 @@
  *   'port' => 3306,
  * );
  *
- * The "driver" property indicates what Drupal database driver the 
+ * The "driver" property indicates what Drupal database driver the
  * connection should use.  This is usually the same as the name of the
  * database type, such as mysql or sqlite, but not always.  The other
  * properties will vary depending on the driver.  For SQLite, you must
@@ -80,7 +80,7 @@
  * A target database allows Drupal to try to send certain queries to a
  * different database if it can but fall back to the default connection if not.
  * That is useful for master/slave replication, as Drupal may try to connect
- * to a slave server when appropriate and if one is not available will simply 
+ * to a slave server when appropriate and if one is not available will simply
  * fall back to the single master server.
  *
  * The general format for the $databases array is as follows:
@@ -290,6 +290,17 @@ ini_set('session.cookie_lifetime', 20000
 # );
 
 /**
+ * Page caching behaviour.
+ *
+ * To use page caching without touching the database set cache to
+ * CACHE_NORMAL. To bypass the various hook_boot and hook_exit implementations,
+ * set the page_cache_fire_hooks variable to FALSE. Also see the IP blocking
+ * section below.
+ */
+# $conf['cache'] = CACHE_NORMAL;
+# $conf['page_cache_fire_hooks'] = FALSE;
+
+/**
  *
  * IP blocking:
  *
@@ -311,3 +322,4 @@ ini_set('session.cookie_lifetime', 20000
 # $conf['blocked_ips'] = array(
 #   'a.b.c.d',
 # );
+

