=== modified file 'includes/bootstrap.inc'
--- includes/bootstrap.inc	
+++ includes/bootstrap.inc	
@@ -151,9 +151,9 @@ function drupal_unset_globals() {
  * Loads the configuration and sets the base URL correctly.
  */
 function conf_init() {
-  global $db_url, $db_prefix, $base_url, $base_path, $base_root, $conf;
+  global $db_url, $db_prefix, $base_url, $base_path, $base_root, $conf, $installed_profile;
   $conf = array();
-  require_once './'. conf_path() .'/settings.php';
+  include_once './'. conf_path() .'/settings.php';
 
   if (isset($base_url)) {
     // Parse fixed base URL from settings.php.
=== modified file 'includes/install.inc'
--- includes/install.inc	
+++ includes/install.inc	
@@ -4,15 +4,33 @@
 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;
+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 +97,865 @@ function drupal_get_installed_schema_ver
 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() {
+  global $profile;
+  require_once './includes/bootstrap.inc';
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
+  require_once './modules/system.install';
+  if (!isset($GLOBALS['installed_profile'])) {
+    if (!empty($_GET['profile'])) {
+      $profile = preg_replace('/[^a-zA-Z_0-9]/', '', $_GET['profile']);
+    }
+    elseif ($profile = drupal_select_profile()) {
+      _install_goto("install.php?profile=$profile");
+    }
+    else {
+      _install_no_profile_error();
+    }
+    // load the profile
+    require_once "./profiles/$profile.profile";
+    // Configure settings.php.
+    install_verify_settings();
+    // Establish a connection to the database.
+    install_verify_db();
+    db_set_active();
+    // Perform actual installation defined in the profile.
+    drupal_install_profile($profile);
+    // We must reload settings.php, it has been rewritten.
+    _install_goto('install.php');
+  }
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  drupal_install_configure();
+  _install_goto('install.php?installed=TRUE');
+}
+
+/**
+ * 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) {
+  global $base_path;
+  header ('Location: '. $base_path . $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)) {
+    // 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;
+  $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(st('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;
+  $first = TRUE;
+  if ($fp = @fopen($settings_file, 'r+')) {
+    // Step line by line through settings.php
+    while (!feof($fp)) {
+      $line = fgets($fp);
+      if ($first && substr($line, 0, 5) != '<?php') {
+        $buffer = "<?php\n\n";
+      }
+      $first = FALSE;
+      // 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 $profile, $db_url, $db_type, $db_prefix, $conf;
+  $settings_file = './'. conf_path() .'/settings.php';
+  include $settings_file;
+
+  $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']), '/');
+  // we always need this because we want to run form_get_errors
+  include_once './includes/form.inc';
+
+  // initialize module subsystem
+  $conf['module_list']['system']['filename'] = 'modules/system.module';
+  $conf['module_list']['filter']['filename'] = 'modules/filter.module';
+  include_once('./includes/module.inc');
+  module_load_all();
+
+  if ($_SERVER['REQUEST_METHOD'] == 'GET') {
+    _drupal_install_settings_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_path, $settings_file);
+    if (!form_get_errors()) {
+      return;
+    }
+  }
+
+  // Database type
+  $form['db_type'] = array(
+    '#type' => 'select',
+    '#title' => 'Database type',
+    '#required' => TRUE,
+    '#options' => drupal_detect_database_types(),
+    '#default_value' => $db_type,
+    '#description' => st('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 <a href="http://drupal.org/node/270#database">supported by Drupal</a> 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())),
+  );
+  // Database username
+  $form['db_user'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Database username',
+    '#default_value' => $db_user,
+    '#size' => 45,
+    '#maxlength' => 45,
+    '#required' => TRUE,
+    '#description' => st('The database username that your %drupal installation will use to connect to your database server.', array('%drupal' => _install_profile_name())),
+  );
+
+  // Database username
+  $form['db_pass'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Database password',
+    '#default_value' => $db_pass,
+    '#size' => 45,
+    '#maxlength' => 45,
+    '#required' => TRUE,
+    '#description' => st('The database username that your %drupal installation will use to connect to your database server.', array('%drupal' => _install_profile_name())),
+  );
+
+  // Database name
+  $form['db_path'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Database name',
+    '#default_value' => $db_path,
+    '#size' => 45,
+    '#maxlength' => 45,
+    '#required' => TRUE,
+    '#description' => st('The name of the database where %drupal can install its database tables.', array('%drupal' => _install_profile_name())),
+  );
+
+  // Database host
+  $form['db_host'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Database host',
+    '#default_value' => $db_host,
+    '#size' => 45,
+    '#maxlength' => 45,
+    '#required' => TRUE,
+    '#description' => st('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())),
+  );
+
+  // Database prefix
+  $form['db_prefix'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Database prefix',
+    '#default_value' => $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 <code>settings.php</code> configuration file.',
+  );
+
+  $form['save'] = array(
+    '#type' => 'submit',
+    '#value' => 'Save configuration',
+  );
+  $form['errors'] = array();
+  $form['settings_file'] = array('#type' => 'value', '#value' => $settings_file);
+  $form['_db_url'] = array('#type' => 'value');
+  $form['#action'] = "install.php?profile=$profile";
+  $form['#redirect'] = NULL;
+  drupal_maintenance_theme();
+  $output = drupal_get_form('drupal_install_settings', $form);
+  drupal_set_title('Database configuration');
+  print theme('install_page', st('<p>Please fill out the following information to configure your %drupal site.</p>', array('%drupal' => _install_profile_name())). $output);
+  exit;
+}
+
+function st($string, $args = array()) {
+  return strtr($string, array_map('check_plain', $args));
+}
+
+function _drupal_install_settings_validate($db_prefix, $db_type, $db_user, $db_pass, $db_host, $db_path, $settings_file, $form = NULL) {
+  global $db_url;
+  if (!empty($db_prefix) && preg_match('/[^A-Za-z0-9_]/', $db_prefix)) {
+    form_set_error('db_prefix', st('The database prefix you have entered, <code>%db_prefix</code>, is invalid.  The database prefix can only contain alphanumeric characters and underscores.', array('%db_prefix' => $db_prefix)), 'error');
+  }
+  if ($db_user == 'username' && $db_pass == 'password') {
+    form_set_error('db_user', st('You have configured %drupal to use the default username and password. This is not allowed for security reasons.', array('%drupal' => _install_profile_name())));
+  }
+  // Verify database settings
+  if (!isset($form)) {
+    $db_type = substr($db_url, 0, strpos($db_url, '://'));
+  }
+  $databases = drupal_detect_database_types();
+  if (!in_array($db_type, $databases)) {
+    form_set_error('db_type', st("In your %settings_file file you have configured Drupal to use a %db_type server, however your PHP installation currently does not support this database type.", array('%settings_file' => $settings_file, '%db_type' => $db_type)));
+  }
+  else {
+    $db_url = $db_type .'://'. $db_user .($db_pass ? ':'. $db_pass : '') .'@'. ($db_host ? $db_host : 'localhost') .'/'. $db_path;
+    if (isset($form)) {
+      form_set_value($form['_db_url'], $db_url);
+    }
+    $success = array();
+    if (!drupal_test_mysql($db_url, $success)) {
+      form_set_error('db_type', '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 <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what any of this means you should probably contact your hosting provider.', 'error');
+    }
+  }
+  if (!drupal_verify_install_file($settings_file, FILE_EXIST|FILE_READABLE|FILE_WRITEABLE)) {
+    form_set_error('errors', 'The Drupal installer requires write permissions to settings.php during the installation process.');
+  }
+}
+
+function drupal_install_settings_validate($form_id, $form_values, $form) {
+  global $db_url;
+  _drupal_install_settings_validate($form_values['db_prefix'], $form_values['db_type'], $form_values['db_user'], $form_values['db_pass'], $form_values['db_host'], $form_values['db_path'], $form_values['settings_file'], $form);
+}
+
+function drupal_install_settings_submit($form_id, $form_values) {
+  global $profile;
+  $settings['db_url'] = array(
+    'value'    => $form_values['_db_url'],
+    'required' => TRUE,
+  );
+  $settings['db_prefix'] = array(
+    'value'    => $form_values['db_prefix'],
+    'required' => TRUE,
+  );
+  drupal_rewrite_settings($settings);
+  _install_goto("install.php?profile=$profile");
+}
+
+/**
+ * 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 action="install.php" method="post">'. $form .'</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');
+}
+
+/**
+ * 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', '<p>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.</p>');
+  exit;
+}
+
+/**
+ * Installed profile.
+ *
+ * @param profile
+ *  Name of profile to install.
+ */
+function drupal_install_profile($profile) {
+  global $db_type;
+
+  include_once './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 <em>$current</em> module is required but was not found. Please move the file <em>$current.module</em> into the <em>modules</em> subdirectory.", 'error');
+    }
+    else {
+      $modules = array_merge($modules, $module);
+    }
+  }
+
+  // Get a list of all .install files
+  $installs = drupal_get_install_files($module_list);
+
+  // 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) {
+    db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES('". $module->filename ."', '". $module->name ."', 'module', '', 1, 0, 0, 0)");
+  }
+
+  // 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);
+}
+
+/**
+ * Page displayed when the installation is complete.  Called from install.php.
+ */
+function drupal_install_complete() {
+  global $base_url;
+
+  require_once './includes/bootstrap.inc';
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIG);
+  if (!isset($GLOBALS['installed_profile'])) {
+    // The installer hasn't run before, start at the beginning.
+    _install_goto('install.php');
+  }
+
+  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+  drupal_maintenance_theme();
+  drupal_set_title(st('%drupal installation complete', array('%drupal' => _install_profile_name())));
+  print theme('maintenance_page', st('<p>Congratulations, %drupal has been successfully installed.  Please review any warnings or errors that you might see above before continuing on to your <a href="%path">new website</a>.', array('%drupal' => _install_profile_name(), '%path' => "$base_url")));
+}
+
+/**
+ * Verify the state of the specified file.
+ *
+ * @param $file
+ *   The file to check for.
+ * @param $mask
+ *   An optional bitmask created from various FILE_* constants.
+ * @param $message_type
+ *   The type of message to create, can be error or status. Passed on to drupal_set_message as second parameter.
+ * @param $type
+ *   The type of file. Can be file (default), dir, or link.
+ * @return
+ *   TRUE on success or FALSE on failure. A messsage is set for the latter.
+ */
+function drupal_verify_install_file($file, $mask = NULL, $message_type = 'error', $type = 'file') {
+  $return = TRUE;
+  // Check for files that shouldn't be there
+  if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) {
+    return FALSE;
+  }
+  // Verify that the file is the type of file it is supposed to be
+  if (isset($type) && file_exists($file)) {
+    $check = 'is_'. $type;
+    if (!function_exists($check) || !$check($file)) {
+      drupal_set_message(st('<em>%file</em> exists but is not a %type.', array('%type' => $type, '%file' => $file)), $message_type);
+      $return = FALSE;
+    }
+  }
+
+  // Verify file permissions
+  if (isset($mask)) {
+    $filetype = ($filetype == 'dir') ? 'Directory' : ucfirst($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 $current_mask) {
+      if ($mask & $current_mask) {
+        switch ($current_mask) {
+          case FILE_EXIST:
+            if (!file_exists($file)) {
+              if ($filetype == 'Directory') {
+                drupal_install_mkdir($file, $mask);
+              }
+              if (!file_exists($file)) {
+                drupal_set_message(st('%type <em>%file</em> does not exist.', array('%type' => $filetype, '%file' => $file)), $message_type);
+                $return = FALSE;
+              }
+            }
+            break;
+          case FILE_READABLE:
+            if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is not readable.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+          case FILE_WRITABLE:
+            if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is not writable.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+          case FILE_EXECUTABLE:
+            if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is not executable.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+          case FILE_NOT_READABLE:
+            if (is_readable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is readable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+          case FILE_NOT_WRITABLE:
+            if (is_writable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is writable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+          case FILE_NOT_EXECUTABLE:
+            if (is_executable($file) && !drupal_install_fix_file($file, $mask)) {
+              drupal_set_message(st('%type <em>%file</em> is executable but should not be.', array('%type' => $filetype, '%file' => $file)), $message_type);
+              $return = FALSE;
+            }
+            break;
+        }
+      }
+    }
+  }
+  return $return;
+}
+
+/**
+ * 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 <em>$file</em>.", 'status');
+    return TRUE;
+  }
+  else {
+    drupal_set_message("Failed to automatically create directory <em>$file</em>, 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 <em>$file</em>.", 'status');
+    return TRUE;
+  }
+  else {
+    drupal_set_message("Failed to automatically fix permissions of file <em>$file</em>, insufficient privileges.", 'error');
+    return FALSE;
+  }
+}
+
+function _mysql_create_table($sql) {
+  global $active_db;
+  static $postfix;
+  if (!isset($postfix)) {
+    $mysql_version = mysql_get_server_info($active_db);
+    $postfix = version_compare($mysql_version, '4.1.0', '<') ? '' : ' DEFAULT CHARACTER SET utf8';
+  }
+  db_query($sql . $postfix);
+}
=== modified file 'includes/module.inc'
--- includes/module.inc	
+++ includes/module.inc	
@@ -47,21 +47,32 @@ function module_list($refresh = FALSE, $
   if ($refresh) {
     unset($sorted_list);
     $list = array();
-    if ($bootstrap) {
-      $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC");
+    if ($fixed_list = variable_get('module_list'. ($bootstrap ? '_bootstrap' : ''), NULL)) {
+      foreach ($fixed_list as $name => $module) {
+        $throttle = isset($module['throttle']) && $module['throttle'] && (variable_get('throttle_level', 0) > 0);
+        if (!$throttle) {
+          drupal_get_filename('module', $name, $module['filename']);
+          $list[$name] = $name;
+        }
+      }
     }
     else {
-      $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
-    }
-    while ($module = db_fetch_object($result)) {
-      if (file_exists($module->filename)) {
-        // Determine the current throttle status and see if the module should be
-        // loaded based on server load. We have to directly access the throttle
-        // variables, since throttle.module may not be loaded yet.
-        $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
-        if (!$throttle) {
-          drupal_get_filename('module', $module->name, $module->filename);
-          $list[$module->name] = $module->name;
+      if ($bootstrap) {
+        $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC");
+      }
+      else {
+        $result = db_query("SELECT name, filename, throttle, bootstrap FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
+      }
+      while ($module = db_fetch_object($result)) {
+        if (file_exists($module->filename)) {
+          // Determine the current throttle status and see if the module should be
+          // loaded based on server load. We have to directly access the throttle
+          // variables, since throttle.module may not be loaded yet.
+          $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
+          if (!$throttle) {
+            drupal_get_filename('module', $module->name, $module->filename);
+            $list[$module->name] = $module->name;
+          }
         }
       }
     }
=== modified file 'includes/theme.inc'
--- includes/theme.inc	
+++ includes/theme.inc	
@@ -453,17 +453,62 @@ function theme_maintenance_page($content
   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('<link rel="shortcut icon" href="'. base_path() .'misc/favicon.ico" type="image/x-icon" />');
+  $output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
+  $output .= '<html xmlns="http://www.w3.org/1999/xhtml">';
+  $output .= '<head>';
+  $output .= ' <title>'. drupal_get_title() .'</title>';
+  $output .= drupal_get_html_head();
+  $output .= theme_get_styles();
+  $output .= '</head>';
+  $output .= '<body>';
+  $output .= '<h1>' . drupal_get_title() . '</h1>';
+
+  $messages = drupal_set_message();
+  if (isset($messages['error'])) {
+    $output .= '<h3>The following errors must be resolved before you can continue the installation process:</h3>';
+    $output .= theme('status_messages', 'error');
+  }
+
+  $output .= "\n<!-- begin content -->\n";
+  $output .= $content;
+  $output .= "\n<!-- end content -->\n";
+
+  if (isset($messages['status'])) {
+    $output .= '<h4>The following installation warnings should be carefully reviewed, but in most cases may be safely ignored:</h4>';
+    $output .= theme('status_messages', 'status');
+  }
+
+  $output .= '</body></html>';
+
+  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 .= "<div class=\"messages $type\">\n";
       if (count($messages) > 1) {
         $output .= " <ul>\n";
@@ -476,6 +521,7 @@ function theme_status_messages() {
         $output .= $messages[0];
       }
       $output .= "</div>\n";
+      unset($data["$type"]);
     }
 
     return $output;
