Verzeichnisstruktur phpBB-3.0.0
- Veröffentlicht
- 12.12.2007
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
database_update.php
0001 <?php
0002 /**
0003 *
0004 * @package install
0005 * @version $Id$
0006 * @copyright (c) 2006 phpBB Group
0007 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
0008 *
0009 */
0010
0011 $updates_to_version = '3.0.0';
0012
0013 // Return if we "just include it" to find out for which version the database update is responsuble for
0014 if (defined('IN_PHPBB') && defined('IN_INSTALL'))
0015 {
0016 return;
0017 }
0018
0019 /**
0020 */
0021 define('IN_PHPBB', true);
0022 define('IN_INSTALL', true);
0023
0024 $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
0025 $phpEx = substr(strrchr(__FILE__, '.'), 1);
0026
0027 // Report all errors, except notices
0028 //error_reporting(E_ALL ^ E_NOTICE);
0029 error_reporting(E_ALL);
0030
0031 @set_time_limit(0);
0032
0033 // Include essential scripts
0034 include($phpbb_root_path . 'config.' . $phpEx);
0035
0036 if (!isset($dbms))
0037 {
0038 die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
0039 }
0040
0041 // Load Extensions
0042 if (!empty($load_extensions))
0043 {
0044 $load_extensions = explode(',', $load_extensions);
0045
0046 foreach ($load_extensions as $extension)
0047 {
0048 @dl(trim($extension));
0049 }
0050 }
0051
0052 // Include files
0053 require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx);
0054 require($phpbb_root_path . 'includes/cache.' . $phpEx);
0055 require($phpbb_root_path . 'includes/template.' . $phpEx);
0056 require($phpbb_root_path . 'includes/session.' . $phpEx);
0057 require($phpbb_root_path . 'includes/auth.' . $phpEx);
0058
0059 require($phpbb_root_path . 'includes/functions.' . $phpEx);
0060
0061 if (file_exists($phpbb_root_path . 'includes/functions_content.' . $phpEx))
0062 {
0063 require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
0064 }
0065
0066 require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
0067 require($phpbb_root_path . 'includes/constants.' . $phpEx);
0068 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
0069 require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
0070
0071 // If we are on PHP >= 6.0.0 we do not need some code
0072 if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
0073 {
0074 /**
0075 * @ignore
0076 */
0077 define('STRIP', false);
0078 }
0079 else
0080 {
0081 set_magic_quotes_runtime(0);
0082 define('STRIP', (get_magic_quotes_gpc()) ? true : false);
0083 }
0084
0085 $user = new user();
0086 $cache = new cache();
0087 $db = new $sql_db();
0088
0089 // Add own hook handler, if present. :o
0090 if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
0091 {
0092 require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
0093 $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
0094
0095 foreach ($cache->obtain_hooks() as $hook)
0096 {
0097 @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
0098 }
0099 }
0100 else
0101 {
0102 $phpbb_hook = false;
0103 }
0104
0105 // Connect to DB
0106 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
0107
0108 // We do not need this any longer, unset for safety purposes
0109 unset($dbpasswd);
0110
0111 $user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
0112
0113 $sql = "SELECT config_value
0114 FROM " . CONFIG_TABLE . "
0115 WHERE config_name = 'default_lang'";
0116 $result = $db->sql_query($sql);
0117 $row = $db->sql_fetchrow($result);
0118 $db->sql_freeresult($result);
0119
0120 $language = basename(request_var('language', ''));
0121
0122 if (!$language)
0123 {
0124 $language = $row['config_value'];
0125 }
0126
0127 if (!file_exists($phpbb_root_path . 'language/' . $language))
0128 {
0129 die('No language found!');
0130 }
0131
0132 // And finally, load the relevant language files
0133 include($phpbb_root_path . 'language/' . $language . '/common.' . $phpEx);
0134 include($phpbb_root_path . 'language/' . $language . '/acp/common.' . $phpEx);
0135 include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx);
0136
0137 // Set PHP error handler to ours
0138 //set_error_handler('msg_handler');
0139
0140 // Define some variables for the database update
0141 $inline_update = (request_var('type', 0)) ? true : false;
0142
0143 // Database column types mapping
0144 $dbms_type_map = array(
0145 'mysql_41' => array(
0146 'INT:' => 'int(%d)',
0147 'BINT' => 'bigint(20)',
0148 'UINT' => 'mediumint(8) UNSIGNED',
0149 'UINT:' => 'int(%d) UNSIGNED',
0150 'TINT:' => 'tinyint(%d)',
0151 'USINT' => 'smallint(4) UNSIGNED',
0152 'BOOL' => 'tinyint(1) UNSIGNED',
0153 'VCHAR' => 'varchar(255)',
0154 'VCHAR:' => 'varchar(%d)',
0155 'CHAR:' => 'char(%d)',
0156 'XSTEXT' => 'text',
0157 'XSTEXT_UNI'=> 'varchar(100)',
0158 'STEXT' => 'text',
0159 'STEXT_UNI' => 'varchar(255)',
0160 'TEXT' => 'text',
0161 'TEXT_UNI' => 'text',
0162 'MTEXT' => 'mediumtext',
0163 'MTEXT_UNI' => 'mediumtext',
0164 'TIMESTAMP' => 'int(11) UNSIGNED',
0165 'DECIMAL' => 'decimal(5,2)',
0166 'VCHAR_UNI' => 'varchar(255)',
0167 'VCHAR_UNI:'=> 'varchar(%d)',
0168 'VCHAR_CI' => 'varchar(255)',
0169 'VARBINARY' => 'varbinary(255)',
0170 ),
0171
0172 'mysql_40' => array(
0173 'INT:' => 'int(%d)',
0174 'BINT' => 'bigint(20)',
0175 'UINT' => 'mediumint(8) UNSIGNED',
0176 'UINT:' => 'int(%d) UNSIGNED',
0177 'TINT:' => 'tinyint(%d)',
0178 'USINT' => 'smallint(4) UNSIGNED',
0179 'BOOL' => 'tinyint(1) UNSIGNED',
0180 'VCHAR' => 'varbinary(255)',
0181 'VCHAR:' => 'varbinary(%d)',
0182 'CHAR:' => 'binary(%d)',
0183 'XSTEXT' => 'blob',
0184 'XSTEXT_UNI'=> 'blob',
0185 'STEXT' => 'blob',
0186 'STEXT_UNI' => 'blob',
0187 'TEXT' => 'blob',
0188 'TEXT_UNI' => 'blob',
0189 'MTEXT' => 'mediumblob',
0190 'MTEXT_UNI' => 'mediumblob',
0191 'TIMESTAMP' => 'int(11) UNSIGNED',
0192 'DECIMAL' => 'decimal(5,2)',
0193 'VCHAR_UNI' => 'blob',
0194 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')),
0195 'VCHAR_CI' => 'blob',
0196 'VARBINARY' => 'varbinary(255)',
0197 ),
0198
0199 'firebird' => array(
0200 'INT:' => 'INTEGER',
0201 'BINT' => 'DOUBLE PRECISION',
0202 'UINT' => 'INTEGER',
0203 'UINT:' => 'INTEGER',
0204 'TINT:' => 'INTEGER',
0205 'USINT' => 'INTEGER',
0206 'BOOL' => 'INTEGER',
0207 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE',
0208 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE',
0209 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE',
0210 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
0211 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
0212 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
0213 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
0214 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8',
0215 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
0216 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
0217 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
0218 'TIMESTAMP' => 'INTEGER',
0219 'DECIMAL' => 'DOUBLE PRECISION',
0220 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
0221 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8',
0222 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8',
0223 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE',
0224 ),
0225
0226 'mssql' => array(
0227 'INT:' => '[int]',
0228 'BINT' => '[float]',
0229 'UINT' => '[int]',
0230 'UINT:' => '[int]',
0231 'TINT:' => '[int]',
0232 'USINT' => '[int]',
0233 'BOOL' => '[int]',
0234 'VCHAR' => '[varchar] (255)',
0235 'VCHAR:' => '[varchar] (%d)',
0236 'CHAR:' => '[char] (%d)',
0237 'XSTEXT' => '[varchar] (1000)',
0238 'STEXT' => '[varchar] (3000)',
0239 'TEXT' => '[varchar] (8000)',
0240 'MTEXT' => '[text]',
0241 'XSTEXT_UNI'=> '[varchar] (100)',
0242 'STEXT_UNI' => '[varchar] (255)',
0243 'TEXT_UNI' => '[varchar] (4000)',
0244 'MTEXT_UNI' => '[text]',
0245 'TIMESTAMP' => '[int]',
0246 'DECIMAL' => '[float]',
0247 'VCHAR_UNI' => '[varchar] (255)',
0248 'VCHAR_UNI:'=> '[varchar] (%d)',
0249 'VCHAR_CI' => '[varchar] (255)',
0250 'VARBINARY' => '[varchar] (255)',
0251 ),
0252
0253 'oracle' => array(
0254 'INT:' => 'number(%d)',
0255 'BINT' => 'number(20)',
0256 'UINT' => 'number(8)',
0257 'UINT:' => 'number(%d)',
0258 'TINT:' => 'number(%d)',
0259 'USINT' => 'number(4)',
0260 'BOOL' => 'number(1)',
0261 'VCHAR' => 'varchar2(255)',
0262 'VCHAR:' => 'varchar2(%d)',
0263 'CHAR:' => 'char(%d)',
0264 'XSTEXT' => 'varchar2(1000)',
0265 'STEXT' => 'varchar2(3000)',
0266 'TEXT' => 'clob',
0267 'MTEXT' => 'clob',
0268 'XSTEXT_UNI'=> 'varchar2(300)',
0269 'STEXT_UNI' => 'varchar2(765)',
0270 'TEXT_UNI' => 'clob',
0271 'MTEXT_UNI' => 'clob',
0272 'TIMESTAMP' => 'number(11)',
0273 'DECIMAL' => 'number(5, 2)',
0274 'VCHAR_UNI' => 'varchar2(765)',
0275 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
0276 'VCHAR_CI' => 'varchar2(255)',
0277 'VARBINARY' => 'raw(255)',
0278 ),
0279
0280 'sqlite' => array(
0281 'INT:' => 'int(%d)',
0282 'BINT' => 'bigint(20)',
0283 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
0284 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
0285 'TINT:' => 'tinyint(%d)',
0286 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
0287 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
0288 'VCHAR' => 'varchar(255)',
0289 'VCHAR:' => 'varchar(%d)',
0290 'CHAR:' => 'char(%d)',
0291 'XSTEXT' => 'text(65535)',
0292 'STEXT' => 'text(65535)',
0293 'TEXT' => 'text(65535)',
0294 'MTEXT' => 'mediumtext(16777215)',
0295 'XSTEXT_UNI'=> 'text(65535)',
0296 'STEXT_UNI' => 'text(65535)',
0297 'TEXT_UNI' => 'text(65535)',
0298 'MTEXT_UNI' => 'mediumtext(16777215)',
0299 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
0300 'DECIMAL' => 'decimal(5,2)',
0301 'VCHAR_UNI' => 'varchar(255)',
0302 'VCHAR_UNI:'=> 'varchar(%d)',
0303 'VCHAR_CI' => 'varchar(255)',
0304 'VARBINARY' => 'blob',
0305 ),
0306
0307 'postgres' => array(
0308 'INT:' => 'INT4',
0309 'BINT' => 'INT8',
0310 'UINT' => 'INT4', // unsigned
0311 'UINT:' => 'INT4', // unsigned
0312 'USINT' => 'INT2', // unsigned
0313 'BOOL' => 'INT2', // unsigned
0314 'TINT:' => 'INT2',
0315 'VCHAR' => 'varchar(255)',
0316 'VCHAR:' => 'varchar(%d)',
0317 'CHAR:' => 'char(%d)',
0318 'XSTEXT' => 'varchar(1000)',
0319 'STEXT' => 'varchar(3000)',
0320 'TEXT' => 'varchar(8000)',
0321 'MTEXT' => 'TEXT',
0322 'XSTEXT_UNI'=> 'varchar(100)',
0323 'STEXT_UNI' => 'varchar(255)',
0324 'TEXT_UNI' => 'varchar(4000)',
0325 'MTEXT_UNI' => 'TEXT',
0326 'TIMESTAMP' => 'INT4', // unsigned
0327 'DECIMAL' => 'decimal(5,2)',
0328 'VCHAR_UNI' => 'varchar(255)',
0329 'VCHAR_UNI:'=> 'varchar(%d)',
0330 'VCHAR_CI' => 'varchar_ci',
0331 'VARBINARY' => 'bytea',
0332 ),
0333 );
0334
0335 // A list of types being unsigned for better reference in some db's
0336 $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
0337
0338 // Only an example, but also commented out
0339 $database_update_info = array(
0340 // Changes from 3.0.RC2 to the next version
0341 '3.0.RC2' => array(
0342 // Change the following columns
0343 'change_columns' => array(
0344 BANLIST_TABLE => array(
0345 'ban_reason' => array('VCHAR_UNI', ''),
0346 'ban_give_reason' => array('VCHAR_UNI', ''),
0347 ),
0348 ),
0349 ),
0350 // Changes from 3.0.RC3 to the next version
0351 '3.0.RC3' => array(
0352 // Change the following columns
0353 'change_columns' => array(
0354 BANLIST_TABLE => array(
0355 'ban_reason' => array('VCHAR_UNI', ''),
0356 'ban_give_reason' => array('VCHAR_UNI', ''),
0357 ),
0358 STYLES_TABLE => array(
0359 'style_id' => array('USINT', 0),
0360 'template_id' => array('USINT', 0),
0361 'theme_id' => array('USINT', 0),
0362 'imageset_id' => array('USINT', 0),
0363 ),
0364 STYLES_TEMPLATE_TABLE => array(
0365 'template_id' => array('USINT', 0),
0366 ),
0367 STYLES_TEMPLATE_DATA_TABLE => array(
0368 'template_id' => array('USINT', 0),
0369 ),
0370 STYLES_THEME_TABLE => array(
0371 'theme_id' => array('USINT', 0),
0372 ),
0373 STYLES_IMAGESET_TABLE => array(
0374 'imageset_id' => array('USINT', 0),
0375 ),
0376 STYLES_IMAGESET_DATA_TABLE => array(
0377 'imageset_id' => array('USINT', 0),
0378 ),
0379 USERS_TABLE => array(
0380 'user_style' => array('USINT', 0),
0381 ),
0382 FORUMS_TABLE => array(
0383 'forum_style' => array('USINT', 0),
0384 ),
0385 GROUPS_TABLE => array(
0386 'group_avatar_type' => array('TINT:2', 0),
0387 'group_avatar_width' => array('USINT', 0),
0388 'group_avatar_height' => array('USINT', 0),
0389 ),
0390 ),
0391 ),
0392 // Changes from 3.0.RC4 to the next version
0393 '3.0.RC4' => array(
0394 // Change the following columns
0395 'change_columns' => array(
0396 STYLES_TABLE => array(
0397 'style_id' => array('USINT', NULL, 'auto_increment'),
0398 'template_id' => array('USINT', 0),
0399 'theme_id' => array('USINT', 0),
0400 'imageset_id' => array('USINT', 0),
0401 ),
0402 STYLES_TEMPLATE_TABLE => array(
0403 'template_id' => array('USINT', NULL, 'auto_increment'),
0404 ),
0405 STYLES_TEMPLATE_DATA_TABLE => array(
0406 'template_id' => array('USINT', 0),
0407 ),
0408 STYLES_THEME_TABLE => array(
0409 'theme_id' => array('USINT', NULL, 'auto_increment'),
0410 ),
0411 STYLES_IMAGESET_TABLE => array(
0412 'imageset_id' => array('USINT', NULL, 'auto_increment'),
0413 ),
0414 STYLES_IMAGESET_DATA_TABLE => array(
0415 'imageset_id' => array('USINT', 0),
0416 ),
0417 USERS_TABLE => array(
0418 'user_style' => array('USINT', 0),
0419 ),
0420 FORUMS_TABLE => array(
0421 'forum_style' => array('USINT', 0),
0422 ),
0423 GROUPS_TABLE => array(
0424 'group_avatar_width' => array('USINT', 0),
0425 'group_avatar_height' => array('USINT', 0),
0426 ),
0427 ),
0428 ),
0429 // Changes from 3.0.RC5 to the next version
0430 '3.0.RC5' => array(
0431 // Add the following columns
0432 'add_columns' => array(
0433 USERS_TABLE => array(
0434 'user_form_salt' => array('VCHAR_UNI:32', ''),
0435 ),
0436 ),
0437 // Change the following columns
0438 'change_columns' => array(
0439 POSTS_TABLE => array(
0440 'bbcode_uid' => array('VCHAR:8', ''),
0441 ),
0442 PRIVMSGS_TABLE => array(
0443 'bbcode_uid' => array('VCHAR:8', ''),
0444 ),
0445 USERS_TABLE => array(
0446 'user_sig_bbcode_uid' => array('VCHAR:8', ''),
0447 ),
0448 ),
0449 ),
0450 // Changes from 3.0.RC6 to the next version
0451 '3.0.RC6' => array(
0452 // Change the following columns
0453 'change_columns' => array(
0454 FORUMS_TABLE => array(
0455 'forum_desc_uid' => array('VCHAR:8', ''),
0456 'forum_rules_uid' => array('VCHAR:8', ''),
0457 ),
0458 GROUPS_TABLE => array(
0459 'group_desc_uid' => array('VCHAR:8', ''),
0460 ),
0461 USERS_TABLE => array(
0462 'user_newpasswd' => array('VCHAR_UNI:40', ''),
0463 ),
0464 ),
0465 ),
0466 // Changes from 3.0.RC8 to the next version
0467 '3.0.RC8' => array(
0468 // Change the following columns
0469 'change_columns' => array(
0470 USERS_TABLE => array(
0471 'user_new_privmsg' => array('INT:4', 0),
0472 'user_unread_privmsg' => array('INT:4', 0),
0473 ),
0474 ),
0475 ),
0476 );
0477
0478 // Determine mapping database type
0479 switch ($db->sql_layer)
0480 {
0481 case 'mysql':
0482 $map_dbms = 'mysql_40';
0483 break;
0484
0485 case 'mysql4':
0486 if (version_compare($db->mysql_version, '4.1.3', '>='))
0487 {
0488 $map_dbms = 'mysql_41';
0489 }
0490 else
0491 {
0492 $map_dbms = 'mysql_40';
0493 }
0494 break;
0495
0496 case 'mysqli':
0497 $map_dbms = 'mysql_41';
0498 break;
0499
0500 case 'mssql':
0501 case 'mssql_odbc':
0502 $map_dbms = 'mssql';
0503 break;
0504
0505 default:
0506 $map_dbms = $db->sql_layer;
0507 break;
0508 }
0509
0510 $error_ary = array();
0511 $errored = false;
0512
0513 header('Content-type: text/html; charset=UTF-8');
0514
0515 ?>
0516 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
0517 <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']; ?>">
0518 <head>
0519
0520 <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
0521 <meta http-equiv="content-language" content="<?php echo $lang['USER_LANG']; ?>" />
0522 <meta http-equiv="content-style-type" content="text/css" />
0523 <meta http-equiv="imagetoolbar" content="no" />
0524
0525 <title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title>
0526
0527 <link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />
0528
0529 </head>
0530
0531 <body>
0532 <div id="wrap">
0533 <div id="page-header"> </div>
0534
0535 <div id="page-body">
0536 <div id="acp">
0537 <div class="panel">
0538 <span class="corners-top"><span></span></span>
0539 <div id="content">
0540 <div id="main">
0541
0542 <h1><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
0543
0544 <br />
0545
0546 <p><?php echo $lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->sql_layer; ?></strong><br />
0547 <?php
0548
0549 // To let set_config() calls succeed, we need to make the config array available globally
0550 $config = array();
0551 $sql = 'SELECT *
0552 FROM ' . CONFIG_TABLE;
0553 $result = $db->sql_query($sql);
0554
0555 while ($row = $db->sql_fetchrow($result))
0556 {
0557 $config[$row['config_name']] = $row['config_value'];
0558 }
0559 $db->sql_freeresult($result);
0560
0561 echo $lang['PREVIOUS_VERSION'] . ' :: <strong>' . $config['version'] . '</strong><br />';
0562 echo $lang['UPDATED_VERSION'] . ' :: <strong>' . $updates_to_version . '</strong></p>';
0563
0564 $current_version = str_replace('rc', 'RC', strtolower($config['version']));
0565 $latest_version = str_replace('rc', 'RC', strtolower($updates_to_version));
0566 $orig_version = $config['version'];
0567
0568 // If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything.
0569 if ($inline_update)
0570 {
0571 if ($current_version !== $latest_version)
0572 {
0573 set_config('version_update_from', $orig_version);
0574 }
0575 }
0576 else
0577 {
0578 // If not called from the update script, we will actually remove the traces
0579 $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
0580 }
0581
0582 // Checks/Operations that have to be completed prior to starting the update itself
0583 $exit = false;
0584 if (version_compare($current_version, '3.0.RC8', '<='))
0585 {
0586 // Define missing language entries...
0587 if (!isset($lang['CLEANING_USERNAMES']))
0588 {
0589 $lang = array_merge($lang, array(
0590 'CLEANING_USERNAMES' => 'Cleaning usernames',
0591 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.',
0592 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.',
0593 'USER_ACTIVE' => 'Active user',
0594 'USER_INACTIVE' => 'Inactive user',
0595 'BOT' => 'Spider/Robot',
0596 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s',
0597
0598 'DELETE_USER_REMOVE' => 'Delete user and remove posts',
0599 'DELETE_USER_RETAIN' => 'Delete user but keep posts',
0600 'EDIT_USERNAME' => 'Edit username',
0601 'KEEP_OLD_NAME' => 'Keep username',
0602 'NEW_USERNAME' => 'New username',
0603 ));
0604 }
0605 ?>
0606 <br /><br />
0607
0608 <h1><?php echo $lang['CLEANING_USERNAMES']; ?></h1>
0609
0610 <br />
0611
0612 <?php
0613 flush();
0614
0615 $submit = (isset($_POST['resolve_conflicts'])) ? true : false;
0616 $modify_users = request_var('modify_users', array(0 => ''));
0617 $new_usernames = request_var('new_usernames', array(0 => ''), true);
0618
0619 if (!class_exists('utf_new_normalizer'))
0620 {
0621 if (!file_exists($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx))
0622 {
0623 global $lang;
0624 trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/new_normalizer.' . $phpEx), E_USER_ERROR);
0625 }
0626 include($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx);
0627 }
0628
0629 // the admin decided to change some usernames
0630 if (sizeof($modify_users) && $submit)
0631 {
0632 $sql = 'SELECT user_id, username, user_type
0633 FROM ' . USERS_TABLE . '
0634 WHERE ' . $db->sql_in_set('user_id', array_keys($modify_users));
0635 $result = $db->sql_query($sql);
0636
0637 $users = 0;
0638 while ($row = $db->sql_fetchrow($result))
0639 {
0640 $users++;
0641 $user_id = (int) $row['user_id'];
0642
0643 if (isset($modify_users[$user_id]))
0644 {
0645 $row['action'] = $modify_users[$user_id];
0646 $modify_users[$user_id] = $row;
0647 }
0648 }
0649 $db->sql_freeresult($result);
0650
0651 // only if all ids really existed
0652 if (sizeof($modify_users) == $users)
0653 {
0654 $user->data['user_id'] = ANONYMOUS;
0655 include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
0656 foreach ($modify_users as $user_id => $row)
0657 {
0658 switch ($row['action'])
0659 {
0660 case 'edit':
0661 if (isset($new_usernames[$user_id]))
0662 {
0663 $data = array('username' => utf8_new_normalize_nfc($new_usernames[$user_id]));
0664 // Need to update config, forum, topic, posting, messages, etc.
0665 if ($data['username'] != $row['username'])
0666 {
0667 $check_ary = array('username' => array(
0668 array('string', false, $config['min_name_chars'], $config['max_name_chars']),
0669 array('username'),
0670 ));
0671 // need a little trick for this to work properly
0672 $user->data['username_clean'] = utf8_clean_string($data['username']) . 'a';
0673 $errors = validate_data($data, $check_ary);
0674
0675 if ($errors)
0676 {
0677 include($phpbb_root_path . 'language/' . $language . '/ucp.' . $phpEx);
0678 echo '<div class="errorbox">';
0679 foreach ($errors as $error)
0680 {
0681 echo '<p>' . $lang[$error] . '</p>';
0682 }
0683 echo '</div>';
0684 }
0685
0686 if (!$errors)
0687 {
0688 $sql = 'UPDATE ' . USERS_TABLE . '
0689 SET ' . $db->sql_build_array('UPDATE', array(
0690 'username' => $data['username'],
0691 'username_clean' => utf8_clean_string($data['username'])
0692 )) . '
0693 WHERE user_id = ' . $user_id;
0694 $db->sql_query($sql);
0695
0696 add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $row['username'], $data['username']);
0697 user_update_name($row['username'], $data['username']);
0698 }
0699 }
0700 }
0701 break;
0702
0703 case 'delete_retain':
0704 case 'delete_remove':
0705 if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
0706 {
0707 user_delete(substr($row['action'], 7), $user_id, $row['username']);
0708 add_log('admin', 'LOG_USER_DELETED', $row['username']);
0709 }
0710 break;
0711 }
0712 }
0713 }
0714 }
0715 ?>
0716
0717 <p><?php echo $lang['LONG_SCRIPT_EXECUTION']; ?></p>
0718 <p><?php echo $lang['PROGRESS']; ?> :: <strong>
0719
0720 <?php
0721 flush();
0722
0723 // after RC3 a different utf8_clean_string function is used, this requires that
0724 // the unique column username_clean is recalculated, during this recalculation
0725 // duplicates might be created. Since the column has to be unique such usernames
0726 // must not exist. We need identify them and let the admin decide what to do
0727 // about them.
0728 // After RC8 this was changed again, but this time only usernames containing spaces
0729 // are affected.
0730 $sql_where = (version_compare($current_version, '3.0.RC4', '<=')) ? '' : "WHERE username_clean LIKE '% %'";
0731 $sql = 'SELECT user_id, username, username_clean
0732 FROM ' . USERS_TABLE . "
0733 $sql_where
0734 ORDER BY user_id ASC";
0735 $result = $db->sql_query($sql);
0736
0737 $colliding_users = $found_names = array();
0738 $echos = 0;
0739
0740 while ($row = $db->sql_fetchrow($result))
0741 {
0742 // Calculate the new clean name. If it differs from the old one we need
0743 // to make sure there is no collision
0744 $clean_name = utf8_new_clean_string($row['username']);
0745
0746 if ($clean_name != $row['username_clean'])
0747 {
0748 // Check if there would be a collission, if not put it up for changing
0749 $user_id = (int) $row['user_id'];
0750
0751 // If this clean name was not the result of another user already ...
0752 if (!isset($found_names[$clean_name]))
0753 {
0754 // then we need to figure out whether there are any other users
0755 // who already had this clean name with the old version
0756 $sql = 'SELECT user_id, username
0757 FROM ' . USERS_TABLE . '
0758 WHERE username_clean = \'' . $db->sql_escape($clean_name) . '\'';
0759 $result2 = $db->sql_query($sql);
0760
0761 $user_ids = array($user_id);
0762 while ($row = $db->sql_fetchrow($result2))
0763 {
0764 // For not trimmed entries this could happen, yes. ;)
0765 if ($row['user_id'] == $user_id)
0766 {
0767 continue;
0768 }
0769
0770 // Make sure this clean name will still be the same with the
0771 // new function. If it is, then we have to add it to the list
0772 // of user ids for this clean name
0773 if (utf8_new_clean_string($row['username']) == $clean_name)
0774 {
0775 $user_ids[] = (int) $row['user_id'];
0776 }
0777 }
0778 $db->sql_freeresult($result2);
0779
0780 // if we already found a collision save it
0781 if (sizeof($user_ids) > 1)
0782 {
0783 $colliding_users[$clean_name] = $user_ids;
0784 $found_names[$clean_name] = true;
0785 }
0786 else
0787 {
0788 // otherwise just mark this name as found
0789 $found_names[$clean_name] = $user_id;
0790 }
0791 }
0792 // Else, if we already found the username
0793 else
0794 {
0795 // If the value in the found_names lookup table is only true ...
0796 if ($found_names[$clean_name] === true)
0797 {
0798 // then the actual data was already added to $colliding_users
0799 // and we only need to append the user_id
0800 $colliding_users[$clean_name][] = $user_id;
0801 }
0802 else
0803 {
0804 // otherwise it still keeps the first user_id for this name
0805 // and we need to move the data to $colliding_users, and set
0806 // the value in the found_names lookup table to true, so
0807 // following users will directly be appended to $colliding_users
0808 $colliding_users[$clean_name] = array($found_names[$clean_name], $user_id);
0809 $found_names[$clean_name] = true;
0810 }
0811 }
0812 }
0813
0814 if (($echos % 1000) == 0)
0815 {
0816 echo '.';
0817 flush();
0818 }
0819 $echos++;
0820 }
0821 $db->sql_freeresult($result);
0822
0823 _write_result(false, $errored, $error_ary);
0824
0825 // now retrieve all information about the users and let the admin decide what to do
0826 if (sizeof($colliding_users))
0827 {
0828 $exit = true;
0829 include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
0830 include($phpbb_root_path . 'language/' . $language . '/memberlist.' . $phpEx);
0831 include($phpbb_root_path . 'language/' . $language . '/acp/users.' . $phpEx);
0832
0833 // link a few things to the correct place so we don't get any problems
0834 $user->lang = &$lang;
0835 $user->data['user_id'] = ANONYMOUS;
0836 $user->date_format = $config['default_dateformat'];
0837
0838 // a little trick to get all user_ids
0839 $user_ids = call_user_func_array('array_merge', array_values($colliding_users));
0840
0841 $sql = 'SELECT session_user_id, MAX(session_time) AS session_time
0842 FROM ' . SESSIONS_TABLE . '
0843 WHERE session_time >= ' . (time() - $config['session_length']) . '
0844 AND ' . $db->sql_in_set('session_user_id', $user_ids) . '
0845 GROUP BY session_user_id';
0846 $result = $db->sql_query($sql);
0847
0848 $session_times = array();
0849 while ($row = $db->sql_fetchrow($result))
0850 {
0851 $session_times[$row['session_user_id']] = $row['session_time'];
0852 }
0853 $db->sql_freeresult($result);
0854
0855 $sql = 'SELECT *
0856 FROM ' . USERS_TABLE . '
0857 WHERE ' . $db->sql_in_set('user_id', $user_ids);
0858 $result = $db->sql_query($sql);
0859
0860 $users = array();
0861 while ($row = $db->sql_fetchrow($result))
0862 {
0863 if (isset($session_times[$row['user_id']]))
0864 {
0865 $row['session_time'] = $session_times[$row['user_id']];
0866 }
0867 else
0868 {
0869 $row['session_time'] = 0;
0870 }
0871 $users[(int) $row['user_id']] = $row;
0872 }
0873 $db->sql_freeresult($result);
0874 unset($session_times);
0875
0876 // now display a table with all users, some information about them and options
0877 // for the admin: keep name, change name (with text input) or delete user
0878 $u_action = "database_update.$phpEx?language=$language&type=$inline_update";
0879 ?>
0880 <br /><br />
0881
0882 <p><?php echo $lang['CHANGE_CLEAN_NAMES']; ?></p>
0883 <form id="change_clean_names" method="post" action="<?php echo $u_action; ?>">
0884
0885
0886 <?php
0887 foreach ($colliding_users as $clean_name => $user_ids)
0888 {
0889 ?>
0890 <fieldset class="tabulated">
0891 <table>
0892 <caption><?php echo sprintf($lang['COLLIDING_CLEAN_USERNAME'], $clean_name); ?></caption>
0893 <thead>
0894 <tr>
0895 <th><?php echo $lang['RANK']; ?> <?php echo $lang['USERNAME']; ?></th>
0896 <th><?php echo $lang['POSTS']; ?></th>
0897 <th><?php echo $lang['INFORMATION']; ?></th>
0898 <th><?php echo $lang['JOINED']; ?></th>
0899 <th><?php echo $lang['LAST_ACTIVE']; ?></th>
0900 <th><?php echo $lang['ACTION']; ?></th>
0901 <th><?php echo $lang['NEW_USERNAME']; ?></th>
0902 </tr>
0903 </thead>
0904 <tbody>
0905 <?php
0906 foreach ($user_ids as $i => $user_id)
0907 {
0908 $row = $users[$user_id];
0909
0910 $rank_title = $rank_img = '';
0911 get_user_rank($row['user_rank'], $row['user_posts'], $rank_title, $rank_img, $rank_img_src);
0912
0913 $last_visit = (!empty($row['session_time'])) ? $row['session_time'] : $row['user_lastvisit'];
0914
0915 $info = '';
0916 switch ($row['user_type'])
0917 {
0918 case USER_INACTIVE:
0919 $info .= $lang['USER_INACTIVE'];
0920 break;
0921
0922 case USER_IGNORE:
0923 $info .= $lang['BOT'];
0924 break;
0925
0926 case USER_FOUNDER:
0927 $info .= $lang['FOUNDER'];
0928 break;
0929
0930 default:
0931 $info .= $lang['USER_ACTIVE'];
0932 }
0933
0934 if ($user_id == ANONYMOUS)
0935 {
0936 $info = $lang['GUEST'];
0937 }
0938 ?>
0939 <tr class="bg<?php echo ($i % 2) + 1; ?>">
0940 <td>
0941 <span class="rank-img"><?php echo ($rank_img) ? $rank_img : $rank_title; ?></span><br />
0942 <?php echo get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']); ?>
0943 </td>
0944 <td class="posts"><?php echo $row['user_posts']; ?></td>
0945 <td class="info"><?php echo $info; ?></td>
0946 <td><?php echo $user->format_date($row['user_regdate']) ?></td>
0947 <td><?php echo (empty($last_visit)) ? ' - ' : $user->format_date($last_visit); ?> </td>
0948 <td>
0949 <label><input type="radio" class="radio" id="keep_user_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="keep" checked="checked" /> <?php echo $lang['KEEP_OLD_NAME']; ?></label><br />
0950 <label><input type="radio" class="radio" id="edit_user_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="edit" /> <?php echo $lang['EDIT_USERNAME']; ?></label><br />
0951 <?php
0952 // some users must not be deleted
0953 if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
0954 {
0955 ?>
0956 <label><input type="radio" class="radio" id="delete_user_retain_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="delete_retain" /> <?php echo $lang['DELETE_USER_RETAIN']; ?></label><br />
0957 <label><input type="radio" class="radio" id="delete_user_remove_<?php echo $user_id; ?>" name="modify_users[<?php echo $user_id; ?>]" value="delete_remove" /> <?php echo $lang['DELETE_USER_REMOVE']; ?></label>
0958 <?php
0959 }
0960 ?>
0961 </td>
0962 <td>
0963 <input id="new_username_<?php echo $user_id; ?>" type="text" name="new_usernames[<?php echo $user_id; ?>]" value="<?php echo $row['username']; ?>" />
0964 </td>
0965 </tr>
0966 <?php
0967 }
0968 ?>
0969 </tbody>
0970 </table>
0971 </fieldset>
0972 <?php
0973 }
0974 ?>
0975 <p class="quick">
0976 <input class="button2" id="resolve_conflicts" type="submit" name="resolve_conflicts" value="<?php echo $lang['SUBMIT']; ?>" />
0977 </p>
0978 </form>
0979 <?php
0980 }
0981 else if (sizeof($found_names))
0982 {
0983 $sql = 'SELECT user_id, username, username_clean
0984 FROM ' . USERS_TABLE . '
0985 WHERE ' . $db->sql_in_set('user_id', array_values($found_names));
0986 $result = $db->sql_query($sql);
0987
0988 $found_names = array();
0989 while ($row = $db->sql_fetchrow($result))
0990 {
0991 $clean_name = utf8_new_clean_string($row['username']);
0992
0993 if ($clean_name != $row['username_clean'])
0994 {
0995 $user_id = (int) $row['user_id'];
0996 $found_names[$user_id] = $clean_name;
0997
0998 // impossible unique clean name
0999 $sql = 'UPDATE ' . USERS_TABLE . "
1000 SET username_clean = ' {$user_id}'
1001 WHERE user_id = {$user_id}";
1002 $db->sql_query($sql);
1003 }
1004 }
1005 $db->sql_freeresult($result);
1006
1007 foreach ($found_names as $user_id => $clean_name)
1008 {
1009 $sql = 'UPDATE ' . USERS_TABLE . '
1010 SET username_clean = \'' . $db->sql_escape($clean_name) . '\'
1011 WHERE user_id = ' . $user_id;
1012 $db->sql_query($sql);
1013 }
1014 }
1015 unset($found_names);
1016 unset($colliding_users);
1017 }
1018
1019 if ($exit)
1020 {
1021 ?>
1022
1023 </div>
1024 </div>
1025 <span class="corners-bottom"><span></span></span>
1026 </div>
1027 </div>
1028 </div>
1029
1030 <div id="page-footer">
1031 Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group
1032 </div>
1033 </div>
1034
1035 </body>
1036 </html>
1037
1038 <?php
1039 if (function_exists('exit_handler'))
1040 {
1041 exit_handler();
1042 }
1043 }
1044
1045 // Schema updates
1046 ?>
1047 <br /><br />
1048
1049 <h1><?php echo $lang['UPDATE_DATABASE_SCHEMA']; ?></h1>
1050
1051 <br />
1052 <p><?php echo $lang['PROGRESS']; ?> :: <strong>
1053
1054 <?php
1055
1056 flush();
1057
1058 // We go through the schema changes from the lowest to the highest version
1059 // We skip those versions older than the current version
1060 $no_updates = true;
1061 foreach ($database_update_info as $version => $schema_changes)
1062 {
1063 if (version_compare($version, $current_version, '<'))
1064 {
1065 continue;
1066 }
1067
1068 if (!sizeof($schema_changes))
1069 {
1070 continue;
1071 }
1072
1073 $no_updates = false;
1074
1075 // Change columns?
1076 if (!empty($schema_changes['change_columns']))
1077 {
1078 foreach ($schema_changes['change_columns'] as $table => $columns)
1079 {
1080 foreach ($columns as $column_name => $column_data)
1081 {
1082 sql_column_change($map_dbms, $table, $column_name, $column_data);
1083 }
1084 }
1085 }
1086
1087 // Add columns?
1088 if (!empty($schema_changes['add_columns']))
1089 {
1090 foreach ($schema_changes['add_columns'] as $table => $columns)
1091 {
1092 foreach ($columns as $column_name => $column_data)
1093 {
1094 // Only add the column if it does not exist yet
1095 if (!column_exists($map_dbms, $table, $column_name))
1096 {
1097 sql_column_add($map_dbms, $table, $column_name, $column_data);
1098 }
1099 }
1100 }
1101 }
1102
1103 // Remove keys?
1104 if (!empty($schema_changes['drop_keys']))
1105 {
1106 foreach ($schema_changes['drop_keys'] as $table => $indexes)
1107 {
1108 foreach ($indexes as $index_name)
1109 {
1110 sql_index_drop($map_dbms, $index_name, $table);
1111 }
1112 }
1113 }
1114
1115 // Drop columns?
1116 if (!empty($schema_changes['drop_columns']))
1117 {
1118 foreach ($schema_changes['drop_columns'] as $table => $columns)
1119 {
1120 foreach ($columns as $column)
1121 {
1122 sql_column_remove($map_dbms, $table, $column);
1123 }
1124 }
1125 }
1126
1127 // Add primary keys?
1128 if (!empty($schema_changes['add_primary_keys']))
1129 {
1130 foreach ($schema_changes['add_primary_keys'] as $table => $columns)
1131 {
1132 sql_create_primary_key($map_dbms, $table, $columns);
1133 }
1134 }
1135
1136 // Add unqiue indexes?
1137 if (!empty($schema_changes['add_unique_index']))
1138 {
1139 foreach ($schema_changes['add_unique_index'] as $table => $index_array)
1140 {
1141 foreach ($index_array as $index_name => $column)
1142 {
1143 sql_create_unique_index($map_dbms, $index_name, $table, $column);
1144 }
1145 }
1146 }
1147
1148 // Add indexes?
1149 if (!empty($schema_changes['add_index']))
1150 {
1151 foreach ($schema_changes['add_index'] as $table => $index_array)
1152 {
1153 foreach ($index_array as $index_name => $column)
1154 {
1155 sql_create_index($map_dbms, $index_name, $table, $column);
1156 }
1157 }
1158 }
1159 }
1160
1161 _write_result($no_updates, $errored, $error_ary);
1162
1163 // Data updates
1164 $error_ary = array();
1165 $errored = $no_updates = false;
1166
1167 ?>
1168
1169 <br /><br />
1170 <h1><?php echo $lang['UPDATING_DATA']; ?></h1>
1171 <br />
1172 <p><?php echo $lang['PROGRESS']; ?> :: <strong>
1173
1174 <?php
1175
1176 flush();
1177
1178 $no_updates = true;
1179
1180 // some code magic
1181 if (version_compare($current_version, '3.0.RC2', '<='))
1182 {
1183 $smileys = array();
1184 $sql = 'SELECT smiley_id, code
1185 FROM ' . SMILIES_TABLE;
1186
1187 $result = $db->sql_query($sql);
1188
1189 while ($row = $db->sql_fetchrow($result))
1190 {
1191 $smileys[$row['smiley_id']] = $row['code'];
1192 }
1193 $db->sql_freeresult($result);
1194
1195 foreach ($smileys as $id => $code)
1196 {
1197 // 2.0 only entitized lt and gt; We need to do something about double quotes.
1198 if (strchr($code, '"') === false)
1199 {
1200 continue;
1201 }
1202
1203 $new_code = str_replace('&', '&', $code);
1204 $new_code = str_replace('<', '<', $new_code);
1205 $new_code = str_replace('>', '>', $new_code);
1206 $new_code = utf8_htmlspecialchars($new_code);
1207
1208 $sql = 'UPDATE ' . SMILIES_TABLE . '
1209 SET code = \'' . $db->sql_escape($new_code) . '\'
1210 WHERE smiley_id = ' . (int) $id;
1211 $db->sql_query($sql);
1212 }
1213
1214 $index_list = sql_list_index($map_dbms, ACL_ROLES_DATA_TABLE);
1215
1216 if (in_array('ath_opt_id', $index_list))
1217 {
1218 sql_index_drop($map_dbms, 'ath_opt_id', ACL_ROLES_DATA_TABLE);
1219 sql_create_index($map_dbms, 'ath_op_id', ACL_ROLES_DATA_TABLE, array('auth_option_id'));
1220 }
1221
1222 $no_updates = false;
1223 }
1224
1225 if (version_compare($current_version, '3.0.RC3', '<='))
1226 {
1227 if ($map_dbms === 'postgres')
1228 {
1229 $sql = "SELECT SETVAL('" . FORUMS_TABLE . "_seq',(select case when max(forum_id)>0 then max(forum_id)+1 else 1 end from " . FORUMS_TABLE . '));';
1230 _sql($sql, $errored, $error_ary);
1231 }
1232
1233 // we check for:
1234 // ath_opt_id
1235 // ath_op_id
1236 // ACL_ROLES_DATA_TABLE_ath_opt_id
1237 // we want ACL_ROLES_DATA_TABLE_ath_op_id
1238
1239 $table_index_fix = array(
1240 ACL_ROLES_DATA_TABLE => array(
1241 'ath_opt_id' => 'ath_op_id',
1242 'ath_op_id' => 'ath_op_id',
1243 ACL_ROLES_DATA_TABLE . '_ath_opt_id' => 'ath_op_id'
1244 ),
1245 STYLES_IMAGESET_DATA_TABLE => array(
1246 'i_id' => 'i_d',
1247 'i_d' => 'i_d',
1248 STYLES_IMAGESET_DATA_TABLE . '_i_id' => 'i_d'
1249 )
1250 );
1251
1252 // we need to create some indicies...
1253 $needed_creation = array();
1254
1255 foreach ($table_index_fix as $table_name => $index_info)
1256 {
1257 $index_list = sql_list_fake($map_dbms, $table_name);
1258 foreach ($index_info as $bad_index => $good_index)
1259 {
1260 if (in_array($bad_index, $index_list))
1261 {
1262 // mysql is actually OK, it won't get a hand in this crud
1263 switch ($map_dbms)
1264 {
1265 // last version, mssql had issues with index removal
1266 case 'mssql':
1267 $sql = 'DROP INDEX ' . $table_name . '.' . $bad_index;
1268 _sql($sql, $errored, $error_ary);
1269 break;
1270
1271 // last version, firebird, oracle, postgresql and sqlite all got bad index names
1272 // we got kinda lucky, tho: they all support the same syntax
1273 case 'firebird':
1274 case 'oracle':
1275 case 'postgres':
1276 case 'sqlite':
1277 $sql = 'DROP INDEX ' . $bad_index;
1278 _sql($sql, $errored, $error_ary);
1279 break;
1280 }
1281
1282 // If the good index already exist we do not need to create it again...
1283 if (($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41') && $bad_index == $good_index)
1284 {
1285 }
1286 else
1287 {
1288 $needed_creation[$table_name][$good_index] = 1;
1289 }
1290 }
1291 }
1292 }
1293
1294 $new_index_defs = array('ath_op_id' => array('auth_option_id'), 'i_d' => array('imageset_id'));
1295
1296 foreach ($needed_creation as $bad_table => $index_repair_list)
1297 {
1298 foreach ($index_repair_list as $new_index => $garbage)
1299 {
1300 sql_create_index($map_dbms, $new_index, $bad_table, $new_index_defs[$new_index]);
1301 $no_updates = false;
1302 }
1303 }
1304
1305 // Make sure empty smiley codes do not exist
1306 $sql = 'DELETE FROM ' . SMILIES_TABLE . "
1307 WHERE code = ''";
1308 _sql($sql, $errored, $error_ary);
1309
1310 set_config('allow_birthdays', '1');
1311 set_config('cron_lock', '0', true);
1312
1313 $no_updates = false;
1314 }
1315
1316 if (version_compare($current_version, '3.0.RC4', '<='))
1317 {
1318 $update_auto_increment = array(
1319 STYLES_TABLE => 'style_id',
1320 STYLES_TEMPLATE_TABLE => 'template_id',
1321 STYLES_THEME_TABLE => 'theme_id',
1322 STYLES_IMAGESET_TABLE => 'imageset_id'
1323 );
1324
1325 $sql = 'SELECT *
1326 FROM ' . STYLES_TABLE . '
1327 WHERE style_id = 0';
1328 $result = _sql($sql, $errored, $error_ary);
1329 $bad_style_row = $db->sql_fetchrow($result);
1330 $db->sql_freeresult($result);
1331
1332 if ($bad_style_row)
1333 {
1334 $sql = 'SELECT MAX(style_id) as max_id
1335 FROM ' . STYLES_TABLE;
1336 $result = _sql($sql, $errored, $error_ary);
1337 $row = $db->sql_fetchrow($result);
1338 $db->sql_freeresult($result);
1339
1340 $proper_id = $row['max_id'] + 1;
1341
1342 _sql('UPDATE ' . STYLES_TABLE . " SET style_id = $proper_id WHERE style_id = 0", $errored, $error_ary);
1343 _sql('UPDATE ' . FORUMS_TABLE . " SET forum_style = $proper_id WHERE forum_style = 0", $errored, $error_ary);
1344 _sql('UPDATE ' . USERS_TABLE . " SET user_style = $proper_id WHERE user_style = 0", $errored, $error_ary);
1345
1346 $sql = 'SELECT config_value
1347 FROM ' . CONFIG_TABLE . "
1348 WHERE config_name = 'default_style'";
1349 $result = _sql($sql, $errored, $error_ary);
1350 $style_config = $db->sql_fetchrow($result);
1351 $db->sql_freeresult($result);
1352
1353 if ($style_config['config_value'] === '0')
1354 {
1355 set_config('default_style', (string) $proper_id);
1356 }
1357 }
1358
1359 $sql = 'SELECT *
1360 FROM ' . STYLES_TEMPLATE_TABLE . '
1361 WHERE template_id = 0';
1362 $result = _sql($sql, $errored, $error_ary);
1363 $bad_style_row = $db->sql_fetchrow($result);
1364 $db->sql_freeresult($result);
1365
1366 if ($bad_style_row)
1367 {
1368 $sql = 'SELECT MAX(template_id) as max_id
1369 FROM ' . STYLES_TEMPLATE_TABLE;
1370 $result = _sql($sql, $errored, $error_ary);
1371 $row = $db->sql_fetchrow($result);
1372 $db->sql_freeresult($result);
1373
1374 $proper_id = $row['max_id'] + 1;
1375
1376 _sql('UPDATE ' . STYLES_TABLE . " SET template_id = $proper_id WHERE template_id = 0", $errored, $error_ary);
1377 }
1378
1379 $sql = 'SELECT *
1380 FROM ' . STYLES_THEME_TABLE . '
1381 WHERE theme_id = 0';
1382 $result = _sql($sql, $errored, $error_ary);
1383 $bad_style_row = $db->sql_fetchrow($result);
1384 $db->sql_freeresult($result);
1385
1386 if ($bad_style_row)
1387 {
1388 $sql = 'SELECT MAX(theme_id) as max_id
1389 FROM ' . STYLES_THEME_TABLE;
1390 $result = _sql($sql, $errored, $error_ary);
1391 $row = $db->sql_fetchrow($result);
1392 $db->sql_freeresult($result);
1393
1394 $proper_id = $row['max_id'] + 1;
1395
1396 _sql('UPDATE ' . STYLES_TABLE . " SET theme_id = $proper_id WHERE theme_id = 0", $errored, $error_ary);
1397 }
1398
1399 $sql = 'SELECT *
1400 FROM ' . STYLES_IMAGESET_TABLE . '
1401 WHERE imageset_id = 0';
1402 $result = _sql($sql, $errored, $error_ary);
1403 $bad_style_row = $db->sql_fetchrow($result);
1404 $db->sql_freeresult($result);
1405
1406 if ($bad_style_row)
1407 {
1408 $sql = 'SELECT MAX(imageset_id) as max_id
1409 FROM ' . STYLES_IMAGESET_TABLE;
1410 $result = _sql($sql, $errored, $error_ary);
1411 $row = $db->sql_fetchrow($result);
1412 $db->sql_freeresult($result);
1413
1414 $proper_id = $row['max_id'] + 1;
1415
1416 _sql('UPDATE ' . STYLES_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary);
1417 _sql('UPDATE ' . STYLES_IMAGESET_DATA_TABLE . " SET imageset_id = $proper_id WHERE imageset_id = 0", $errored, $error_ary);
1418 }
1419
1420 if ($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41')
1421 {
1422 foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
1423 {
1424 $sql = "SELECT MAX({$auto_column_name}) as max_id
1425 FROM {$auto_table_name}";
1426 $result = _sql($sql, $errored, $error_ary);
1427 $row = $db->sql_fetchrow($result);
1428 $db->sql_freeresult($result);
1429
1430 $max_id = ((int) $row['max_id']) + 1;
1431 _sql("ALTER TABLE {$auto_table_name} AUTO_INCREMENT = {$max_id}", $errored, $error_ary);
1432 }
1433
1434 $no_updates = false;
1435 }
1436 else if ($map_dbms == 'postgres')
1437 {
1438 foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
1439 {
1440 $sql = "SELECT SETVAL('" . $auto_table_name . "_seq',(select case when max({$auto_column_name})>0 then max({$auto_column_name})+1 else 1 end from " . $auto_table_name . '));';
1441 _sql($sql, $errored, $error_ary);
1442 }
1443
1444 $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
1445 _sql($sql, $errored, $error_ary);
1446 }
1447 else if ($map_dbms == 'firebird')
1448 {
1449 $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
1450 _sql($sql, $errored, $error_ary);
1451
1452 $sql = 'DROP GENERATOR ' . STYLES_TEMPLATE_DATA_TABLE . '_gen';
1453 _sql($sql, $errored, $error_ary);
1454 }
1455 else if ($map_dbms == 'oracle')
1456 {
1457 $sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
1458 _sql($sql, $errored, $error_ary);
1459
1460 $sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
1461 _sql($sql, $errored, $error_ary);
1462 }
1463 else if ($map_dbms == 'mssql')
1464 {
1465 // we use transactions because we need to have a working DB at the end of all of this
1466 $db->sql_transaction('begin');
1467
1468 $sql = 'SELECT *
1469 FROM ' . STYLES_TEMPLATE_DATA_TABLE;
1470 $result = _sql($sql, $errored, $error_ary);
1471 $old_style_rows = array();
1472 while ($row = $db->sql_fetchrow($result))
1473 {
1474 $old_style_rows[] = $row;
1475 }
1476 $db->sql_freeresult($result);
1477
1478 // death to the table, it is evil!
1479 $sql = 'DROP TABLE ' . STYLES_TEMPLATE_DATA_TABLE;
1480 _sql($sql, $errored, $error_ary);
1481
1482 // the table of awesomeness, praise be to it (or something)
1483 $sql = 'CREATE TABLE [' . STYLES_TEMPLATE_DATA_TABLE . "] (
1484 [template_id] [int] DEFAULT (0) NOT NULL ,
1485 [template_filename] [varchar] (100) DEFAULT ('') NOT NULL ,
1486 [template_included] [varchar] (8000) DEFAULT ('') NOT NULL ,
1487 [template_mtime] [int] DEFAULT (0) NOT NULL ,
1488 [template_data] [text] DEFAULT ('') NOT NULL
1489 ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]";
1490 _sql($sql, $errored, $error_ary);
1491
1492 // index? index
1493 $sql = 'CREATE INDEX [tid] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_id]) ON [PRIMARY]';
1494 _sql($sql, $errored, $error_ary);
1495
1496 // yet another index
1497 $sql = 'CREATE INDEX [tfn] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_filename]) ON [PRIMARY]';
1498 _sql($sql, $errored, $error_ary);
1499
1500 foreach ($old_style_rows as $return_row)
1501 {
1502 _sql('INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $return_row), $errored, $error_ary);
1503 }
1504
1505 $db->sql_transaction('commit');
1506 }
1507
1508 // Setting this here again because new installations may not have it...
1509 set_config('cron_lock', '0', true);
1510 set_config('ldap_port', '');
1511 set_config('ldap_user_filter', '');
1512
1513 $no_updates = false;
1514 }
1515
1516 if (version_compare($current_version, '3.0.RC5', '<='))
1517 {
1518 // In case the user is having the bot mediapartner google "as is", adjust it.
1519 $sql = 'UPDATE ' . BOTS_TABLE . "
1520 SET bot_agent = '" . $db->sql_escape('Mediapartners-Google') . "'
1521 WHERE bot_agent = '" . $db->sql_escape('Mediapartners-Google/') . "'";
1522 _sql($sql, $errored, $error_ary);
1523
1524 set_config('form_token_lifetime', '7200');
1525 set_config('form_token_mintime', '0');
1526 set_config('min_time_reg', '5');
1527 set_config('min_time_terms', '2');
1528 set_config('form_token_sid_guests', '1');
1529
1530 $db->sql_transaction('begin');
1531
1532 $sql = 'SELECT forum_id, forum_password
1533 FROM ' . FORUMS_TABLE;
1534 $result = _sql($sql, $errored, $error_ary);
1535
1536 while ($row = $db->sql_fetchrow($result))
1537 {
1538 if (!empty($row['forum_password']))
1539 {
1540 _sql('UPDATE ' . FORUMS_TABLE . " SET forum_password = '" . md5($row['forum_password']) . "' WHERE forum_id = {$row['forum_id']}", $errored, $error_ary);
1541 }
1542 }
1543 $db->sql_freeresult($result);
1544
1545 $db->sql_transaction('commit');
1546
1547 $no_updates = false;
1548 }
1549
1550 _write_result($no_updates, $errored, $error_ary);
1551
1552 $error_ary = array();
1553 $errored = $no_updates = false;
1554
1555 ?>
1556
1557 <br /><br />
1558 <h1><?php echo $lang['UPDATE_VERSION_OPTIMIZE']; ?></h1>
1559 <br />
1560 <p><?php echo $lang['PROGRESS']; ?> :: <strong>
1561
1562 <?php
1563
1564 flush();
1565
1566 // update the version
1567 $sql = "UPDATE " . CONFIG_TABLE . "
1568 SET config_value = '$updates_to_version'
1569 WHERE config_name = 'version'";
1570 _sql($sql, $errored, $error_ary);
1571
1572 // Reset permissions
1573 $sql = 'UPDATE ' . USERS_TABLE . "
1574 SET user_permissions = ''";
1575 _sql($sql, $errored, $error_ary);
1576
1577 /* Optimize/vacuum analyze the tables where appropriate
1578 // this should be done for each version in future along with
1579 // the version number update
1580 switch ($db->sql_layer)
1581 {
1582 case 'mysql':
1583 case 'mysqli':
1584 case 'mysql4':
1585 $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';
1586 _sql($sql, $errored, $error_ary);
1587 break;
1588
1589 case 'postgresql':
1590 _sql("VACUUM ANALYZE", $errored, $error_ary);
1591 break;
1592 }
1593 */
1594
1595 _write_result($no_updates, $errored, $error_ary);
1596
1597 ?>
1598
1599 <br />
1600 <h1><?php echo $lang['UPDATE_COMPLETED']; ?></h1>
1601
1602 <br />
1603
1604 <?php
1605
1606 if (!$inline_update)
1607 {
1608 ?>
1609
1610 <p style="color:red"><?php echo $lang['UPDATE_FILES_NOTICE']; ?></p>
1611
1612 <p><?php echo $lang['COMPLETE_LOGIN_TO_BOARD']; ?></p>
1613
1614 <?php
1615 }
1616 else
1617 {
1618 ?>
1619
1620 <p><?php echo ((isset($lang['INLINE_UPDATE_SUCCESSFUL'])) ? $lang['INLINE_UPDATE_SUCCESSFUL'] : 'The database update was successful. Now you need to continue the update process.'); ?></p>
1621
1622 <p><a href="<?php echo append_sid("{$phpbb_root_path}install/index.{$phpEx}", "mode=update&sub=file_check&lang=$language"); ?>" class="button1"><?php echo (isset($lang['CONTINUE_UPDATE_NOW'])) ? $lang['CONTINUE_UPDATE_NOW'] : 'Continue the update process now'; ?></a></p>
1623
1624 <?php
1625 }
1626
1627 // Add database update to log
1628 add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version);
1629
1630 // Now we purge the session table as well as all cache files
1631 $cache->purge();
1632
1633 ?>
1634
1635 </div>
1636 </div>
1637 <span class="corners-bottom"><span></span></span>
1638 </div>
1639 </div>
1640 </div>
1641
1642 <div id="page-footer">
1643 Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>
1644 </div>
1645 </div>
1646
1647 </body>
1648 </html>
1649
1650 <?php
1651
1652 garbage_collection();
1653
1654 if (function_exists('exit_handler'))
1655 {
1656 exit_handler();
1657 }
1658
1659
1660 /**
1661 * Function for triggering an sql statement
1662 */
1663 function _sql($sql, &$errored, &$error_ary, $echo_dot = true)
1664 {
1665 global $db;
1666
1667 if (defined('DEBUG_EXTRA'))
1668 {
1669 echo "<br />\n{$sql}\n<br />";
1670 }
1671
1672 $db->sql_return_on_error(true);
1673
1674 $result = $db->sql_query($sql);
1675 if ($db->sql_error_triggered)
1676 {
1677 $errored = true;
1678 $error_ary['sql'][] = $db->sql_error_sql;
1679 $error_ary['error_code'][] = $db->_sql_error();
1680 }
1681
1682 $db->sql_return_on_error(false);
1683
1684 if ($echo_dot)
1685 {
1686 echo ". \n";
1687 flush();
1688 }
1689
1690 return $result;
1691 }
1692
1693 function _write_result($no_updates, $errored, $error_ary)
1694 {
1695 global $lang;
1696
1697 if ($no_updates)
1698 {
1699 echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '</strong></p>';
1700 }
1701 else
1702 {
1703 echo ' <span class="success">' . $lang['DONE'] . '</span></strong><br />' . $lang['RESULT'] . ' :: ';
1704
1705 if ($errored)
1706 {
1707 echo ' <strong>' . $lang['SOME_QUERIES_FAILED'] . '</strong> <ul>';
1708
1709 for ($i = 0; $i < sizeof($error_ary['sql']); $i++)
1710 {
1711 echo '<li>' . $lang['ERROR'] . ' :: <strong>' . htmlspecialchars($error_ary['error_code'][$i]['message']) . '</strong><br />';
1712 echo $lang['SQL'] . ' :: <strong>' . htmlspecialchars($error_ary['sql'][$i]) . '</strong><br /><br /></li>';
1713 }
1714
1715 echo '</ul> <br /><br />' . $lang['SQL_FAILURE_EXPLAIN'] . '</p>';
1716 }
1717 else
1718 {
1719 echo '<strong>' . $lang['NO_ERRORS'] . '</strong></p>';
1720 }
1721 }
1722 }
1723
1724 /**
1725 * Check if a specified column exist
1726 */
1727 function column_exists($dbms, $table, $column_name)
1728 {
1729 global $db;
1730
1731 switch ($dbms)
1732 {
1733 case 'mysql_40':
1734 case 'mysql_41':
1735 $sql = "SHOW COLUMNS
1736 FROM $table";
1737 $result = $db->sql_query($sql);
1738 while ($row = $db->sql_fetchrow($result))
1739 {
1740 // lower case just in case
1741 if (strtolower($row['Field']) == $column_name)
1742 {
1743 $db->sql_freeresult($result);
1744 return true;
1745 }
1746 }
1747 $db->sql_freeresult($result);
1748 return false;
1749 break;
1750
1751 // PostgreSQL has a way of doing this in a much simpler way but would
1752 // not allow us to support all versions of PostgreSQL
1753 case 'postgres':
1754 $sql = "SELECT a.attname
1755 FROM pg_class c, pg_attribute a
1756 WHERE c.relname = '{$table}'
1757 AND a.attnum > 0
1758 AND a.attrelid = c.oid";
1759 $result = $db->sql_query($sql);
1760 while ($row = $db->sql_fetchrow($result))
1761 {
1762 // lower case just in case
1763 if (strtolower($row['attname']) == $column_name)
1764 {
1765 $db->sql_freeresult($result);
1766 return true;
1767 }
1768 }
1769 $db->sql_freeresult($result);
1770 return false;
1771 break;
1772
1773 // same deal with PostgreSQL, we must perform more complex operations than
1774 // we technically could
1775 case 'mssql':
1776 $sql = "SELECT c.name
1777 FROM syscolumns c
1778 LEFT JOIN sysobjects o ON c.id = o.id
1779 WHERE o.name = '{$table}'";
1780 $result = $db->sql_query($sql);
1781 while ($row = $db->sql_fetchrow($result))
1782 {
1783 // lower case just in case
1784 if (strtolower($row['name']) == $column_name)
1785 {
1786 $db->sql_freeresult($result);
1787 return true;
1788 }
1789 }
1790 $db->sql_freeresult($result);
1791 return false;
1792 break;
1793
1794 case 'oracle':
1795 $sql = "SELECT column_name
1796 FROM user_tab_columns
1797 WHERE table_name = '{$table}'";
1798 $result = $db->sql_query($sql);
1799 while ($row = $db->sql_fetchrow($result))
1800 {
1801 // lower case just in case
1802 if (strtolower($row['column_name']) == $column_name)
1803 {
1804 $db->sql_freeresult($result);
1805 return true;
1806 }
1807 }
1808 $db->sql_freeresult($result);
1809 return false;
1810 break;
1811
1812 case 'firebird':
1813 $sql = "SELECT RDB\$FIELD_NAME as FNAME
1814 FROM RDB\$RELATION_FIELDS
1815 WHERE RDB\$RELATION_NAME = '{$table}'";
1816 $result = $db->sql_query($sql);
1817 while ($row = $db->sql_fetchrow($result))
1818 {
1819 // lower case just in case
1820 if (strtolower($row['fname']) == $column_name)
1821 {
1822 $db->sql_freeresult($result);
1823 return true;
1824 }
1825 }
1826 $db->sql_freeresult($result);
1827 return false;
1828 break;
1829
1830 // ugh, SQLite
1831 case 'sqlite':
1832 $sql = "SELECT sql
1833 FROM sqlite_master
1834 WHERE type = 'table'
1835 AND name = '{$table}'";
1836 $result = $db->sql_query($sql);
1837
1838 if (!$result)
1839 {
1840 return false;
1841 }
1842
1843 $row = $db->sql_fetchrow($result);
1844 $db->sql_freeresult($result);
1845
1846 preg_match('#\((.*)\)#s', $row['sql'], $matches);
1847
1848 $cols = trim($matches[1]);
1849 $col_array = preg_split('/,(?![\s\w]+\))/m', $cols);
1850
1851 foreach ($col_array as $declaration)
1852 {
1853 $entities = preg_split('#\s+#', trim($declaration));
1854 if ($entities[0] == 'PRIMARY')
1855 {
1856 continue;
1857 }
1858
1859 if (strtolower($entities[0]) == $column_name)
1860 {
1861 return true;
1862 }
1863 }
1864 return false;
1865 break;
1866 }
1867 }
1868
1869 /**
1870 * Function to prepare some column information for better usage
1871 */
1872 function prepare_column_data($dbms, $column_data, $table_name, $column_name)
1873 {
1874 global $dbms_type_map, $unsigned_types;
1875
1876 // Get type
1877 if (strpos($column_data[0], ':') !== false)
1878 {
1879 list($orig_column_type, $column_length) = explode(':', $column_data[0]);
1880
1881 if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':']))
1882 {
1883 $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length);
1884 }
1885 else
1886 {
1887 if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule']))
1888 {
1889 switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0])
1890 {
1891 case 'div':
1892 $column_length /= $dbms_type_map[$dbms][$orig_column_type . ':']['rule'][1];
1893 $column_length = ceil($column_length);
1894 $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
1895 break;
1896 }
1897 }
1898
1899 if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit']))
1900 {
1901 switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0])
1902 {
1903 case 'mult':
1904 $column_length *= $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][1];
1905 if ($column_length > $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][2])
1906 {
1907 $column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3];
1908 }
1909 else
1910 {
1911 $column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
1912 }
1913 break;
1914 }
1915 }
1916 }
1917 $orig_column_type .= ':';
1918 }
1919 else
1920 {
1921 $orig_column_type = $column_data[0];
1922 $column_type = $dbms_type_map[$dbms][$column_data[0]];
1923 }
1924
1925 // Adjust default value if db-dependant specified
1926 if (is_array($column_data[1]))
1927 {
1928 $column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default'];
1929 }
1930
1931 $sql = '';
1932 $return_array = array();
1933
1934 switch ($dbms)
1935 {
1936 case 'firebird':
1937 $sql .= " {$column_type} ";
1938
1939 if (!is_null($column_data[1]))
1940 {
1941 $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
1942 }
1943
1944 $sql .= 'NOT NULL';
1945
1946 // This is a UNICODE column and thus should be given it's fair share
1947 if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0]))
1948 {
1949 $sql .= ' COLLATE UNICODE';
1950 }
1951
1952 break;
1953
1954 case 'mssql':
1955 $sql .= " {$column_type} ";
1956 $sql_default = " {$column_type} ";
1957
1958 // For adding columns we need the default definition
1959 if (!is_null($column_data[1]))
1960 {
1961 // For hexadecimal values do not use single quotes
1962 if (strpos($column_data[1], '0x') === 0)
1963 {
1964 $sql_default .= 'DEFAULT (' . $column_data[1] . ') ';
1965 }
1966 else
1967 {
1968 $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
1969 }
1970 }
1971
1972 $sql .= 'NOT NULL';
1973 $sql_default .= 'NOT NULL';
1974
1975 $return_array['column_type_sql_default'] = $sql_default;
1976 break;
1977
1978 case 'mysql_40':
1979 case 'mysql_41':
1980 $sql .= " {$column_type} ";
1981
1982 // For hexadecimal values do not use single quotes
1983 if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob')
1984 {
1985 $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
1986 }
1987 $sql .= 'NOT NULL';
1988
1989 if (isset($column_data[2]))
1990 {
1991 if ($column_data[2] == 'auto_increment')
1992 {
1993 $sql .= ' auto_increment';
1994 }
1995 else if ($dbms === 'mysql_41' && $column_data[2] == 'true_sort')
1996 {
1997 $sql .= ' COLLATE utf8_unicode_ci';
1998 }
1999 }
2000
2001 break;
2002
2003 case 'oracle':
2004 $sql .= " {$column_type} ";
2005 $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
2006
2007 // In Oracle empty strings ('') are treated as NULL.
2008 // Therefore in oracle we allow NULL's for all DEFAULT '' entries
2009 // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields)
2010 if (preg_match('/number/i', $column_type))
2011 {
2012 $sql .= ($column_data[1] === '') ? '' : 'NOT NULL';
2013 }
2014 break;
2015
2016 case 'postgres':
2017 $return_array['column_type'] = $column_type;
2018
2019 $sql .= " {$column_type} ";
2020
2021 if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
2022 {
2023 $default_val = "nextval('{$table_name}_seq')";
2024 }
2025 else if (!is_null($column_data[1]))
2026 {
2027 $default_val = "'" . $column_data[1] . "'";
2028 $return_array['null'] = 'NOT NULL';
2029 $sql .= 'NOT NULL ';
2030 }
2031
2032 $return_array['default'] = $default_val;
2033
2034 $sql .= "DEFAULT {$default_val}";
2035
2036 // Unsigned? Then add a CHECK contraint
2037 if (in_array($orig_column_type, $unsigned_types))
2038 {
2039 $return_array['constraint'] = "CHECK ({$column_name} >= 0)";
2040 $sql .= " CHECK ({$column_name} >= 0)";
2041 }
2042 break;
2043
2044 case 'sqlite':
2045 if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
2046 {
2047 $sql .= ' INTEGER PRIMARY KEY';
2048 }
2049 else
2050 {
2051 $sql .= ' ' . $column_type;
2052 }
2053
2054 $sql .= ' NOT NULL ';
2055 $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
2056 break;
2057 }
2058
2059 $return_array['column_type_sql'] = $sql;
2060
2061 return $return_array;
2062 }
2063
2064 /**
2065 * Add new column
2066 */
2067 function sql_column_add($dbms, $table_name, $column_name, $column_data)
2068 {
2069 global $errored, $error_ary;
2070
2071 $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
2072
2073 switch ($dbms)
2074 {
2075 case 'firebird':
2076 $sql = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql'];
2077 _sql($sql, $errored, $error_ary);
2078 break;
2079
2080 case 'mssql':
2081 $sql = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
2082 _sql($sql, $errored, $error_ary);
2083 break;
2084
2085 case 'mysql_40':
2086 case 'mysql_41':
2087 $sql = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'];
2088 _sql($sql, $errored, $error_ary);
2089 break;
2090
2091 case 'oracle':
2092 $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
2093 _sql($sql, $errored, $error_ary);
2094 break;
2095
2096 case 'postgres':
2097 $sql = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
2098 _sql($sql, $errored, $error_ary);
2099 break;
2100
2101 case 'sqlite':
2102 if (version_compare(sqlite_libversion(), '3.0') == -1)
2103 {
2104 global $db;
2105 $sql = "SELECT sql
2106 FROM sqlite_master
2107 WHERE type = 'table'
2108 AND name = '{$table_name}'
2109 ORDER BY type DESC, name;";
2110 $result = $db->sql_query($sql);
2111
2112 if (!$result)
2113 {
2114 break;
2115 }
2116
2117 $row = $db->sql_fetchrow($result);
2118 $db->sql_freeresult($result);
2119
2120 $db->sql_transaction('begin');
2121
2122 // Create a backup table and populate it, destroy the existing one
2123 $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
2124 $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
2125 $db->sql_query('DROP TABLE ' . $table_name);
2126
2127 preg_match('#\((.*)\)#s', $row['sql'], $matches);
2128
2129 $new_table_cols = trim($matches[1]);
2130 $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2131 $column_list = array();
2132
2133 foreach ($old_table_cols as $declaration)
2134 {
2135 $entities = preg_split('#\s+#', trim($declaration));
2136 if ($entities[0] == 'PRIMARY')
2137 {
2138 continue;
2139 }
2140 $column_list[] = $entities[0];
2141 }
2142
2143 $columns = implode(',', $column_list);
2144
2145 $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols;
2146
2147 // create a new table and fill it up. destroy the temp one
2148 $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');');
2149 $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
2150 $db->sql_query('DROP TABLE ' . $table_name . '_temp');
2151
2152 $db->sql_transaction('commit');
2153 }
2154 else
2155 {
2156 $sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']';
2157 _sql($sql, $errored, $error_ary);
2158 }
2159 break;
2160 }
2161 }
2162
2163 /**
2164 * Drop column
2165 */
2166 function sql_column_remove($dbms, $table_name, $column_name)
2167 {
2168 global $errored, $error_ary;
2169
2170 switch ($dbms)
2171 {
2172 case 'firebird':
2173 $sql = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"';
2174 _sql($sql, $errored, $error_ary);
2175 break;
2176
2177 case 'mssql':
2178 $sql = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
2179 _sql($sql, $errored, $error_ary);
2180 break;
2181
2182 case 'mysql_40':
2183 case 'mysql_41':
2184 $sql = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
2185 _sql($sql, $errored, $error_ary);
2186 break;
2187
2188 case 'oracle':
2189 $sql = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name;
2190 _sql($sql, $errored, $error_ary);
2191 break;
2192
2193 case 'postgres':
2194 $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
2195 _sql($sql, $errored, $error_ary);
2196 break;
2197
2198 case 'sqlite':
2199 if (version_compare(sqlite_libversion(), '3.0') == -1)
2200 {
2201 global $db;
2202 $sql = "SELECT sql
2203 FROM sqlite_master
2204 WHERE type = 'table'
2205 AND name = '{$table_name}'
2206 ORDER BY type DESC, name;";
2207 $result = $db->sql_query($sql);
2208
2209 if (!$result)
2210 {
2211 break;
2212 }
2213
2214 $row = $db->sql_fetchrow($result);
2215 $db->sql_freeresult($result);
2216
2217 $db->sql_transaction('begin');
2218
2219 // Create a backup table and populate it, destroy the existing one
2220 $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
2221 $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
2222 $db->sql_query('DROP TABLE ' . $table_name);
2223
2224 preg_match('#\((.*)\)#s', $row['sql'], $matches);
2225
2226 $new_table_cols = trim($matches[1]);
2227 $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2228 $column_list = array();
2229
2230 foreach ($old_table_cols as $declaration)
2231 {
2232 $entities = preg_split('#\s+#', trim($declaration));
2233 if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name)
2234 {
2235 continue;
2236 }
2237 $column_list[] = $entities[0];
2238 }
2239
2240 $columns = implode(',', $column_list);
2241
2242 $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
2243
2244 // create a new table and fill it up. destroy the temp one
2245 $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');');
2246 $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
2247 $db->sql_query('DROP TABLE ' . $table_name . '_temp');
2248
2249 $db->sql_transaction('commit');
2250 }
2251 else
2252 {
2253 $sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
2254 _sql($sql, $errored, $error_ary);
2255 }
2256 break;
2257 }
2258 }
2259
2260 function sql_index_drop($dbms, $index_name, $table_name)
2261 {
2262 global $dbms_type_map, $db;
2263 global $errored, $error_ary;
2264
2265 switch ($dbms)
2266 {
2267 case 'mssql':
2268 $sql = 'DROP INDEX ' . $table_name . '.' . $index_name;
2269 _sql($sql, $errored, $error_ary);
2270 break;
2271
2272 case 'mysql_40':
2273 case 'mysql_41':
2274 $sql = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
2275 _sql($sql, $errored, $error_ary);
2276 break;
2277
2278 case 'firebird':
2279 case 'oracle':
2280 case 'postgres':
2281 case 'sqlite':
2282 $sql = 'DROP INDEX ' . $table_name . '_' . $index_name;
2283 _sql($sql, $errored, $error_ary);
2284 break;
2285 }
2286 }
2287
2288 function sql_create_primary_key($dbms, $table_name, $column)
2289 {
2290 global $dbms_type_map, $db;
2291 global $errored, $error_ary;
2292
2293 switch ($dbms)
2294 {
2295 case 'firebird':
2296 case 'postgres':
2297 $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
2298 _sql($sql, $errored, $error_ary);
2299 break;
2300
2301 case 'mssql':
2302 $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD ";
2303 $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED (";
2304 $sql .= '[' . implode("],\n\t\t[", $column) . ']';
2305 $sql .= ') ON [PRIMARY]';
2306 _sql($sql, $errored, $error_ary);
2307 break;
2308
2309 case 'mysql_40':
2310 case 'mysql_41':
2311 $sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
2312 _sql($sql, $errored, $error_ary);
2313 break;
2314
2315 case 'oracle':
2316 $sql = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
2317 _sql($sql, $errored, $error_ary);
2318 break;
2319
2320 case 'sqlite':
2321 $sql = "SELECT sql
2322 FROM sqlite_master
2323 WHERE type = 'table'
2324 AND name = '{$table_name}'
2325 ORDER BY type DESC, name;";
2326 $result = _sql($sql, $errored, $error_ary);
2327
2328 if (!$result)
2329 {
2330 break;
2331 }
2332
2333 $row = $db->sql_fetchrow($result);
2334 $db->sql_freeresult($result);
2335
2336 $db->sql_transaction('begin');
2337
2338 // Create a backup table and populate it, destroy the existing one
2339 $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
2340 $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
2341 $db->sql_query('DROP TABLE ' . $table_name);
2342
2343 preg_match('#\((.*)\)#s', $row['sql'], $matches);
2344
2345 $new_table_cols = trim($matches[1]);
2346 $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2347 $column_list = array();
2348
2349 foreach ($old_table_cols as $declaration)
2350 {
2351 $entities = preg_split('#\s+#', trim($declaration));
2352 if ($entities[0] == 'PRIMARY')
2353 {
2354 continue;
2355 }
2356 $column_list[] = $entities[0];
2357 }
2358
2359 $columns = implode(',', $column_list);
2360
2361 // create a new table and fill it up. destroy the temp one
2362 $db->sql_query('CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));');
2363 $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
2364 $db->sql_query('DROP TABLE ' . $table_name . '_temp');
2365
2366 $db->sql_transaction('commit');
2367 break;
2368 }
2369 }
2370
2371 function sql_create_unique_index($dbms, $index_name, $table_name, $column)
2372 {
2373 global $dbms_type_map, $db;
2374 global $errored, $error_ary;
2375
2376 switch ($dbms)
2377 {
2378 case 'firebird':
2379 case 'postgres':
2380 case 'oracle':
2381 case 'sqlite':
2382 $sql = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2383 _sql($sql, $errored, $error_ary);
2384 break;
2385
2386 case 'mysql_40':
2387 case 'mysql_41':
2388 $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2389 _sql($sql, $errored, $error_ary);
2390 break;
2391
2392 case 'mssql':
2393 $sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
2394 _sql($sql, $errored, $error_ary);
2395 break;
2396 }
2397 }
2398
2399 function sql_create_index($dbms, $index_name, $table_name, $column)
2400 {
2401 global $dbms_type_map, $db;
2402 global $errored, $error_ary;
2403
2404 switch ($dbms)
2405 {
2406 case 'firebird':
2407 case 'postgres':
2408 case 'oracle':
2409 case 'sqlite':
2410 $sql = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2411 _sql($sql, $errored, $error_ary);
2412 break;
2413
2414 case 'mysql_40':
2415 case 'mysql_41':
2416 $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2417 _sql($sql, $errored, $error_ary);
2418 break;
2419
2420 case 'mssql':
2421 $sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
2422 _sql($sql, $errored, $error_ary);
2423 break;
2424 }
2425 }
2426
2427 // List all of the indices that belong to a table,
2428 // does not count:
2429 // * UNIQUE indices
2430 // * PRIMARY keys
2431 function sql_list_index($dbms, $table_name)
2432 {
2433 global $dbms_type_map, $db;
2434 global $errored, $error_ary;
2435
2436 $index_array = array();
2437
2438 if ($dbms == 'mssql')
2439 {
2440 $sql = "EXEC sp_statistics '$table_name'";
2441 $result = $db->sql_query($sql);
2442 while ($row = $db->sql_fetchrow($result))
2443 {
2444 if ($row['TYPE'] == 3)
2445 {
2446 $index_array[] = $row['INDEX_NAME'];
2447 }
2448 }
2449 $db->sql_freeresult($result);
2450 }
2451 else
2452 {
2453 switch ($dbms)
2454 {
2455 case 'firebird':
2456 $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
2457 FROM RDB\$INDICES
2458 WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . "
2459 AND RDB\$UNIQUE_FLAG IS NULL
2460 AND RDB\$FOREIGN_KEY IS NULL";
2461 $col = 'index_name';
2462 break;
2463
2464 case 'postgres':
2465 $sql = "SELECT ic.relname as index_name
2466 FROM pg_class bc, pg_class ic, pg_index i
2467 WHERE (bc.oid = i.indrelid)
2468 AND (ic.oid = i.indexrelid)
2469 AND (bc.relname = '" . $table_name . "')
2470 AND (i.indisunique != 't')
2471 AND (i.indisprimary != 't')";
2472 $col = 'index_name';
2473 break;
2474
2475 case 'mysql_40':
2476 case 'mysql_41':
2477 $sql = 'SHOW KEYS
2478 FROM ' . $table_name;
2479 $col = 'Key_name';
2480 break;
2481
2482 case 'oracle':
2483 $sql = "SELECT index_name
2484 FROM user_indexes
2485 WHERE table_name = '" . $table_name . "'
2486 AND generated = 'N'";
2487 break;
2488
2489 case 'sqlite':
2490 $sql = "PRAGMA index_info('" . $table_name . "');";
2491 $col = 'name';
2492 break;
2493 }
2494
2495 $result = $db->sql_query($sql);
2496 while ($row = $db->sql_fetchrow($result))
2497 {
2498 if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
2499 {
2500 continue;
2501 }
2502
2503 switch ($dbms)
2504 {
2505 case 'firebird':
2506 case 'oracle':
2507 case 'postgres':
2508 case 'sqlite':
2509 $row[$col] = substr($row[$col], strlen($table_name) + 1);
2510 break;
2511 }
2512
2513 $index_array[] = $row[$col];
2514 }
2515 $db->sql_freeresult($result);
2516 }
2517
2518 return array_map('strtolower', $index_array);
2519 }
2520
2521 // This is totally fake, never use it
2522 // it exists only to mend bad update functions introduced
2523 // * UNIQUE indices
2524 // * PRIMARY keys
2525 function sql_list_fake($dbms, $table_name)
2526 {
2527 global $dbms_type_map, $db;
2528 global $errored, $error_ary;
2529
2530 $index_array = array();
2531
2532 if ($dbms == 'mssql')
2533 {
2534 $sql = "EXEC sp_statistics '$table_name'";
2535 $result = $db->sql_query($sql);
2536 while ($row = $db->sql_fetchrow($result))
2537 {
2538 if ($row['TYPE'] == 3)
2539 {
2540 $index_array[] = $row['INDEX_NAME'];
2541 }
2542 }
2543 $db->sql_freeresult($result);
2544 }
2545 else
2546 {
2547 switch ($dbms)
2548 {
2549 case 'firebird':
2550 $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
2551 FROM RDB\$INDICES
2552 WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . "
2553 AND RDB\$UNIQUE_FLAG IS NULL
2554 AND RDB\$FOREIGN_KEY IS NULL";
2555 $col = 'index_name';
2556 break;
2557
2558 case 'postgres':
2559 $sql = "SELECT ic.relname as index_name
2560 FROM pg_class bc, pg_class ic, pg_index i
2561 WHERE (bc.oid = i.indrelid)
2562 AND (ic.oid = i.indexrelid)
2563 AND (bc.relname = '" . $table_name . "')
2564 AND (i.indisunique != 't')
2565 AND (i.indisprimary != 't')";
2566 $col = 'index_name';
2567 break;
2568
2569 case 'mysql_40':
2570 case 'mysql_41':
2571 $sql = 'SHOW KEYS
2572 FROM ' . $table_name;
2573 $col = 'Key_name';
2574 break;
2575
2576 case 'oracle':
2577 $sql = "SELECT index_name
2578 FROM user_indexes
2579 WHERE table_name = '" . $table_name . "'
2580 AND generated = 'N'";
2581 break;
2582
2583 case 'sqlite':
2584 $sql = "PRAGMA index_info('" . $table_name . "');";
2585 $col = 'name';
2586 break;
2587 }
2588
2589 $result = $db->sql_query($sql);
2590 while ($row = $db->sql_fetchrow($result))
2591 {
2592 if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
2593 {
2594 continue;
2595 }
2596
2597 $index_array[] = $row[$col];
2598 }
2599 $db->sql_freeresult($result);
2600 }
2601
2602 return array_map('strtolower', $index_array);
2603 }
2604
2605 /**
2606 * Change column type (not name!)
2607 */
2608 function sql_column_change($dbms, $table_name, $column_name, $column_data)
2609 {
2610 global $dbms_type_map, $db;
2611 global $errored, $error_ary;
2612
2613 $column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
2614
2615 switch ($dbms)
2616 {
2617 case 'firebird':
2618 // Change type...
2619 $sql = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql'];
2620 _sql($sql, $errored, $error_ary);
2621 break;
2622
2623 case 'mssql':
2624 $sql = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
2625 _sql($sql, $errored, $error_ary);
2626 break;
2627
2628 case 'mysql_40':
2629 case 'mysql_41':
2630 $sql = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
2631 _sql($sql, $errored, $error_ary);
2632 break;
2633
2634 case 'oracle':
2635 $sql = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql'];
2636 _sql($sql, $errored, $error_ary);
2637 break;
2638
2639 case 'postgres':
2640 $sql = 'ALTER TABLE ' . $table_name . ' ';
2641
2642 $sql_array = array();
2643 $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
2644
2645 if (isset($column_data['null']))
2646 {
2647 if ($column_data['null'] == 'NOT NULL')
2648 {
2649 $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
2650 }
2651 else if ($column_data['null'] == 'NULL')
2652 {
2653 $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
2654 }
2655 }
2656
2657 if (isset($column_data['default']))
2658 {
2659 $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
2660 }
2661
2662 // we don't want to double up on constraints if we change different number data types
2663 if (isset($column_data['constraint']))
2664 {
2665 $constraint_sql = "SELECT consrc as constraint_data
2666 FROM pg_constraint, pg_class bc
2667 WHERE conrelid = bc.oid
2668 AND bc.relname = '{$table_name}'
2669 AND NOT EXISTS (
2670 SELECT *
2671 FROM pg_constraint as c, pg_inherits as i
2672 WHERE i.inhrelid = pg_constraint.conrelid
2673 AND c.conname = pg_constraint.conname
2674 AND c.consrc = pg_constraint.consrc
2675 AND c.conrelid = i.inhparent
2676 )";
2677
2678 $constraint_exists = false;
2679
2680 $result = $db->sql_query($constraint_sql);
2681 while ($row = $db->sql_fetchrow($result))
2682 {
2683 if (trim($row['constraint_data']) == trim($column_data['constraint']))
2684 {
2685 $constraint_exists = true;
2686 break;
2687 }
2688 }
2689 $db->sql_freeresult($result);
2690
2691 if (!$constraint_exists)
2692 {
2693 $sql_array[] = 'ADD ' . $column_data['constraint'];
2694 }
2695 }
2696
2697 $sql .= implode(', ', $sql_array);
2698
2699 _sql($sql, $errored, $error_ary);
2700 break;
2701
2702 case 'sqlite':
2703
2704 $sql = "SELECT sql
2705 FROM sqlite_master
2706 WHERE type = 'table'
2707 AND name = '{$table_name}'
2708 ORDER BY type DESC, name;";
2709 $result = _sql($sql, $errored, $error_ary);
2710
2711 if (!$result)
2712 {
2713 break;
2714 }
2715
2716 $row = $db->sql_fetchrow($result);
2717 $db->sql_freeresult($result);
2718
2719 $db->sql_transaction('begin');
2720
2721 // Create a temp table and populate it, destroy the existing one
2722 $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']));
2723 $db->sql_query('INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name);
2724 $db->sql_query('DROP TABLE ' . $table_name);
2725
2726 preg_match('#\((.*)\)#s', $row['sql'], $matches);
2727
2728 $new_table_cols = trim($matches[1]);
2729 $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2730 $column_list = array();
2731
2732 foreach ($old_table_cols as $key => $declaration)
2733 {
2734 $entities = preg_split('#\s+#', trim($declaration));
2735 $column_list[] = $entities[0];
2736 if ($entities[0] == $column_name)
2737 {
2738 $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
2739 }
2740 }
2741
2742 $columns = implode(',', $column_list);
2743
2744 // create a new table and fill it up. destroy the temp one
2745 $db->sql_query('CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');');
2746 $db->sql_query('INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;');
2747 $db->sql_query('DROP TABLE ' . $table_name . '_temp');
2748
2749 $db->sql_transaction('commit');
2750
2751 break;
2752 }
2753 }
2754
2755 function utf8_new_clean_string($text)
2756 {
2757 static $homographs = array();
2758 static $utf8_case_fold_nfkc = '';
2759 if (empty($homographs))
2760 {
2761 global $phpbb_root_path, $phpEx;
2762 if (!function_exists('utf8_case_fold_nfkc') || !file_exists($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx))
2763 {
2764 if (!file_exists($phpbb_root_path . 'install/data/confusables.' . $phpEx))
2765 {
2766 global $lang;
2767 trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/confusables.' . $phpEx), E_USER_ERROR);
2768 }
2769 $homographs = include($phpbb_root_path . 'install/data/confusables.' . $phpEx);
2770 $utf8_case_fold_nfkc = 'utf8_new_case_fold_nfkc';
2771 }
2772 else
2773 {
2774 $homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx);
2775 $utf8_case_fold_nfkc = 'utf8_case_fold_nfkc';
2776 }
2777 }
2778
2779 $text = $utf8_case_fold_nfkc($text);
2780 $text = strtr($text, $homographs);
2781 // Other control characters
2782 $text = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $text);
2783
2784 $text = preg_replace('# {2,}#', ' ', $text);
2785
2786 // we can use trim here as all the other space characters should have been turned
2787 // into normal ASCII spaces by now
2788 return trim($text);
2789 }
2790
2791 ?>