--- install.php.orig 1969-12-31 19:00:00.000000000 -0500 +++ install.php 2006-06-07 14:30:19.000000000 -0400 @@ -0,0 +1,15 @@ + --- includes/install.inc.orig 2006-06-07 14:37:30.000000000 -0400 +++ includes/install.inc 2006-06-07 22:40:34.000000000 -0400 @@ -4,15 +4,40 @@ define('SCHEMA_UNINSTALLED', -1); define('SCHEMA_INSTALLED', 0); +define('DRUPAL_MINIMUM_PHP', '4.3.3'); +define('DRUPAL_MINIMUM_MEMORY', '8M'); +define('DRUPAL_MINIMUM_MYSQL', '3.23.17'); // If using MySQL +define('DRUPAL_MINIMUM_PGSQL', '7.3'); // If using PostgreSQL +define('DRUPAL_MINIMUM_APACHE', '1.3'); // If using Apache -// The system module (Drupal core) is currently a special case -include_once './database/updates.inc'; +define('FILE_EXIST', 1); +define('FILE_READABLE', 2); +define('FILE_WRITABLE', 4); +define('FILE_WRITEABLE', 4); +define('FILE_EXECUTABLE', 8); +define('FILE_NOT_EXIST', 16); +define('FILE_NOT_READABLE', 32); +define('FILE_NOT_WRITABLE', 64); +define('FILE_NOT_WRITEABLE', 64); +define('FILE_NOT_EXECUTABLE', 128); -// Include install files for each module -foreach (module_list() as $module) { - $install_file = './'. drupal_get_path('module', $module) .'/'. $module .'.install'; - if (is_file($install_file)) { - include_once $install_file; +define('INSTALL_BOOTSTRAP_ENVIRONMENT', 0); +define('INSTALL_BOOTSTRAP_PROFILES', 1); +define('INSTALL_BOOTSTRAP_SETTINGS', 2); +define('INSTALL_BOOTSTRAP_DATABASE', 3); +define('INSTALL_PROFILES', 4); +define('INSTALL_CONFIGURE', 5); + +if (!$install) { + // The system module (Drupal core) is currently a special case + include_once './database/updates.inc'; + + // Include install files for each module + foreach (module_list() as $module) { + $install_file = './'. drupal_get_path('module', $module) .'/'. $module .'.install'; + if (is_file($install_file)) { + include_once $install_file; + } } } @@ -79,3 +104,1273 @@ function drupal_set_installed_schema_version($module, $version) { db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module); } + +/** + * The Drupal installation happens in a series of steps. We begin by verifying + * that the current environment meets our minimum requirements. We then go + * on to verify that settings.php is properly configured. From there we + * connect to the configured database and verify that it meets our minimum + * requirements. Finally we can allow the user to select an installation + * profile and complete the installation process. + * + * @param $phase + * The installation phase we should proceed to. + */ +function drupal_install($phase) { + static $phases = array(INSTALL_BOOTSTRAP_ENVIRONMENT, INSTALL_BOOTSTRAP_PROFILES, INSTALL_BOOTSTRAP_SETTINGS, INSTALL_BOOTSTRAP_DATABASE, INSTALL_PROFILES, INSTALL_CONFIGURE); + + while (!is_null($current_phase = array_shift($phases))) { + _drupal_install($current_phase); + if ($phase == $current_phase) { + return; + } + } +} + +/** + * The individual Drupal installation phase definitions. + * + * @param $phase + * The current phase. + */ +function _drupal_install($phase) { + switch ($phase) { + + // Verify that this system supports Drupal's minimum requirements. + case INSTALL_BOOTSTRAP_ENVIRONMENT: + if (_profile_installed() || $_GET['profile']) + continue; + require_once './modules/system.install'; + drupal_verify_install(system_requirements_bootstrap()); + if (_install_errors()) { + drupal_maintenance_theme(); + drupal_set_title('Verify your install environment'); + print theme('install_page', '

The errors above must be resolved before you can install Drupal. Find additional information about Drupal\'s minimum system requirements here.

