* Menu (STEP 1) * ----------------------------------------------------------------------------------- */ track_step('installer-menu'); display_locale_selector(); ?> <h1><?php echo T_('How would you like your b2evolution installed?'); ?> </h1> <?php $old_db_version = get_db_version(); $require_charset_update = false; if (!is_null($old_db_version)) { $expected_connection_charset = $DB->php_to_mysql_charmap($evo_charset); if ($DB->connection_charset != $expected_connection_charset) { display_install_messages(sprintf(T_('In order to install b2evolution with the %s locale, your MySQL needs to support the %s connection charset.') . ' (mysqli::set_charset(%s))', $current_locale, $evo_charset, $expected_connection_charset)); // sam2kb> TODO: If something is not supported we can display a message saying "do this and that, enable extension X etc. etc... or switch to a better hosting". break; } else { // Check if some of the tables have different charset than what we expect load_funcs('tools/model/_system.funcs.php'); if (system_check_charset_update()) { if (!is_null($old_db_version) && $old_db_version < $new_db_version) { // DB is not updagraded to new version yet, We should not suggest to normalize DB to avoid errors display_install_messages(sprintf(T_('WARNING: Some of your tables have a different charset than the expected %s. You should normalize your database after upgrade.'), utf8_strtoupper($evo_charset)), 'warning'); } else { // DB is already upgraded to last version, Siggest to normalize DB $require_charset_update = true; display_install_messages(sprintf(T_('WARNING: Some of your tables have a different charset than the expected %s. It is strongly recommended to normalize your database charset by running the preselected task below:'), utf8_strtoupper($evo_charset)));
/** * Update file /conf/_basic_config.php * * @param string Current action, updated by reference * @param array Params * @return boolean TRUE on success */ function update_basic_config_file($params = array()) { global $DB, $db_config, $evo_charset, $conf_path, $default_locale; // These global params should be rewritten by this function on success result global $baseurl, $admin_email, $config_is_done, $action; $params = array_merge(array('db_user' => '', 'db_password' => '', 'db_name' => '', 'db_host' => '', 'db_tableprefix' => '', 'baseurl' => '', 'admin_email' => '', 'print_messages' => true, 'quick_install' => false), $params); if (!$params['print_messages']) { // Start to get all messages instead of printing on screen: ob_start(); // Use this global var to store all messages global $basic_config_file_result_messages; } // Connect to DB: $DB = new DB(array('user' => $params['db_user'], 'password' => $params['db_password'], 'name' => $params['db_name'], 'host' => $params['db_host'], 'aliases' => $db_config['aliases'], 'connection_charset' => empty($db_config['connection_charset']) ? DB::php_to_mysql_charmap($evo_charset) : $db_config['connection_charset'], 'halt_on_error' => false)); if ($DB->error) { // restart conf display_install_messages(T_('It seems that the database config settings you entered don\'t work. Please check them carefully and try again...')); $action = 'start'; } else { $conf_template_filepath = $conf_path . '_basic_config.template.php'; $conf_filepath = $conf_path . '_basic_config.php'; // Read original: $file_loaded = @file($conf_template_filepath); if (empty($file_loaded)) { // This should actually never happen, just in case... display_install_messages(sprintf(T_('Could not load original conf file [%s]. Is it missing?'), $conf_filepath)); if (!$params['print_messages']) { // Return all messages instead of printing on screen $basic_config_file_result_messages = ob_get_clean(); } return false; } // File loaded... $conf = implode('', $file_loaded); // Update conf: $conf = preg_replace(array('#\\$db_config\\s*=\\s*array\\( \\s*[\'"]user[\'"]\\s*=>\\s*[\'"].*?[\'"], ([^\\n\\r]*\\r?\\n) \\s*[\'"]password[\'"]\\s*=>\\s*[\'"].*?[\'"], ([^\\n\\r]*\\r?\\n) \\s*[\'"]name[\'"]\\s*=>\\s*[\'"].*?[\'"], ([^\\n\\r]*\\r?\\n) \\s*[\'"]host[\'"]\\s*=>\\s*[\'"].*?[\'"], ([^\\n\\r]*\\r?\\n) #ixs', "#tableprefix\\s*=\\s*'.*?';#", "#baseurl\\s*=\\s*'.*?';#", "#admin_email\\s*=\\s*'.*?';#", "#config_is_done\\s*=.*?;#"), array("\$db_config = array(\n" . "\t'user' => '" . str_replace(array("'", "\$"), array("\\'", "\\\$"), $params['db_user']) . "',\$1" . "\t'password' => '" . str_replace(array("'", "\$"), array("\\'", "\\\$"), $params['db_password']) . "',\$2" . "\t'name' => '" . str_replace(array("'", "\$"), array("\\'", "\\\$"), $params['db_name']) . "',\$3" . "\t'host' => '" . str_replace(array("'", "\$"), array("\\'", "\\\$"), $params['db_host']) . "',\$4", "tableprefix = '" . str_replace("'", "\\'", $params['db_tableprefix']) . "';", "baseurl = '" . str_replace("'", "\\'", $params['baseurl']) . "';", "admin_email = '" . str_replace("'", "\\'", $params['admin_email']) . "';", 'config_is_done = 1;'), $conf); // Write new contents: if (save_to_file($conf, $conf_filepath, 'w')) { display_install_messages(sprintf(T_('Your configuration file <code>%s</code> has been successfully created.') . '</p>', $conf_filepath), 'success'); $tableprefix = $params['db_tableprefix']; $baseurl = $params['baseurl']; $admin_email = $params['admin_email']; $config_is_done = 1; if (!$params['quick_install']) { // Switch to menu only on standard installation: $action = 'menu'; } } else { ?> <h1><?php echo T_('Config file update'); ?> </h1> <p><strong><?php printf(T_('We cannot automatically create or update your config file [%s]!'), $conf_filepath); ?> </strong></p> <p><?php echo T_('There are two ways to deal with this:'); ?> </p> <ul> <li><strong><?php echo T_('You can allow the installer to create the config file by changing permissions for the /conf directory:'); ?> </strong> <ol> <li><?php printf(T_('Make sure there is no existing and potentially locked configuration file named <code>%s</code>. If so, please delete it.'), $conf_filepath); ?> </li> <li><?php printf(T_('<code>chmod 777 %s</code>. If needed, see the <a %s>online manual about permissions</a>.'), $conf_path, 'href="' . get_manual_url('directory-and-file-permissions') . '" target="_blank"'); ?> </li> <li><?php echo T_('Come back to this page and refresh/reload.'); ?> </li> </ol> <br /> </li> <li><strong><?php echo T_('Alternatively, you can update the config file manually:'); ?> </strong> <ol> <li><?php echo T_('Create a new text file with a text editor.'); ?> </li> <li><?php echo T_('Copy the contents from the box below.'); ?> </li> <li><?php echo T_('Paste them into your local text editor. <strong>ATTENTION: make sure there is ABSOLUTELY NO WHITESPACE after the final <code>?></code> in the file.</strong> Any space, tab, newline or blank line at the end of the conf file may prevent cookies from being set when you try to log in later.'); ?> </li> <li><?php echo T_('Save the file locally under the name <code>_basic_config.php</code>'); ?> </li> <li><?php echo T_('Upload the file to your server, into the <code>/_conf</code> folder.'); ?> </li> <li><?php printf(T_('<a %s>Call the installer from scratch</a>.'), 'href="index.php?locale=' . $default_locale . '"'); ?> </li> </ol> </li> </ul> <p><?php echo T_('This is how your _basic_config.php should look like:'); ?> </p> <blockquote> <pre><?php echo htmlspecialchars($conf); ?> </pre> </blockquote> <?php if (!$params['print_messages']) { // Return all messages instead of printing on screen $basic_config_file_result_messages = ob_get_clean(); } return false; } } if (!$params['print_messages']) { // Return all messages instead of printing on screen $basic_config_file_result_messages = ob_get_clean(); } return true; }
/** * DB Constructor * * Connects to the server and selects a database. * * @param array An array of parameters. * Manadatory: * - 'user': username to connect with * - 'password': password to connect with * OR * - 'handle': a MySQL Database handle (from a previous {@link mysqli_init()}) * Optional: * - 'name': the name of the default database, see {@link DB::select()} * - 'host': host of the database; Default: 'localhost' * - 'show_errors': Display SQL errors? (true/false); Default: don't change member default ({@link $show_errors}) * - 'halt_on_error': Halt on error? (true/false); Default: don't change member default ({@link $halt_on_error}) * - 'table_options': sets {@link $table_options} * - 'use_transactions': sets {@link $use_transactions} * - 'aliases': Aliases for tables (array( alias => table name )); Default: no aliases. * - 'new_link': don't use a persistent connection * - 'client_flags': optional settings like compression or SSL encryption. See {@link http://www.php.net/manual/en/mysqli.constants.php}. * (requires PHP 4.3) * - 'log_queries': should queries get logged internally? (follows $debug by default, and requires it to be enabled otherwise) * This is a requirement for the following options: * - 'debug_dump_rows': Number of rows to dump * - 'debug_explain_joins': Explain JOINS? (calls "EXPLAIN $query") * - 'debug_profile_queries': Profile queries? (calls "SHOW PROFILE" after each query) * - 'debug_dump_function_trace_for_queries': Collect call stack for queries? (showing where queries have been called) */ function __construct($params) { global $debug, $evo_charset; // Mandatory parameters: if (isset($params['handle'])) { // DB-Link provided: $this->dbhandle = $params['handle']; } else { $this->dbuser = $params['user']; $this->dbpassword = $params['password']; } // Optional parameters (Allow overriding through $params): if (isset($params['name'])) { $this->dbname = $params['name']; } if (isset($params['host'])) { $this->dbhost = $params['host']; } if (isset($params['show_errors'])) { $this->show_errors = $params['show_errors']; } if (isset($params['halt_on_error'])) { $this->halt_on_error = $params['halt_on_error']; } if (isset($params['table_options'])) { $this->table_options = $params['table_options']; } if (isset($params['use_transactions'])) { $this->use_transactions = $params['use_transactions']; } if (isset($params['debug_dump_rows'])) { $this->debug_dump_rows = $params['debug_dump_rows']; } // Nb of rows to dump if (isset($params['debug_explain_joins'])) { $this->debug_explain_joins = $params['debug_explain_joins']; } if (isset($params['debug_profile_queries'])) { $this->debug_profile_queries = $params['debug_profile_queries']; } if (isset($params['debug_dump_function_trace_for_queries'])) { $this->debug_dump_function_trace_for_queries = $params['debug_dump_function_trace_for_queries']; } if (isset($params['log_queries'])) { $this->log_queries = $debug && $params['log_queries']; } elseif (isset($debug) && !isset($this->log_queries)) { // $log_queries follows $debug and respects subclasses, which may define it: $this->log_queries = (bool) $debug; } if (!extension_loaded('mysqli')) { // The mysql extension is not loaded, try to dynamically load it: if (function_exists('dl')) { $mysql_ext_file = is_windows() ? 'php_mysqli.dll' : 'mysqli.so'; $php_errormsg = null; $old_track_errors = ini_set('track_errors', 1); $old_html_errors = ini_set('html_errors', 0); @dl($mysql_ext_file); $error_msg = $php_errormsg; if ($old_track_errors !== false) { ini_set('track_errors', $old_track_errors); } if ($old_html_errors !== false) { ini_set('html_errors', $old_html_errors); } } else { $error_msg = 'The PHP mysqli extension is not installed and we cannot load it dynamically.'; } if (!extension_loaded('mysqli')) { // Still not loaded: $this->print_error('The PHP MySQL Improved module could not be loaded.', ' <p><strong>Error:</strong> ' . $error_msg . '</p> <p>You probably have to edit your php configuration (php.ini) and enable this module (' . $mysql_ext_file . ').</p> <p>Do not forget to restart your webserver (if necessary) after editing the PHP conf.</p>', false); return; } } $new_link = isset($params['new_link']) ? $params['new_link'] : false; $client_flags = isset($params['client_flags']) ? $params['client_flags'] : 0; if (!$this->dbhandle) { // Connect to the Database: // echo "mysqli_real_connect( $this->dbhost, $this->dbuser, $this->dbpassword, $this->dbname, $this->dbport, $this->dbsocket, $client_flags )"; // mysqli::$connect_error is tied to an established connection // if the connection fails we need a different method to get the error message $php_errormsg = null; $old_track_errors = ini_set('track_errors', 1); $old_html_errors = ini_set('html_errors', 0); $this->dbhandle = mysqli_init(); @mysqli_real_connect($this->dbhandle, $new_link || version_compare(PHP_VERSION, '5.3', '<') ? $this->dbhost : 'p:' . $this->dbhost, $this->dbuser, $this->dbpassword, '', ini_get('mysqli.default_port'), ini_get('mysqli.default_socket'), $client_flags); $mysql_error = $php_errormsg; if ($old_track_errors !== false) { ini_set('track_errors', $old_track_errors); } if ($old_html_errors !== false) { ini_set('html_errors', $old_html_errors); } } if (0 != $this->dbhandle->connect_errno) { $this->print_error('Error establishing a database connection!', ($mysql_error ? '<p>(' . $mysql_error . ')</p>' : '') . ' <ol> <li>Are you sure you have typed the correct user/password?</li> <li>Are you sure that you have typed the correct hostname?</li> <li>Are you sure that the database server is running?</li> </ol>', false); } elseif (isset($this->dbname)) { $this->select($this->dbname); } if (!empty($params['connection_charset'])) { // Specify which charset we are using on the client: $this->set_connection_charset($params['connection_charset']); } elseif (!empty($evo_charset)) { // Use the internal charset if it is defined $this->set_connection_charset(DB::php_to_mysql_charmap($evo_charset)); } /* echo '<br />Server: '.$this->get_var( 'SELECT @@character_set_server' ); echo '<br />Database: '.$this->get_var( 'SELECT @@character_set_database' ); echo '<br />Connection: '.$this->get_var( 'SELECT @@character_set_connection' ); echo '<br />Client: '.$this->get_var( 'SELECT @@character_set_client' ); echo '<br />Results: '.$this->get_var( 'SELECT @@character_set_results' ); */ if (isset($params['aliases'])) { // Prepare aliases for replacements: foreach ($params['aliases'] as $dbalias => $dbreplace) { $this->dbaliases[] = '#\\b' . $dbalias . '\\b#'; // \b = word boundary $this->dbreplaces[] = $dbreplace; // echo '<br />'.'#\b'.$dbalias.'\b#'; } // echo count($this->dbaliases); } // Force MySQL strict mode $this->query('SET sql_mode = "TRADITIONAL"', 'Force MySQL "strict" mode (and make sure server is not configured with a weird incompatible mode)'); if ($this->debug_profile_queries) { // dh> this will fail, if it is not supported, but has to be enabled manually anyway. $this->query('SET profiling = 1'); // Requires 5.0.37. } }
/** * Check if some of the tables have different charset than what we expect * * @return boolean TRUE if the update is required */ function system_check_charset_update() { global $DB, $evo_charset, $db_config, $tableprefix; $expected_connection_charset = DB::php_to_mysql_charmap($evo_charset); $curr_db_charset = $DB->get_var('SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = ' . $DB->quote($db_config['name'])); $require_charset_update = $curr_db_charset != $expected_connection_charset || $DB->get_var('SELECT COUNT( T.table_name ) FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema = ' . $DB->quote($db_config['name']) . ' AND T.table_name LIKE "' . $tableprefix . '%" AND CCSA.character_set_name != ' . $DB->quote($expected_connection_charset)); return $require_charset_update; }
/** * Upgrade DB to UTF-8 and fix ASCII fields */ function db_check_utf8_ascii() { global $db_config, $tableprefix, $DB, $evo_charset; echo '<h2 class="page-title">' . T_('Normalizing DB charsets...') . '</h2>'; evo_flush(); // Get the tables that have different charset than what we expect $expected_connection_charset = DB::php_to_mysql_charmap($evo_charset); $tables = $DB->get_col('SELECT T.table_name FROM information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema = ' . $DB->quote($db_config['name']) . ' AND T.table_name LIKE "' . $tableprefix . '%" AND CCSA.character_set_name != ' . $DB->quote($expected_connection_charset)); if (empty($tables)) { // All tables are correct echo '<p>' . T_('All your tables seem to be using UTF-8. You can still run the normalization tool to make a deep check.') . '</p>'; } else { // Display what tables should be normalized echo '<p>' . T_('We have detected the following tables as not using UTF-8:') . '</p>'; echo '<ul>'; foreach ($tables as $table) { echo '<li>' . $table . '</li>'; } echo '</ul>'; } }