1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-02-13 20:44:43 +01:00
php-phpbb/phpBB/install/database_update.php
Meik Sievertsen 333b3515ed Some... fixes... laying around here.
git-svn-id: file:///svn/phpbb/trunk@6970 89ea8834-ac86-4346-8a33-228a782c2dd0
2007-02-06 19:09:43 +00:00

1469 lines
40 KiB
PHP

<?php
/**
*
* @package install
* @version $Id$
* @copyright (c) 2006 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
$updates_to_version = '3.0.B5';
if (defined('IN_PHPBB') && defined('IN_INSTALL'))
{
return;
}
/**
*/
define('IN_PHPBB', true);
define('IN_INSTALL', true);
$phpbb_root_path = './../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
// Report all errors, except notices
//error_reporting(E_ALL ^ E_NOTICE);
error_reporting(E_ALL);
@set_time_limit(0);
// Include essential scripts
include($phpbb_root_path . 'config.' . $phpEx);
if (!isset($dbms))
{
die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
}
// Load Extensions
if (!empty($load_extensions))
{
$load_extensions = explode(',', $load_extensions);
foreach ($load_extensions as $extension)
{
@dl(trim($extension));
}
}
// Include files
require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx);
require($phpbb_root_path . 'includes/cache.' . $phpEx);
require($phpbb_root_path . 'includes/template.' . $phpEx);
require($phpbb_root_path . 'includes/session.' . $phpEx);
require($phpbb_root_path . 'includes/auth.' . $phpEx);
require($phpbb_root_path . 'includes/functions.' . $phpEx);
require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
$user = new user();
$cache = new cache();
$db = new $sql_db();
// Connect to DB
$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false);
// We do not need this any longer, unset for safety purposes
unset($dbpasswd);
$sql = "SELECT config_value
FROM " . CONFIG_TABLE . "
WHERE config_name = 'default_lang'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// And finally, load the relevant language files
include($phpbb_root_path . 'language/' . $row['config_value'] . '/common.' . $phpEx);
include($phpbb_root_path . 'language/' . $row['config_value'] . '/acp/common.' . $phpEx);
include($phpbb_root_path . 'language/' . $row['config_value'] . '/install.' . $phpEx);
// Set PHP error handler to ours
//set_error_handler('msg_handler');
// Define some variables for the database update
$inline_update = (request_var('type', 0)) ? true : false;
// Database column types mapping
$dbms_type_map = array(
'mysql_41' => array(
'INT:' => 'int(%d)',
'BINT' => 'bigint(20)',
'UINT' => 'mediumint(8) UNSIGNED',
'UINT:' => 'int(%d) UNSIGNED',
'TINT:' => 'tinyint(%d)',
'USINT' => 'smallint(4) UNSIGNED',
'BOOL' => 'tinyint(1) UNSIGNED',
'VCHAR' => 'varchar(255)',
'VCHAR:' => 'varchar(%d)',
'CHAR:' => 'char(%d)',
'XSTEXT' => 'text',
'XSTEXT_UNI'=> 'varchar(100)',
'STEXT' => 'text',
'STEXT_UNI' => 'varchar(255)',
'TEXT' => 'text',
'TEXT_UNI' => 'text',
'MTEXT' => 'mediumtext',
'MTEXT_UNI' => 'mediumtext',
'TIMESTAMP' => 'int(11) UNSIGNED',
'DECIMAL' => 'decimal(5,2)',
'VCHAR_UNI' => 'varchar(255)',
'VCHAR_UNI:'=> 'varchar(%d)',
'VCHAR_CI' => 'varchar(255)',
'VARBINARY' => 'varbinary(255)',
),
'mysql_40' => array(
'INT:' => 'int(%d)',
'BINT' => 'bigint(20)',
'UINT' => 'mediumint(8) UNSIGNED',
'UINT:' => 'int(%d) UNSIGNED',
'TINT:' => 'tinyint(%d)',
'USINT' => 'smallint(4) UNSIGNED',
'BOOL' => 'tinyint(1) UNSIGNED',
'VCHAR' => 'varchar(255)',
'VCHAR:' => 'varchar(%d)',
'CHAR:' => 'char(%d)',
'XSTEXT' => 'text',
'XSTEXT_UNI'=> 'text',
'STEXT' => 'text',
'STEXT_UNI' => 'text',
'TEXT' => 'text',
'TEXT_UNI' => 'text',
'MTEXT' => 'mediumtext',
'MTEXT_UNI' => 'mediumtext',
'TIMESTAMP' => 'int(11) UNSIGNED',
'DECIMAL' => 'decimal(5,2)',
'VCHAR_UNI' => 'text',
'VCHAR_UNI:'=> array('varchar(%d)', 'limit' => array('mult', 3, 255, 'text')),
'VCHAR_CI' => 'text',
'VARBINARY' => 'varbinary(255)',
),
'firebird' => array(
'INT:' => 'INTEGER',
'BINT' => 'DOUBLE PRECISION',
'UINT' => 'INTEGER',
'UINT:' => 'INTEGER',
'TINT:' => 'INTEGER',
'USINT' => 'INTEGER',
'BOOL' => 'INTEGER',
'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE',
'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE',
'CHAR:' => 'CHAR(%d) CHARACTER SET NONE',
'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8',
'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
'TIMESTAMP' => 'INTEGER',
'DECIMAL' => 'DOUBLE PRECISION',
'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8',
'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8',
'VARBINARY' => 'CHAR(255) CHARACTER SET NONE',
),
'mssql' => array(
'INT:' => '[int]',
'BINT' => '[float]',
'UINT' => '[int]',
'UINT:' => '[int]',
'TINT:' => '[int]',
'USINT' => '[int]',
'BOOL' => '[int]',
'VCHAR' => '[varchar] (255)',
'VCHAR:' => '[varchar] (%d)',
'CHAR:' => '[char] (%d)',
'XSTEXT' => '[varchar] (1000)',
'STEXT' => '[varchar] (3000)',
'TEXT' => '[varchar] (8000)',
'MTEXT' => '[text]',
'XSTEXT_UNI'=> '[varchar] (100)',
'STEXT_UNI' => '[varchar] (255)',
'TEXT_UNI' => '[varchar] (4000)',
'MTEXT_UNI' => '[text]',
'TIMESTAMP' => '[int]',
'DECIMAL' => '[float]',
'VCHAR_UNI' => '[varchar] (255)',
'VCHAR_UNI:'=> '[varchar] (%d)',
'VCHAR_CI' => '[varchar] (255)',
'VARBINARY' => '[varchar] (255)',
),
'oracle' => array(
'INT:' => 'number(%d)',
'BINT' => 'number(20)',
'UINT' => 'number(8)',
'UINT:' => 'number(%d)',
'TINT:' => 'number(%d)',
'USINT' => 'number(4)',
'BOOL' => 'number(1)',
'VCHAR' => 'varchar2(255)',
'VCHAR:' => 'varchar2(%d)',
'CHAR:' => 'char(%d)',
'XSTEXT' => 'varchar2(1000)',
'STEXT' => 'varchar2(3000)',
'TEXT' => 'clob',
'MTEXT' => 'clob',
'XSTEXT_UNI'=> 'varchar2(300)',
'STEXT_UNI' => 'varchar2(765)',
'TEXT_UNI' => 'clob',
'MTEXT_UNI' => 'clob',
'TIMESTAMP' => 'number(11)',
'DECIMAL' => 'number(5, 2)',
'VCHAR_UNI' => 'varchar2(765)',
'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
'VCHAR_CI' => 'varchar2(255)',
'VARBINARY' => 'raw(255)',
),
'sqlite' => array(
'INT:' => 'int(%d)',
'BINT' => 'bigint(20)',
'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
'TINT:' => 'tinyint(%d)',
'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
'VCHAR' => 'varchar(255)',
'VCHAR:' => 'varchar(%d)',
'CHAR:' => 'char(%d)',
'XSTEXT' => 'text(65535)',
'STEXT' => 'text(65535)',
'TEXT' => 'text(65535)',
'MTEXT' => 'mediumtext(16777215)',
'XSTEXT_UNI'=> 'text(65535)',
'STEXT_UNI' => 'text(65535)',
'TEXT_UNI' => 'text(65535)',
'MTEXT_UNI' => 'mediumtext(16777215)',
'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
'DECIMAL' => 'decimal(5,2)',
'VCHAR_UNI' => 'varchar(255)',
'VCHAR_UNI:'=> 'varchar(%d)',
'VCHAR_CI' => 'varchar(255)',
'VARBINARY' => 'blob',
),
'postgres' => array(
'INT:' => 'INT4',
'BINT' => 'INT8',
'UINT' => 'INT4', // unsigned
'UINT:' => 'INT4', // unsigned
'USINT' => 'INT2', // unsigned
'BOOL' => 'INT2', // unsigned
'TINT:' => 'INT2',
'VCHAR' => 'varchar(255)',
'VCHAR:' => 'varchar(%d)',
'CHAR:' => 'char(%d)',
'XSTEXT' => 'varchar(1000)',
'STEXT' => 'varchar(3000)',
'TEXT' => 'varchar(8000)',
'MTEXT' => 'TEXT',
'XSTEXT_UNI'=> 'varchar(100)',
'STEXT_UNI' => 'varchar(255)',
'TEXT_UNI' => 'varchar(4000)',
'MTEXT_UNI' => 'TEXT',
'TIMESTAMP' => 'INT4', // unsigned
'DECIMAL' => 'decimal(5,2)',
'VCHAR_UNI' => 'varchar(255)',
'VCHAR_UNI:'=> 'varchar(%d)',
'VCHAR_CI' => 'varchar_ci',
'VARBINARY' => 'bytea',
),
);
// A list of types being unsigned for better reference in some db's
$unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
// Only an example, but also commented out
$database_update_info = array(
// Changes from 3.0.b3 to the next version
'3.0.b3' => array(
// Change the following columns...
'change_columns' => array(
BBCODES_TABLE => array(
'bbcode_helpline' => array('VCHAR_UNI', ''),
),
USERS_TABLE => array(
'user_occ' => array('TEXT_UNI', ''),
),
CONFIG_TABLE => array(
'config_value' => array('VCHAR_UNI', ''),
),
),
// Add the following columns
'add_columns' => array(
GROUPS_TABLE => array(
'group_founder_manage' => array('BOOL', 0),
),
USERS_TABLE => array(
'user_pass_convert' => array('BOOL', 0),
),
),
),
// Changes from 3.0.b4 to the next version
'3.0.b4' => array(
// Add the following columns
'add_columns' => array(
CONFIRM_TABLE => array(
'seed' => array('UINT:10', 0),
),
SESSIONS_TABLE => array(
'session_forwarded_for' => array('VCHAR:255', 0),
),
),
'change_columns' => array(
USERS_TABLE => array(
'user_options' => array('UINT:11', 895),
),
FORUMS_TABLE => array(
'prune_days' => array('UINT', 0),
'prune_viewed' => array('UINT', 0),
'prune_freq' => array('UINT', 0),
),
PRIVMSGS_RULES_TABLE => array(
'rule_folder_id' => array('INT:11', 0),
),
PRIVMSGS_TO_TABLE => array(
'folder_id' => array('INT:11', 0),
),
),
// Remove the following keys
'drop_keys' => array(
ZEBRA_TABLE => array(
'user_id',
'zebra_id',
),
),
// Add the following primary keys
'add_primary_keys' => array(
ZEBRA_TABLE => array(
'user_id',
'zebra_id',
),
),
),
);
// Determine mapping database type
switch ($db->sql_layer)
{
case 'mysql':
$map_dbms = 'mysql_40';
break;
case 'mysql4':
case 'mysqli':
$map_dbms = 'mysql_41';
break;
case 'mssql':
case 'mssql_odbc':
$map_dbms = 'mssql';
break;
default:
$map_dbms = $db->sql_layer;
break;
}
$error_ary = array();
$errored = false;
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="<?php echo $lang['DIRECTION']; ?>" lang="<?php echo $lang['USER_LANG']; ?>" xml:lang="<?php echo $lang['USER_LANG']; ?>">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="content-language" content="<?php echo $lang['USER_LANG']; ?>" />
<meta http-equiv="content-style-type" content="text/css" />
<meta http-equiv="imagetoolbar" content="no" />
<title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title>
<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />
</head>
<body>
<div id="wrap">
<div id="page-header">&nbsp;</div>
<div id="page-body">
<div class="panel">
<span class="corners-top"><span></span></span>
<div id="content">
<div id="main">
<h1><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
<br />
<p><?php echo $lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->sql_layer; ?></strong><br />
<?php
// To let set_config() calls succeed, we need to make the config array available globally
$config = array();
$sql = 'SELECT *
FROM ' . CONFIG_TABLE;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$config[$row['config_name']] = $row['config_value'];
}
$db->sql_freeresult($result);
echo $lang['PREVIOUS_VERSION'] . ' :: <strong>' . $config['version'] . '</strong><br />';
echo $lang['UPDATED_VERSION'] . ' :: <strong>' . $updates_to_version . '</strong>';
$current_version = strtolower($config['version']);
$latest_version = strtolower($updates_to_version);
$orig_version = $config['version'];
// If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything.
if ($inline_update)
{
if ($current_version !== $latest_version)
{
set_config('version_update_from', $orig_version);
}
}
else
{
// If not called from the update script, we will actually remove the traces
$db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
}
// Schema updates
?>
</p><br /><br />
<h1><?php echo $lang['UPDATE_DATABASE_SCHEMA']; ?></h1>
<br />
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
<?php
flush();
// We go through the schema changes from the lowest to the highest version
// We skip those versions older than the current version
$no_updates = true;
foreach ($database_update_info as $version => $schema_changes)
{
if (version_compare($version, $current_version, '<'))
{
continue;
}
if (!sizeof($schema_changes))
{
continue;
}
$no_updates = false;
// Change columns?
if (!empty($schema_changes['change_columns']))
{
foreach ($schema_changes['change_columns'] as $table => $columns)
{
foreach ($columns as $column_name => $column_data)
{
sql_column_change($map_dbms, $table, $column_name, $column_data);
}
}
}
// Add columns?
if (!empty($schema_changes['add_columns']))
{
foreach ($schema_changes['add_columns'] as $table => $columns)
{
foreach ($columns as $column_name => $column_data)
{
// Only add the column if it does not exist yet
if (!column_exists($map_dbms, $table, $column_name))
{
sql_column_add($map_dbms, $table, $column_name, $column_data);
}
}
}
}
// Remove keys?
if (!empty($schema_changes['drop_keys']))
{
foreach ($schema_changes['drop_keys'] as $table => $indexes)
{
foreach ($indexes as $index_name)
{
sql_index_drop($map_dbms, $index_name, $table);
}
}
}
// Add primary keys?
if (!empty($schema_changes['add_primary_keys']))
{
foreach ($schema_changes['add_primary_keys'] as $table => $columns)
{
sql_create_primary_key($map_dbms, $table, $columns);
}
}
}
_write_result($no_updates, $errored, $error_ary);
// Data updates
$error_ary = array();
$errored = $no_updates = false;
?>
<br /><br />
<h1><?php echo $lang['UPDATING_DATA']; ?></h1>
<br />
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
<?php
flush();
$no_updates = true;
// some code magic
if (version_compare($current_version, '3.0.b3', '<='))
{
// Set group_founder_manage for administrators group
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'ADMINISTRATORS'
AND group_type = " . GROUP_SPECIAL;
$result = $db->sql_query($sql);
$group_id = (int) $db->sql_fetchfield('group_id');
$db->sql_freeresult($result);
if ($group_id)
{
$sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_founder_manage = 1 WHERE group_id = ' . $group_id;
_sql($sql, $errored, $error_ary);
}
add_bots();
$no_updates = false;
}
if (version_compare($current_version, '3.0.b4', '<='))
{
// Add config values
set_config('script_path', '/');
set_config('forwarded_for_check', '0');
set_config('ldap_password', '');
set_config('ldap_user', '');
set_config('fulltext_native_common_thres', '20');
// Remove config variables
$sql = 'DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'send_encoding'";
_sql($sql, $errored, $error_ary);
$sql = 'SELECT user_colour
FROM ' . USERS_TABLE . '
WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
ORDER BY user_id DESC';
$result = $db->sql_query_limit($sql, 1);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
set_config('newest_user_colour', $row['user_colour'], true);
switch ($config['allow_name_chars'])
{
case '[\w]+':
set_config('allow_name_chars', '[a-z]+');
break;
case '[\w_\+\. \-\[\]]+':
set_config('allow_name_chars', '[-\]_+ [a-z]+');
break;
}
switch ($config['pass_complex'])
{
case '.*':
set_config('pass_complex', 'PASS_TYPE_ANY');
break;
case '[a-zA-Z]':
set_config('pass_complex', 'PASS_TYPE_CASE');
break;
case '[a-zA-Z0-9]':
set_config('pass_complex', 'PASS_TYPE_ALPHA');
break;
case '[a-zA-Z\W]':
set_config('pass_complex', 'PASS_TYPE_SYMBOL');
break;
}
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_options = 895 WHERE user_options = 893';
_sql($sql, $errored, $error_ary);
$sql = 'UPDATE ' . MODULES_TABLE . " SET module_auth = 'acl_a_board'
WHERE module_class = 'acp' AND module_mode = 'version_check' AND module_auth = 'acl_a_'";
_sql($sql, $errored, $error_ary);
// Because the email hash could have been calculated wrongly as well as the clean string function changed,
// we will update it for every user.
// Since this is not used in a live environment there are not much... not used in a live environment, yes!
$sql = 'SELECT user_id, user_email, username
FROM ' . USERS_TABLE;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$sql = 'UPDATE ' . USERS_TABLE . "
SET username_clean = '" . $db->sql_escape(utf8_clean_string($row['username'])) . "'";
if ($row['user_email'])
{
$sql .= ', user_email_hash = ' . (crc32($row['user_email']) . strlen($row['user_email']));
}
$sql .= ' WHERE user_id = ' . $row['user_id'];
_sql($sql, $errored, $error_ary);
}
$db->sql_freeresult($result);
$no_updates = false;
}
_write_result($no_updates, $errored, $error_ary);
$error_ary = array();
$errored = $no_updates = false;
?>
<br /><br />
<h1><?php echo $lang['UPDATE_VERSION_OPTIMIZE']; ?></h1>
<br />
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
<?php
flush();
// update the version
$sql = "UPDATE " . CONFIG_TABLE . "
SET config_value = '$updates_to_version'
WHERE config_name = 'version'";
_sql($sql, $errored, $error_ary);
/* Optimize/vacuum analyze the tables where appropriate
// this should be done for each version in future along with
// the version number update
switch ($db->sql_layer)
{
case 'mysql':
case 'mysqli':
case 'mysql4':
$sql = 'OPTIMIZE TABLE ' . $table_prefix . 'auth_access, ' . $table_prefix . 'banlist, ' . $table_prefix . 'categories, ' . $table_prefix . 'config, ' . $table_prefix . 'disallow, ' . $table_prefix . 'forum_prune, ' . $table_prefix . 'forums, ' . $table_prefix . 'groups, ' . $table_prefix . 'posts, ' . $table_prefix . 'posts_text, ' . $table_prefix . 'privmsgs, ' . $table_prefix . 'privmsgs_text, ' . $table_prefix . 'ranks, ' . $table_prefix . 'search_results, ' . $table_prefix . 'search_wordlist, ' . $table_prefix . 'search_wordmatch, ' . $table_prefix . 'sessions_keys' . $table_prefix . 'smilies, ' . $table_prefix . 'themes, ' . $table_prefix . 'themes_name, ' . $table_prefix . 'topics, ' . $table_prefix . 'topics_watch, ' . $table_prefix . 'user_group, ' . $table_prefix . 'users, ' . $table_prefix . 'vote_desc, ' . $table_prefix . 'vote_results, ' . $table_prefix . 'vote_voters, ' . $table_prefix . 'words';
_sql($sql, $errored, $error_ary);
break;
case 'postgresql':
_sql("VACUUM ANALYZE", $errored, $error_ary);
break;
}
*/
_write_result($no_updates, $errored, $error_ary);
?>
<br />
<h1><?php echo $lang['UPDATE_COMPLETED']; ?></h1>
<br />
<?php
if (!$inline_update)
{
?>
<p style="color:red"><?php echo $lang['UPDATE_FILES_NOTICE']; ?></p>
<p><?php echo $lang['COMPLETE_LOGIN_TO_BOARD']; ?></p>
<?php
}
else
{
?>
<p><?php echo ((isset($lang['CONTINUE_INLINE_UPDATE'])) ? $lang['CONTINUE_INLINE_UPDATE'] : 'The database update was successful. Now please close this window and continue the update process as explained.'); ?></p>
<p><a href="#" onclick="window.close();">&raquo; <?php echo $lang['CLOSE_WINDOW']; ?></a></p>
<?php
}
// Add database update to log
$user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version);
// Now we purge the session table as well as all cache files
$cache->purge();
?>
</div>
</div>
<span class="corners-bottom"><span></span></span>
</div>
</div>
<div id="page-footer">
Powered by phpBB &copy; <?php echo date('Y'); ?> <a href="http://www.phpbb.com/">phpBB Group</a>
</div>
</div>
</body>
</html>
<?php
/**
* Function for triggering an sql statement
*/
function _sql($sql, &$errored, &$error_ary, $echo_dot = true)
{
global $db;
if (defined('DEBUG_EXTRA'))
{
echo "<br />\n{$sql}\n<br />";
}
$db->sql_return_on_error(true);
$result = $db->sql_query($sql);
if ($db->sql_error_triggered)
{
$errored = true;
$error_ary['sql'][] = $db->sql_error_sql;
$error_ary['error_code'][] = $db->_sql_error();
}
$db->sql_return_on_error(false);
if ($echo_dot)
{
echo ". \n";
flush();
}
return $result;
}
function _write_result($no_updates, $errored, $error_ary)
{
global $lang;
if ($no_updates)
{
echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '</strong></p>';
}
else
{
echo ' <span class="success">' . $lang['DONE'] . '</span></strong><br />' . $lang['RESULT'] . ' :: ';
if ($errored)
{
echo ' <strong>' . $lang['SOME_QUERIES_FAILED'] . '</strong> <ul>';
for ($i = 0; $i < sizeof($error_ary['sql']); $i++)
{
echo '<li>' . $lang['ERROR'] . ' :: <strong>' . $error_ary['error_code'][$i]['message'] . '</strong><br />';
echo $lang['SQL'] . ' :: <strong>' . $error_ary['sql'][$i] . '</strong><br /><br /></li>';
}
echo '</ul> <br /><br />' . $lang['SQL_FAILURE_EXPLAIN'] . '</p>';
}
else
{
echo '<strong>' . $lang['NO_ERRORS'] . '</strong></p>';
}
}
}
/**
* Check if a specified column exist
*/
function column_exists($dbms, $table, $column_name)
{
global $db;
$db->sql_return_on_error(true);
$sql = "SELECT $column_name FROM $table";
$result = $db->sql_query_limit($sql, 1);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$error = ($db->sql_error_triggered) ? true : false;
$db->sql_return_on_error(false);
return (!$error) ? true : false;
}
/**
* Function to prepare some column information for better usage
*/
function prepare_column_data($dbms, $column_data)
{
global $dbms_type_map, $unsigned_types;
// Get type
if (strpos($column_data[0], ':') !== false)
{
list($orig_column_type, $column_length) = explode(':', $column_data[0]);
if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':']))
{
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length);
}
else
{
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule']))
{
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0])
{
case 'div':
$column_length /= $dbms_type_map[$dbms][$orig_column_type . ':']['rule'][1];
$column_length = ceil($column_length);
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
break;
}
}
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit']))
{
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0])
{
case 'mult':
$column_length *= $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][1];
if ($column_length > $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][2])
{
$column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3];
}
else
{
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
}
break;
}
}
}
$orig_column_type .= ':';
}
else
{
$orig_column_type = $column_data[0];
$column_type = $dbms_type_map[$dbms][$column_data[0]];
}
// Adjust default value if db-dependant specified
if (is_array($column_data[1]))
{
$column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default'];
}
$sql = '';
switch ($dbms)
{
case 'firebird':
$sql .= " {$column_type} ";
if (!is_null($column_data[1]))
{
$sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
}
$sql .= 'NOT NULL';
// This is a UNICODE column and thus should be given it's fair share
if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0]))
{
$sql .= ' COLLATE UNICODE';
}
break;
case 'mssql':
$sql .= " {$column_type} ";
if (!is_null($column_data[1]))
{
// For hexadecimal values do not use single quotes
if (strpos($column_data[1], '0x') === 0)
{
$sql .= 'DEFAULT (' . $column_data[1] . ') ';
}
else
{
$sql .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
}
}
$sql .= 'NOT NULL';
break;
case 'mysql_40':
case 'mysql_41':
$sql .= " {$column_type} ";
// For hexadecimal values do not use single quotes
if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text')
{
$sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
}
$sql .= 'NOT NULL';
break;
case 'oracle':
$sql .= " {$column_type} ";
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
// In Oracle empty strings ('') are treated as NULL.
// Therefore in oracle we allow NULL's for all DEFAULT '' entries
$sql .= ($column_data[1] === '') ? '' : 'NOT NULL';
break;
case 'postgres':
$sql .= " {$column_type} ";
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
$sql .= 'NOT NULL';
// Unsigned? Then add a CHECK contraint
if (in_array($orig_column_type, $unsigned_types))
{
$sql .= " CHECK ({$column_name} >= 0)";
}
break;
case 'sqlite':
$sql .= ' ' . $column_type . ' NOT NULL ';
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
break;
}
return array(
'column_type_sql' => $sql,
);
}
/**
* Add new column
*/
function sql_column_add($dbms, $table_name, $column_name, $column_data)
{
global $errored, $error_ary;
$column_data = prepare_column_data($dbms, $column_data);
switch ($dbms)
{
case 'firebird':
$sql = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'mssql':
$sql = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'mysql_40':
case 'mysql_41':
$sql = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'oracle':
$sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'postgres':
$sql = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'sqlite':
if (version_compare(sqlite_libversion(), '3.0') == -1)
{
global $db;
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
AND name = '{$table_name}'
ORDER BY type DESC, name;";
$result = $db->sql_query($sql);
if (!$result)
{
break;
}
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$db->sql_transaction('begin');
// Create a backup table and populate it, destroy the existing one
$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
$db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
$db->sql_query('DROP TABLE ' . $table_name);
preg_match('#\((.*)\)#s', $row['sql'], $matches);
$new_table_cols = trim($matches[1]);
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
$column_list = array();
foreach ($old_table_cols as $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if ($entities[0] == 'PRIMARY')
{
continue;
}
$column_list[] = $entities[0];
}
$columns = implode(',', $column_list);
$new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols;
// create a new table and fill it up. destroy the temp one
$db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');');
$db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
$db->sql_query('DROP TABLE ' . $table_name . '_temp');
$db->sql_transaction('commit');
}
else
{
$sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']';
_sql($sql, $errored, $error_ary);
}
break;
}
}
function sql_index_drop($dbms, $index_name, $table_name)
{
global $dbms_type_map, $db;
global $errored, $error_ary;
switch ($dbms)
{
case 'mssql':
$sql = 'DROP INDEX ' . $table_name . '\.' . $index_name . ' ON ' . $table_name;
_sql($sql, $errored, $error_ary);
break;
case 'mysql_40':
case 'mysql_41':
$sql = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
_sql($sql, $errored, $error_ary);
break;
case 'firebird':
case 'oracle':
case 'postgres':
case 'sqlite':
$sql = 'DROP INDEX ' . $table_name . '_' . $index_name;
_sql($sql, $errored, $error_ary);
break;
}
}
function sql_create_primary_key($dbms, $table_name, $column)
{
global $dbms_type_map, $db;
global $errored, $error_ary;
switch ($dbms)
{
case 'firebird':
case 'postgres':
$sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
_sql($sql, $errored, $error_ary);
break;
case 'mssql':
$sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
$sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
$sql .= '[' . implode("],\n\t\t[", $column) . ']';
$sql .= ') ON [PRIMARY]';
_sql($sql, $errored, $error_ary);
break;
case 'mysql_40':
case 'mysql_41':
$sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
_sql($sql, $errored, $error_ary);
break;
case 'oracle':
$sql = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
_sql($sql, $errored, $error_ary);
break;
case 'sqlite':
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
AND name = '{$table_name}'
ORDER BY type DESC, name;";
$result = _sql($sql, $errored, $error_ary);
if (!$result)
{
break;
}
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$db->sql_transaction('begin');
// Create a backup table and populate it, destroy the existing one
$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
$db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
$db->sql_query('DROP TABLE ' . $table_name);
preg_match('#\((.*)\)#s', $row['sql'], $matches);
$new_table_cols = trim($matches[1]);
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
$column_list = array();
foreach ($old_table_cols as $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
if ($entities[0] == 'PRIMARY')
{
continue;
}
$column_list[] = $entities[0];
}
$columns = implode(',', $column_list);
// create a new table and fill it up. destroy the temp one
$db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));');
$db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
$db->sql_query('DROP TABLE ' . $table_name . '_temp');
$db->sql_transaction('commit');
break;
}
}
/**
* Change column type (not name!)
*/
function sql_column_change($dbms, $table_name, $column_name, $column_data)
{
global $dbms_type_map, $db;
global $errored, $error_ary;
$column_data = prepare_column_data($dbms, $column_data);
switch ($dbms)
{
case 'firebird':
// Change type...
$sql = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'mssql':
$sql = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'mysql_40':
case 'mysql_41':
$sql = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'oracle':
$sql = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'postgres':
$sql = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN ' . $column_name . ' SET ' . $column_data['column_type_sql'];
_sql($sql, $errored, $error_ary);
break;
case 'sqlite':
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
AND name = '{$table_name}'
ORDER BY type DESC, name;";
$result = _sql($sql, $errored, $error_ary);
if (!$result)
{
break;
}
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$db->sql_transaction('begin');
// Create a temp table and populate it, destroy the existing one
$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
$db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
$db->sql_query('DROP TABLE ' . $table_name);
preg_match('#\((.*)\)#s', $row['sql'], $matches);
$new_table_cols = trim($matches[1]);
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
$column_list = array();
foreach ($old_table_cols as $key => $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
$column_list[] = $entities[0];
if ($entities[0] == $column_name)
{
$old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
}
}
$columns = implode(',', $column_list);
// create a new table and fill it up. destroy the temp one
$db->sql_query('CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');');
$db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
$db->sql_query('DROP TABLE ' . $table_name . '_temp');
$db->sql_transaction('commit');
break;
}
}
/**
* Add search robots to the database
* @ignore
*/
function add_bots()
{
global $db, $config, $phpbb_root_path, $phpEx;
$sql = 'SELECT *
FROM ' . CONFIG_TABLE;
$result = $db->sql_query($sql);
$config = array();
while ($row = $db->sql_fetchrow($result))
{
$config[$row['config_name']] = $row['config_value'];
}
$db->sql_freeresult($result);
// Obtain any submitted data
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'BOTS'";
$result = $db->sql_query($sql);
$group_id = (int) $db->sql_fetchfield('group_id');
$db->sql_freeresult($result);
if (!$group_id)
{
return;
}
// First of all, remove the old bots...
$sql = 'SELECT bot_id
FROM ' . BOTS_TABLE . "
WHERE bot_name IN ('Alexa', 'Fastcrawler', 'Googlebot', 'Inktomi')";
$result = $db->sql_query($sql);
$bot_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$bot_ids[] = $row['bot_id'];
}
$db->sql_freeresult($result);
if (sizeof($bot_ids))
{
// We need to delete the relevant user, usergroup and bot entries ...
$sql_id = ' IN (' . implode(', ', $bot_ids) . ')';
$sql = 'SELECT bot_name, user_id
FROM ' . BOTS_TABLE . "
WHERE bot_id $sql_id";
$result = $db->sql_query($sql);
$user_id_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$user_id_ary[] = (int) $row['user_id'];
}
$db->sql_freeresult($result);
$sql = 'DELETE FROM ' . BOTS_TABLE . "
WHERE bot_id $sql_id";
$db->sql_query($sql);
if (sizeof($user_id_ary))
{
$_tables = array(USERS_TABLE, USER_GROUP_TABLE);
foreach ($_tables as $table)
{
$sql = "DELETE FROM $table
WHERE " . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
}
}
}
else
{
// If the old bots are missing we can safely assume the user tries to execute the database update twice and
// fiddled around...
return;
}
if (!function_exists('user_add'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
global $errored, $error_ary;
$bot_list = array(
'AdsBot [Google]' => array('AdsBot-Google', ''),
'Alexa [Bot]' => array('ia_archiver', ''),
'Alta Vista [Bot]' => array('Scooter/', ''),
'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
'Baidu [Spider]' => array('Baiduspider+(', ''),
'Exabot [Bot]' => array('Exabot/', ''),
'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
'Francis [Bot]' => array('http://www.neomo.de/', ''),
'Gigabot [Bot]' => array('Gigabot/', ''),
'Google Adsense [Bot]' => array('Mediapartners-Google/', ''),
'Google Desktop' => array('Google Desktop', ''),
'Google Feedfetcher' => array('Feedfetcher-Google', ''),
'Google [Bot]' => array('Googlebot', ''),
'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
'Heritrix [Crawler]' => array('heritrix/1.', ''),
'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
'ichiro [Crawler]' => array('ichiro/2', ''),
'Majestic-12 [Bot]' => array('MJ12bot/', ''),
'Metager [Bot]' => array('MetagerBot/', ''),
'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
'MSN [Bot]' => array('msnbot/', ''),
'MSNbot Media' => array('msnbot-media/', ''),
'NG-Search [Bot]' => array('NG-Search/', ''),
'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
'Nutch/CVS [Bot]' => array('NutchCVS/', ''),
'OmniExplorer [Bot]' => array('OmniExplorer_Bot/', ''),
'Online link [Validator]' => array('online link validator', ''),
'psbot [Picsearch]' => array('psbot/0', ''),
'Seekport [Bot]' => array('Seekbot/', ''),
'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
'SEO Crawler' => array('SEO search Crawler/', ''),
'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
'SEOSearch [Crawler]' => array('SEOsearch/', ''),
'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
'Synoo [Bot]' => array('SynooBot/', ''),
'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
'Voyager [Bot]' => array('voyager/1.0', ''),
'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
'W3C [Linkcheck]' => array('W3C-checklink/', ''),
'W3C [Validator]' => array('W3C_*Validator', ''),
'WiseNut [Bot]' => array('http://www.WISEnutbot.com', ''),
'YaCy [Bot]' => array('yacybot', ''),
'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
);
foreach ($bot_list as $bot_name => $bot_ary)
{
$user_row = array(
'user_type' => USER_IGNORE,
'group_id' => $group_id,
'username' => $bot_name,
'user_regdate' => time(),
'user_password' => '',
'user_colour' => '9E8DA7',
'user_email' => '',
'user_lang' => $config['default_lang'],
'user_style' => 1,
'user_timezone' => 0,
'user_dateformat' => $config['default_dateformat'],
'user_allow_massemail' => 0,
);
$user_id = user_add($user_row);
if ($user_id)
{
$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
'bot_active' => 1,
'bot_name' => $bot_name,
'user_id' => $user_id,
'bot_agent' => $bot_ary[0],
'bot_ip' => $bot_ary[1],
));
_sql($sql, $errored, $error_ary);
}
}
}
?>