'); + exit; + } + break; + + // Select an installation profile. + case INSTALL_BOOTSTRAP_PROFILES: + if (_profile_installed() || $_GET['profile']) + continue; + if ($profile = drupal_select_profile()) { + _install_goto("install.php?profile=$profile"); + } + _install_no_profile_error(); + break; + + // Configure settings.php. + case INSTALL_BOOTSTRAP_SETTINGS: + if (_profile_installed()) + continue; + install_verify_settings(); + break; + + // Establish a connection to the database. + case INSTALL_BOOTSTRAP_DATABASE: + if (_profile_installed()) + continue; + install_verify_db(); + if (_install_errors()) { + drupal_maintenance_theme(); + drupal_set_title('Database configuration'); + print theme('install_page', drupal_install_settings_form()); + exit; + } + db_set_active(); + break; + + // Perform actual installation defined in the profile. + case INSTALL_PROFILES: + if (_profile_installed()) + continue; + $profile = $_GET['profile']; + drupal_install_profile($profile); + drupal_install_profile_post($profile); + // We must reload settings.php, it has been rewritten. + _install_goto('install.php'); + break; + + // Perform any special configuration defined by the profile. + case INSTALL_CONFIGURE: + drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + drupal_install_configure(); + _install_goto('install.php?installed=TRUE'); + break; + + } +} + +/** + * Check if there are any errors at this point in the installation process. + * + * @return + * An array of errors, if any. + */ +function _install_errors() { + $messages = drupal_set_message(); + return $messages['error']; +} + +function _install_include_settings_php() { + global $installed_profile, $base_url, $db_prefix, $db_url, $db_type, $active_db; + + require_once './includes/bootstrap.inc'; + include_once './'. conf_path() .'/settings.php'; + +} + +/** + * Test for the existence of $profile in settings.php. + * + * @return + * TRUE/FALSE if $profile exists. + */ +function _profile_installed() { + global $installed_profile; + _install_include_settings_php(); + + if ($installed_profile) { + return $installed_profile; + } + else { + return FALSE; + } +} + +/** + * Send the user to a different installer page. This issues an on-site HTTP + * redirect. Messages (and errors) are erased. + * + * @param $path + * An installer path. + */ +function _install_goto($path) { + header ('Location: '. $path); + exit(); +} + +/** + * Loads the profile definition, extracting the profile's defined name. + * + * @return + * The name defined in the profile's _profile_details() hook. + */ +function _install_profile_name() { + global $profile; + static $name = NULL; + + if (!isset($name)) { + $profile = $profile ? $profile : $_GET['profile']; + if (!$profile && !($profile = _profile_installed())) { + _install_goto('install.php'); + } + require_once "./profiles/$profile.profile"; + // load profile details + $function = $profile .'_profile_details'; + if (function_exists($function)) { + $details = $function(); + } + $name = isset($details['name']) ? $details['name'] : 'Drupal'; + } + + return $name; +} + +/** + * Auto detect the base_url with PHP predefined variables. + * + * @param $file + * The name of the file calling this function so we can strip it out of + * the URI when generating the base_url. + * + * @return + * The auto-detected $base_url that should be configured in settings.php + */ +function drupal_detect_baseurl($file = 'install.php') { + global $profile; + if (!$profile) { + $profile = $_GET['profile']; + } + $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://'; + $host = $_SERVER['SERVER_NAME']; + $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'. $_SERVER['SERVER_PORT']); + $uri = str_replace("?profile=$profile", '', $_SERVER['REQUEST_URI']); + $dir = str_replace("/$file", '', $uri); + + return "$proto$host$port$dir"; +} + +/** + * Detect all databases supported by Drupal that are compiled into the current + * PHP installation. + * + * @return + * An array of database types compiled into PHP. + */ +function drupal_detect_database_types() { + $databases = array(); + + if (file_exists('./includes/install.mysql.inc')) { + include_once './includes/install.mysql.inc'; + if (mysql_is_available()) { + $databases['mysql'] = 'mysql'; + } + } + if (file_exists('./includes/install.mysqli.inc')) { + include_once './includes/install.mysqli.inc'; + if (mysqli_is_available()) { + $databases['mysqli'] = 'mysqli'; + } + } + if (file_exists('./includes/install.pgsql.inc')) { + include_once './includes/install.pgsql.inc'; + if (pgsql_is_available()) { + $databases['pgsql'] = 'pgsql'; + } + } + + return $databases; +} + +/** + * Verifies that we are able to connect to the defined database, and that we + * have sufficient permissions. + * + * @return + * TRUE/FALSE if we have sufficient permissions. + */ +function install_verify_db() { + global $db_url, $db_type; + + require_once './includes/database.inc'; + + $function = 'drupal_test_'. $db_type; + if (function_exists("$function")) { + return $function($db_url); + } + else { + drupal_set_message(strtr('Installation error: function "%function" does not exist.', array('%function' => $function)), 'error'); + } + return FALSE; +} + +/** + * Read settings.php into a buffer line by line, changing values specified in + * $settings array, then over-writing the old settings.php file. + * + * @param $settings + * An array of settings that need to be updated. + */ +function drupal_rewrite_settings($settings = array(), $prefix = '') { + $settings_file = './'. conf_path() .'/'. $prefix . 'settings.php'; + + $keys = array(); + foreach ($settings as $setting => $data) { + $keys[] = $setting; + } + + $buffer = NULL; + if ($fp = @fopen($settings_file, 'r+')) { + // Step line by line through settings.php + while (!feof($fp)) { + $line = fgets($fp); + // Check for constants + if (substr($line, 0, 7) == 'define(') { + preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line, $variable); + if (in_array($variable[1], $keys)) { + $setting = $settings[$variable[1]]; + $buffer .= str_replace($variable[2], " '". $setting['value'] ."'", $line); + unset($settings[$variable[1]]); + unset($settings[$variable[2]]); + } + else { + $buffer .= $line; + } + } + // Check for variables + elseif (substr($line, 0, 1) == '$') { + preg_match('/\$(.*) /U', $line, $variable); + if (in_array($variable[1], $keys)) { + // Write new value to settings.php in the following format: + // $'setting' = 'value'; // 'comment' + $setting = $settings[$variable[1]]; + $buffer .= '$'. $variable[1] ." = '". $setting['value'] ."';". ($setting['comment'] ? ' // '. $setting['comment'] ."\n" : "\n"); + unset($settings[$variable[1]]); + } + else { + $buffer .= $line; + } + } + else { + $buffer .= $line; + } + } + fclose($fp); + + // Add required settings that were missing from settings.php + foreach ($settings as $setting => $data) { + if ($data['required']) { + $buffer .= "\$$setting = '". $data['value'] ."';\n"; + } + } + + $fp = fopen($settings_file, 'w'); + if ($fp && fwrite($fp, $buffer) === FALSE) { + drupal_set_message("Failed to modify $settings_file, please verify the file permissions.", 'error'); + } + } + else { + drupal_set_message("Failed to open $settings_file, please verify the file permissions.", 'error'); + } +} + +/** + * Verify settings.php, rewriting if necessary. + */ +function install_verify_settings() { + global $db_url, $db_prefix, $db_type, $profile; + $settings_file = './'. conf_path() .'/settings.php'; + + if (isset($_POST['save'])) { + $settings['db_url'] = array( + 'value' => $_POST['db_type'] .'://'. $_POST['db_user'] .($_POST['db_pass'] ? ':'. $_POST['db_pass'] : '') .'@'. ($_POST['db_host'] ? $_POST['db_host'] : 'localhost') .'/'. $_POST['db_path'], + 'required' => TRUE, + ); + if (isset($_POST['db_prefix']) && eregi('[^A-Za-z0-9_]+', $_POST['db_prefix'])) { + drupal_set_message('You database prefix you have entered, '. $_POST['db_prefix'] .', is invalid. The database prefix can only contain alphanumeric characters and underscores.', 'error'); + } + $settings['db_prefix'] = array( + 'value' => $_POST['db_prefix'], + 'required' => TRUE, + ); + drupal_rewrite_settings($settings); + } + + include $settings_file; + + // Verify database settings + $db_type = substr($db_url, 0, strpos($db_url, '://')); + $databases = drupal_detect_database_types(); + if (!in_array($db_type, $databases)) { + drupal_set_message("In your $settings_file file you have configured Drupal to use a $db_type database server, however your PHP installation currently does not support this database type.", 'error'); + } + $url = parse_url($db_url); + $db_user = urldecode($url['user']); + $db_pass = urldecode($url['pass']); + if ($db_user == 'username' && $db_pass == 'password') { + if (isset($_POST['save'])) { + drupal_set_message(strtr('You have configured %drupal to use the default username and password. This is not allowed for security reasons.', array('%drupal' => _install_profile_name())), 'error'); + } + else { + drupal_maintenance_theme(); + drupal_set_title('Database configuration'); + print theme('install_page', strtr('

Please fill out the following information to configure your %drupal site.

', array('%drupal' => _install_profile_name())). drupal_install_settings_form()); + exit; + } + } +} + +/** + * Displays a simple for to configure settings.php. This form is displayed + * before core Drupal code is bootstrapped, so we have to manually create the + * form, unable to use the Forms API. + * + * @return + * A form for modifying settings.php. + */ +function drupal_install_settings_form() { + global $profile, $db_url, $db_type, $db_prefix; + if (!$profile) { + $profile = $_GET['profile']; + } + $url = parse_url($db_url); + $db_user = urldecode($url['user']); + $db_pass = urldecode($url['pass']); + $db_host = urldecode($url['host']); + $db_path = ltrim(urldecode($url['path']), '/'); + + include_once './includes/form.inc'; + include_once './modules/filter.module'; + + // Database type + $element = array( + '#type' => 'select', + '#title' => 'Database type', + '#value' => $_POST['db_type'], + '#name' => 'db_type', + '#required' => TRUE, + '#options' => drupal_detect_database_types(), + '#description' => strtr('Select the type of database you would like to use with your %drupal installation. If you do not find your preferred database type listed here, verify that the database type is supported by Drupal then confirm that it is properly installed and accessible from PHP. Only properly installed databases that are accessible from PHP and recognized by %drupal are displayed in this menu.', array('%drupal' => _install_profile_name())), + '#parents' => array() + ); + $form .= theme('select', $element); + + // Database username + $element = array( + '#type' => 'textfield', + '#title' => 'Database username', + '#value' => $db_user, + '#name' => 'db_user', + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => strtr('The database username that your %drupal installation will use to connect to your database server.', array('%drupal' => _install_profile_name())), + '#parents' => array() + ); + $form .= theme('textfield', $element); + + // Database username + $element = array( + '#type' => 'textfield', + '#title' => 'Database password', + '#value' => $db_pass, + '#name' => 'db_pass', + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => strtr('The database username that your %drupal installation will use to connect to your database server.', array('%drupal' => _install_profile_name())), + '#parents' => array() + ); + $form .= theme('textfield', $element); + + // Database name + $element = array( + '#type' => 'textfield', + '#title' => 'Database name', + '#value' => $db_path, + '#name' => 'db_path', + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => strtr('The name of the database where %drupal can install its database tables.', array('%drupal' => _install_profile_name())), + '#parents' => array() + ); + $form .= theme('textfield', $element); + + // Database host + $element = array( + '#type' => 'textfield', + '#title' => 'Database host', + '#value' => $db_host, + '#name' => 'db_host', + '#size' => 45, + '#maxlength' => 45, + '#required' => TRUE, + '#description' => strtr('The hostname or IP address of your database server. If your database server is on the same machine as you are installing %drupal, you should probably enter "localhost".', array('%drupal' => _install_profile_name())), + '#parents' => array() + ); + $form .= theme('textfield', $element); + + // Database prefix + $element = array( + '#type' => 'textfield', + '#title' => 'Database prefix', + '#value' => $db_prefix, + '#name' => 'db_prefix', + '#size' => 45, + '#maxlength' => 45, + '#required' => FALSE, + '#description' => 'Optionally set a prefix for all database table names. If a prefix is specified, all table names will be prepended with this value. Only alphanumeric characters and the underscore are allowed. If you do not wish to use a prefix, leave this field empty. If you wish to only prefix specific tables, you will need to manually edit your settings.php configuration file.', + '#parents' => array() + ); + $form .= theme('textfield', $element); + + $element = array( + '#type' => 'submit', + '#name' => 'save', + '#value' => 'Save configuration', + ); + $form .= theme('submit', $element); + + $element = array( + '#action' => "install.php?profile=$profile", + '#method' => 'post', + '#children' => $form + ); + return theme('form', $element); + + return "
". $form .'
'; +} + +/** + * Find all .profile's and allow admin to select which to install. + * + * @return + * The selected profile. + */ +function drupal_select_profile() { + include_once './includes/file.inc'; + include_once './includes/form.inc'; + + $profiles = file_scan_directory('./profiles', '\.profile$', array('.', '..', 'CVS'), 0, TRUE, 'name', 0); + // Don't need to choose profile if only one available + if (sizeof($profiles) == 1) { + $profile = array_pop($profiles); + require_once $profile->filename; + return $profile->name; + } + elseif (sizeof($profiles) > 1) { + drupal_maintenance_theme(); + $form = ''; + foreach ($profiles as $profile) { + include_once($profile->filename); + if ($_POST['profile'] == "$profile->name") { + return "$profile->name"; + } + // load profile details + $function = $profile->name .'_profile_details'; + if (function_exists($function)) { + $details = $function(); + } + + // If set, used defined name. Otherwise use file name. + $name = isset($details['name']) ? $details['name'] : $profile->name; + + // Build a quick form. We can't use the core forms api because we + // aren't able to bootstrap Drupal yet. + $element = array( + '#type' => 'radio', + '#name' => 'profile', + '#value' => 'default', + '#return_value' => "$profile->name", + '#title' => "$name", + '#description' => $details['description'], + '#parents' => array() + ); + $group = theme('radio', $element); + + $element = array( + '#value' => $group, + ); + $form .= theme('fieldset', $element); + + } + $element = array( + '#type' => 'submit', + '#name' => 'save', + '#value' => 'Save configuration', + ); + $form .= theme('submit', $element); + + drupal_set_title('Select an installation profile'); + print theme('install_page', '
'. $form .'
'); + exit; + } + else { + return NULL; + } +} + +/** + * Provide module .installs and profiles a chance to request any additional + * configuration. Configuration is performed using the core Forms API, + * through the use of _install_configure(), _install_configure_validate(), and + * _install_configure_submit() hooks. + */ +function drupal_install_configure() { + global $installed_profile, $installs; + require_once "./profiles/$installed_profile.profile"; + + $form = array(); + drupal_set_title('Configuration'); + + $modules = $installed_profile .'_profile_modules'; + $module_list = $modules(); + $installs = drupal_get_install_files($module_list); + foreach ($installs as $install) { + require_once $install->filename; + $install_configure = $install->name .'_install_configure'; + if (function_exists("$install_configure")) { + $install_configure($form); + } + } + + $install_configure = $installed_profile .'_install_configure'; + if (function_exists("$install_configure")) { + $install_configure($form); + } + + if ($form != array()) { + drupal_maintenance_theme(); + $form['submit'] = array('#type' => 'submit', + '#value' => 'Submit'); + + print theme('install_page', drupal_get_form('drupal_install_configure_form', $form)); + exit; + } +} + +/** + * Calls _install_configure_validate hook where exists in .install and .profile + * files. Treat like the standard forms API _validate hook. Note that the + * .profile is called last, so it can modify anything done by module .install + * files. + * + * @param $form_id + * @param $edit + */ +function drupal_install_configure_form_validate($form_id, $edit, $form) { + global $profile, $installs; + + foreach ($installs as $install) { + require_once $install->filename; + $install_configure_validate = $install->name .'_install_configure_validate'; + if (function_exists("$install_configure_validate")) { + $install_configure_validate($form_id, $edit, $form); + } + } + + $install_configure_validate = $profile .'_install_configure_validate'; + if (function_exists("$install_configure_validate")) { + $install_configure_validate($form_id, $edit); + } + +} + +/** + * Calls _install_configure_submit hook where exists in .install and .profile + * files. Treat like the standard forms API _submit hook. Note that the + * .profile is called last, so it can modify anything done by module .install + * files. + * + * @param $form_id + * @param $edit + */ +function drupal_install_configure_form_submit($form_id, $edit) { + global $profile, $installs; + + foreach ($installs as $install) { + require_once $install->filename; + $install_configure_submit = $install->name .'_install_configure_submit'; + if (function_exists("$install_configure_submit")) { + $install_configure_submit($form_id, $edit); + } + } + + $install_configure_submit = $profile .'_install_configure_submit'; + if (function_exists("$install_configure_submit")) { + $install_configure_submit($form_id, $edit); + } + + _install_goto('install.php?installed=TRUE'); +} + +/** + * Merge requirements arrays. + */ +/** + * Merge requirements arrays. + */ +function _merge_requirements($requirements_old, $requirements_new) { + foreach ($requirements_new as $new => $data) { + if (isset($requirements_old["$new"])) { + // Use largest version + if (isset($data['required_version'])) { + if (version_compare($requirements_old["$new"]['required_version'], $data['required_version']) < 0) { + $requirements_old["$new"] = $data; + } + } + // Use largest value + elseif (isset($data['required_value'])) { + if ($requirements_old["$new"]['required_value'] < $data['required_value']) { + $requirements_old["$new"] = $data; + } + } + elseif (is_array($data)) { + $requirements_old["$new"] = _merge_requirements($requirements_old["$new"], $data); + } + } + else { + $requirements_old["$new"] = $data; + } + } + return $requirements_old; +} + +/** + * Merge table creation scripts. If the same table is defined multiple times, + * use the latest version of the schema. + */ +function _merge_tables($tables_old, $tables_new) { + foreach ($tables_new as $new => $data) { + if (isset($tables_old["$new"])) { + if ($tables_old["$new"]['schema'] < $data['schema']) { + $tables_old["$new"] = $data; + } + } + else { + $tables_old["$new"] = $data; + } + } + return $tables_old; +} + +/** + * Get list of all .install files. + * + * @param $module_list + * An array of modules to search for their .install files. + */ +function drupal_get_install_files($module_list = array()) { + $installs = array(); + foreach ($module_list as $module) { + $installs = array_merge($installs, file_scan_directory('./modules', "^$module.install$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0)); + } + return $installs; +} + +/** + * An error page to display when there are no profiles available. + */ +function _install_no_profile_error() { + drupal_maintenance_theme(); + drupal_set_title('No profiles available'); + print theme('install_page', '

We were unable to find any installer profiles. Installer profiles tell us what modules to enable, and what schema to install in the database. A profile is necessary to continue with the installation process.

'); + exit; +} + +/** + * Installed profile. + * + * @param profile + * Name of profile to install. + */ +function drupal_install_profile($profile) { + global $db_type; + + include './includes/module.inc'; + include './includes/file.inc'; + + $profile_file = "./profiles/$profile.profile"; + + if (!isset($profile) || !file_exists($profile_file)) { + _install_no_profile_error(); + } + + require_once($profile_file); + + // Get a list of modules required by this profile + $function = $profile .'_profile_modules'; + $module_list = $function(); + + // Verify that all required modules exist + $modules = array(); + foreach ($module_list as $current) { + $module = file_scan_directory('./modules', "^$current.module$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0); + if (empty($module)) { + drupal_set_message("The $current module is required but was not found. Please move the file $current.module into the modules subdirectory.", 'error'); + } + else { + $modules = array_merge($modules, $module); + } + } + + // Get a list of all .install files + $installs = drupal_get_install_files($module_list); + + // Verify the _requirements_pre for this profile and all its modules + $requirements = array(); + $function = $profile .'_requirements_pre'; + if (function_exists("$function")) { + $requirements = $function(); + } + foreach ($installs as $install) { + require_once $install->filename; + $function = $install->name .'_requirements_pre'; + if (function_exists("$function")) { + $requirements = _merge_requirements($requirements, $function()); + } + } + drupal_verify_install($requirements); + if (_install_errors()) { + drupal_maintenance_theme(); + drupal_set_title('Verify your install environment'); + print theme('install_page', '

The errors above must be resolved before you can install Drupal. Find additional information about Drupal\'s minimum system requirements here.

'); + exit; + } + + // Install schemas for profile and all its modules + $function = $profile .'_install'; + if (function_exists($function)) { + $function(); + } + + foreach ($installs as $install) { + module_invoke($install->name, 'install'); + } + + // Enable the modules required by the profile + db_query("DELETE FROM {system} WHERE type = 'module'"); + foreach ($modules as $module) { + switch ($db_type) { + case 'mysql': + case 'mysqli': + db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES('". $module->filename ."', '". $module->name ."', 'module', '', 1, 0, 0, 0)"); + break; + case 'pgsql': + break; + } + } + + // Update settings.php to show that the installer has already been run + $settings = array(); + $settings['installed_profile'] = array( + 'value' => $profile, + 'required' => TRUE + ); + drupal_rewrite_settings($settings); +} + +/** + * Execute the _requirements_post hook in module installs and profiles. + * + * @param $profile + */ +function drupal_install_profile_post($profile = NULL) { + if (!isset($profile)) { + // Nothing to do, exit + return; + } + require_once "./profiles/$profile.profile"; + require_once "./includes/file.inc"; + + // Get a list of modules required by this profile + $function = $profile .'_profile_modules'; + $module_list = $function(); + + // Get a list of all .install files + $installs = drupal_get_install_files($module_list); + + // Verify the _requirements_post for this profile and all its modules + $requirements = array(); + $function = $profile .'_requirements_post'; + if (function_exists("$function")) { + $requirements = $function(); + } + foreach ($installs as $install) { + require_once $install->filename; + $function = $install->name .'_requirements_post'; + if (function_exists("$function")) { + $requirements = _merge_requirements($requirements, $function()); + } + } + drupal_verify_install($requirements); +} + +/** + * Page displayed when the installation is complete. Called from install.php. + */ +function drupal_install_complete() { + global $base_url; + + if (!_profile_installed()) { + // The installer hasn't run before, start at the beginning. + _install_goto('install.php'); + } + + require_once './includes/bootstrap.inc'; + drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); + drupal_maintenance_theme(); + drupal_set_title(strtr('%drupal installation complete', array('%drupal' => _install_profile_name()))); + print theme('maintenance_page', strtr('

Congratulations, %drupal has been successfully installed. Please review any warnings or errors that you might see above before continuing on to your new website.', array('%drupal' => _install_profile_name(), '%path' => "$base_url"))); +} + +/** + * Call the appropriate installation function. If the function is not + * available, attempt to load the appropriate include file then try again. + * + * @param $requirements + * An array of requirements. + */ +function drupal_verify_install($requirements = array()) { + foreach ($requirements as $type => $data) { + $function = "drupal_verify_install_$type"; + if (function_exists("$function")) { + $function($data); + } + else { + switch ($type) { + case 'mysql': + case 'mysqli': + case 'pgsql': + // The include files for all available database types have already + // been included. Thus, we are not using this database type and this + // requirement does not apply to the current installation. + continue; + case 'apache': + default: + $include = './includes/install.'. $type .'.inc'; + if (file_exists($include)) { + require_once($include); + if (function_exists("$function")) { + $function($data); + } + else { + drupal_set_message(strtr('Installation error: function "%function" does not exist.', array('%function' => $function)), 'error'); + } + } + else { + drupal_set_message(strtr('Installation error: unable to find file "%file", function "%function" does not exist.', array('%file' => $include, '%function' => $function)), 'error'); + } + } + } + } +} + +/** + * Some php.ini options are written in shorthand (ie 1K instead of 1024 bytes). + * This function converts php.ini shorthand into bytes. + * + * @param $shorthand + * A memory string in php.ini shorthand notation (ie 1K, 8M, 10G) + * + * @return + * The shorthand value converted to bytes. + */ +function drupal_shorthand_to_bytes($shorthand) { + $result = trim($shorthand); + $modifier = strtolower($result{strlen($result)-1}); + switch ($modifier) { + case 'g': + $result *= 1024; + case 'm': + $result *= 1024; + case 'k': + $result *= 1024; + } + return $result; +} + +/** + * Verify that the installed version of PHP meets our minimum requirements. + * + * @param $version + * An array with some or all of the following directives: + * 'required_version' = the required version of PHP + * 'message' = message to display if version is invalid + * ("%required_version" and "%installed_version" will be + * automatically replaced if included in the message + * text.) + * 'message_type' = message type (ie, 'error', 'status') + */ +function drupal_verify_version_php($version = array()) { + if (!function_exists(version_compare) || + version_compare(phpversion(), $version['required_version'], '<')) { + // version_compare() was added in PHP 4.1. + $message_type = $version['message_type'] ? $version['message_type'] : 'status'; + drupal_set_message(strtr($version['message'], array('%required_version' => $version['required_version'], '%installed_version' => phpversion())), $message_type); + } +} + +/** + * Verify the value of the specified configuration option as found in php.ini. + * + * @param $setting + * An array with some or all of the following directives: + * 'required_value' = the required value of the configuration option + * 'shorthand' = TRUE/FALSE whether the option is in shorthand notation + * 'operator' = optional comparison operator + * 'message' = message to display if comparison fails + * ("%required_value" and "%current_value" will be + * automatically replaced if included in the message + * text.) + * 'message_type' = message type (ie, 'error', 'status') + */ +function drupal_verify_install_php($requirements = array()) { + foreach ($requirements as $requirement => $data) { + // Handle special case (not from php.ini) + if ($requirement == 'version') { + drupal_verify_version_php($data); + } + else { + if ($data['shorthand']) { + $required = drupal_shorthand_to_bytes($data['required_value']); + $current = drupal_shorthand_to_bytes(ini_get($requirement)); + } + else { + $required = $data['required_value']; + $current = ini_get($requirement); + } + + switch ($data['operator']) { + case '<': + $valid = ($current < $required); + break; + case '<=': + $valid = ($current <= $required); + break; + case '==': + default: + $valid = ($current == $required); + break; + case '>=': + $valid = ($current >= $required); + break; + case '>': + $valid = ($current > $required); + break; + case '!=': + case '<>': + $valid = ($current != $required); + break; + case '===': + $valid = ($current === $required); + break; + case '!==': + $valid = ($current !== $required); + break; + } + + if (!$valid && isset($data['message'])) { + $message_type = $data['message_type'] ? $data['message_type'] : 'status'; + drupal_set_message(strtr($data['message'], array('%current_value' => ini_get($requirement), '%required_value' => $data['required_value'])), $message_type); + } + } + } +} + +/** + * Verify the state of the specified file. + * + * @param $requirements + * An array with some or all of the following directives: + * 'required' = whether or not this file is required + * 'mask' = permissions information about the file + * 'type' = file type (file, directory, link) + * 'message' = message to display if something is wrong with file + * ("%required_value" and "%current_value" will be + * automatically replaced if included in the message + * text.) + * 'message_type' = message type (ie, 'error', 'status') + */ +function drupal_verify_install_file($requirements = array()) { + foreach ($requirements as $file => $data) { + // Handle special case files (ie settings.php) + switch ($file) { + case '%settings.php': + $file = './'. conf_path() .'/settings.php'; + break; + } + + $err = FALSE; + $message_type = ($data['required'] ? 'error' : 'status'); + // Check for files that shouldn't be there + if (isset($data['mask']) && $data['mask'] & FILE_NOT_EXIST) { + if (file_exists($file)) { + drupal_set_message(strtr('%type %file exists but should not.', array('%type' => $data['type'], '%file' => $file)), $message_type); + $err = TRUE; + } + } + else { + // Verfiy that the file is the type of file it is supposed to be + if (isset($data['type']) && file_exists($file)) { + switch ($data['type']) { + case 'file': + if (!is_file($file)) { + $err = TRUE; + } + break; + case 'directory': + if (!is_dir($file)) { + $err = TRUE; + } + break; + case 'link': + if (!is_link($file)) { + $err = TRUE; + } + break; + } + if ($err) { + drupal_set_message(strtr('%file exists but is not a %type.', array('%type' => $data['type'], '%file' => $file)), $message_type); + } + } + + // Verify file permissions + if (isset($data['mask'])) { + $filetype = ucfirst($data['type']); + $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_EXIST, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); + foreach ($masks as $mask) { + if ($data['mask'] & $mask && !$err) { + switch ($mask) { + case FILE_EXIST: + if (!file_exists($file)) { + if ($filetype == 'Directory') { + drupal_install_mkdir($file, $data['mask']); + } + if (!file_exists($file)) { + drupal_set_message(strtr('%type %file does not exist.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + } + break; + case FILE_READABLE: + if (!is_readable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is not readable.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + case FILE_WRITABLE: + if (!is_writable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is not writable.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + case FILE_EXECUTABLE: + if (!is_executable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is not executable.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + case FILE_NOT_READABLE: + if (is_readable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is readable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + case FILE_NOT_WRITABLE: + if (is_writable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is writable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + case FILE_NOT_EXECUTABLE: + if (is_executable($file) && !drupal_install_fix_file($file, $data['mask'])) { + drupal_set_message(strtr('%type %file is executable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type); + $err = TRUE; + } + break; + } + } + } + } + } + if ($err && isset($data['message'])) { + $message_type = $data['message_type'] ? $data['message_type'] : 'status'; + drupal_set_message($data['message'], $message_type); + } + } +} + +/** + * Create a directory with specified permissions. + * + * @param file + * The name of the directory to create; + * @param mask + * The permissions of the directory to create. + * + * @return + * TRUE/FALSE whether or not the directory was successfully created. + */ +function drupal_install_mkdir($file, $mask) { + $mod = 0; + $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); + foreach ($masks as $m) { + if ($mask & $m) { + switch ($m) { + case FILE_READABLE: + $mod += 444; + break; + case FILE_WRITABLE: + $mod += 222; + break; + case FILE_EXECUTABLE: + $mod += 111; + break; + } + } + } + + if (@mkdir($file, intval("0$mod", 8))) { + drupal_set_message("Automatically created directory $file.", 'status'); + return TRUE; + } + else { + drupal_set_message("Failed to automatically create directory $file, insufficient privileges.", 'status'); + } +} + +/** + * Attempt to fix file permissions. + * + * @param $file + * The name of the file with permissions to fix. + * @param $mask + * The desired permissions for the file. + * + * @return + * TRUE/FALSE whether or not we were able to fix the file's permissions. + */ +function drupal_install_fix_file($file, $mask) { + $mod = substr(sprintf('%o', fileperms($file)), -4); + $prefix = substr($mod, 0, 1); + $mod = substr($mod, 1 ,4); + $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); + foreach ($masks as $m) { + if ($mask & $m) { + switch ($m) { + case FILE_READABLE: + if (!is_readable($file)) { + $mod += 444; + } + break; + case FILE_WRITABLE: + if (!is_writable($file)) { + $mod += 222; + } + break; + case FILE_EXECUTABLE: + if (!is_executable($file)) { + $mod += 111; + } + break; + case FILE_NOT_READABLE: + if (is_readable($file)) { + $mod -= 444; + } + break; + case FILE_NOT_WRITABLE: + if (is_writable($file)) { + $mod -= 222; + } + break; + case FILE_NOT_EXECUTABLE: + if (is_executable($file)) { + $mod -= 111; + } + break; + } + } + } + + if (@chmod($file, intval("$prefix$mod", 8))) { + drupal_set_message("Automatically fixed the permissions of file $file.", 'status'); + return TRUE; + } + else { + drupal_set_message("Failed to automatically fix permissions of file $file, insufficient privileges.", 'status'); + return FALSE; + } +} + +/** + * Verify that a function exists. + * + * @param $requirements + * An array with some or all of the following directives: + * 'message' = message to display if the function does not exist. + * 'message_type' = message type (ie, 'error', 'status') + */ +function drupal_verify_install_function($requirements = array()) { + foreach ($requirements as $function => $data) { + if (!function_exists("$function")) { + $message_type = $data['message_type'] ? $data['message_type'] : 'status'; + drupal_set_message($data['message'], $message_type); + } + } +} + +?> --- includes/theme.inc.orig 2006-06-07 14:37:37.000000000 -0400 +++ includes/theme.inc 2006-06-07 14:34:57.000000000 -0400 @@ -453,17 +453,62 @@ return $output; } +function theme_install_page($content) { + drupal_set_header('Content-Type: text/html; charset=utf-8'); + theme('add_style', 'misc/maintenance.css'); + drupal_set_html_head(''); + $output = "\n"; + $output .= ''; + $output .= ''; + $output .= ' '. drupal_get_title() .''; + $output .= drupal_get_html_head(); + $output .= theme_get_styles(); + $output .= ''; + $output .= ''; + $output .= '

' . drupal_get_title() . '

'; + + $messages = drupal_set_message(); + if (isset($messages['error'])) { + $output .= '

The following errors must be resolved before you can continue the installation process:

'; + $output .= theme('status_messages', 'error'); + } + + $output .= "\n\n"; + $output .= $content; + $output .= "\n\n"; + + if (isset($messages['status'])) { + $output .= '

The following installation warnings should be carefully reviewed, but in most cases may be safely ignored:

'; + $output .= theme('status_messages', 'status'); + } + + $output .= ''; + + return $output; +} + /** * Returns themed set of status and/or error messages. The messages are grouped * by type. * + * @param $display + * Optional string if wish to display only 'error' or 'status' messages. + * * @return * A string containing the messages. */ -function theme_status_messages() { - if ($data = drupal_get_messages()) { +function theme_status_messages($display = NULL) { + static $data; + + if (!$data) { + $data = drupal_get_messages(); + } + if ($data) { $output = ''; foreach ($data as $type => $messages) { + if ($display && $display != $type) { + continue; + } $output .= "
\n"; if (count($messages) > 1) { $output .= "
\n"; + unset($data["$type"]); } return $output; --- includes/install.mysql.inc.orig 1969-12-31 19:00:00.000000000 -0500 +++ includes/install.mysql.inc 2006-06-07 14:30:19.000000000 -0400 @@ -0,0 +1,195 @@ + $data) { + switch ($requirement) { + case 'version': + drupal_verify_version_mysql($data); + break; + } + } +} + +/** + * Check if MySQL is available. + * + * @return + * TRUE/FALSE + */ +function mysql_is_available() { + if (function_exists('mysql_connect')) { + return TRUE; + } + return FALSE; +} + +/** + * Check if we can connect to MySQL. + * + * @return + * TRUE/FALSE + */ +function drupal_test_mysql($url) { + if (!mysql_is_available()) { + drupal_set_message('PHP MySQL support not enabled.', 'error'); + } + + $url = parse_url($url); + + // Decode url-encoded information in the db connection string + $url['user'] = urldecode($url['user']); + $url['pass'] = urldecode($url['pass']); + $url['host'] = urldecode($url['host']); + $url['path'] = urldecode($url['path']); + + // Allow for non-standard MySQL port. + if (isset($url['port'])) { + $url['host'] = $url['host'] .':'. $url['port']; + } + + if ($connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2)) { + // Test selecting the database + if (!mysql_select_db(substr($url['path'], 1))) { + drupal_set_message('We were able to connect to the MySQL database server (which means your username and password are valid) but not able to select your database. MySQL reports the following message: '. mysql_error() .'For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', 'error'); + return FALSE; + } + + // Test CREATE + $query = 'CREATE TABLE drupal_install_test (id int(1) NULL);'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to create a test table on your MySQL database server. MySQL reports the following message: "'. $error .'"For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', 'error'); + return FALSE; + } + $err = FALSE; + $success = array('SELECT', 'CREATE'); + + // Test INSERT + $query = 'INSERT INTO drupal_install_test (id) VALUES(1);'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to insert a value into a test table on your MySQL database server. We tried inserting a value with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'INSERT'; + } + + // Test UPDATE + $query = 'UPDATE drupal_install_test SET id = 2;'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to update a value in a test table on your MySQL database server. We tried updating a value with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'UPDATE'; + } + + // Test LOCK + $query = 'LOCK TABLES drupal_install_test WRITE;'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to lock a test table on your MySQL database server. We tried locking a table with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'LOCK'; + } + + // Test UNLOCK + $query = 'UNLOCK TABLES;'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to unlock a test table on your MySQL database server. We tried unlocking a table with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'UNLOCK'; + } + + // Test DELETE + $query = 'DELETE FROM drupal_install_test;'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to delete a value from a test table on your MySQL database server. We tried deleting a value with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'DELETE'; + } + + // Test DROP + $query = 'DROP TABLE drupal_install_test;'; + $result = mysql_query("$query"); + if ($error = mysql_error()) { + drupal_set_message('We were unable to drop a test table from your MySQL database server. We tried dropping a table with the command "'. $query .'" and MySQL reported the following error: "'. $error .'".', 'error'); + $err = TRUE; + } + else { + $success[] = 'DROP'; + } + + if ($err) { + drupal_set_message('In order for Drupal to work and to proceed with the installation process you must resolve all MySQL permission issues reported above. We were able to verify that we have permission for the following MySQL commands: '. implode($success, ', ') .'. For more help with configuring your MySQL database server, see the Installation and upgrading handbook. If you are unsure what any of this means you should probably contact your hosting provider.', 'error'); + return FALSE; + } + + mysql_close($connection); + return TRUE; + } + else { + drupal_set_message('Failure to connect to your MySQL database server. MySQL reports the following message: '. mysql_error() .'For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.', 'error'); + } + return FALSE; +} + +/** + * Check if MySQL is currently being used. + * + * @return + * 0 = not MySQL, 1 = MySQL + */ +function _using_mysql() { + global $db_type; + + if ($db_type == 'mysql') { + return 1; + } + else { + return 0; + } +} + +/** + * Retrieve the version of MySQL that is currently being used. + * + * @param $version + * An array containing version information and a message if the installed + * version of MySQL doesn't meet the minimum requirements. + * Recognized options: + * - 'required_version': the required version of MySQL + * - 'message': message to display if insufficient version of MySQL + * - 'message_type': 'error' if critical, 'status' if warning + */ +function drupal_verify_version_mysql($version = array()) { + global $active_db; + + if (!isset($active_db)) { + drupal_set_message('No connection to MySQL database, unable to verify MySQL version.', 'error'); + } + elseif (version_compare(mysql_get_server_info($active_db), $version['required_version'], '<')) { + drupal_set_message(strtr($version['message'], array('%required_version' => $version['required_version'], '%installed_version' => mysql_get_server_info($active_db))), $version['message_type']); + } +} + +?> --- includes/install.apache.inc.orig 1969-12-31 19:00:00.000000000 -0500 +++ includes/install.apache.inc 2006-06-07 14:30:19.000000000 -0400 @@ -0,0 +1,78 @@ + $data) { + switch ($requirement) { + case 'version': + _drupal_verify_version_apache($data); + break; + case 'module': + _drupal_verify_modules_apache($data); + break; + } + } +} + +/** + * Check if Apache is currently being used to serve Drupal pages. + * + * @return + * 0 = not Apache, 1 = Apache + */ +function _using_apache() { + return preg_match('/apache/i', $_SERVER['SERVER_SOFTWARE']); +} + +/** + * Verify that the version of Apache that is currently being used meets our + * minimum requirements. + * + * @param $version + * An array containing version information and a message if the installed + * version of Apache doesn't meet the minimum requirements. + * Recognized options: + * - 'required_version': the required version of Apache + * - 'message': message to display if insufficient version of Apache + * - 'message_type': 'error' if critical, 'status' if warning + */ +function _drupal_verify_version_apache($version = array()) { + preg_match('!Apache/(.*) !U', apache_get_version(), $v); + $installed_version = $v[1]; + if (version_compare($installed_version, $version['required_version'], '<')) { + $message_type = $data['message_type'] ? $version['message_type'] : 'status'; + drupal_set_message(strtr($version['message'], array('%required_version' => $version['required_version'], '%installed_version' => $installed_version)), $message_type); + } +} + +/** + * Check to see if the required Apache modules are installed. + * + * @param @modules + * An array of required modules. + */ +function _drupal_verify_modules_apache($modules = array()) { + // TODO: Is it possible to verify Apache modules without using the function + // apache_get_modules()? + if (function_exists('apache_get_modules')) { + foreach ($modules as $module => $data) { + if (!in_array($module, apache_get_modules())) { + $message_type = $data['message_type'] ? $data['message_type'] : 'status'; + drupal_set_message($data['message'], $message_type); + } + } + } +} +?> --- includes/database.mysql.inc.orig 2006-06-07 14:37:49.000000000 -0400 +++ includes/database.mysql.inc 2006-06-07 14:30:19.000000000 -0400 @@ -51,6 +51,12 @@ // (matched) rows, not the number of affected rows. $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2); if (!$connection) { + global $install; + $install = TRUE; + include_once './includes/install.inc'; + if (!_profile_installed()) { + _install_goto('install.php'); + } drupal_maintenance_theme(); drupal_set_title('Unable to connect to database server'); print theme('maintenance_page', '

This either means that the username and password information in your settings.php file is incorrect or we can\'t contact the MySQL database server. This could mean your hosting provider\'s database server is down.

--- includes/database.mysqli.inc.orig 2006-06-07 14:37:54.000000000 -0400 +++ includes/database.mysqli.inc 2006-06-07 14:30:19.000000000 -0400 @@ -43,6 +43,12 @@ // Find all database connection errors and error 1045 for access denied for user account if (mysqli_connect_errno() >= 2000 || mysqli_connect_errno() == 1045) { + global $install; + $install = TRUE; + include_once './includes/install.inc'; + if (!_profile_installed()) { + _install_goto('install.php'); + } drupal_maintenance_theme(); drupal_set_title('Unable to connect to database server'); print theme('maintenance_page', '

This either means that the username and password information in your settings.php file is incorrect or we can\'t contact the MySQL database server through the mysqli libraries. This could also mean your hosting provider\'s database server is down.

--- modules/system.install.orig 1969-12-31 19:00:00.000000000 -0500 +++ modules/system.install 2006-06-07 22:56:00.000000000 -0400 @@ -0,0 +1,1446 @@ + DRUPAL_MINIMUM_PHP, + 'message' => 'Drupal requires PHP version %required_version or greater. You are using PHP version %installed_version so Drupal will not work properly on this installation.', + 'message_type' => 'error' + ); + + // Verify safe_mode + $requirements['php']['safe_mode'] = array( + 'required_value' => 0, + 'message' => 'PHP safe_mode is currently enabled. You must disable safe_mode for Drupal to properly function.', + 'message_type' => 'error' + ); + + // Verify register_globals + $requirements['php']['register_globals'] = array( + 'required_value' => 0, + 'message' => 'PHP register_globals is currently enabled. As of Drupal 4.2.0 it is advised that you disable register_globals.' + ); + + // Verify PHP memory limits + if (function_exists(memory_get_usage)) { + // memory_get_usage() will only be defined if PHP is compiled with + // the --enable-memory-limit configuration option. + $requirements['php']['memory_limit'] = array( + 'required_value' => DRUPAL_MINIMUM_MEMORY, + 'operator' => '>=', + 'message' => 'Your PHP installation limits Drupal to using only %current_value of RAM. It is suggested that you modify the memory_limit directive to allow at least %required_value of RAM.', + 'shorthand' => TRUE + ); + } + + $requirements['file']['./cron.php'] = array( + 'type' => 'file', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_NOT_WRITEABLE, + 'message' => 'The cron.php file provides automation for Drupal functionality. Most installations will want this file properly installed. The file should be readable not writeable (The file must not be writeable as that would be a security risk).', + 'message_type' => 'error' + ); + + $requirements['file']['./index.php'] = array( + 'type' => 'file', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_NOT_WRITEABLE, + 'required' => TRUE, + 'message' => 'The index.php file is Drupal\'s main interface with the world. This file must be readable and not writeable. (The file must not be writeable as that would be a security risk).', + 'message_type' => 'error' + ); + + $requirements['file']['./xmlrpc.php'] = array( + 'type' => 'file', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_NOT_WRITEABLE, + 'required' => TRUE + ); + + // %settings.php is a special case, Drupal will search for it... + $requirements['file']['%settings.php'] = array( + 'type' => 'file', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_WRITEABLE, + 'required' => TRUE, + 'message' => 'The Drupal installer requires write permissions to settings.php during the installation process.', + 'message_type' => 'error' + ); + + $requirements['file']['./files'] = array( + 'type' => 'directory', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_WRITEABLE, + 'required' => FALSE, + 'message' => 'The "files" subdirectory can be created in your installation directory to store files such as custom logos, user avatars, and other media associated with your new site. The sub-directory requires "read and write" permission by the Drupal server process if you wish to provide this functionality.', + ); + + // If using Apache to serve pages + $requirements['apache']['version'] = array( + 'required_version' => DRUPAL_MINIMUM_APACHE, + 'message' => 'Drupal requires Apache version %required_version or greater. You are using Apache version %installed_version so Drupal will not work properly on this installation.', + 'message_type' => 'error' + ); + + $requirements['apache']['module']['mod_rewrite'] = array( + 'message' => 'Apache\'s mod_rewrite is not enabled. You will need to enable mod_rewrite if you wish to use Drupal\'s Clean URL functionality.' + ); + + $requirements['function']['gzencode4'] = array( + 'message' => 'For improved Drupal performance and reduced bandwidth consumption you can enable the PHP zlib extension. If enabled, Drupal will compress cached pages and serve these pre-compressed pages to web browsers that support gzip.' + ); + + return $requirements; +} + +/** + * The install _requirements_pre hook is called after we have a established a + * connection to the database. This hook will be called in non-core modules + * after Drupal core has been successfully installed. + */ +function system_requirements_pre() { + $requirements = array(); + + $requirements['mysql']['version'] = array( + 'required_version' => DRUPAL_MINIMUM_MYSQL, + 'message' => 'Drupal requires MySQL version %required_version or greater. You are using MySQL version %installed_version so Drupal will not work properly on this installation.', + 'message_type' => 'error' + ); + $requirements['pgsql']['version'] = array( + 'required_version' => DRUPAL_MINIMUM_PGSQL, + 'message' => 'Drupal requires PostgreSQL version %required_version or greater. You are using PostgreSQL version %installed_version so Drupal will not work properly on this installation.', + 'message_type' => 'error' + ); + + return $requirements; +} + +/** + * Install _requirements_post hook is called after the installation process + * is complete. + */ +function system_requirements_post() { + $requirements['file']['%settings.php'] = array( + 'type' => 'file', + 'mask' => FILE_EXIST|FILE_READABLE|FILE_NOT_WRITEABLE, + 'required' => TRUE, + 'message' => 'All necessary changes to settings.php have been made, so you should now remove write permissions to this file. Failure to remove write permissions to this file is a security risk.', + 'message_type' => 'error' + ); + + return $requirements; +} + +?> --- profiles/default.profile.orig 1969-12-31 19:00:00.000000000 -0500 +++ profiles/default.profile 2006-06-07 14:30:19.000000000 -0400 @@ -0,0 +1,22 @@ + 'Drupal', + 'description' => 'Select this profile to enable some basic Drupal functionality and the default theme.'); +} + +?>