diff --git a/cron.php b/cron.php
index 98026de151058356cb0c29edf2b302ee8c68d203..51afe406b7e19268700e1f6f4659dbbc03454141 100644
--- a/cron.php
+++ b/cron.php
@@ -7,7 +7,7 @@
  */
 
 include_once 'includes/bootstrap.inc';
-include_once 'includes/common.inc' ;
+drupal_bootstrap('full');
 
 // If not in 'safe mode', increase the maximum execution time:
 if (!ini_get('safe_mode')) {
diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index 0fde1d2596382d68a76c00bdc27d2b08fead80b3..0e8df86e4a142d5dc54052d08084482f475a606d 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -789,27 +789,71 @@ function drupal_is_denied($type, $mask) {
   return $deny && !$allow;
 }
 
+/**
+ * A string describing a phase of Drupal to load. Each phase adds to the
+ * previous one, so invoking a later phase automatically runs the earlier
+ * phases too. The most important usage is that if you want to access
+ * Drupal database from a script without loading anything else, you can
+ * include bootstrap.inc, and call drupal_bootstrap('database').
+ *
+ * @param $phase
+ *   A string. Allowed values are:
+ *    'database': initialize database layer.
+ *    'session': initialize session handling.
+ *    'page cache': load bootstrap.inc and module.inc, start the variable
+ *                  system and try to serve a page from the cache.
+ *    'full': Drupal is fully loaded, validate and fix input data.
+ */
+function drupal_bootstrap($phase) {
+  static $phases = array('database', 'session', 'page cache', 'full');
+
+  while ($current_phase = array_shift($phases)) {
+    _drupal_bootstrap($current_phase);
+    if ($phase == $current_phase) {
+      return;
+    }
+  }
+}
 
-// Start a page timer:
-timer_start('page');
-
-unset($conf);
-$config = conf_init();
+function _drupal_bootstrap($phase) {
+  global $conf;
 
-include_once "$config/settings.php";
-include_once 'includes/database.inc';
+  switch ($phase) {
+    case 'database':
+      global $db_url, $base_url;
+      unset($conf);
+      require_once conf_init() .'/settings.php';
+      require_once './includes/database.inc';
+      // Initialize the default database.
+      db_set_active();
+      break;
+    case 'session':
+      require_once './includes/session.inc';
+      session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
+      session_start();
+      break;
+    case 'page cache':
+      require_once './includes/bootstrap.inc';
+      require_once './includes/module.inc';
+      // Start a page timer:
+      timer_start('page');
+
+      // deny access to hosts which were banned. t() is not yet available.
+      if (drupal_is_denied('host', $_SERVER['REMOTE_ADDR'])) {
+        header('HTTP/1.0 403 Forbidden');
+        print "Sorry, ". $_SERVER['REMOTE_ADDR']. " has been banned.";
+        exit();
+      }
 
-// deny access to hosts which were banned. t() is not yet available.
-if (drupal_is_denied('host', $_SERVER['REMOTE_ADDR'])) {
-  header('HTTP/1.0 403 Forbidden');
-  print "Sorry, ". $_SERVER['REMOTE_ADDR']. " has been banned.";
-  exit();
+      // Initialize configuration variables, using values from conf.php if available.
+      $conf = variable_init(isset($conf) ? $conf : array());
+      drupal_page_header();
+      break;
+    case 'full':
+      require_once './includes/common.inc';
+      _drupal_bootstrap_full();
+      break;
+  }
 }
 
-include_once 'includes/session.inc';
-include_once 'includes/module.inc';
-
-// Initialize configuration variables, using values from conf.php if available.
-$conf = variable_init(isset($conf) ? $conf : array());
-
 ?>
diff --git a/includes/common.inc b/includes/common.inc
index 0cd68bb4aaba8f149fe72cf082651d15fbe1b386..020d0c5d8e478c7ebc67350bf7bf53344ac9348c 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -812,7 +812,7 @@ function format_plural($count, $singular, $plural) {
   if ($count == 1) return t($singular, array("%count" => $count));
 
   // get the plural index through the gettext formula
-  $index = (function_exists('locale')) ? locale_get_plural($count) : -1;
+  $index = (function_exists('locale_get_plural')) ? locale_get_plural($count) : -1;
   if ($index < 0) { // backward compatibility
     return t($plural, array("%count" => $count));
   }
@@ -2001,12 +2001,8 @@ function drupal_get_path($type, $name) {
 /**
  * Provide a substitute clone() function for PHP4.
  */
-if (version_compare(phpversion(), '5.0') < 0) {
-  eval('
-    function clone($object) {
-      return $object;
-    }
-  ');
+function drupal_clone($object) {
+  return version_compare(phpversion(), '5.0') < 0 ? $object : clone($object);
 }
 
 /**
@@ -2054,44 +2050,48 @@ function drupal_implode_autocomplete($array) {
   return implode('||', $output);
 }
 
-// Set the Drupal custom error handler.
-set_error_handler('error_handler');
-
-include_once 'includes/theme.inc';
-include_once 'includes/pager.inc';
-include_once 'includes/menu.inc';
-include_once 'includes/tablesort.inc';
-include_once 'includes/file.inc';
-include_once 'includes/xmlrpc.inc';
-include_once 'includes/image.inc';
-
-// Emit the correct charset HTTP header.
-drupal_set_header('Content-Type: text/html; charset=utf-8');
-
-// Initialize $_GET['q'] prior to loading modules and invoking hook_init().
-if (!empty($_GET['q'])) {
-  $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
-}
-else {
-  $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
-}
-
-// Initialize all enabled modules.
-module_init();
+function _drupal_bootstrap_full() {
+  static $called;
+  global $locale;
 
-if (!user_access('bypass input data check')) {
-  // We can't use $_REQUEST because it consists of the contents of $_POST,
-  // $_GET and $_COOKIE: if any of the input arrays share a key, only one
-  // value will be verified.
-  if (!valid_input_data($_GET)
-   || !valid_input_data($_POST)
-   || !valid_input_data($_COOKIE)
-   || !valid_input_data($_FILES)) {
-    die('Terminated request because of suspicious input data.');
+  if ($called) {
+    return;
+  }
+  $called = 1;
+  require_once './includes/theme.inc';
+  require_once './includes/pager.inc';
+  require_once './includes/menu.inc';
+  require_once './includes/tablesort.inc';
+  require_once './includes/file.inc';
+  require_once './includes/xmlrpc.inc';
+  require_once './includes/image.inc';
+  // Set the Drupal custom error handler.
+  set_error_handler('error_handler');
+  // Emit the correct charset HTTP header.
+  drupal_set_header('Content-Type: text/html; charset=utf-8');
+  // Initialize $_GET['q'] prior to loading modules and invoking hook_init().
+  if (!empty($_GET['q'])) {
+    $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
+  }
+  else {
+    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
+  }
+  // Initialize all enabled modules.
+  module_init();
+  if (!user_access('bypass input data check')) {
+    // We can't use $_REQUEST because it consists of the contents of $_POST,
+    // $_GET and $_COOKIE: if any of the input arrays share a key, only one
+    // value will be verified.
+    if (!valid_input_data($_GET)
+    || !valid_input_data($_POST)
+    || !valid_input_data($_COOKIE)
+    || !valid_input_data($_FILES)) {
+      die('Terminated request because of suspicious input data.');
+    }
   }
+  fix_gpc_magic();
+  fix_checkboxes();
+  // Initialize the localization system.
+  $locale = locale_initialize();
 }
-
-// Initialize the localization system.
-$locale = locale_initialize();
-
 ?>
diff --git a/includes/database.inc b/includes/database.inc
index 06d150d309566c8196a71b758d17e20f4633566e..c76b0083d4548b91dc4188a5dac3a928f4f081de 100644
--- a/includes/database.inc
+++ b/includes/database.inc
@@ -279,7 +279,4 @@ function db_rewrite_sql($query, $primary_table = 'n', $primary_field = 'nid',  $
  * @} End of "defgroup database".
  */
 
-// Initialize the default database.
-db_set_active();
-
 ?>
diff --git a/includes/database.mysql.inc b/includes/database.mysql.inc
index 786a1dfd847b1890ffcce34937e5feff0495e826..78bd24656ac08b38823336d13955cb8ca4bc2f2e 100644
--- a/includes/database.mysql.inc
+++ b/includes/database.mysql.inc
@@ -47,15 +47,20 @@ function db_connect($url) {
 function _db_query($query, $debug = 0) {
   global $active_db;
   global $queries;
+  static $dev_query;
 
-  if (variable_get('dev_query', 0)) {
+  if (!isset($dev_query)) {
+    $dev_query = function_exists('dev_query') ? variable_get('dev_query', 0) : $GLOBALS['conf']['dev_query'];
+  }
+
+  if ($dev_query) {
     list($usec, $sec) = explode(' ', microtime());
     $timer = (float)$usec + (float)$sec;
   }
 
   $result = mysql_query($query, $active_db);
 
-  if (variable_get('dev_query', 0)) {
+  if ($dev_query) {
     list($usec, $sec) = explode(' ', microtime());
     $stop = (float)$usec + (float)$sec;
     $diff = $stop - $timer;
diff --git a/includes/database.pgsql.inc b/includes/database.pgsql.inc
index 15eda4d830356aba251927fdedc75c5d0dfd9be9..9e4ecf21bb8796a867e5941081530d28b348e3b4 100644
--- a/includes/database.pgsql.inc
+++ b/includes/database.pgsql.inc
@@ -36,15 +36,20 @@ function db_connect($url) {
 function _db_query($query, $debug = 0) {
   global $active_db, $last_result;
   global $queries;
+  static $dev_query;
 
-  if (variable_get('dev_query', 0)) {
+  if (!isset($dev_query)) {
+    $dev_query = function_exists('dev_query') ? variable_get('dev_query', 0) : $GLOBALS['conf']['dev_query'];
+  }
+
+  if ($dev_query) {
     list($usec, $sec) = explode(' ', microtime());
     $timer = (float)$usec + (float)$sec;
   }
 
   $last_result = pg_query($active_db, $query);
 
-  if (variable_get('dev_query', 0)) {
+  if ($dev_query) {
     list($usec, $sec) = explode(' ', microtime());
     $stop = (float)$usec + (float)$sec;
     $diff = $stop - $timer;
diff --git a/includes/menu.inc b/includes/menu.inc
index cf8a7c007ae85ab0cf2d16ad5111256667a4fb9f..67b474b3ac87043753b985466e22b72bf64650f6 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -351,7 +351,7 @@ function menu_execute_active_handler() {
     $arguments = array_merge($arguments, explode('/', $arg));
   }
 
-  return call_user_func_array($menu['items'][$mid]['callback'], $arguments);
+  return function_exists($menu['items'][$mid]['callback']) ?  call_user_func_array($menu['items'][$mid]['callback'], $arguments) : '';
 }
 
 /**
diff --git a/includes/session.inc b/includes/session.inc
index 126c56f024595934252c42527f6d161b7b41e446..d1dde2f2a331fb877c6464095e483984df92187d 100644
--- a/includes/session.inc
+++ b/includes/session.inc
@@ -6,9 +6,6 @@
  * User session handling functions.
  */
 
-session_set_save_handler("sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc");
-session_start();
-
 /*** Session functions *****************************************************/
 
 function sess_open($save_path, $session_name) {
diff --git a/includes/theme.inc b/includes/theme.inc
index d35e83fea14b23154eef832633abc7e0848985ec..7d3cd8cbd48f9355a9ef506d2f0816bc757d5065 100644
--- a/includes/theme.inc
+++ b/includes/theme.inc
@@ -34,6 +34,7 @@
 function init_theme() {
   global $user, $custom_theme, $theme_engine, $theme_key;
 
+  drupal_bootstrap('database');
   $themes = list_themes();
 
   // Only select the user selected theme if it is available in the
diff --git a/index.php b/index.php
index c2e7647fc027d38711a444a53f4bc25dabda49d8..6816599b8a3af64aaf392287949b641eb62d84d5 100644
--- a/index.php
+++ b/index.php
@@ -9,12 +9,8 @@
  * prints the appropriate page.
  */
 
-include_once 'includes/bootstrap.inc';
-drupal_page_header();
-include_once 'includes/common.inc';
-
-fix_gpc_magic();
-fix_checkboxes();
+require_once './includes/bootstrap.inc';
+drupal_bootstrap('full');
 
 $return = menu_execute_active_handler();
 switch ($return) {
diff --git a/modules/node.module b/modules/node.module
index 5f22252d6c835f8fd1a43a274858fd22fd72a3fd..54a6285e752f2a68488c5bab085fef5af526c880 100644
--- a/modules/node.module
+++ b/modules/node.module
@@ -1470,7 +1470,7 @@ function node_preview($node) {
 
     // Display a preview of the node:
     // Previewing alters $node so it needs to be cloned.
-    $output = theme('node_preview', clone($node));
+    $output = theme('node_preview', drupal_clone($node));
 
     $output .= node_form($node);
 
diff --git a/modules/node/node.module b/modules/node/node.module
index 5f22252d6c835f8fd1a43a274858fd22fd72a3fd..54a6285e752f2a68488c5bab085fef5af526c880 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -1470,7 +1470,7 @@ function node_preview($node) {
 
     // Display a preview of the node:
     // Previewing alters $node so it needs to be cloned.
-    $output = theme('node_preview', clone($node));
+    $output = theme('node_preview', drupal_clone($node));
 
     $output .= node_form($node);
 
diff --git a/xmlrpc.php b/xmlrpc.php
index 11f6ab74f28172124635a28215ccdc5e10080c17..d93055075c79bebf7fbe4d778855dd4eecf3f946 100644
--- a/xmlrpc.php
+++ b/xmlrpc.php
@@ -7,8 +7,7 @@
  */
 
 include_once 'includes/bootstrap.inc';
-include_once 'includes/common.inc';
-include_once 'includes/xmlrpc.inc';
+drupal_bootstrap('full');
 include_once 'includes/xmlrpcs.inc';
 
 $functions = module_invoke_all('xmlrpc');