=== modified file 'includes/bootstrap.inc' --- includes/bootstrap.inc 2008-11-24 10:41:39 +0000 +++ includes/bootstrap.inc 2008-11-28 06:01:01 +0000 @@ -428,8 +428,7 @@ function conf_init() { global $base_url, $base_path, $base_root; // Export the following settings.php variables to the global namespace - global $databases, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access; - $conf = array(); + global $db_prefix, $cookie_domain, $installed_profile, $update_free_access; if (!drupal_valid_http_host()) { // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack. @@ -581,7 +580,8 @@ function drupal_get_filename($type, $nam * with variable_set() as well as those explicitly specified in the configuration * file. */ -function variable_init($conf = array()) { +function variable_init() { + $db_active = db_set_active('_bootstrap'); // NOTE: caching the variables improves performance by 20% when serving cached pages. if ($cached = cache_get('variables', 'cache')) { $variables = $cached->data; @@ -590,10 +590,7 @@ function variable_init($conf = array()) $variables = array_map('unserialize', db_query('SELECT name, value FROM {variable}')->fetchAllKeyed()); cache_set('variables', $variables); } - - foreach ($conf as $name => $value) { - $variables[$name] = $value; - } + db_set_active($db_active); return $variables; } @@ -626,9 +623,11 @@ function variable_get($name, $default) { function variable_set($name, $value) { global $conf; + $active_db = db_set_active('_bootstrap'); db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute(); cache_clear_all('variables', 'cache'); + db_set_active($active_db); $conf[$name] = $value; } @@ -1052,7 +1051,7 @@ 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_DATABASE, DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE, DRUPAL_BOOTSTRAP_ACCESS, DRUPAL_BOOTSTRAP_SESSION, DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE, DRUPAL_BOOTSTRAP_LANGUAGE, DRUPAL_BOOTSTRAP_PATH, DRUPAL_BOOTSTRAP_FULL), $completed_phase = -1; if (isset($phase)) { while ($phases && $phase > $completed_phase) { @@ -1076,22 +1075,39 @@ function drupal_get_bootstrap_phase() { } function _drupal_bootstrap($phase) { - global $conf; + global $conf, $databases; switch ($phase) { - case DRUPAL_BOOTSTRAP_CONFIGURATION: + case DRUPAL_BOOTSTRAP_DATABASE: + // Allow specifying special cache handlers using memcached or files for + // storing cache information. + require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc'); + // Initialize the database system. Note that the connection + // won't be initialized until it is actually requested. + require_once DRUPAL_ROOT . '/includes/database/database.inc'; + // Register autoload functions so that we can access classes and interfaces. + spl_autoload_register('drupal_autoload_class'); + spl_autoload_register('drupal_autoload_interface'); + // Initialize configuration variables. + $conf = variable_init(); drupal_initialize_variables(); - // Start a page timer: - timer_start('page'); // Initialize the configuration conf_init(); + $databases = variable_get('databases', NULL); + // If there are no databases then we need to install. + if (!$databases && basename($_SERVER['SCRIPT_NAME']) != 'install.php') { + require_once DRUPAL_ROOT . '/includes/install.inc'; + install_goto('install.php'); + } + else { + db_set_active(); + } + // Start a page timer: + timer_start('page'); break; case DRUPAL_BOOTSTRAP_EARLY_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 @@ -1101,15 +1117,6 @@ function _drupal_bootstrap($phase) { } break; - case DRUPAL_BOOTSTRAP_DATABASE: - // Initialize the database system. Note that the connection - // won't be initialized until it is actually requested. - require_once DRUPAL_ROOT . '/includes/database/database.inc'; - // Register autoload functions so that we can access classes and interfaces. - spl_autoload_register('drupal_autoload_class'); - spl_autoload_register('drupal_autoload_interface'); - break; - case DRUPAL_BOOTSTRAP_ACCESS: // Deny access to blocked IP addresses - t() is not yet available. if (drupal_is_denied(ip_address())) { @@ -1125,11 +1132,6 @@ function _drupal_bootstrap($phase) { session_start(); 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. @@ -1479,6 +1481,7 @@ function drupal_autoload_class($class) { function _registry_check_code($type, $name = NULL) { static $lookup_cache, $cache_update_needed; + $db_active = db_set_active('_bootstrap'); if (!isset($lookup_cache)) { $lookup_cache = _registry_get_lookup_cache(); } @@ -1488,6 +1491,7 @@ function _registry_check_code($type, $na if ($type == REGISTRY_RESET_LOOKUP_CACHE) { $cache_update_needed = TRUE; $lookup_cache = NULL; + db_set_active($db_active); return; } @@ -1497,6 +1501,7 @@ function _registry_check_code($type, $na if ($cache_update_needed) { _registry_set_lookup_cache($lookup_cache); } + db_set_active($db_active); return; } @@ -1507,13 +1512,14 @@ function _registry_check_code($type, $na if ($lookup_cache[$cache_key]) { require_once DRUPAL_ROOT . '/' . $lookup_cache[$cache_key]; } + db_set_active($db_active); return $lookup_cache[$cache_key]; } // This function may get called when the default database is not active, but // there is no reason we'd ever want to not use the default database for // this query. - $file = Database::getConnection('default')->query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( + $file = db_query("SELECT filename FROM {registry} WHERE name = :name AND type = :type", array( ':name' => $name, ':type' => $type, )) @@ -1525,6 +1531,7 @@ function _registry_check_code($type, $na // Misses are valuable information worth caching, so cache even if // $file is FALSE. $lookup_cache[$cache_key] = $file; + db_set_active($db_active); if ($file) { require_once DRUPAL_ROOT . '/' . $file; === modified file 'includes/database/database.inc' --- includes/database/database.inc 2008-11-22 13:51:38 +0000 +++ includes/database/database.inc 2008-11-28 05:44:18 +0000 @@ -797,7 +797,15 @@ abstract class Database { * * @var array */ - static protected $databaseInfo = NULL; + static protected $databaseInfo = array( + '_bootstrap' => array( + 'default' => array( + 'driver' => 'sqlite', + 'database' => 'sites/default/files/.ht.boot.sqlite', + ), + ), + ); + /** * A list of key/target credentials to simply ignore. @@ -811,7 +819,7 @@ abstract class Database { * * @var string */ - static protected $activeKey = 'default'; + static protected $activeKey = '_bootstrap'; /** * An array of active query log objects. @@ -949,7 +957,7 @@ abstract class Database { * The previous database connection key. */ final public static function setActiveConnection($key = 'default') { - if (empty(self::$databaseInfo)) { + if (empty(self::$databaseInfo[$key])) { self::parseConnectionInfo(); } @@ -968,7 +976,7 @@ abstract class Database { _db_check_install_needed(); - $databaseInfo = $databases; + $databaseInfo = $databases ? $databases : array(); foreach ($databaseInfo as $index => $info) { foreach ($databaseInfo[$index] as $target => $value) { // If there is no "driver" property, then we assume it's an array of @@ -980,7 +988,7 @@ abstract class Database { } } - self::$databaseInfo = $databaseInfo; + self::$databaseInfo = $databaseInfo + self::$databaseInfo; } /** @@ -1016,7 +1024,7 @@ abstract class Database { * The connection key for which we want information. */ final public static function getConnectionInfo($key = 'default') { - if (empty(self::$databaseInfo)) { + if (empty(self::$databaseInfo[$key])) { self::parseConnectionInfo(); } === modified file 'includes/database/sqlite/database.inc' --- includes/database/sqlite/database.inc 2008-11-23 06:06:15 +0000 +++ includes/database/sqlite/database.inc 2008-11-27 13:54:36 +0000 @@ -31,6 +31,7 @@ class DatabaseConnection_sqlite extends $this->transactionSupport = isset($connection_options['transactions']) ? $connection_options['transactions'] : TRUE; + $this->readOnly = !is_writable($connection_options['database']); parent::__construct('sqlite:'. $connection_options['database'], '', '', $connection_options); $this->exec('PRAGMA encoding="UTF-8"'); === modified file 'includes/database/sqlite/query.inc' --- includes/database/sqlite/query.inc 2008-11-23 06:06:15 +0000 +++ includes/database/sqlite/query.inc 2008-11-27 13:54:56 +0000 @@ -16,7 +16,7 @@ class InsertQuery_sqlite extends InsertQuery { public function execute() { - if (count($this->insertFields) + count($this->defaultFields) == 0) { + if ($this->connection->readOnly || count($this->insertFields) + count($this->defaultFields) == 0) { return NULL; } if (count($this->insertFields)) { @@ -69,6 +69,9 @@ class UpdateQuery_sqlite extends UpdateQ } public function execute() { + if ($this->connection->readOnly) { + return FALSE; + } // Get the fields used in the update query, and remove those that are already // in the condition. $fields = $this->expressionFields + $this->fields; @@ -115,6 +118,9 @@ class UpdateQuery_sqlite extends UpdateQ */ class DeleteQuery_sqlite extends DeleteQuery { public function execute() { + if ($this->connection->readOnly) { + return FALSE; + } if (!count($this->condition)) { $total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField(); parent::execute(); === modified file 'includes/install.inc' --- includes/install.inc 2008-11-24 10:41:39 +0000 +++ includes/install.inc 2008-11-28 05:54:06 +0000 @@ -537,27 +537,6 @@ function _drupal_install_module($module) } /** - * Manually include all files for the active database. - * - * Because we have no registry yet, we need to manually include the - * necessary database include files. - */ -function drupal_install_init_database() { - static $included = FALSE; - - if (!$included) { - $connection_info = Database::getConnectionInfo(); - $driver = $connection_info['default']['driver']; - require_once DRUPAL_ROOT . '/includes/database/query.inc'; - require_once DRUPAL_ROOT . '/includes/database/select.inc'; - require_once DRUPAL_ROOT . '/includes/database/schema.inc'; - foreach (glob(DRUPAL_ROOT . '/includes/database/' . $driver . '/*.inc') as $include_file) { - require_once $include_file; - } - } -} - -/** * Callback to install the system module. * * Separated from the installation of other modules so core system @@ -566,14 +545,12 @@ function drupal_install_init_database() function drupal_install_system() { $system_path = dirname(drupal_get_filename('module', 'system', NULL)); require_once DRUPAL_ROOT . '/' . $system_path . '/system.install'; - drupal_install_init_database(); module_invoke('system', 'install'); $system_versions = drupal_get_schema_versions('system'); $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; db_query("INSERT INTO {system} (filename, name, type, owner, status, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d)", $system_path . '/system.module', 'system', 'module', '', 1, $system_version); // Now that we've installed things properly, bootstrap the full Drupal environment - drupal_install_init_database(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); module_rebuild_cache(); } === modified file 'install.php' --- install.php 2008-11-24 10:41:39 +0000 +++ install.php 2008-11-28 07:12:06 +0000 @@ -34,12 +34,12 @@ function install_main() { } require_once DRUPAL_ROOT . '/includes/bootstrap.inc'; - drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); + drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); // This must go after drupal_bootstrap(), which unsets globals! global $profile, $install_locale, $conf; - require_once DRUPAL_ROOT . '/modules/system/system.install'; + require_once DRUPAL_ROOT . '/includes/module.inc'; require_once DRUPAL_ROOT . '/includes/file.inc'; // Ensure correct page headers are sent (e.g. caching) @@ -48,13 +48,10 @@ function install_main() { // Set up $language, so t() caller functions will still work. drupal_init_language(); - // Load module basics (needed for hook invokes). - include_once DRUPAL_ROOT . '/includes/module.inc'; - $module_list['system']['filename'] = 'modules/system/system.module'; - $module_list['filter']['filename'] = 'modules/filter/filter.module'; - module_list(TRUE, FALSE, $module_list); - drupal_load('module', 'system'); - drupal_load('module', 'filter'); + // Load filter and system modules here. + db_set_active('_bootstrap'); + module_load_all(); + db_set_active(); // Set up theme system for the maintenance page. drupal_maintenance_theme(); @@ -62,33 +59,11 @@ function install_main() { // Check existing settings.php. $verify = install_verify_settings(); - if ($verify) { - // Since we have a database connection, we use the normal cache system. - // This is important, as the installer calls into the Drupal system for - // the clean URL checks, so we should maintain the cache properly. - require_once DRUPAL_ROOT . '/includes/cache.inc'; - $conf['cache_inc'] = 'includes/cache.inc'; - - // Initialize the database system. Note that the connection - // won't be initialized until it is actually requested. - require_once DRUPAL_ROOT . '/includes/database/database.inc'; - // Check if Drupal is installed. $task = install_verify_drupal(); if ($task == 'done') { install_already_done_error(); } - } - else { - // Since no persistent storage is available yet, and functions that check - // for cached data will fail, we temporarily replace the normal cache - // system with a stubbed-out version that short-circuits the actual - // caching process and avoids any errors. - require_once DRUPAL_ROOT . '/includes/cache-install.inc'; - $conf['cache_inc'] = 'includes/cache-install.inc'; - - $task = NULL; - } // Decide which profile to use. if (!empty($_GET['profile'])) { @@ -162,9 +137,8 @@ function install_main() { * Verify if Drupal is installed. */ function install_verify_drupal() { - // Read the variable manually using the @ so we don't trigger an error if it fails. try { - if ($result = db_query("SELECT value FROM {variable} WHERE name = '%s'", 'install_task')) { + if ($result = Database::getConnection('_bootstrap')->query("SELECT value FROM {variable} WHERE name = 'install_task'")) { return unserialize(db_result($result)); } } @@ -390,15 +364,11 @@ function install_settings_form_submit($f global $profile, $install_locale; $database = array_intersect_key($form_state['values']['_database'], array_flip(array('driver', 'database', 'username', 'password', 'host', 'port'))); - // Update global settings array and save - $settings['databases'] = array( - 'value' => array('default' => array('default' => $database)), - 'required' => TRUE, - ); $settings['db_prefix'] = array( 'value' => $form_state['values']['db_prefix'], 'required' => TRUE, ); + variable_set('databases', array('default' => array('default' => $database))); drupal_rewrite_settings($settings); // Continue to install profile step @@ -625,7 +595,6 @@ function install_tasks($profile, $task) // Bootstrap newly installed Drupal, while preserving existing messages. $messages = isset($_SESSION['messages']) ? $_SESSION['messages'] : ''; - drupal_install_init_database(); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); $_SESSION['messages'] = $messages;