5
* @version $Id: database_update.php,v 1.149 2007/12/12 10:54:50 acydburn Exp $
6
* @copyright (c) 2006 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
11
$updates_to_version = '3.0.0';
13
// Return if we "just include it" to find out for which version the database update is responsuble for
14
if (defined('IN_PHPBB') && defined('IN_INSTALL'))
21
define('IN_PHPBB', true);
22
define('IN_INSTALL', true);
24
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
25
$phpEx = substr(strrchr(__FILE__, '.'), 1);
27
// Report all errors, except notices
28
//error_reporting(E_ALL ^ E_NOTICE);
29
error_reporting(E_ALL);
33
// Include essential scripts
34
include($phpbb_root_path . 'config.' . $phpEx);
38
die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
42
if (!empty($load_extensions))
44
$load_extensions = explode(',', $load_extensions);
46
foreach ($load_extensions as $extension)
48
@dl(trim($extension));
53
require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx);
54
require($phpbb_root_path . 'includes/cache.' . $phpEx);
55
require($phpbb_root_path . 'includes/template.' . $phpEx);
56
require($phpbb_root_path . 'includes/session.' . $phpEx);
57
require($phpbb_root_path . 'includes/auth.' . $phpEx);
59
require($phpbb_root_path . 'includes/functions.' . $phpEx);
61
if (file_exists($phpbb_root_path . 'includes/functions_content.' . $phpEx))
63
require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
66
require($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
67
require($phpbb_root_path . 'includes/constants.' . $phpEx);
68
require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
69
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
71
// If we are on PHP >= 6.0.0 we do not need some code
72
if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
77
define('STRIP', false);
81
set_magic_quotes_runtime(0);
82
define('STRIP', (get_magic_quotes_gpc()) ? true : false);
89
// Add own hook handler, if present. :o
90
if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
92
require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
93
$phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
95
foreach ($cache->obtain_hooks() as $hook)
97
@include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
106
$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
108
// We do not need this any longer, unset for safety purposes
111
$user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : '';
113
$sql = "SELECT config_value
114
FROM " . CONFIG_TABLE . "
115
WHERE config_name = 'default_lang'";
116
$result = $db->sql_query($sql);
117
$row = $db->sql_fetchrow($result);
118
$db->sql_freeresult($result);
120
$language = basename(request_var('language', ''));
124
$language = $row['config_value'];
127
if (!file_exists($phpbb_root_path . 'language/' . $language))
129
die('No language found!');
132
// And finally, load the relevant language files
133
include($phpbb_root_path . 'language/' . $language . '/common.' . $phpEx);
134
include($phpbb_root_path . 'language/' . $language . '/acp/common.' . $phpEx);
135
include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx);
137
// Set PHP error handler to ours
138
//set_error_handler('msg_handler');
140
// Define some variables for the database update
141
$inline_update = (request_var('type', 0)) ? true : false;
143
// Database column types mapping
144
$dbms_type_map = array(
147
'BINT' => 'bigint(20)',
148
'UINT' => 'mediumint(8) UNSIGNED',
149
'UINT:' => 'int(%d) UNSIGNED',
150
'TINT:' => 'tinyint(%d)',
151
'USINT' => 'smallint(4) UNSIGNED',
152
'BOOL' => 'tinyint(1) UNSIGNED',
153
'VCHAR' => 'varchar(255)',
154
'VCHAR:' => 'varchar(%d)',
155
'CHAR:' => 'char(%d)',
157
'XSTEXT_UNI'=> 'varchar(100)',
159
'STEXT_UNI' => 'varchar(255)',
161
'TEXT_UNI' => 'text',
162
'MTEXT' => 'mediumtext',
163
'MTEXT_UNI' => 'mediumtext',
164
'TIMESTAMP' => 'int(11) UNSIGNED',
165
'DECIMAL' => 'decimal(5,2)',
166
'VCHAR_UNI' => 'varchar(255)',
167
'VCHAR_UNI:'=> 'varchar(%d)',
168
'VCHAR_CI' => 'varchar(255)',
169
'VARBINARY' => 'varbinary(255)',
174
'BINT' => 'bigint(20)',
175
'UINT' => 'mediumint(8) UNSIGNED',
176
'UINT:' => 'int(%d) UNSIGNED',
177
'TINT:' => 'tinyint(%d)',
178
'USINT' => 'smallint(4) UNSIGNED',
179
'BOOL' => 'tinyint(1) UNSIGNED',
180
'VCHAR' => 'varbinary(255)',
181
'VCHAR:' => 'varbinary(%d)',
182
'CHAR:' => 'binary(%d)',
184
'XSTEXT_UNI'=> 'blob',
186
'STEXT_UNI' => 'blob',
188
'TEXT_UNI' => 'blob',
189
'MTEXT' => 'mediumblob',
190
'MTEXT_UNI' => 'mediumblob',
191
'TIMESTAMP' => 'int(11) UNSIGNED',
192
'DECIMAL' => 'decimal(5,2)',
193
'VCHAR_UNI' => 'blob',
194
'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')),
195
'VCHAR_CI' => 'blob',
196
'VARBINARY' => 'varbinary(255)',
201
'BINT' => 'DOUBLE PRECISION',
203
'UINT:' => 'INTEGER',
204
'TINT:' => 'INTEGER',
205
'USINT' => 'INTEGER',
207
'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE',
208
'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE',
209
'CHAR:' => 'CHAR(%d) CHARACTER SET NONE',
210
'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
211
'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
212
'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
213
'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE',
214
'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8',
215
'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
216
'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
217
'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8',
218
'TIMESTAMP' => 'INTEGER',
219
'DECIMAL' => 'DOUBLE PRECISION',
220
'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8',
221
'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8',
222
'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8',
223
'VARBINARY' => 'CHAR(255) CHARACTER SET NONE',
234
'VCHAR' => '[varchar] (255)',
235
'VCHAR:' => '[varchar] (%d)',
236
'CHAR:' => '[char] (%d)',
237
'XSTEXT' => '[varchar] (1000)',
238
'STEXT' => '[varchar] (3000)',
239
'TEXT' => '[varchar] (8000)',
241
'XSTEXT_UNI'=> '[varchar] (100)',
242
'STEXT_UNI' => '[varchar] (255)',
243
'TEXT_UNI' => '[varchar] (4000)',
244
'MTEXT_UNI' => '[text]',
245
'TIMESTAMP' => '[int]',
246
'DECIMAL' => '[float]',
247
'VCHAR_UNI' => '[varchar] (255)',
248
'VCHAR_UNI:'=> '[varchar] (%d)',
249
'VCHAR_CI' => '[varchar] (255)',
250
'VARBINARY' => '[varchar] (255)',
254
'INT:' => 'number(%d)',
255
'BINT' => 'number(20)',
256
'UINT' => 'number(8)',
257
'UINT:' => 'number(%d)',
258
'TINT:' => 'number(%d)',
259
'USINT' => 'number(4)',
260
'BOOL' => 'number(1)',
261
'VCHAR' => 'varchar2(255)',
262
'VCHAR:' => 'varchar2(%d)',
263
'CHAR:' => 'char(%d)',
264
'XSTEXT' => 'varchar2(1000)',
265
'STEXT' => 'varchar2(3000)',
268
'XSTEXT_UNI'=> 'varchar2(300)',
269
'STEXT_UNI' => 'varchar2(765)',
270
'TEXT_UNI' => 'clob',
271
'MTEXT_UNI' => 'clob',
272
'TIMESTAMP' => 'number(11)',
273
'DECIMAL' => 'number(5, 2)',
274
'VCHAR_UNI' => 'varchar2(765)',
275
'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')),
276
'VCHAR_CI' => 'varchar2(255)',
277
'VARBINARY' => 'raw(255)',
282
'BINT' => 'bigint(20)',
283
'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED',
284
'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED',
285
'TINT:' => 'tinyint(%d)',
286
'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED',
287
'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED',
288
'VCHAR' => 'varchar(255)',
289
'VCHAR:' => 'varchar(%d)',
290
'CHAR:' => 'char(%d)',
291
'XSTEXT' => 'text(65535)',
292
'STEXT' => 'text(65535)',
293
'TEXT' => 'text(65535)',
294
'MTEXT' => 'mediumtext(16777215)',
295
'XSTEXT_UNI'=> 'text(65535)',
296
'STEXT_UNI' => 'text(65535)',
297
'TEXT_UNI' => 'text(65535)',
298
'MTEXT_UNI' => 'mediumtext(16777215)',
299
'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED',
300
'DECIMAL' => 'decimal(5,2)',
301
'VCHAR_UNI' => 'varchar(255)',
302
'VCHAR_UNI:'=> 'varchar(%d)',
303
'VCHAR_CI' => 'varchar(255)',
304
'VARBINARY' => 'blob',
310
'UINT' => 'INT4', // unsigned
311
'UINT:' => 'INT4', // unsigned
312
'USINT' => 'INT2', // unsigned
313
'BOOL' => 'INT2', // unsigned
315
'VCHAR' => 'varchar(255)',
316
'VCHAR:' => 'varchar(%d)',
317
'CHAR:' => 'char(%d)',
318
'XSTEXT' => 'varchar(1000)',
319
'STEXT' => 'varchar(3000)',
320
'TEXT' => 'varchar(8000)',
322
'XSTEXT_UNI'=> 'varchar(100)',
323
'STEXT_UNI' => 'varchar(255)',
324
'TEXT_UNI' => 'varchar(4000)',
325
'MTEXT_UNI' => 'TEXT',
326
'TIMESTAMP' => 'INT4', // unsigned
327
'DECIMAL' => 'decimal(5,2)',
328
'VCHAR_UNI' => 'varchar(255)',
329
'VCHAR_UNI:'=> 'varchar(%d)',
330
'VCHAR_CI' => 'varchar_ci',
331
'VARBINARY' => 'bytea',
335
// A list of types being unsigned for better reference in some db's
336
$unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP');
338
// Only an example, but also commented out
339
$database_update_info = array(
340
// Changes from 3.0.RC2 to the next version
342
// Change the following columns
343
'change_columns' => array(
344
BANLIST_TABLE => array(
345
'ban_reason' => array('VCHAR_UNI', ''),
346
'ban_give_reason' => array('VCHAR_UNI', ''),
350
// Changes from 3.0.RC3 to the next version
352
// Change the following columns
353
'change_columns' => array(
354
BANLIST_TABLE => array(
355
'ban_reason' => array('VCHAR_UNI', ''),
356
'ban_give_reason' => array('VCHAR_UNI', ''),
358
STYLES_TABLE => array(
359
'style_id' => array('USINT', 0),
360
'template_id' => array('USINT', 0),
361
'theme_id' => array('USINT', 0),
362
'imageset_id' => array('USINT', 0),
364
STYLES_TEMPLATE_TABLE => array(
365
'template_id' => array('USINT', 0),
367
STYLES_TEMPLATE_DATA_TABLE => array(
368
'template_id' => array('USINT', 0),
370
STYLES_THEME_TABLE => array(
371
'theme_id' => array('USINT', 0),
373
STYLES_IMAGESET_TABLE => array(
374
'imageset_id' => array('USINT', 0),
376
STYLES_IMAGESET_DATA_TABLE => array(
377
'imageset_id' => array('USINT', 0),
379
USERS_TABLE => array(
380
'user_style' => array('USINT', 0),
382
FORUMS_TABLE => array(
383
'forum_style' => array('USINT', 0),
385
GROUPS_TABLE => array(
386
'group_avatar_type' => array('TINT:2', 0),
387
'group_avatar_width' => array('USINT', 0),
388
'group_avatar_height' => array('USINT', 0),
392
// Changes from 3.0.RC4 to the next version
394
// Change the following columns
395
'change_columns' => array(
396
STYLES_TABLE => array(
397
'style_id' => array('USINT', NULL, 'auto_increment'),
398
'template_id' => array('USINT', 0),
399
'theme_id' => array('USINT', 0),
400
'imageset_id' => array('USINT', 0),
402
STYLES_TEMPLATE_TABLE => array(
403
'template_id' => array('USINT', NULL, 'auto_increment'),
405
STYLES_TEMPLATE_DATA_TABLE => array(
406
'template_id' => array('USINT', 0),
408
STYLES_THEME_TABLE => array(
409
'theme_id' => array('USINT', NULL, 'auto_increment'),
411
STYLES_IMAGESET_TABLE => array(
412
'imageset_id' => array('USINT', NULL, 'auto_increment'),
414
STYLES_IMAGESET_DATA_TABLE => array(
415
'imageset_id' => array('USINT', 0),
417
USERS_TABLE => array(
418
'user_style' => array('USINT', 0),
420
FORUMS_TABLE => array(
421
'forum_style' => array('USINT', 0),
423
GROUPS_TABLE => array(
424
'group_avatar_width' => array('USINT', 0),
425
'group_avatar_height' => array('USINT', 0),
429
// Changes from 3.0.RC5 to the next version
431
// Add the following columns
432
'add_columns' => array(
433
USERS_TABLE => array(
434
'user_form_salt' => array('VCHAR_UNI:32', ''),
437
// Change the following columns
438
'change_columns' => array(
439
POSTS_TABLE => array(
440
'bbcode_uid' => array('VCHAR:8', ''),
442
PRIVMSGS_TABLE => array(
443
'bbcode_uid' => array('VCHAR:8', ''),
445
USERS_TABLE => array(
446
'user_sig_bbcode_uid' => array('VCHAR:8', ''),
450
// Changes from 3.0.RC6 to the next version
452
// Change the following columns
453
'change_columns' => array(
454
FORUMS_TABLE => array(
455
'forum_desc_uid' => array('VCHAR:8', ''),
456
'forum_rules_uid' => array('VCHAR:8', ''),
458
GROUPS_TABLE => array(
459
'group_desc_uid' => array('VCHAR:8', ''),
461
USERS_TABLE => array(
462
'user_newpasswd' => array('VCHAR_UNI:40', ''),
466
// Changes from 3.0.RC8 to the next version
468
// Change the following columns
469
'change_columns' => array(
470
USERS_TABLE => array(
471
'user_new_privmsg' => array('INT:4', 0),
472
'user_unread_privmsg' => array('INT:4', 0),
478
// Determine mapping database type
479
switch ($db->sql_layer)
482
$map_dbms = 'mysql_40';
486
if (version_compare($db->mysql_version, '4.1.3', '>='))
488
$map_dbms = 'mysql_41';
492
$map_dbms = 'mysql_40';
497
$map_dbms = 'mysql_41';
506
$map_dbms = $db->sql_layer;
510
$error_ary = array();
513
header('Content-type: text/html; charset=UTF-8');
516
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
517
<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']; ?>">
520
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
521
<meta http-equiv="content-language" content="<?php echo $lang['USER_LANG']; ?>" />
522
<meta http-equiv="content-style-type" content="text/css" />
523
<meta http-equiv="imagetoolbar" content="no" />
525
<title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title>
527
<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />
533
<div id="page-header"> </div>
538
<span class="corners-top"><span></span></span>
542
<h1><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
546
<p><?php echo $lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->sql_layer; ?></strong><br />
549
// To let set_config() calls succeed, we need to make the config array available globally
552
FROM ' . CONFIG_TABLE;
553
$result = $db->sql_query($sql);
555
while ($row = $db->sql_fetchrow($result))
557
$config[$row['config_name']] = $row['config_value'];
559
$db->sql_freeresult($result);
561
echo $lang['PREVIOUS_VERSION'] . ' :: <strong>' . $config['version'] . '</strong><br />';
562
echo $lang['UPDATED_VERSION'] . ' :: <strong>' . $updates_to_version . '</strong></p>';
564
$current_version = str_replace('rc', 'RC', strtolower($config['version']));
565
$latest_version = str_replace('rc', 'RC', strtolower($updates_to_version));
566
$orig_version = $config['version'];
568
// If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything.
571
if ($current_version !== $latest_version)
573
set_config('version_update_from', $orig_version);
578
// If not called from the update script, we will actually remove the traces
579
$db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
582
// Checks/Operations that have to be completed prior to starting the update itself
584
if (version_compare($current_version, '3.0.RC8', '<='))
586
// Define missing language entries...
587
if (!isset($lang['CLEANING_USERNAMES']))
589
$lang = array_merge($lang, array(
590
'CLEANING_USERNAMES' => 'Cleaning usernames',
591
'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.',
592
'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.',
593
'USER_ACTIVE' => 'Active user',
594
'USER_INACTIVE' => 'Inactive user',
595
'BOT' => 'Spider/Robot',
596
'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s',
598
'DELETE_USER_REMOVE' => 'Delete user and remove posts',
599
'DELETE_USER_RETAIN' => 'Delete user but keep posts',
600
'EDIT_USERNAME' => 'Edit username',
601
'KEEP_OLD_NAME' => 'Keep username',
602
'NEW_USERNAME' => 'New username',
608
<h1><?php echo $lang['CLEANING_USERNAMES']; ?></h1>
615
$submit = (isset($_POST['resolve_conflicts'])) ? true : false;
616
$modify_users = request_var('modify_users', array(0 => ''));
617
$new_usernames = request_var('new_usernames', array(0 => ''), true);
619
if (!class_exists('utf_new_normalizer'))
621
if (!file_exists($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx))
624
trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/new_normalizer.' . $phpEx), E_USER_ERROR);
626
include($phpbb_root_path . 'install/data/new_normalizer.' . $phpEx);
629
// the admin decided to change some usernames
630
if (sizeof($modify_users) && $submit)
632
$sql = 'SELECT user_id, username, user_type
633
FROM ' . USERS_TABLE . '
634
WHERE ' . $db->sql_in_set('user_id', array_keys($modify_users));
635
$result = $db->sql_query($sql);
638
while ($row = $db->sql_fetchrow($result))
641
$user_id = (int) $row['user_id'];
643
if (isset($modify_users[$user_id]))
645
$row['action'] = $modify_users[$user_id];
646
$modify_users[$user_id] = $row;
649
$db->sql_freeresult($result);
651
// only if all ids really existed
652
if (sizeof($modify_users) == $users)
654
$user->data['user_id'] = ANONYMOUS;
655
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
656
foreach ($modify_users as $user_id => $row)
658
switch ($row['action'])
661
if (isset($new_usernames[$user_id]))
663
$data = array('username' => utf8_new_normalize_nfc($new_usernames[$user_id]));
664
// Need to update config, forum, topic, posting, messages, etc.
665
if ($data['username'] != $row['username'])
667
$check_ary = array('username' => array(
668
array('string', false, $config['min_name_chars'], $config['max_name_chars']),
671
// need a little trick for this to work properly
672
$user->data['username_clean'] = utf8_clean_string($data['username']) . 'a';
673
$errors = validate_data($data, $check_ary);
677
include($phpbb_root_path . 'language/' . $language . '/ucp.' . $phpEx);
678
echo '<div class="errorbox">';
679
foreach ($errors as $error)
681
echo '<p>' . $lang[$error] . '</p>';
688
$sql = 'UPDATE ' . USERS_TABLE . '
689
SET ' . $db->sql_build_array('UPDATE', array(
690
'username' => $data['username'],
691
'username_clean' => utf8_clean_string($data['username'])
693
WHERE user_id = ' . $user_id;
694
$db->sql_query($sql);
696
add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $row['username'], $data['username']);
697
user_update_name($row['username'], $data['username']);
703
case 'delete_retain':
704
case 'delete_remove':
705
if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
707
user_delete(substr($row['action'], 7), $user_id, $row['username']);
708
add_log('admin', 'LOG_USER_DELETED', $row['username']);
717
<p><?php echo $lang['LONG_SCRIPT_EXECUTION']; ?></p>
718
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
723
// after RC3 a different utf8_clean_string function is used, this requires that
724
// the unique column username_clean is recalculated, during this recalculation
725
// duplicates might be created. Since the column has to be unique such usernames
726
// must not exist. We need identify them and let the admin decide what to do
728
// After RC8 this was changed again, but this time only usernames containing spaces
730
$sql_where = (version_compare($current_version, '3.0.RC4', '<=')) ? '' : "WHERE username_clean LIKE '% %'";
731
$sql = 'SELECT user_id, username, username_clean
732
FROM ' . USERS_TABLE . "
734
ORDER BY user_id ASC";
735
$result = $db->sql_query($sql);
737
$colliding_users = $found_names = array();
740
while ($row = $db->sql_fetchrow($result))
742
// Calculate the new clean name. If it differs from the old one we need
743
// to make sure there is no collision
744
$clean_name = utf8_new_clean_string($row['username']);
746
if ($clean_name != $row['username_clean'])
748
// Check if there would be a collission, if not put it up for changing
749
$user_id = (int) $row['user_id'];
751
// If this clean name was not the result of another user already ...
752
if (!isset($found_names[$clean_name]))
754
// then we need to figure out whether there are any other users
755
// who already had this clean name with the old version
756
$sql = 'SELECT user_id, username
757
FROM ' . USERS_TABLE . '
758
WHERE username_clean = \'' . $db->sql_escape($clean_name) . '\'';
759
$result2 = $db->sql_query($sql);
761
$user_ids = array($user_id);
762
while ($row = $db->sql_fetchrow($result2))
764
// For not trimmed entries this could happen, yes. ;)
765
if ($row['user_id'] == $user_id)
770
// Make sure this clean name will still be the same with the
771
// new function. If it is, then we have to add it to the list
772
// of user ids for this clean name
773
if (utf8_new_clean_string($row['username']) == $clean_name)
775
$user_ids[] = (int) $row['user_id'];
778
$db->sql_freeresult($result2);
780
// if we already found a collision save it
781
if (sizeof($user_ids) > 1)
783
$colliding_users[$clean_name] = $user_ids;
784
$found_names[$clean_name] = true;
788
// otherwise just mark this name as found
789
$found_names[$clean_name] = $user_id;
792
// Else, if we already found the username
795
// If the value in the found_names lookup table is only true ...
796
if ($found_names[$clean_name] === true)
798
// then the actual data was already added to $colliding_users
799
// and we only need to append the user_id
800
$colliding_users[$clean_name][] = $user_id;
804
// otherwise it still keeps the first user_id for this name
805
// and we need to move the data to $colliding_users, and set
806
// the value in the found_names lookup table to true, so
807
// following users will directly be appended to $colliding_users
808
$colliding_users[$clean_name] = array($found_names[$clean_name], $user_id);
809
$found_names[$clean_name] = true;
814
if (($echos % 1000) == 0)
821
$db->sql_freeresult($result);
823
_write_result(false, $errored, $error_ary);
825
// now retrieve all information about the users and let the admin decide what to do
826
if (sizeof($colliding_users))
829
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
830
include($phpbb_root_path . 'language/' . $language . '/memberlist.' . $phpEx);
831
include($phpbb_root_path . 'language/' . $language . '/acp/users.' . $phpEx);
833
// link a few things to the correct place so we don't get any problems
834
$user->lang = &$lang;
835
$user->data['user_id'] = ANONYMOUS;
836
$user->date_format = $config['default_dateformat'];
838
// a little trick to get all user_ids
839
$user_ids = call_user_func_array('array_merge', array_values($colliding_users));
841
$sql = 'SELECT session_user_id, MAX(session_time) AS session_time
842
FROM ' . SESSIONS_TABLE . '
843
WHERE session_time >= ' . (time() - $config['session_length']) . '
844
AND ' . $db->sql_in_set('session_user_id', $user_ids) . '
845
GROUP BY session_user_id';
846
$result = $db->sql_query($sql);
848
$session_times = array();
849
while ($row = $db->sql_fetchrow($result))
851
$session_times[$row['session_user_id']] = $row['session_time'];
853
$db->sql_freeresult($result);
856
FROM ' . USERS_TABLE . '
857
WHERE ' . $db->sql_in_set('user_id', $user_ids);
858
$result = $db->sql_query($sql);
861
while ($row = $db->sql_fetchrow($result))
863
if (isset($session_times[$row['user_id']]))
865
$row['session_time'] = $session_times[$row['user_id']];
869
$row['session_time'] = 0;
871
$users[(int) $row['user_id']] = $row;
873
$db->sql_freeresult($result);
874
unset($session_times);
876
// now display a table with all users, some information about them and options
877
// for the admin: keep name, change name (with text input) or delete user
878
$u_action = "database_update.$phpEx?language=$language&type=$inline_update";
882
<p><?php echo $lang['CHANGE_CLEAN_NAMES']; ?></p>
883
<form id="change_clean_names" method="post" action="<?php echo $u_action; ?>">
887
foreach ($colliding_users as $clean_name => $user_ids)
890
<fieldset class="tabulated">
892
<caption><?php echo sprintf($lang['COLLIDING_CLEAN_USERNAME'], $clean_name); ?></caption>
895
<th><?php echo $lang['RANK']; ?> <?php echo $lang['USERNAME']; ?></th>
896
<th><?php echo $lang['POSTS']; ?></th>
897
<th><?php echo $lang['INFORMATION']; ?></th>
898
<th><?php echo $lang['JOINED']; ?></th>
899
<th><?php echo $lang['LAST_ACTIVE']; ?></th>
900
<th><?php echo $lang['ACTION']; ?></th>
901
<th><?php echo $lang['NEW_USERNAME']; ?></th>
906
foreach ($user_ids as $i => $user_id)
908
$row = $users[$user_id];
910
$rank_title = $rank_img = '';
911
get_user_rank($row['user_rank'], $row['user_posts'], $rank_title, $rank_img, $rank_img_src);
913
$last_visit = (!empty($row['session_time'])) ? $row['session_time'] : $row['user_lastvisit'];
916
switch ($row['user_type'])
919
$info .= $lang['USER_INACTIVE'];
923
$info .= $lang['BOT'];
927
$info .= $lang['FOUNDER'];
931
$info .= $lang['USER_ACTIVE'];
934
if ($user_id == ANONYMOUS)
936
$info = $lang['GUEST'];
939
<tr class="bg<?php echo ($i % 2) + 1; ?>">
941
<span class="rank-img"><?php echo ($rank_img) ? $rank_img : $rank_title; ?></span><br />
942
<?php echo get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']); ?>
944
<td class="posts"><?php echo $row['user_posts']; ?></td>
945
<td class="info"><?php echo $info; ?></td>
946
<td><?php echo $user->format_date($row['user_regdate']) ?></td>
947
<td><?php echo (empty($last_visit)) ? ' - ' : $user->format_date($last_visit); ?> </td>
949
<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 />
950
<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 />
952
// some users must not be deleted
953
if ($user_id != ANONYMOUS && $row['user_type'] != USER_FOUNDER)
956
<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 />
957
<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>
963
<input id="new_username_<?php echo $user_id; ?>" type="text" name="new_usernames[<?php echo $user_id; ?>]" value="<?php echo $row['username']; ?>" />
976
<input class="button2" id="resolve_conflicts" type="submit" name="resolve_conflicts" value="<?php echo $lang['SUBMIT']; ?>" />
981
else if (sizeof($found_names))
983
$sql = 'SELECT user_id, username, username_clean
984
FROM ' . USERS_TABLE . '
985
WHERE ' . $db->sql_in_set('user_id', array_values($found_names));
986
$result = $db->sql_query($sql);
988
$found_names = array();
989
while ($row = $db->sql_fetchrow($result))
991
$clean_name = utf8_new_clean_string($row['username']);
993
if ($clean_name != $row['username_clean'])
995
$user_id = (int) $row['user_id'];
996
$found_names[$user_id] = $clean_name;
998
// impossible unique clean name
999
$sql = 'UPDATE ' . USERS_TABLE . "
1000
SET username_clean = ' {$user_id}'
1001
WHERE user_id = {$user_id}";
1002
$db->sql_query($sql);
1005
$db->sql_freeresult($result);
1007
foreach ($found_names as $user_id => $clean_name)
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);
1015
unset($found_names);
1016
unset($colliding_users);
1025
<span class="corners-bottom"><span></span></span>
1030
<div id="page-footer">
1031
Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group
1039
if (function_exists('exit_handler'))
1049
<h1><?php echo $lang['UPDATE_DATABASE_SCHEMA']; ?></h1>
1052
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
1058
// We go through the schema changes from the lowest to the highest version
1059
// We skip those versions older than the current version
1061
foreach ($database_update_info as $version => $schema_changes)
1063
if (version_compare($version, $current_version, '<'))
1068
if (!sizeof($schema_changes))
1073
$no_updates = false;
1076
if (!empty($schema_changes['change_columns']))
1078
foreach ($schema_changes['change_columns'] as $table => $columns)
1080
foreach ($columns as $column_name => $column_data)
1082
sql_column_change($map_dbms, $table, $column_name, $column_data);
1088
if (!empty($schema_changes['add_columns']))
1090
foreach ($schema_changes['add_columns'] as $table => $columns)
1092
foreach ($columns as $column_name => $column_data)
1094
// Only add the column if it does not exist yet
1095
if (!column_exists($map_dbms, $table, $column_name))
1097
sql_column_add($map_dbms, $table, $column_name, $column_data);
1104
if (!empty($schema_changes['drop_keys']))
1106
foreach ($schema_changes['drop_keys'] as $table => $indexes)
1108
foreach ($indexes as $index_name)
1110
sql_index_drop($map_dbms, $index_name, $table);
1116
if (!empty($schema_changes['drop_columns']))
1118
foreach ($schema_changes['drop_columns'] as $table => $columns)
1120
foreach ($columns as $column)
1122
sql_column_remove($map_dbms, $table, $column);
1127
// Add primary keys?
1128
if (!empty($schema_changes['add_primary_keys']))
1130
foreach ($schema_changes['add_primary_keys'] as $table => $columns)
1132
sql_create_primary_key($map_dbms, $table, $columns);
1136
// Add unqiue indexes?
1137
if (!empty($schema_changes['add_unique_index']))
1139
foreach ($schema_changes['add_unique_index'] as $table => $index_array)
1141
foreach ($index_array as $index_name => $column)
1143
sql_create_unique_index($map_dbms, $index_name, $table, $column);
1149
if (!empty($schema_changes['add_index']))
1151
foreach ($schema_changes['add_index'] as $table => $index_array)
1153
foreach ($index_array as $index_name => $column)
1155
sql_create_index($map_dbms, $index_name, $table, $column);
1161
_write_result($no_updates, $errored, $error_ary);
1164
$error_ary = array();
1165
$errored = $no_updates = false;
1170
<h1><?php echo $lang['UPDATING_DATA']; ?></h1>
1172
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
1181
if (version_compare($current_version, '3.0.RC2', '<='))
1184
$sql = 'SELECT smiley_id, code
1185
FROM ' . SMILIES_TABLE;
1187
$result = $db->sql_query($sql);
1189
while ($row = $db->sql_fetchrow($result))
1191
$smileys[$row['smiley_id']] = $row['code'];
1193
$db->sql_freeresult($result);
1195
foreach ($smileys as $id => $code)
1197
// 2.0 only entitized lt and gt; We need to do something about double quotes.
1198
if (strchr($code, '"') === false)
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);
1208
$sql = 'UPDATE ' . SMILIES_TABLE . '
1209
SET code = \'' . $db->sql_escape($new_code) . '\'
1210
WHERE smiley_id = ' . (int) $id;
1211
$db->sql_query($sql);
1214
$index_list = sql_list_index($map_dbms, ACL_ROLES_DATA_TABLE);
1216
if (in_array('ath_opt_id', $index_list))
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'));
1222
$no_updates = false;
1225
if (version_compare($current_version, '3.0.RC3', '<='))
1227
if ($map_dbms === 'postgres')
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);
1236
// ACL_ROLES_DATA_TABLE_ath_opt_id
1237
// we want ACL_ROLES_DATA_TABLE_ath_op_id
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'
1245
STYLES_IMAGESET_DATA_TABLE => array(
1248
STYLES_IMAGESET_DATA_TABLE . '_i_id' => 'i_d'
1252
// we need to create some indicies...
1253
$needed_creation = array();
1255
foreach ($table_index_fix as $table_name => $index_info)
1257
$index_list = sql_list_fake($map_dbms, $table_name);
1258
foreach ($index_info as $bad_index => $good_index)
1260
if (in_array($bad_index, $index_list))
1262
// mysql is actually OK, it won't get a hand in this crud
1265
// last version, mssql had issues with index removal
1267
$sql = 'DROP INDEX ' . $table_name . '.' . $bad_index;
1268
_sql($sql, $errored, $error_ary);
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
1277
$sql = 'DROP INDEX ' . $bad_index;
1278
_sql($sql, $errored, $error_ary);
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)
1288
$needed_creation[$table_name][$good_index] = 1;
1294
$new_index_defs = array('ath_op_id' => array('auth_option_id'), 'i_d' => array('imageset_id'));
1296
foreach ($needed_creation as $bad_table => $index_repair_list)
1298
foreach ($index_repair_list as $new_index => $garbage)
1300
sql_create_index($map_dbms, $new_index, $bad_table, $new_index_defs[$new_index]);
1301
$no_updates = false;
1305
// Make sure empty smiley codes do not exist
1306
$sql = 'DELETE FROM ' . SMILIES_TABLE . "
1308
_sql($sql, $errored, $error_ary);
1310
set_config('allow_birthdays', '1');
1311
set_config('cron_lock', '0', true);
1313
$no_updates = false;
1316
if (version_compare($current_version, '3.0.RC4', '<='))
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'
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);
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);
1340
$proper_id = $row['max_id'] + 1;
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);
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);
1353
if ($style_config['config_value'] === '0')
1355
set_config('default_style', (string) $proper_id);
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);
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);
1374
$proper_id = $row['max_id'] + 1;
1376
_sql('UPDATE ' . STYLES_TABLE . " SET template_id = $proper_id WHERE template_id = 0", $errored, $error_ary);
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);
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);
1394
$proper_id = $row['max_id'] + 1;
1396
_sql('UPDATE ' . STYLES_TABLE . " SET theme_id = $proper_id WHERE theme_id = 0", $errored, $error_ary);
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);
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);
1414
$proper_id = $row['max_id'] + 1;
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);
1420
if ($map_dbms == 'mysql_40' || $map_dbms == 'mysql_41')
1422
foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
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);
1430
$max_id = ((int) $row['max_id']) + 1;
1431
_sql("ALTER TABLE {$auto_table_name} AUTO_INCREMENT = {$max_id}", $errored, $error_ary);
1434
$no_updates = false;
1436
else if ($map_dbms == 'postgres')
1438
foreach ($update_auto_increment as $auto_table_name => $auto_column_name)
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);
1444
$sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
1445
_sql($sql, $errored, $error_ary);
1447
else if ($map_dbms == 'firebird')
1449
$sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
1450
_sql($sql, $errored, $error_ary);
1452
$sql = 'DROP GENERATOR ' . STYLES_TEMPLATE_DATA_TABLE . '_gen';
1453
_sql($sql, $errored, $error_ary);
1455
else if ($map_dbms == 'oracle')
1457
$sql = 'DROP TRIGGER t_' . STYLES_TEMPLATE_DATA_TABLE;
1458
_sql($sql, $errored, $error_ary);
1460
$sql = 'DROP SEQUENCE ' . STYLES_TEMPLATE_DATA_TABLE . '_seq';
1461
_sql($sql, $errored, $error_ary);
1463
else if ($map_dbms == 'mssql')
1465
// we use transactions because we need to have a working DB at the end of all of this
1466
$db->sql_transaction('begin');
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))
1474
$old_style_rows[] = $row;
1476
$db->sql_freeresult($result);
1478
// death to the table, it is evil!
1479
$sql = 'DROP TABLE ' . STYLES_TEMPLATE_DATA_TABLE;
1480
_sql($sql, $errored, $error_ary);
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);
1493
$sql = 'CREATE INDEX [tid] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_id]) ON [PRIMARY]';
1494
_sql($sql, $errored, $error_ary);
1496
// yet another index
1497
$sql = 'CREATE INDEX [tfn] ON [' . STYLES_TEMPLATE_DATA_TABLE . ']([template_filename]) ON [PRIMARY]';
1498
_sql($sql, $errored, $error_ary);
1500
foreach ($old_style_rows as $return_row)
1502
_sql('INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $return_row), $errored, $error_ary);
1505
$db->sql_transaction('commit');
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', '');
1513
$no_updates = false;
1516
if (version_compare($current_version, '3.0.RC5', '<='))
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);
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');
1530
$db->sql_transaction('begin');
1532
$sql = 'SELECT forum_id, forum_password
1533
FROM ' . FORUMS_TABLE;
1534
$result = _sql($sql, $errored, $error_ary);
1536
while ($row = $db->sql_fetchrow($result))
1538
if (!empty($row['forum_password']))
1540
_sql('UPDATE ' . FORUMS_TABLE . " SET forum_password = '" . md5($row['forum_password']) . "' WHERE forum_id = {$row['forum_id']}", $errored, $error_ary);
1543
$db->sql_freeresult($result);
1545
$db->sql_transaction('commit');
1547
$no_updates = false;
1550
_write_result($no_updates, $errored, $error_ary);
1552
$error_ary = array();
1553
$errored = $no_updates = false;
1558
<h1><?php echo $lang['UPDATE_VERSION_OPTIMIZE']; ?></h1>
1560
<p><?php echo $lang['PROGRESS']; ?> :: <strong>
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);
1572
// Reset permissions
1573
$sql = 'UPDATE ' . USERS_TABLE . "
1574
SET user_permissions = ''";
1575
_sql($sql, $errored, $error_ary);
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)
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);
1590
_sql("VACUUM ANALYZE", $errored, $error_ary);
1595
_write_result($no_updates, $errored, $error_ary);
1600
<h1><?php echo $lang['UPDATE_COMPLETED']; ?></h1>
1606
if (!$inline_update)
1610
<p style="color:red"><?php echo $lang['UPDATE_FILES_NOTICE']; ?></p>
1612
<p><?php echo $lang['COMPLETE_LOGIN_TO_BOARD']; ?></p>
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>
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>
1627
// Add database update to log
1628
add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version);
1630
// Now we purge the session table as well as all cache files
1637
<span class="corners-bottom"><span></span></span>
1642
<div id="page-footer">
1643
Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>
1652
garbage_collection();
1654
if (function_exists('exit_handler'))
1661
* Function for triggering an sql statement
1663
function _sql($sql, &$errored, &$error_ary, $echo_dot = true)
1667
if (defined('DEBUG_EXTRA'))
1669
echo "<br />\n{$sql}\n<br />";
1672
$db->sql_return_on_error(true);
1674
$result = $db->sql_query($sql);
1675
if ($db->sql_error_triggered)
1678
$error_ary['sql'][] = $db->sql_error_sql;
1679
$error_ary['error_code'][] = $db->_sql_error();
1682
$db->sql_return_on_error(false);
1693
function _write_result($no_updates, $errored, $error_ary)
1699
echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '</strong></p>';
1703
echo ' <span class="success">' . $lang['DONE'] . '</span></strong><br />' . $lang['RESULT'] . ' :: ';
1707
echo ' <strong>' . $lang['SOME_QUERIES_FAILED'] . '</strong> <ul>';
1709
for ($i = 0; $i < sizeof($error_ary['sql']); $i++)
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>';
1715
echo '</ul> <br /><br />' . $lang['SQL_FAILURE_EXPLAIN'] . '</p>';
1719
echo '<strong>' . $lang['NO_ERRORS'] . '</strong></p>';
1725
* Check if a specified column exist
1727
function column_exists($dbms, $table, $column_name)
1735
$sql = "SHOW COLUMNS
1737
$result = $db->sql_query($sql);
1738
while ($row = $db->sql_fetchrow($result))
1740
// lower case just in case
1741
if (strtolower($row['Field']) == $column_name)
1743
$db->sql_freeresult($result);
1747
$db->sql_freeresult($result);
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
1754
$sql = "SELECT a.attname
1755
FROM pg_class c, pg_attribute a
1756
WHERE c.relname = '{$table}'
1758
AND a.attrelid = c.oid";
1759
$result = $db->sql_query($sql);
1760
while ($row = $db->sql_fetchrow($result))
1762
// lower case just in case
1763
if (strtolower($row['attname']) == $column_name)
1765
$db->sql_freeresult($result);
1769
$db->sql_freeresult($result);
1773
// same deal with PostgreSQL, we must perform more complex operations than
1774
// we technically could
1776
$sql = "SELECT c.name
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))
1783
// lower case just in case
1784
if (strtolower($row['name']) == $column_name)
1786
$db->sql_freeresult($result);
1790
$db->sql_freeresult($result);
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))
1801
// lower case just in case
1802
if (strtolower($row['column_name']) == $column_name)
1804
$db->sql_freeresult($result);
1808
$db->sql_freeresult($result);
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))
1819
// lower case just in case
1820
if (strtolower($row['fname']) == $column_name)
1822
$db->sql_freeresult($result);
1826
$db->sql_freeresult($result);
1834
WHERE type = 'table'
1835
AND name = '{$table}'";
1836
$result = $db->sql_query($sql);
1843
$row = $db->sql_fetchrow($result);
1844
$db->sql_freeresult($result);
1846
preg_match('#\((.*)\)#s', $row['sql'], $matches);
1848
$cols = trim($matches[1]);
1849
$col_array = preg_split('/,(?![\s\w]+\))/m', $cols);
1851
foreach ($col_array as $declaration)
1853
$entities = preg_split('#\s+#', trim($declaration));
1854
if ($entities[0] == 'PRIMARY')
1859
if (strtolower($entities[0]) == $column_name)
1870
* Function to prepare some column information for better usage
1872
function prepare_column_data($dbms, $column_data, $table_name, $column_name)
1874
global $dbms_type_map, $unsigned_types;
1877
if (strpos($column_data[0], ':') !== false)
1879
list($orig_column_type, $column_length) = explode(':', $column_data[0]);
1881
if (!is_array($dbms_type_map[$dbms][$orig_column_type . ':']))
1883
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'], $column_length);
1887
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['rule']))
1889
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['rule'][0])
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);
1899
if (isset($dbms_type_map[$dbms][$orig_column_type . ':']['limit']))
1901
switch ($dbms_type_map[$dbms][$orig_column_type . ':']['limit'][0])
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])
1907
$column_type = $dbms_type_map[$dbms][$orig_column_type . ':']['limit'][3];
1911
$column_type = sprintf($dbms_type_map[$dbms][$orig_column_type . ':'][0], $column_length);
1917
$orig_column_type .= ':';
1921
$orig_column_type = $column_data[0];
1922
$column_type = $dbms_type_map[$dbms][$column_data[0]];
1925
// Adjust default value if db-dependant specified
1926
if (is_array($column_data[1]))
1928
$column_data[1] = (isset($column_data[1][$dbms])) ? $column_data[1][$dbms] : $column_data[1]['default'];
1932
$return_array = array();
1937
$sql .= " {$column_type} ";
1939
if (!is_null($column_data[1]))
1941
$sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' ';
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]))
1949
$sql .= ' COLLATE UNICODE';
1955
$sql .= " {$column_type} ";
1956
$sql_default = " {$column_type} ";
1958
// For adding columns we need the default definition
1959
if (!is_null($column_data[1]))
1961
// For hexadecimal values do not use single quotes
1962
if (strpos($column_data[1], '0x') === 0)
1964
$sql_default .= 'DEFAULT (' . $column_data[1] . ') ';
1968
$sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') ';
1973
$sql_default .= 'NOT NULL';
1975
$return_array['column_type_sql_default'] = $sql_default;
1980
$sql .= " {$column_type} ";
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')
1985
$sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' ";
1989
if (isset($column_data[2]))
1991
if ($column_data[2] == 'auto_increment')
1993
$sql .= ' auto_increment';
1995
else if ($dbms === 'mysql_41' && $column_data[2] == 'true_sort')
1997
$sql .= ' COLLATE utf8_unicode_ci';
2004
$sql .= " {$column_type} ";
2005
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : '';
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))
2012
$sql .= ($column_data[1] === '') ? '' : 'NOT NULL';
2017
$return_array['column_type'] = $column_type;
2019
$sql .= " {$column_type} ";
2021
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
2023
$default_val = "nextval('{$table_name}_seq')";
2025
else if (!is_null($column_data[1]))
2027
$default_val = "'" . $column_data[1] . "'";
2028
$return_array['null'] = 'NOT NULL';
2029
$sql .= 'NOT NULL ';
2032
$return_array['default'] = $default_val;
2034
$sql .= "DEFAULT {$default_val}";
2036
// Unsigned? Then add a CHECK contraint
2037
if (in_array($orig_column_type, $unsigned_types))
2039
$return_array['constraint'] = "CHECK ({$column_name} >= 0)";
2040
$sql .= " CHECK ({$column_name} >= 0)";
2045
if (isset($column_data[2]) && $column_data[2] == 'auto_increment')
2047
$sql .= ' INTEGER PRIMARY KEY';
2051
$sql .= ' ' . $column_type;
2054
$sql .= ' NOT NULL ';
2055
$sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : '';
2059
$return_array['column_type_sql'] = $sql;
2061
return $return_array;
2067
function sql_column_add($dbms, $table_name, $column_name, $column_data)
2069
global $errored, $error_ary;
2071
$column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
2076
$sql = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql'];
2077
_sql($sql, $errored, $error_ary);
2081
$sql = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default'];
2082
_sql($sql, $errored, $error_ary);
2087
$sql = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql'];
2088
_sql($sql, $errored, $error_ary);
2092
$sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql'];
2093
_sql($sql, $errored, $error_ary);
2097
$sql = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql'];
2098
_sql($sql, $errored, $error_ary);
2102
if (version_compare(sqlite_libversion(), '3.0') == -1)
2107
WHERE type = 'table'
2108
AND name = '{$table_name}'
2109
ORDER BY type DESC, name;";
2110
$result = $db->sql_query($sql);
2117
$row = $db->sql_fetchrow($result);
2118
$db->sql_freeresult($result);
2120
$db->sql_transaction('begin');
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);
2127
preg_match('#\((.*)\)#s', $row['sql'], $matches);
2129
$new_table_cols = trim($matches[1]);
2130
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2131
$column_list = array();
2133
foreach ($old_table_cols as $declaration)
2135
$entities = preg_split('#\s+#', trim($declaration));
2136
if ($entities[0] == 'PRIMARY')
2140
$column_list[] = $entities[0];
2143
$columns = implode(',', $column_list);
2145
$new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols;
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');
2152
$db->sql_transaction('commit');
2156
$sql = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']';
2157
_sql($sql, $errored, $error_ary);
2166
function sql_column_remove($dbms, $table_name, $column_name)
2168
global $errored, $error_ary;
2173
$sql = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"';
2174
_sql($sql, $errored, $error_ary);
2178
$sql = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
2179
_sql($sql, $errored, $error_ary);
2184
$sql = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`';
2185
_sql($sql, $errored, $error_ary);
2189
$sql = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name;
2190
_sql($sql, $errored, $error_ary);
2194
$sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"';
2195
_sql($sql, $errored, $error_ary);
2199
if (version_compare(sqlite_libversion(), '3.0') == -1)
2204
WHERE type = 'table'
2205
AND name = '{$table_name}'
2206
ORDER BY type DESC, name;";
2207
$result = $db->sql_query($sql);
2214
$row = $db->sql_fetchrow($result);
2215
$db->sql_freeresult($result);
2217
$db->sql_transaction('begin');
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);
2224
preg_match('#\((.*)\)#s', $row['sql'], $matches);
2226
$new_table_cols = trim($matches[1]);
2227
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2228
$column_list = array();
2230
foreach ($old_table_cols as $declaration)
2232
$entities = preg_split('#\s+#', trim($declaration));
2233
if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name)
2237
$column_list[] = $entities[0];
2240
$columns = implode(',', $column_list);
2242
$new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols);
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');
2249
$db->sql_transaction('commit');
2253
$sql = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
2254
_sql($sql, $errored, $error_ary);
2260
function sql_index_drop($dbms, $index_name, $table_name)
2262
global $dbms_type_map, $db;
2263
global $errored, $error_ary;
2268
$sql = 'DROP INDEX ' . $table_name . '.' . $index_name;
2269
_sql($sql, $errored, $error_ary);
2274
$sql = 'DROP INDEX ' . $index_name . ' ON ' . $table_name;
2275
_sql($sql, $errored, $error_ary);
2282
$sql = 'DROP INDEX ' . $table_name . '_' . $index_name;
2283
_sql($sql, $errored, $error_ary);
2288
function sql_create_primary_key($dbms, $table_name, $column)
2290
global $dbms_type_map, $db;
2291
global $errored, $error_ary;
2297
$sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
2298
_sql($sql, $errored, $error_ary);
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);
2311
$sql = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')';
2312
_sql($sql, $errored, $error_ary);
2316
$sql = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')';
2317
_sql($sql, $errored, $error_ary);
2323
WHERE type = 'table'
2324
AND name = '{$table_name}'
2325
ORDER BY type DESC, name;";
2326
$result = _sql($sql, $errored, $error_ary);
2333
$row = $db->sql_fetchrow($result);
2334
$db->sql_freeresult($result);
2336
$db->sql_transaction('begin');
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);
2343
preg_match('#\((.*)\)#s', $row['sql'], $matches);
2345
$new_table_cols = trim($matches[1]);
2346
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2347
$column_list = array();
2349
foreach ($old_table_cols as $declaration)
2351
$entities = preg_split('#\s+#', trim($declaration));
2352
if ($entities[0] == 'PRIMARY')
2356
$column_list[] = $entities[0];
2359
$columns = implode(',', $column_list);
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');
2366
$db->sql_transaction('commit');
2371
function sql_create_unique_index($dbms, $index_name, $table_name, $column)
2373
global $dbms_type_map, $db;
2374
global $errored, $error_ary;
2382
$sql = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2383
_sql($sql, $errored, $error_ary);
2388
$sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2389
_sql($sql, $errored, $error_ary);
2393
$sql = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
2394
_sql($sql, $errored, $error_ary);
2399
function sql_create_index($dbms, $index_name, $table_name, $column)
2401
global $dbms_type_map, $db;
2402
global $errored, $error_ary;
2410
$sql = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2411
_sql($sql, $errored, $error_ary);
2416
$sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')';
2417
_sql($sql, $errored, $error_ary);
2421
$sql = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]';
2422
_sql($sql, $errored, $error_ary);
2427
// List all of the indices that belong to a table,
2431
function sql_list_index($dbms, $table_name)
2433
global $dbms_type_map, $db;
2434
global $errored, $error_ary;
2436
$index_array = array();
2438
if ($dbms == 'mssql')
2440
$sql = "EXEC sp_statistics '$table_name'";
2441
$result = $db->sql_query($sql);
2442
while ($row = $db->sql_fetchrow($result))
2444
if ($row['TYPE'] == 3)
2446
$index_array[] = $row['INDEX_NAME'];
2449
$db->sql_freeresult($result);
2456
$sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
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';
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';
2478
FROM ' . $table_name;
2483
$sql = "SELECT index_name
2485
WHERE table_name = '" . $table_name . "'
2486
AND generated = 'N'";
2490
$sql = "PRAGMA index_info('" . $table_name . "');";
2495
$result = $db->sql_query($sql);
2496
while ($row = $db->sql_fetchrow($result))
2498
if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
2509
$row[$col] = substr($row[$col], strlen($table_name) + 1);
2513
$index_array[] = $row[$col];
2515
$db->sql_freeresult($result);
2518
return array_map('strtolower', $index_array);
2521
// This is totally fake, never use it
2522
// it exists only to mend bad update functions introduced
2525
function sql_list_fake($dbms, $table_name)
2527
global $dbms_type_map, $db;
2528
global $errored, $error_ary;
2530
$index_array = array();
2532
if ($dbms == 'mssql')
2534
$sql = "EXEC sp_statistics '$table_name'";
2535
$result = $db->sql_query($sql);
2536
while ($row = $db->sql_fetchrow($result))
2538
if ($row['TYPE'] == 3)
2540
$index_array[] = $row['INDEX_NAME'];
2543
$db->sql_freeresult($result);
2550
$sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name
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';
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';
2572
FROM ' . $table_name;
2577
$sql = "SELECT index_name
2579
WHERE table_name = '" . $table_name . "'
2580
AND generated = 'N'";
2584
$sql = "PRAGMA index_info('" . $table_name . "');";
2589
$result = $db->sql_query($sql);
2590
while ($row = $db->sql_fetchrow($result))
2592
if (($dbms == 'mysql_40' || $dbms == 'mysql_41') && !$row['Non_unique'])
2597
$index_array[] = $row[$col];
2599
$db->sql_freeresult($result);
2602
return array_map('strtolower', $index_array);
2606
* Change column type (not name!)
2608
function sql_column_change($dbms, $table_name, $column_name, $column_data)
2610
global $dbms_type_map, $db;
2611
global $errored, $error_ary;
2613
$column_data = prepare_column_data($dbms, $column_data, $table_name, $column_name);
2619
$sql = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql'];
2620
_sql($sql, $errored, $error_ary);
2624
$sql = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql'];
2625
_sql($sql, $errored, $error_ary);
2630
$sql = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql'];
2631
_sql($sql, $errored, $error_ary);
2635
$sql = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql'];
2636
_sql($sql, $errored, $error_ary);
2640
$sql = 'ALTER TABLE ' . $table_name . ' ';
2642
$sql_array = array();
2643
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type'];
2645
if (isset($column_data['null']))
2647
if ($column_data['null'] == 'NOT NULL')
2649
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL';
2651
else if ($column_data['null'] == 'NULL')
2653
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL';
2657
if (isset($column_data['default']))
2659
$sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default'];
2662
// we don't want to double up on constraints if we change different number data types
2663
if (isset($column_data['constraint']))
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}'
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
2678
$constraint_exists = false;
2680
$result = $db->sql_query($constraint_sql);
2681
while ($row = $db->sql_fetchrow($result))
2683
if (trim($row['constraint_data']) == trim($column_data['constraint']))
2685
$constraint_exists = true;
2689
$db->sql_freeresult($result);
2691
if (!$constraint_exists)
2693
$sql_array[] = 'ADD ' . $column_data['constraint'];
2697
$sql .= implode(', ', $sql_array);
2699
_sql($sql, $errored, $error_ary);
2706
WHERE type = 'table'
2707
AND name = '{$table_name}'
2708
ORDER BY type DESC, name;";
2709
$result = _sql($sql, $errored, $error_ary);
2716
$row = $db->sql_fetchrow($result);
2717
$db->sql_freeresult($result);
2719
$db->sql_transaction('begin');
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);
2726
preg_match('#\((.*)\)#s', $row['sql'], $matches);
2728
$new_table_cols = trim($matches[1]);
2729
$old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols);
2730
$column_list = array();
2732
foreach ($old_table_cols as $key => $declaration)
2734
$entities = preg_split('#\s+#', trim($declaration));
2735
$column_list[] = $entities[0];
2736
if ($entities[0] == $column_name)
2738
$old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql'];
2742
$columns = implode(',', $column_list);
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');
2749
$db->sql_transaction('commit');
2755
function utf8_new_clean_string($text)
2757
static $homographs = array();
2758
static $utf8_case_fold_nfkc = '';
2759
if (empty($homographs))
2761
global $phpbb_root_path, $phpEx;
2762
if (!function_exists('utf8_case_fold_nfkc') || !file_exists($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx))
2764
if (!file_exists($phpbb_root_path . 'install/data/confusables.' . $phpEx))
2767
trigger_error(sprintf($lang['UPDATE_REQUIRES_FILE'], $phpbb_root_path . 'install/data/confusables.' . $phpEx), E_USER_ERROR);
2769
$homographs = include($phpbb_root_path . 'install/data/confusables.' . $phpEx);
2770
$utf8_case_fold_nfkc = 'utf8_new_case_fold_nfkc';
2774
$homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx);
2775
$utf8_case_fold_nfkc = 'utf8_case_fold_nfkc';
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);
2784
$text = preg_replace('# {2,}#', ' ', $text);
2786
// we can use trim here as all the other space characters should have been turned
2787
// into normal ASCII spaces by now
b'\\ No newline at end of file'