[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package install 5 * @version $Id$ 6 * @copyright (c) 2006 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 define('UPDATES_TO_VERSION', '3.0.12'); 12 13 // Enter any version to update from to test updates. The version within the db will not be updated. 14 define('DEBUG_FROM_VERSION', false); 15 16 // Which oldest version does this updater support? 17 define('OLDEST_FROM_VERSION', '3.0.0'); 18 19 // Return if we "just include it" to find out for which version the database update is responsible for 20 if (defined('IN_PHPBB') && defined('IN_INSTALL')) 21 { 22 $updates_to_version = UPDATES_TO_VERSION; 23 $debug_from_version = DEBUG_FROM_VERSION; 24 $oldest_from_version = OLDEST_FROM_VERSION; 25 26 return; 27 } 28 29 /** 30 */ 31 define('IN_PHPBB', true); 32 define('IN_INSTALL', true); 33 34 $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../'; 35 $phpEx = substr(strrchr(__FILE__, '.'), 1); 36 37 if (!function_exists('phpbb_require_updated')) 38 { 39 function phpbb_require_updated($path, $optional = false) 40 { 41 global $phpbb_root_path; 42 43 $new_path = $phpbb_root_path . 'install/update/new/' . $path; 44 $old_path = $phpbb_root_path . $path; 45 46 if (file_exists($new_path)) 47 { 48 require($new_path); 49 } 50 else if (!$optional || file_exists($old_path)) 51 { 52 require($old_path); 53 } 54 } 55 } 56 57 phpbb_require_updated('includes/startup.' . $phpEx); 58 59 $updates_to_version = UPDATES_TO_VERSION; 60 $debug_from_version = DEBUG_FROM_VERSION; 61 $oldest_from_version = OLDEST_FROM_VERSION; 62 63 @set_time_limit(0); 64 65 // Include essential scripts 66 include($phpbb_root_path . 'config.' . $phpEx); 67 68 if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type)) 69 { 70 die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update."); 71 } 72 73 // Load Extensions 74 if (!empty($load_extensions) && function_exists('dl')) 75 { 76 $load_extensions = explode(',', $load_extensions); 77 78 foreach ($load_extensions as $extension) 79 { 80 @dl(trim($extension)); 81 } 82 } 83 84 // Include files 85 require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx); 86 require($phpbb_root_path . 'includes/cache.' . $phpEx); 87 require($phpbb_root_path . 'includes/template.' . $phpEx); 88 require($phpbb_root_path . 'includes/session.' . $phpEx); 89 require($phpbb_root_path . 'includes/auth.' . $phpEx); 90 91 require($phpbb_root_path . 'includes/functions.' . $phpEx); 92 93 phpbb_require_updated('includes/functions_content.' . $phpEx, true); 94 95 require($phpbb_root_path . 'includes/functions_admin.' . $phpEx); 96 require($phpbb_root_path . 'includes/constants.' . $phpEx); 97 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); 98 require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); 99 100 phpbb_require_updated('includes/db/db_tools.' . $phpEx); 101 102 // new table constants are separately defined here in case the updater is run 103 // before the files are updated 104 if (!defined('LOGIN_ATTEMPT_TABLE')) 105 { 106 define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts'); 107 } 108 109 $user = new user(); 110 $cache = new cache(); 111 $db = new $sql_db(); 112 113 // Add own hook handler, if present. :o 114 if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) 115 { 116 require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); 117 $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); 118 119 foreach ($cache->obtain_hooks() as $hook) 120 { 121 @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx); 122 } 123 } 124 else 125 { 126 $phpbb_hook = false; 127 } 128 129 // Connect to DB 130 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false); 131 132 // We do not need this any longer, unset for safety purposes 133 unset($dbpasswd); 134 135 $user->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : ''; 136 $user->ip = (stripos($user->ip, '::ffff:') === 0) ? substr($user->ip, 7) : $user->ip; 137 138 $sql = "SELECT config_value 139 FROM " . CONFIG_TABLE . " 140 WHERE config_name = 'default_lang'"; 141 $result = $db->sql_query($sql); 142 $row = $db->sql_fetchrow($result); 143 $db->sql_freeresult($result); 144 145 $language = basename(request_var('language', '')); 146 147 if (!$language) 148 { 149 $language = $row['config_value']; 150 } 151 152 if (!file_exists($phpbb_root_path . 'language/' . $language)) 153 { 154 die('No language found!'); 155 } 156 157 // And finally, load the relevant language files 158 include($phpbb_root_path . 'language/' . $language . '/common.' . $phpEx); 159 include($phpbb_root_path . 'language/' . $language . '/acp/common.' . $phpEx); 160 include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx); 161 162 // Set PHP error handler to ours 163 //set_error_handler('msg_handler'); 164 165 // Define some variables for the database update 166 $inline_update = (request_var('type', 0)) ? true : false; 167 168 // To let set_config() calls succeed, we need to make the config array available globally 169 $config = array(); 170 171 $sql = 'SELECT * 172 FROM ' . CONFIG_TABLE; 173 $result = $db->sql_query($sql); 174 175 while ($row = $db->sql_fetchrow($result)) 176 { 177 $config[$row['config_name']] = $row['config_value']; 178 } 179 $db->sql_freeresult($result); 180 181 // phpbb_db_tools will be taken from new files (under install/update/new) 182 // if possible, falling back to the board's copy. 183 $db_tools = new phpbb_db_tools($db, true); 184 185 $database_update_info = database_update_info(); 186 187 $error_ary = array(); 188 $errored = false; 189 190 header('Content-type: text/html; charset=UTF-8'); 191 192 ?> 193 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 194 <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']; ?>"> 195 <head> 196 197 <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> 198 <meta http-equiv="content-language" content="<?php echo $lang['USER_LANG']; ?>" /> 199 <meta http-equiv="content-style-type" content="text/css" /> 200 <meta http-equiv="imagetoolbar" content="no" /> 201 202 <title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title> 203 204 <link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> 205 206 </head> 207 208 <body> 209 <div id="wrap"> 210 <div id="page-header"> </div> 211 212 <div id="page-body"> 213 <div id="acp"> 214 <div class="panel"> 215 <span class="corners-top"><span></span></span> 216 <div id="content"> 217 <div id="main" class="install-body"> 218 219 <h1><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></h1> 220 221 <br /> 222 223 <p><?php echo $lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->sql_layer; ?></strong><br /> 224 <?php 225 226 if ($debug_from_version !== false) 227 { 228 $config['version'] = $debug_from_version; 229 } 230 231 echo $lang['PREVIOUS_VERSION'] . ' :: <strong>' . $config['version'] . '</strong><br />'; 232 echo $lang['UPDATED_VERSION'] . ' :: <strong>' . $updates_to_version . '</strong></p>'; 233 234 $current_version = str_replace('rc', 'RC', strtolower($config['version'])); 235 $latest_version = str_replace('rc', 'RC', strtolower($updates_to_version)); 236 $orig_version = $config['version']; 237 238 // Fill DB version 239 if (empty($config['dbms_version'])) 240 { 241 set_config('dbms_version', $db->sql_server_info(true)); 242 } 243 244 // Firebird update from Firebird 2.0 to 2.1+ required? 245 if ($db->sql_layer == 'firebird') 246 { 247 // We do not trust any PHP5 function enabled, we will simply test for a function new in 2.1 248 $db->sql_return_on_error(true); 249 250 $sql = 'SELECT 1 FROM RDB$DATABASE 251 WHERE BIN_AND(10, 1) = 0'; 252 $result = $db->sql_query($sql); 253 254 if (!$result || $db->sql_error_triggered) 255 { 256 echo '<br /><br />'; 257 echo '<h1>' . $lang['ERROR'] . '</h1><br />'; 258 259 echo '<p>' . $lang['FIREBIRD_DBMS_UPDATE_REQUIRED'] . '</p>'; 260 261 _print_footer(); 262 263 exit_handler(); 264 exit; 265 } 266 267 $db->sql_freeresult($result); 268 $db->sql_return_on_error(false); 269 } 270 271 // MySQL update from MySQL 3.x/4.x to > 4.1.x required? 272 if ($db->sql_layer == 'mysql' || $db->sql_layer == 'mysql4' || $db->sql_layer == 'mysqli') 273 { 274 // Verify by fetching column... if the column type matches the new type we update dbms_version... 275 $sql = "SHOW COLUMNS FROM " . CONFIG_TABLE; 276 $result = $db->sql_query($sql); 277 278 $column_type = ''; 279 while ($row = $db->sql_fetchrow($result)) 280 { 281 $field = strtolower($row['Field']); 282 283 if ($field == 'config_value') 284 { 285 $column_type = strtolower($row['Type']); 286 break; 287 } 288 } 289 $db->sql_freeresult($result); 290 291 // If column type is blob, but mysql version says we are on > 4.1.3, then the schema needs an update 292 if (strpos($column_type, 'blob') !== false && version_compare($db->sql_server_info(true), '4.1.3', '>=')) 293 { 294 echo '<br /><br />'; 295 echo '<h1>' . $lang['ERROR'] . '</h1><br />'; 296 297 echo '<p>' . sprintf($lang['MYSQL_SCHEMA_UPDATE_REQUIRED'], $config['dbms_version'], $db->sql_server_info(true)) . '</p>'; 298 299 _print_footer(); 300 301 exit_handler(); 302 exit; 303 } 304 } 305 306 // Now check if the user wants to update from a version we no longer support updates from 307 if (version_compare($current_version, $oldest_from_version, '<')) 308 { 309 echo '<br /><br /><h1>' . $lang['ERROR'] . '</h1><br />'; 310 echo '<p>' . sprintf($lang['DB_UPDATE_NOT_SUPPORTED'], $oldest_from_version, $current_version) . '</p>'; 311 312 _print_footer(); 313 exit_handler(); 314 exit; 315 } 316 317 // If the latest version and the current version are 'unequal', we will update the version_update_from, else we do not update anything. 318 if ($inline_update) 319 { 320 if ($current_version !== $latest_version) 321 { 322 set_config('version_update_from', $orig_version); 323 } 324 } 325 else 326 { 327 // If not called from the update script, we will actually remove the traces 328 $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'"); 329 } 330 331 // Schema updates 332 ?> 333 <br /><br /> 334 335 <h1><?php echo $lang['UPDATE_DATABASE_SCHEMA']; ?></h1> 336 337 <br /> 338 <p><?php echo $lang['PROGRESS']; ?> :: <strong> 339 340 <?php 341 342 flush(); 343 344 // We go through the schema changes from the lowest to the highest version 345 // We try to also include versions 'in-between'... 346 $no_updates = true; 347 $versions = array_keys($database_update_info); 348 for ($i = 0; $i < sizeof($versions); $i++) 349 { 350 $version = $versions[$i]; 351 $schema_changes = $database_update_info[$version]; 352 353 $next_version = (isset($versions[$i + 1])) ? $versions[$i + 1] : $updates_to_version; 354 355 // If the installed version to be updated to is < than the current version, and if the current version is >= as the version to be updated to next, we will skip the process 356 if (version_compare($version, $current_version, '<') && version_compare($current_version, $next_version, '>=')) 357 { 358 continue; 359 } 360 361 if (!sizeof($schema_changes)) 362 { 363 continue; 364 } 365 366 $no_updates = false; 367 368 // We run one index after the other... to be consistent with schema changes... 369 foreach ($schema_changes as $key => $changes) 370 { 371 $statements = $db_tools->perform_schema_changes(array($key => $changes)); 372 373 foreach ($statements as $sql) 374 { 375 _sql($sql, $errored, $error_ary); 376 } 377 } 378 } 379 380 _write_result($no_updates, $errored, $error_ary); 381 382 // Data updates 383 $error_ary = array(); 384 $errored = $no_updates = false; 385 386 ?> 387 388 <br /><br /> 389 <h1><?php echo $lang['UPDATING_DATA']; ?></h1> 390 <br /> 391 <p><?php echo $lang['PROGRESS']; ?> :: <strong> 392 393 <?php 394 395 flush(); 396 397 $no_updates = true; 398 $versions = array_keys($database_update_info); 399 400 // some code magic 401 for ($i = 0; $i < sizeof($versions); $i++) 402 { 403 $version = $versions[$i]; 404 $next_version = (isset($versions[$i + 1])) ? $versions[$i + 1] : $updates_to_version; 405 406 // If the installed version to be updated to is < than the current version, and if the current version is >= as the version to be updated to next, we will skip the process 407 if (version_compare($version, $current_version, '<') && version_compare($current_version, $next_version, '>=')) 408 { 409 continue; 410 } 411 412 change_database_data($no_updates, $version); 413 } 414 415 _write_result($no_updates, $errored, $error_ary); 416 417 $error_ary = array(); 418 $errored = $no_updates = false; 419 420 ?> 421 422 <br /><br /> 423 <h1><?php echo $lang['UPDATE_VERSION_OPTIMIZE']; ?></h1> 424 <br /> 425 <p><?php echo $lang['PROGRESS']; ?> :: <strong> 426 427 <?php 428 429 flush(); 430 431 if ($debug_from_version === false) 432 { 433 // update the version 434 $sql = "UPDATE " . CONFIG_TABLE . " 435 SET config_value = '$updates_to_version' 436 WHERE config_name = 'version'"; 437 _sql($sql, $errored, $error_ary); 438 } 439 440 // Reset permissions 441 $sql = 'UPDATE ' . USERS_TABLE . " 442 SET user_permissions = '', 443 user_perm_from = 0"; 444 _sql($sql, $errored, $error_ary); 445 446 // Update the dbms version if everything is ok... 447 set_config('dbms_version', $db->sql_server_info(true)); 448 449 /* Optimize/vacuum analyze the tables where appropriate 450 // this should be done for each version in future along with 451 // the version number update 452 switch ($db->sql_layer) 453 { 454 case 'mysql': 455 case 'mysqli': 456 case 'mysql4': 457 $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'; 458 _sql($sql, $errored, $error_ary); 459 break; 460 461 case 'postgresql': 462 _sql("VACUUM ANALYZE", $errored, $error_ary); 463 break; 464 } 465 */ 466 467 _write_result($no_updates, $errored, $error_ary); 468 469 ?> 470 471 <br /> 472 <h1><?php echo $lang['UPDATE_COMPLETED']; ?></h1> 473 474 <br /> 475 476 <?php 477 478 if (!$inline_update) 479 { 480 ?> 481 482 <p style="color:red"><?php echo $lang['UPDATE_FILES_NOTICE']; ?></p> 483 484 <p><?php echo $lang['COMPLETE_LOGIN_TO_BOARD']; ?></p> 485 486 <?php 487 } 488 else 489 { 490 ?> 491 492 <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> 493 494 <p><a href="<?php echo append_sid("{$phpbb_root_path}install/index.{$phpEx}", "mode=update&sub=file_check&language=$language"); ?>" class="button1"><?php echo (isset($lang['CONTINUE_UPDATE_NOW'])) ? $lang['CONTINUE_UPDATE_NOW'] : 'Continue the update process now'; ?></a></p> 495 496 <?php 497 } 498 499 // Add database update to log 500 add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version); 501 502 // Now we purge the session table as well as all cache files 503 $cache->purge(); 504 505 _print_footer(); 506 507 garbage_collection(); 508 509 if (function_exists('exit_handler')) 510 { 511 exit_handler(); 512 } 513 514 /** 515 * Print out footer 516 */ 517 function _print_footer() 518 { 519 echo <<<EOF 520 </div> 521 </div> 522 <span class="corners-bottom"><span></span></span> 523 </div> 524 </div> 525 </div> 526 527 <div id="page-footer"> 528 Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group 529 </div> 530 </div> 531 532 </body> 533 </html> 534 EOF; 535 } 536 537 /** 538 * Function for triggering an sql statement 539 */ 540 function _sql($sql, &$errored, &$error_ary, $echo_dot = true) 541 { 542 global $db; 543 544 if (defined('DEBUG_EXTRA')) 545 { 546 echo "<br />\n{$sql}\n<br />"; 547 } 548 549 $db->sql_return_on_error(true); 550 551 if ($sql === 'begin') 552 { 553 $result = $db->sql_transaction('begin'); 554 } 555 else if ($sql === 'commit') 556 { 557 $result = $db->sql_transaction('commit'); 558 } 559 else 560 { 561 $result = $db->sql_query($sql); 562 if ($db->sql_error_triggered) 563 { 564 $errored = true; 565 $error_ary['sql'][] = $db->sql_error_sql; 566 $error_ary['error_code'][] = $db->sql_error_returned; 567 } 568 } 569 570 $db->sql_return_on_error(false); 571 572 if ($echo_dot) 573 { 574 echo ". \n"; 575 flush(); 576 } 577 578 return $result; 579 } 580 581 function _write_result($no_updates, $errored, $error_ary) 582 { 583 global $lang; 584 585 if ($no_updates) 586 { 587 echo ' ' . $lang['NO_UPDATES_REQUIRED'] . '</strong></p>'; 588 } 589 else 590 { 591 echo ' <span class="success">' . $lang['DONE'] . '</span></strong><br />' . $lang['RESULT'] . ' :: '; 592 593 if ($errored) 594 { 595 echo ' <strong>' . $lang['SOME_QUERIES_FAILED'] . '</strong> <ul>'; 596 597 for ($i = 0; $i < sizeof($error_ary['sql']); $i++) 598 { 599 echo '<li>' . $lang['ERROR'] . ' :: <strong>' . htmlspecialchars($error_ary['error_code'][$i]['message']) . '</strong><br />'; 600 echo $lang['SQL'] . ' :: <strong>' . htmlspecialchars($error_ary['sql'][$i]) . '</strong><br /><br /></li>'; 601 } 602 603 echo '</ul> <br /><br />' . $lang['SQL_FAILURE_EXPLAIN'] . '</p>'; 604 } 605 else 606 { 607 echo '<strong>' . $lang['NO_ERRORS'] . '</strong></p>'; 608 } 609 } 610 } 611 612 function _add_modules($modules_to_install) 613 { 614 global $phpbb_root_path, $phpEx, $db; 615 616 include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx); 617 618 $_module = new acp_modules(); 619 620 foreach ($modules_to_install as $module_mode => $module_data) 621 { 622 $_module->module_class = $module_data['class']; 623 624 // Determine parent id first 625 $sql = 'SELECT module_id 626 FROM ' . MODULES_TABLE . " 627 WHERE module_class = '" . $db->sql_escape($module_data['class']) . "' 628 AND module_langname = '" . $db->sql_escape($module_data['cat']) . "' 629 AND module_mode = '' 630 AND module_basename = ''"; 631 $result = $db->sql_query($sql); 632 633 // There may be more than one categories with the same name 634 $categories = array(); 635 while ($row = $db->sql_fetchrow($result)) 636 { 637 $categories[] = (int) $row['module_id']; 638 } 639 $db->sql_freeresult($result); 640 641 if (!sizeof($categories)) 642 { 643 continue; 644 } 645 646 // Add the module to all categories found 647 foreach ($categories as $parent_id) 648 { 649 // Check if the module already exists 650 $sql = 'SELECT * 651 FROM ' . MODULES_TABLE . " 652 WHERE module_basename = '" . $db->sql_escape($module_data['base']) . "' 653 AND module_class = '" . $db->sql_escape($module_data['class']) . "' 654 AND module_langname = '" . $db->sql_escape($module_data['title']) . "' 655 AND module_mode = '" . $db->sql_escape($module_mode) . "' 656 AND module_auth = '" . $db->sql_escape($module_data['auth']) . "' 657 AND parent_id = {$parent_id}"; 658 $result = $db->sql_query($sql); 659 $row = $db->sql_fetchrow($result); 660 $db->sql_freeresult($result); 661 662 // If it exists, we simply continue with the next category 663 if ($row) 664 { 665 continue; 666 } 667 668 // Build the module sql row 669 $module_row = array( 670 'module_basename' => $module_data['base'], 671 'module_enabled' => (isset($module_data['enabled'])) ? (int) $module_data['enabled'] : 1, 672 'module_display' => (isset($module_data['display'])) ? (int) $module_data['display'] : 1, 673 'parent_id' => $parent_id, 674 'module_class' => $module_data['class'], 675 'module_langname' => $module_data['title'], 676 'module_mode' => $module_mode, 677 'module_auth' => $module_data['auth'], 678 ); 679 680 $_module->update_module_data($module_row, true); 681 682 // Ok, do we need to re-order the module, move it up or down? 683 if (!isset($module_data['after'])) 684 { 685 continue; 686 } 687 688 $after_mode = $module_data['after'][0]; 689 $after_langname = $module_data['after'][1]; 690 691 // First of all, get the module id for the module this one has to be placed after 692 $sql = 'SELECT left_id 693 FROM ' . MODULES_TABLE . " 694 WHERE module_class = '" . $db->sql_escape($module_data['class']) . "' 695 AND module_basename = '" . $db->sql_escape($module_data['base']) . "' 696 AND module_langname = '" . $db->sql_escape($after_langname) . "' 697 AND module_mode = '" . $db->sql_escape($after_mode) . "' 698 AND parent_id = '{$parent_id}'"; 699 $result = $db->sql_query($sql); 700 $first_left_id = (int) $db->sql_fetchfield('left_id'); 701 $db->sql_freeresult($result); 702 703 if (!$first_left_id) 704 { 705 continue; 706 } 707 708 // Ok, count the number of modules between $after_mode and the added module 709 $sql = 'SELECT COUNT(module_id) as num_modules 710 FROM ' . MODULES_TABLE . " 711 WHERE module_class = '" . $db->sql_escape($module_data['class']) . "' 712 AND parent_id = {$parent_id} 713 AND left_id BETWEEN {$first_left_id} AND {$module_row['left_id']}"; 714 $result = $db->sql_query($sql); 715 $steps = (int) $db->sql_fetchfield('num_modules'); 716 $db->sql_freeresult($result); 717 718 // We need to substract 2 719 $steps -= 2; 720 721 if ($steps <= 0) 722 { 723 continue; 724 } 725 726 // Ok, move module up $num_modules times. ;) 727 $_module->move_module_by($module_row, 'move_up', $steps); 728 } 729 } 730 731 $_module->remove_cache_file(); 732 } 733 734 /**************************************************************************** 735 * ADD YOUR DATABASE SCHEMA CHANGES HERE * 736 *****************************************************************************/ 737 function database_update_info() 738 { 739 return array( 740 // Changes from 3.0.0 to the next version 741 '3.0.0' => array( 742 // Add the following columns 743 'add_columns' => array( 744 FORUMS_TABLE => array( 745 'display_subforum_list' => array('BOOL', 1), 746 ), 747 SESSIONS_TABLE => array( 748 'session_forum_id' => array('UINT', 0), 749 ), 750 ), 751 'drop_keys' => array( 752 GROUPS_TABLE => array('group_legend'), 753 ), 754 'add_index' => array( 755 SESSIONS_TABLE => array( 756 'session_forum_id' => array('session_forum_id'), 757 ), 758 GROUPS_TABLE => array( 759 'group_legend_name' => array('group_legend', 'group_name'), 760 ), 761 ), 762 ), 763 // No changes from 3.0.1-RC1 to 3.0.1 764 '3.0.1-RC1' => array(), 765 // No changes from 3.0.1 to 3.0.2-RC1 766 '3.0.1' => array(), 767 // Changes from 3.0.2-RC1 to 3.0.2-RC2 768 '3.0.2-RC1' => array( 769 'change_columns' => array( 770 DRAFTS_TABLE => array( 771 'draft_subject' => array('STEXT_UNI', ''), 772 ), 773 FORUMS_TABLE => array( 774 'forum_last_post_subject' => array('STEXT_UNI', ''), 775 ), 776 POSTS_TABLE => array( 777 'post_subject' => array('STEXT_UNI', '', 'true_sort'), 778 ), 779 PRIVMSGS_TABLE => array( 780 'message_subject' => array('STEXT_UNI', ''), 781 ), 782 TOPICS_TABLE => array( 783 'topic_title' => array('STEXT_UNI', '', 'true_sort'), 784 'topic_last_post_subject' => array('STEXT_UNI', ''), 785 ), 786 ), 787 'drop_keys' => array( 788 SESSIONS_TABLE => array('session_forum_id'), 789 ), 790 'add_index' => array( 791 SESSIONS_TABLE => array( 792 'session_fid' => array('session_forum_id'), 793 ), 794 ), 795 ), 796 // No changes from 3.0.2-RC2 to 3.0.2 797 '3.0.2-RC2' => array(), 798 799 // Changes from 3.0.2 to 3.0.3-RC1 800 '3.0.2' => array( 801 // Add the following columns 802 'add_columns' => array( 803 STYLES_TEMPLATE_TABLE => array( 804 'template_inherits_id' => array('UINT:4', 0), 805 'template_inherit_path' => array('VCHAR', ''), 806 ), 807 GROUPS_TABLE => array( 808 'group_max_recipients' => array('UINT', 0), 809 ), 810 ), 811 ), 812 813 // No changes from 3.0.3-RC1 to 3.0.3 814 '3.0.3-RC1' => array(), 815 816 // Changes from 3.0.3 to 3.0.4-RC1 817 '3.0.3' => array( 818 'add_columns' => array( 819 PROFILE_FIELDS_TABLE => array( 820 'field_show_profile' => array('BOOL', 0), 821 ), 822 ), 823 'change_columns' => array( 824 STYLES_TABLE => array( 825 'style_id' => array('UINT', NULL, 'auto_increment'), 826 'template_id' => array('UINT', 0), 827 'theme_id' => array('UINT', 0), 828 'imageset_id' => array('UINT', 0), 829 ), 830 STYLES_IMAGESET_TABLE => array( 831 'imageset_id' => array('UINT', NULL, 'auto_increment'), 832 ), 833 STYLES_IMAGESET_DATA_TABLE => array( 834 'image_id' => array('UINT', NULL, 'auto_increment'), 835 'imageset_id' => array('UINT', 0), 836 ), 837 STYLES_THEME_TABLE => array( 838 'theme_id' => array('UINT', NULL, 'auto_increment'), 839 ), 840 STYLES_TEMPLATE_TABLE => array( 841 'template_id' => array('UINT', NULL, 'auto_increment'), 842 ), 843 STYLES_TEMPLATE_DATA_TABLE => array( 844 'template_id' => array('UINT', 0), 845 ), 846 FORUMS_TABLE => array( 847 'forum_style' => array('UINT', 0), 848 ), 849 USERS_TABLE => array( 850 'user_style' => array('UINT', 0), 851 ), 852 ), 853 ), 854 855 // Changes from 3.0.4-RC1 to 3.0.4 856 '3.0.4-RC1' => array(), 857 858 // Changes from 3.0.4 to 3.0.5-RC1 859 '3.0.4' => array( 860 'change_columns' => array( 861 FORUMS_TABLE => array( 862 'forum_style' => array('UINT', 0), 863 ), 864 ), 865 ), 866 867 // No changes from 3.0.5-RC1 to 3.0.5 868 '3.0.5-RC1' => array(), 869 870 // Changes from 3.0.5 to 3.0.6-RC1 871 '3.0.5' => array( 872 'add_columns' => array( 873 CONFIRM_TABLE => array( 874 'attempts' => array('UINT', 0), 875 ), 876 USERS_TABLE => array( 877 'user_new' => array('BOOL', 1), 878 'user_reminded' => array('TINT:4', 0), 879 'user_reminded_time'=> array('TIMESTAMP', 0), 880 ), 881 GROUPS_TABLE => array( 882 'group_skip_auth' => array('BOOL', 0, 'after' => 'group_founder_manage'), 883 ), 884 PRIVMSGS_TABLE => array( 885 'message_reported' => array('BOOL', 0), 886 ), 887 REPORTS_TABLE => array( 888 'pm_id' => array('UINT', 0), 889 ), 890 PROFILE_FIELDS_TABLE => array( 891 'field_show_on_vt' => array('BOOL', 0), 892 ), 893 FORUMS_TABLE => array( 894 'forum_options' => array('UINT:20', 0), 895 ), 896 ), 897 'change_columns' => array( 898 USERS_TABLE => array( 899 'user_options' => array('UINT:11', 230271), 900 ), 901 ), 902 'add_index' => array( 903 REPORTS_TABLE => array( 904 'post_id' => array('post_id'), 905 'pm_id' => array('pm_id'), 906 ), 907 POSTS_TABLE => array( 908 'post_username' => array('post_username:255'), 909 ), 910 ), 911 ), 912 913 // No changes from 3.0.6-RC1 to 3.0.6-RC2 914 '3.0.6-RC1' => array(), 915 // No changes from 3.0.6-RC2 to 3.0.6-RC3 916 '3.0.6-RC2' => array(), 917 // No changes from 3.0.6-RC3 to 3.0.6-RC4 918 '3.0.6-RC3' => array(), 919 // No changes from 3.0.6-RC4 to 3.0.6 920 '3.0.6-RC4' => array(), 921 922 // Changes from 3.0.6 to 3.0.7-RC1 923 '3.0.6' => array( 924 'drop_keys' => array( 925 LOG_TABLE => array('log_time'), 926 ), 927 'add_index' => array( 928 TOPICS_TRACK_TABLE => array( 929 'topic_id' => array('topic_id'), 930 ), 931 ), 932 ), 933 934 // No changes from 3.0.7-RC1 to 3.0.7-RC2 935 '3.0.7-RC1' => array(), 936 // No changes from 3.0.7-RC2 to 3.0.7 937 '3.0.7-RC2' => array(), 938 // No changes from 3.0.7 to 3.0.7-PL1 939 '3.0.7' => array(), 940 // No changes from 3.0.7-PL1 to 3.0.8-RC1 941 '3.0.7-PL1' => array(), 942 // No changes from 3.0.8-RC1 to 3.0.8 943 '3.0.8-RC1' => array(), 944 // Changes from 3.0.8 to 3.0.9-RC1 945 '3.0.8' => array( 946 'add_tables' => array( 947 LOGIN_ATTEMPT_TABLE => array( 948 'COLUMNS' => array( 949 // this column was removed from the database updater 950 // after 3.0.9-RC3 was released. It might still exist 951 // in 3.0.9-RCX installations and has to be dropped in 952 // 3.0.13 after the db_tools class is capable of properly 953 // removing a primary key. 954 // 'attempt_id' => array('UINT', NULL, 'auto_increment'), 955 'attempt_ip' => array('VCHAR:40', ''), 956 'attempt_browser' => array('VCHAR:150', ''), 957 'attempt_forwarded_for' => array('VCHAR:255', ''), 958 'attempt_time' => array('TIMESTAMP', 0), 959 'user_id' => array('UINT', 0), 960 'username' => array('VCHAR_UNI:255', 0), 961 'username_clean' => array('VCHAR_CI', 0), 962 ), 963 //'PRIMARY_KEY' => 'attempt_id', 964 'KEYS' => array( 965 'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')), 966 'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')), 967 'att_time' => array('INDEX', array('attempt_time')), 968 'user_id' => array('INDEX', 'user_id'), 969 ), 970 ), 971 ), 972 'change_columns' => array( 973 BBCODES_TABLE => array( 974 'bbcode_id' => array('USINT', 0), 975 ), 976 ), 977 ), 978 // No changes from 3.0.9-RC1 to 3.0.9-RC2 979 '3.0.9-RC1' => array(), 980 // No changes from 3.0.9-RC2 to 3.0.9-RC3 981 '3.0.9-RC2' => array(), 982 // No changes from 3.0.9-RC3 to 3.0.9-RC4 983 '3.0.9-RC3' => array(), 984 // No changes from 3.0.9-RC4 to 3.0.9 985 '3.0.9-RC4' => array(), 986 // No changes from 3.0.9 to 3.0.10-RC1 987 '3.0.9' => array(), 988 // No changes from 3.0.10-RC1 to 3.0.10-RC2 989 '3.0.10-RC1' => array(), 990 // No changes from 3.0.10-RC2 to 3.0.10-RC3 991 '3.0.10-RC2' => array(), 992 // No changes from 3.0.10-RC3 to 3.0.10 993 '3.0.10-RC3' => array(), 994 // No changes from 3.0.10 to 3.0.11-RC1 995 '3.0.10' => array(), 996 // Changes from 3.0.11-RC1 to 3.0.11-RC2 997 '3.0.11-RC1' => array( 998 'add_columns' => array( 999 PROFILE_FIELDS_TABLE => array( 1000 'field_show_novalue' => array('BOOL', 0), 1001 ), 1002 ), 1003 ), 1004 // No changes from 3.0.11-RC2 to 3.0.11 1005 '3.0.11-RC2' => array(), 1006 // No changes from 3.0.11 to 3.0.12-RC1 1007 '3.0.11' => array(), 1008 // No changes from 3.0.12-RC1 to 3.0.12-RC2 1009 '3.0.12-RC1' => array(), 1010 // No changes from 3.0.12-RC2 to 3.0.12-RC3 1011 '3.0.12-RC2' => array(), 1012 // No changes from 3.0.12-RC3 to 3.0.12 1013 '3.0.12-RC3' => array(), 1014 1015 /** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.13-RC1 */ 1016 ); 1017 } 1018 1019 /**************************************************************************** 1020 * ADD YOUR DATABASE DATA CHANGES HERE * 1021 * REMEMBER: You NEED to enter a schema array above and a data array here, * 1022 * even if both or one of them are empty. * 1023 *****************************************************************************/ 1024 function change_database_data(&$no_updates, $version) 1025 { 1026 global $db, $db_tools, $errored, $error_ary, $config, $table_prefix, $phpbb_root_path, $phpEx; 1027 1028 switch ($version) 1029 { 1030 case '3.0.0': 1031 1032 $sql = 'UPDATE ' . TOPICS_TABLE . " 1033 SET topic_last_view_time = topic_last_post_time 1034 WHERE topic_last_view_time = 0"; 1035 _sql($sql, $errored, $error_ary); 1036 1037 // Update smiley sizes 1038 $smileys = array('icon_e_surprised.gif', 'icon_eek.gif', 'icon_cool.gif', 'icon_lol.gif', 'icon_mad.gif', 'icon_razz.gif', 'icon_redface.gif', 'icon_cry.gif', 'icon_evil.gif', 'icon_twisted.gif', 'icon_rolleyes.gif', 'icon_exclaim.gif', 'icon_question.gif', 'icon_idea.gif', 'icon_arrow.gif', 'icon_neutral.gif', 'icon_mrgreen.gif', 'icon_e_ugeek.gif'); 1039 1040 foreach ($smileys as $smiley) 1041 { 1042 if (file_exists($phpbb_root_path . 'images/smilies/' . $smiley)) 1043 { 1044 list($width, $height) = getimagesize($phpbb_root_path . 'images/smilies/' . $smiley); 1045 1046 $sql = 'UPDATE ' . SMILIES_TABLE . ' 1047 SET smiley_width = ' . $width . ', smiley_height = ' . $height . " 1048 WHERE smiley_url = '" . $db->sql_escape($smiley) . "'"; 1049 1050 _sql($sql, $errored, $error_ary); 1051 } 1052 } 1053 1054 $no_updates = false; 1055 break; 1056 1057 // No changes from 3.0.1-RC1 to 3.0.1 1058 case '3.0.1-RC1': 1059 break; 1060 1061 // changes from 3.0.1 to 3.0.2-RC1 1062 case '3.0.1': 1063 1064 set_config('referer_validation', '1'); 1065 set_config('check_attachment_content', '1'); 1066 set_config('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title'); 1067 1068 $no_updates = false; 1069 break; 1070 1071 // No changes from 3.0.2-RC1 to 3.0.2-RC2 1072 case '3.0.2-RC1': 1073 break; 1074 1075 // No changes from 3.0.2-RC2 to 3.0.2 1076 case '3.0.2-RC2': 1077 break; 1078 1079 // Changes from 3.0.2 to 3.0.3-RC1 1080 case '3.0.2': 1081 set_config('enable_queue_trigger', '0'); 1082 set_config('queue_trigger_posts', '3'); 1083 1084 set_config('pm_max_recipients', '0'); 1085 1086 // Set maximum number of recipients for the registered users, bots, guests group 1087 $sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5 1088 WHERE ' . $db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS')); 1089 _sql($sql, $errored, $error_ary); 1090 1091 // Not prefilling yet 1092 set_config('dbms_version', ''); 1093 1094 // Add new permission u_masspm_group and duplicate settings from u_masspm 1095 include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); 1096 $auth_admin = new auth_admin(); 1097 1098 // Only add the new permission if it does not already exist 1099 if (empty($auth_admin->acl_options['id']['u_masspm_group'])) 1100 { 1101 $auth_admin->acl_add_option(array('global' => array('u_masspm_group'))); 1102 1103 // Now the tricky part, filling the permission 1104 $old_id = $auth_admin->acl_options['id']['u_masspm']; 1105 $new_id = $auth_admin->acl_options['id']['u_masspm_group']; 1106 1107 $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE); 1108 1109 foreach ($tables as $table) 1110 { 1111 $sql = 'SELECT * 1112 FROM ' . $table . ' 1113 WHERE auth_option_id = ' . $old_id; 1114 $result = _sql($sql, $errored, $error_ary); 1115 1116 $sql_ary = array(); 1117 while ($row = $db->sql_fetchrow($result)) 1118 { 1119 $row['auth_option_id'] = $new_id; 1120 $sql_ary[] = $row; 1121 } 1122 $db->sql_freeresult($result); 1123 1124 if (sizeof($sql_ary)) 1125 { 1126 $db->sql_multi_insert($table, $sql_ary); 1127 } 1128 } 1129 1130 // Remove any old permission entries 1131 $auth_admin->acl_clear_prefetch(); 1132 } 1133 1134 /** 1135 * Do not resync post counts here. An admin may do this later from the ACP 1136 $start = 0; 1137 $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000; 1138 1139 $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = 0'; 1140 _sql($sql, $errored, $error_ary); 1141 1142 do 1143 { 1144 $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id 1145 FROM ' . POSTS_TABLE . ' 1146 WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' 1147 AND post_postcount = 1 AND post_approved = 1 1148 GROUP BY poster_id'; 1149 $result = _sql($sql, $errored, $error_ary); 1150 1151 if ($row = $db->sql_fetchrow($result)) 1152 { 1153 do 1154 { 1155 $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}"; 1156 _sql($sql, $errored, $error_ary); 1157 } 1158 while ($row = $db->sql_fetchrow($result)); 1159 1160 $start += $step; 1161 } 1162 else 1163 { 1164 $start = 0; 1165 } 1166 $db->sql_freeresult($result); 1167 } 1168 while ($start); 1169 */ 1170 1171 $sql = 'UPDATE ' . MODULES_TABLE . ' 1172 SET module_auth = \'acl_a_email && cfg_email_enable\' 1173 WHERE module_class = \'acp\' 1174 AND module_basename = \'email\''; 1175 _sql($sql, $errored, $error_ary); 1176 1177 $no_updates = false; 1178 break; 1179 1180 // Changes from 3.0.3-RC1 to 3.0.3 1181 case '3.0.3-RC1': 1182 if ($db->sql_layer == 'oracle') 1183 { 1184 // log_operation is CLOB - but we can change this later 1185 $sql = 'UPDATE ' . LOG_TABLE . " 1186 SET log_operation = 'LOG_DELETE_TOPIC' 1187 WHERE log_operation LIKE 'LOG_TOPIC_DELETED'"; 1188 _sql($sql, $errored, $error_ary); 1189 } 1190 else 1191 { 1192 $sql = 'UPDATE ' . LOG_TABLE . " 1193 SET log_operation = 'LOG_DELETE_TOPIC' 1194 WHERE log_operation = 'LOG_TOPIC_DELETED'"; 1195 _sql($sql, $errored, $error_ary); 1196 } 1197 1198 $no_updates = false; 1199 break; 1200 1201 // Changes from 3.0.3 to 3.0.4-RC1 1202 case '3.0.3': 1203 // Update the Custom Profile Fields based on previous settings to the new format 1204 $sql = 'SELECT field_id, field_required, field_show_on_reg, field_hide 1205 FROM ' . PROFILE_FIELDS_TABLE; 1206 $result = _sql($sql, $errored, $error_ary); 1207 1208 while ($row = $db->sql_fetchrow($result)) 1209 { 1210 $sql_ary = array( 1211 'field_required' => 0, 1212 'field_show_on_reg' => 0, 1213 'field_hide' => 0, 1214 'field_show_profile'=> 0, 1215 ); 1216 1217 if ($row['field_required']) 1218 { 1219 $sql_ary['field_required'] = $sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1; 1220 } 1221 else if ($row['field_show_on_reg']) 1222 { 1223 $sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1; 1224 } 1225 else if ($row['field_hide']) 1226 { 1227 // Only administrators and moderators can see this CPF, if the view is enabled, they can see it, otherwise just admins in the acp_users module 1228 $sql_ary['field_hide'] = 1; 1229 } 1230 else 1231 { 1232 // equivelant to "none", which is the "Display in user control panel" option 1233 $sql_ary['field_show_profile'] = 1; 1234 } 1235 1236 _sql('UPDATE ' . PROFILE_FIELDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE field_id = ' . $row['field_id'], $errored, $error_ary); 1237 } 1238 $no_updates = false; 1239 1240 break; 1241 1242 // Changes from 3.0.4-RC1 to 3.0.4 1243 case '3.0.4-RC1': 1244 break; 1245 1246 // Changes from 3.0.4 to 3.0.5-RC1 1247 case '3.0.4': 1248 1249 // Captcha config variables 1250 set_config('captcha_gd_wave', 0); 1251 set_config('captcha_gd_3d_noise', 1); 1252 set_config('captcha_gd_fonts', 1); 1253 set_config('confirm_refresh', 1); 1254 1255 // Maximum number of keywords 1256 set_config('max_num_search_keywords', 10); 1257 1258 // Remove static config var and put it back as dynamic variable 1259 $sql = 'UPDATE ' . CONFIG_TABLE . " 1260 SET is_dynamic = 1 1261 WHERE config_name = 'search_indexing_state'"; 1262 _sql($sql, $errored, $error_ary); 1263 1264 // Hash old MD5 passwords 1265 $sql = 'SELECT user_id, user_password 1266 FROM ' . USERS_TABLE . ' 1267 WHERE user_pass_convert = 1'; 1268 $result = _sql($sql, $errored, $error_ary); 1269 1270 while ($row = $db->sql_fetchrow($result)) 1271 { 1272 if (strlen($row['user_password']) == 32) 1273 { 1274 $sql_ary = array( 1275 'user_password' => phpbb_hash($row['user_password']), 1276 ); 1277 1278 _sql('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $row['user_id'], $errored, $error_ary); 1279 } 1280 } 1281 $db->sql_freeresult($result); 1282 1283 // Adjust bot entry 1284 $sql = 'UPDATE ' . BOTS_TABLE . " 1285 SET bot_agent = 'ichiro/' 1286 WHERE bot_agent = 'ichiro/2'"; 1287 _sql($sql, $errored, $error_ary); 1288 1289 1290 // Before we are able to add a unique key to auth_option, we need to remove duplicate entries 1291 1292 // We get duplicate entries first 1293 $sql = 'SELECT auth_option 1294 FROM ' . ACL_OPTIONS_TABLE . ' 1295 GROUP BY auth_option 1296 HAVING COUNT(*) >= 2'; 1297 $result = $db->sql_query($sql); 1298 1299 $auth_options = array(); 1300 while ($row = $db->sql_fetchrow($result)) 1301 { 1302 $auth_options[] = $row['auth_option']; 1303 } 1304 $db->sql_freeresult($result); 1305 1306 // Remove specific auth options 1307 if (!empty($auth_options)) 1308 { 1309 foreach ($auth_options as $option) 1310 { 1311 // Select auth_option_ids... the largest id will be preserved 1312 $sql = 'SELECT auth_option_id 1313 FROM ' . ACL_OPTIONS_TABLE . " 1314 WHERE auth_option = '" . $db->sql_escape($option) . "' 1315 ORDER BY auth_option_id DESC"; 1316 // sql_query_limit not possible here, due to bug in postgresql layer 1317 $result = $db->sql_query($sql); 1318 1319 // Skip first row, this is our original auth option we want to preserve 1320 $row = $db->sql_fetchrow($result); 1321 1322 while ($row = $db->sql_fetchrow($result)) 1323 { 1324 // Ok, remove this auth option... 1325 _sql('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); 1326 _sql('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); 1327 _sql('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); 1328 _sql('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id'], $errored, $error_ary); 1329 } 1330 $db->sql_freeresult($result); 1331 } 1332 } 1333 1334 // Now make auth_option UNIQUE, by dropping the old index and adding a UNIQUE one. 1335 $changes = array( 1336 'drop_keys' => array( 1337 ACL_OPTIONS_TABLE => array('auth_option'), 1338 ), 1339 ); 1340 1341 $statements = $db_tools->perform_schema_changes($changes); 1342 1343 foreach ($statements as $sql) 1344 { 1345 _sql($sql, $errored, $error_ary); 1346 } 1347 1348 $changes = array( 1349 'add_unique_index' => array( 1350 ACL_OPTIONS_TABLE => array( 1351 'auth_option' => array('auth_option'), 1352 ), 1353 ), 1354 ); 1355 1356 $statements = $db_tools->perform_schema_changes($changes); 1357 1358 foreach ($statements as $sql) 1359 { 1360 _sql($sql, $errored, $error_ary); 1361 } 1362 1363 $no_updates = false; 1364 1365 break; 1366 1367 // No changes from 3.0.5-RC1 to 3.0.5 1368 case '3.0.5-RC1': 1369 break; 1370 1371 // Changes from 3.0.5 to 3.0.6-RC1 1372 case '3.0.5': 1373 // Let's see if the GD Captcha can be enabled... we simply look for what *is* enabled... 1374 if (!empty($config['captcha_gd']) && !isset($config['captcha_plugin'])) 1375 { 1376 set_config('captcha_plugin', 'phpbb_captcha_gd'); 1377 } 1378 else if (!isset($config['captcha_plugin'])) 1379 { 1380 set_config('captcha_plugin', 'phpbb_captcha_nogd'); 1381 } 1382 1383 // Entries for the Feed Feature 1384 set_config('feed_enable', '0'); 1385 set_config('feed_limit', '10'); 1386 1387 set_config('feed_overall_forums', '1'); 1388 set_config('feed_overall_forums_limit', '15'); 1389 1390 set_config('feed_overall_topics', '0'); 1391 set_config('feed_overall_topics_limit', '15'); 1392 1393 set_config('feed_forum', '1'); 1394 set_config('feed_topic', '1'); 1395 set_config('feed_item_statistics', '1'); 1396 1397 // Entries for smiley pagination 1398 set_config('smilies_per_page', '50'); 1399 1400 // Entry for reporting PMs 1401 set_config('allow_pm_report', '1'); 1402 1403 // Install modules 1404 $modules_to_install = array( 1405 'feed' => array( 1406 'base' => 'board', 1407 'class' => 'acp', 1408 'title' => 'ACP_FEED_SETTINGS', 1409 'auth' => 'acl_a_board', 1410 'cat' => 'ACP_BOARD_CONFIGURATION', 1411 'after' => array('signature', 'ACP_SIGNATURE_SETTINGS') 1412 ), 1413 'warnings' => array( 1414 'base' => 'users', 1415 'class' => 'acp', 1416 'title' => 'ACP_USER_WARNINGS', 1417 'auth' => 'acl_a_user', 1418 'display' => 0, 1419 'cat' => 'ACP_CAT_USERS', 1420 'after' => array('feedback', 'ACP_USER_FEEDBACK') 1421 ), 1422 'send_statistics' => array( 1423 'base' => 'send_statistics', 1424 'class' => 'acp', 1425 'title' => 'ACP_SEND_STATISTICS', 1426 'auth' => 'acl_a_server', 1427 'cat' => 'ACP_SERVER_CONFIGURATION' 1428 ), 1429 'setting_forum_copy' => array( 1430 'base' => 'permissions', 1431 'class' => 'acp', 1432 'title' => 'ACP_FORUM_PERMISSIONS_COPY', 1433 'auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', 1434 'cat' => 'ACP_FORUM_BASED_PERMISSIONS', 1435 'after' => array('setting_forum_local', 'ACP_FORUM_PERMISSIONS') 1436 ), 1437 'pm_reports' => array( 1438 'base' => 'pm_reports', 1439 'class' => 'mcp', 1440 'title' => 'MCP_PM_REPORTS_OPEN', 1441 'auth' => 'aclf_m_report', 1442 'cat' => 'MCP_REPORTS' 1443 ), 1444 'pm_reports_closed' => array( 1445 'base' => 'pm_reports', 1446 'class' => 'mcp', 1447 'title' => 'MCP_PM_REPORTS_CLOSED', 1448 'auth' => 'aclf_m_report', 1449 'cat' => 'MCP_REPORTS' 1450 ), 1451 'pm_report_details' => array( 1452 'base' => 'pm_reports', 1453 'class' => 'mcp', 1454 'title' => 'MCP_PM_REPORT_DETAILS', 1455 'auth' => 'aclf_m_report', 1456 'cat' => 'MCP_REPORTS' 1457 ), 1458 ); 1459 1460 _add_modules($modules_to_install); 1461 1462 // Add newly_registered group... but check if it already exists (we always supported running the updater on any schema) 1463 $sql = 'SELECT group_id 1464 FROM ' . GROUPS_TABLE . " 1465 WHERE group_name = 'NEWLY_REGISTERED'"; 1466 $result = $db->sql_query($sql); 1467 $group_id = (int) $db->sql_fetchfield('group_id'); 1468 $db->sql_freeresult($result); 1469 1470 if (!$group_id) 1471 { 1472 $sql = 'INSERT INTO ' . GROUPS_TABLE . " (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5)"; 1473 _sql($sql, $errored, $error_ary); 1474 1475 $group_id = $db->sql_nextid(); 1476 } 1477 1478 // Insert new user role... at the end of the chain 1479 $sql = 'SELECT role_id 1480 FROM ' . ACL_ROLES_TABLE . " 1481 WHERE role_name = 'ROLE_USER_NEW_MEMBER' 1482 AND role_type = 'u_'"; 1483 $result = $db->sql_query($sql); 1484 $u_role = (int) $db->sql_fetchfield('role_id'); 1485 $db->sql_freeresult($result); 1486 1487 if (!$u_role) 1488 { 1489 $sql = 'SELECT MAX(role_order) as max_order_id 1490 FROM ' . ACL_ROLES_TABLE . " 1491 WHERE role_type = 'u_'"; 1492 $result = $db->sql_query($sql); 1493 $next_order_id = (int) $db->sql_fetchfield('max_order_id'); 1494 $db->sql_freeresult($result); 1495 1496 $next_order_id++; 1497 1498 $sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', $next_order_id)"; 1499 _sql($sql, $errored, $error_ary); 1500 $u_role = $db->sql_nextid(); 1501 1502 if (!$errored) 1503 { 1504 // Now add the correct data to the roles... 1505 // The standard role says that new users are not able to send a PM, Mass PM, are not able to PM groups 1506 $sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $u_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group')"; 1507 _sql($sql, $errored, $error_ary); 1508 1509 // Add user role to group 1510 $sql = 'INSERT INTO ' . ACL_GROUPS_TABLE . " (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES ($group_id, 0, 0, $u_role, 0)"; 1511 _sql($sql, $errored, $error_ary); 1512 } 1513 } 1514 1515 // Insert new forum role 1516 $sql = 'SELECT role_id 1517 FROM ' . ACL_ROLES_TABLE . " 1518 WHERE role_name = 'ROLE_FORUM_NEW_MEMBER' 1519 AND role_type = 'f_'"; 1520 $result = $db->sql_query($sql); 1521 $f_role = (int) $db->sql_fetchfield('role_id'); 1522 $db->sql_freeresult($result); 1523 1524 if (!$f_role) 1525 { 1526 $sql = 'SELECT MAX(role_order) as max_order_id 1527 FROM ' . ACL_ROLES_TABLE . " 1528 WHERE role_type = 'f_'"; 1529 $result = $db->sql_query($sql); 1530 $next_order_id = (int) $db->sql_fetchfield('max_order_id'); 1531 $db->sql_freeresult($result); 1532 1533 $next_order_id++; 1534 1535 $sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', $next_order_id)"; 1536 _sql($sql, $errored, $error_ary); 1537 $f_role = $db->sql_nextid(); 1538 1539 if (!$errored) 1540 { 1541 $sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $f_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove')"; 1542 _sql($sql, $errored, $error_ary); 1543 } 1544 } 1545 1546 // Set every members user_new column to 0 (old users) only if there is no one yet (this makes sure we do not execute this more than once) 1547 $sql = 'SELECT 1 1548 FROM ' . USERS_TABLE . ' 1549 WHERE user_new = 0'; 1550 $result = $db->sql_query_limit($sql, 1); 1551 $row = $db->sql_fetchrow($result); 1552 $db->sql_freeresult($result); 1553 1554 if (!$row) 1555 { 1556 $sql = 'UPDATE ' . USERS_TABLE . ' SET user_new = 0'; 1557 _sql($sql, $errored, $error_ary); 1558 } 1559 1560 // Newly registered users limit 1561 if (!isset($config['new_member_post_limit'])) 1562 { 1563 set_config('new_member_post_limit', (!empty($config['enable_queue_trigger'])) ? $config['queue_trigger_posts'] : 0); 1564 } 1565 1566 if (!isset($config['new_member_group_default'])) 1567 { 1568 set_config('new_member_group_default', 0); 1569 } 1570 1571 // To mimick the old "feature" we will assign the forum role to every forum, regardless of the setting (this makes sure there are no "this does not work!!!! YUO!!!" posts... 1572 // Check if the role is already assigned... 1573 $sql = 'SELECT forum_id 1574 FROM ' . ACL_GROUPS_TABLE . ' 1575 WHERE group_id = ' . $group_id . ' 1576 AND auth_role_id = ' . $f_role; 1577 $result = $db->sql_query($sql); 1578 $is_options = (int) $db->sql_fetchfield('forum_id'); 1579 $db->sql_freeresult($result); 1580 1581 // Not assigned at all... :/ 1582 if (!$is_options) 1583 { 1584 // Get postable forums 1585 $sql = 'SELECT forum_id 1586 FROM ' . FORUMS_TABLE . ' 1587 WHERE forum_type != ' . FORUM_LINK; 1588 $result = $db->sql_query($sql); 1589 1590 while ($row = $db->sql_fetchrow($result)) 1591 { 1592 _sql('INSERT INTO ' . ACL_GROUPS_TABLE . ' (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (' . $group_id . ', ' . (int) $row['forum_id'] . ', 0, ' . $f_role . ', 0)', $errored, $error_ary); 1593 } 1594 $db->sql_freeresult($result); 1595 } 1596 1597 // Clear permissions... 1598 include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); 1599 $auth_admin = new auth_admin(); 1600 $auth_admin->acl_clear_prefetch(); 1601 1602 if (!isset($config['allow_avatar'])) 1603 { 1604 if ($config['allow_avatar_upload'] || $config['allow_avatar_local'] || $config['allow_avatar_remote']) 1605 { 1606 set_config('allow_avatar', '1'); 1607 } 1608 else 1609 { 1610 set_config('allow_avatar', '0'); 1611 } 1612 } 1613 1614 if (!isset($config['allow_avatar_remote_upload'])) 1615 { 1616 if ($config['allow_avatar_remote'] && $config['allow_avatar_upload']) 1617 { 1618 set_config('allow_avatar_remote_upload', '1'); 1619 } 1620 else 1621 { 1622 set_config('allow_avatar_remote_upload', '0'); 1623 } 1624 } 1625 1626 // Minimum number of characters 1627 if (!isset($config['min_post_chars'])) 1628 { 1629 set_config('min_post_chars', '1'); 1630 } 1631 1632 if (!isset($config['allow_quick_reply'])) 1633 { 1634 set_config('allow_quick_reply', '1'); 1635 } 1636 1637 // Set every members user_options column to enable 1638 // bbcode, smilies and URLs for signatures by default 1639 $sql = 'SELECT user_options 1640 FROM ' . USERS_TABLE . ' 1641 WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; 1642 $result = $db->sql_query_limit($sql, 1); 1643 $user_option = (int) $db->sql_fetchfield('user_options'); 1644 $db->sql_freeresult($result); 1645 1646 // Check if we already updated the database by checking bit 15 which we used to store the sig_bbcode option 1647 if (!($user_option & 1 << 15)) 1648 { 1649 // 229376 is the added value to enable all three signature options 1650 $sql = 'UPDATE ' . USERS_TABLE . ' SET user_options = user_options + 229376'; 1651 _sql($sql, $errored, $error_ary); 1652 } 1653 1654 if (!isset($config['delete_time'])) 1655 { 1656 set_config('delete_time', $config['edit_time']); 1657 } 1658 1659 $no_updates = false; 1660 break; 1661 1662 // No changes from 3.0.6-RC1 to 3.0.6-RC2 1663 case '3.0.6-RC1': 1664 break; 1665 1666 // Changes from 3.0.6-RC2 to 3.0.6-RC3 1667 case '3.0.6-RC2': 1668 1669 // Update the Custom Profile Fields based on previous settings to the new format 1670 $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . ' 1671 SET field_show_on_vt = 1 1672 WHERE field_hide = 0 1673 AND (field_required = 1 OR field_show_on_reg = 1 OR field_show_profile = 1)'; 1674 _sql($sql, $errored, $error_ary); 1675 $no_updates = false; 1676 1677 break; 1678 1679 // No changes from 3.0.6-RC3 to 3.0.6-RC4 1680 case '3.0.6-RC3': 1681 break; 1682 1683 // No changes from 3.0.6-RC4 to 3.0.6 1684 case '3.0.6-RC4': 1685 break; 1686 1687 // Changes from 3.0.6 to 3.0.7-RC1 1688 case '3.0.6': 1689 1690 // ATOM Feeds 1691 set_config('feed_overall', '1'); 1692 set_config('feed_http_auth', '0'); 1693 set_config('feed_limit_post', (string) (isset($config['feed_limit']) ? (int) $config['feed_limit'] : 15)); 1694 set_config('feed_limit_topic', (string) (isset($config['feed_overall_topics_limit']) ? (int) $config['feed_overall_topics_limit'] : 10)); 1695 set_config('feed_topics_new', (!empty($config['feed_overall_topics']) ? '1' : '0')); 1696 set_config('feed_topics_active', (!empty($config['feed_overall_topics']) ? '1' : '0')); 1697 1698 // Delete all text-templates from the template_data 1699 $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' 1700 WHERE template_filename ' . $db->sql_like_expression($db->any_char . '.txt'); 1701 _sql($sql, $errored, $error_ary); 1702 1703 $no_updates = false; 1704 break; 1705 1706 // Changes from 3.0.7-RC1 to 3.0.7-RC2 1707 case '3.0.7-RC1': 1708 1709 $sql = 'SELECT user_id, user_email, user_email_hash 1710 FROM ' . USERS_TABLE . ' 1711 WHERE user_type <> ' . USER_IGNORE . " 1712 AND user_email <> ''"; 1713 $result = $db->sql_query($sql); 1714 1715 $i = 0; 1716 while ($row = $db->sql_fetchrow($result)) 1717 { 1718 // Snapshot of the phpbb_email_hash() function 1719 // We cannot call it directly because the auto updater updates the DB first. :/ 1720 $user_email_hash = sprintf('%u', crc32(strtolower($row['user_email']))) . strlen($row['user_email']); 1721 1722 if ($user_email_hash != $row['user_email_hash']) 1723 { 1724 $sql_ary = array( 1725 'user_email_hash' => $user_email_hash, 1726 ); 1727 1728 $sql = 'UPDATE ' . USERS_TABLE . ' 1729 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 1730 WHERE user_id = ' . (int) $row['user_id']; 1731 _sql($sql, $errored, $error_ary, ($i % 100 == 0)); 1732 1733 ++$i; 1734 } 1735 } 1736 $db->sql_freeresult($result); 1737 1738 $no_updates = false; 1739 1740 break; 1741 1742 // No changes from 3.0.7-RC2 to 3.0.7 1743 case '3.0.7-RC2': 1744 break; 1745 1746 // No changes from 3.0.7 to 3.0.7-PL1 1747 case '3.0.7': 1748 break; 1749 1750 // Changes from 3.0.7-PL1 to 3.0.8-RC1 1751 case '3.0.7-PL1': 1752 // Update file extension group names to use language strings. 1753 $sql = 'SELECT lang_dir 1754 FROM ' . LANG_TABLE; 1755 $result = $db->sql_query($sql); 1756 1757 $extension_groups_updated = array(); 1758 while ($lang_dir = $db->sql_fetchfield('lang_dir')) 1759 { 1760 $lang_dir = basename($lang_dir); 1761 1762 // The language strings we need are either in language/.../acp/attachments.php 1763 // in the update package if we're updating to 3.0.8-RC1 or later, 1764 // or they are in language/.../install.php when we're updating from 3.0.7-PL1 or earlier. 1765 // On an already updated board, they can also already be in language/.../acp/attachments.php 1766 // in the board root. 1767 $lang_files = array( 1768 "{$phpbb_root_path}install/update/new/language/$lang_dir/acp/attachments.$phpEx", 1769 "{$phpbb_root_path}language/$lang_dir/install.$phpEx", 1770 "{$phpbb_root_path}language/$lang_dir/acp/attachments.$phpEx", 1771 ); 1772 1773 foreach ($lang_files as $lang_file) 1774 { 1775 if (!file_exists($lang_file)) 1776 { 1777 continue; 1778 } 1779 1780 $lang = array(); 1781 include($lang_file); 1782 1783 foreach($lang as $lang_key => $lang_val) 1784 { 1785 if (isset($extension_groups_updated[$lang_key]) || strpos($lang_key, 'EXT_GROUP_') !== 0) 1786 { 1787 continue; 1788 } 1789 1790 $sql_ary = array( 1791 'group_name' => substr($lang_key, 10), // Strip off 'EXT_GROUP_' 1792 ); 1793 1794 $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' 1795 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " 1796 WHERE group_name = '" . $db->sql_escape($lang_val) . "'"; 1797 _sql($sql, $errored, $error_ary); 1798 1799 $extension_groups_updated[$lang_key] = true; 1800 } 1801 } 1802 } 1803 $db->sql_freeresult($result); 1804 1805 // Install modules 1806 $modules_to_install = array( 1807 'post' => array( 1808 'base' => 'board', 1809 'class' => 'acp', 1810 'title' => 'ACP_POST_SETTINGS', 1811 'auth' => 'acl_a_board', 1812 'cat' => 'ACP_MESSAGES', 1813 'after' => array('message', 'ACP_MESSAGE_SETTINGS') 1814 ), 1815 ); 1816 1817 _add_modules($modules_to_install); 1818 1819 // update 1820 $sql = 'UPDATE ' . MODULES_TABLE . ' 1821 SET module_auth = \'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)\' 1822 WHERE module_class = \'ucp\' 1823 AND module_basename = \'profile\' 1824 AND module_mode = \'avatar\''; 1825 _sql($sql, $errored, $error_ary); 1826 1827 // add Bing Bot 1828 $bot_name = 'Bing [Bot]'; 1829 $bot_name_clean = utf8_clean_string($bot_name); 1830 1831 $sql = 'SELECT user_id 1832 FROM ' . USERS_TABLE . " 1833 WHERE username_clean = '" . $db->sql_escape($bot_name_clean) . "'"; 1834 $result = $db->sql_query($sql); 1835 $bing_already_added = (bool) $db->sql_fetchfield('user_id'); 1836 $db->sql_freeresult($result); 1837 1838 if (!$bing_already_added) 1839 { 1840 $bot_agent = 'bingbot/'; 1841 $bot_ip = ''; 1842 $sql = 'SELECT group_id, group_colour 1843 FROM ' . GROUPS_TABLE . " 1844 WHERE group_name = 'BOTS'"; 1845 $result = $db->sql_query($sql); 1846 $group_row = $db->sql_fetchrow($result); 1847 $db->sql_freeresult($result); 1848 1849 if (!$group_row) 1850 { 1851 // default fallback, should never get here 1852 $group_row['group_id'] = 6; 1853 $group_row['group_colour'] = '9E8DA7'; 1854 } 1855 1856 if (!function_exists('user_add')) 1857 { 1858 include($phpbb_root_path . 'includes/functions_user.' . $phpEx); 1859 } 1860 1861 $user_row = array( 1862 'user_type' => USER_IGNORE, 1863 'group_id' => $group_row['group_id'], 1864 'username' => $bot_name, 1865 'user_regdate' => time(), 1866 'user_password' => '', 1867 'user_colour' => $group_row['group_colour'], 1868 'user_email' => '', 1869 'user_lang' => $config['default_lang'], 1870 'user_style' => $config['default_style'], 1871 'user_timezone' => 0, 1872 'user_dateformat' => $config['default_dateformat'], 1873 'user_allow_massemail' => 0, 1874 ); 1875 1876 $user_id = user_add($user_row); 1877 1878 $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( 1879 'bot_active' => 1, 1880 'bot_name' => (string) $bot_name, 1881 'user_id' => (int) $user_id, 1882 'bot_agent' => (string) $bot_agent, 1883 'bot_ip' => (string) $bot_ip, 1884 )); 1885 1886 _sql($sql, $errored, $error_ary); 1887 } 1888 // end Bing Bot addition 1889 1890 // Delete shadow topics pointing to not existing topics 1891 $batch_size = 500; 1892 1893 // Set of affected forums we have to resync 1894 $sync_forum_ids = array(); 1895 1896 do 1897 { 1898 $sql_array = array( 1899 'SELECT' => 't1.topic_id, t1.forum_id', 1900 'FROM' => array( 1901 TOPICS_TABLE => 't1', 1902 ), 1903 'LEFT_JOIN' => array( 1904 array( 1905 'FROM' => array(TOPICS_TABLE => 't2'), 1906 'ON' => 't1.topic_moved_id = t2.topic_id', 1907 ), 1908 ), 1909 'WHERE' => 't1.topic_moved_id <> 0 1910 AND t2.topic_id IS NULL', 1911 ); 1912 $sql = $db->sql_build_query('SELECT', $sql_array); 1913 $result = $db->sql_query_limit($sql, $batch_size); 1914 1915 $topic_ids = array(); 1916 while ($row = $db->sql_fetchrow($result)) 1917 { 1918 $topic_ids[] = (int) $row['topic_id']; 1919 1920 $sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id']; 1921 } 1922 $db->sql_freeresult($result); 1923 1924 if (!empty($topic_ids)) 1925 { 1926 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 1927 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 1928 $db->sql_query($sql); 1929 } 1930 } 1931 while (sizeof($topic_ids) == $batch_size); 1932 1933 // Sync the forums we have deleted shadow topics from. 1934 sync('forum', 'forum_id', $sync_forum_ids, true, true); 1935 1936 // Unread posts search load switch 1937 set_config('load_unreads_search', '1'); 1938 1939 // Reduce queue interval to 60 seconds, email package size to 20 1940 if ($config['queue_interval'] == 600) 1941 { 1942 set_config('queue_interval', '60'); 1943 } 1944 1945 if ($config['email_package_size'] == 50) 1946 { 1947 set_config('email_package_size', '20'); 1948 } 1949 1950 $no_updates = false; 1951 break; 1952 1953 // No changes from 3.0.8-RC1 to 3.0.8 1954 case '3.0.8-RC1': 1955 break; 1956 1957 // Changes from 3.0.8 to 3.0.9-RC1 1958 case '3.0.8': 1959 set_config('ip_login_limit_max', '50'); 1960 set_config('ip_login_limit_time', '21600'); 1961 set_config('ip_login_limit_use_forwarded', '0'); 1962 1963 // Update file extension group names to use language strings, again. 1964 $sql = 'SELECT group_id, group_name 1965 FROM ' . EXTENSION_GROUPS_TABLE . ' 1966 WHERE group_name ' . $db->sql_like_expression('EXT_GROUP_' . $db->any_char); 1967 $result = $db->sql_query($sql); 1968 1969 while ($row = $db->sql_fetchrow($result)) 1970 { 1971 $sql_ary = array( 1972 'group_name' => substr($row['group_name'], 10), // Strip off 'EXT_GROUP_' 1973 ); 1974 1975 $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' 1976 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 1977 WHERE group_id = ' . $row['group_id']; 1978 _sql($sql, $errored, $error_ary); 1979 } 1980 $db->sql_freeresult($result); 1981 1982 /* 1983 * Due to a bug, vanilla phpbb could not create captcha tables 1984 * in 3.0.8 on firebird. It was possible for board administrators 1985 * to adjust the code to work. If code was manually adjusted by 1986 * board administrators, index names would not be the same as 1987 * what 3.0.9 and newer expect. This code fragment drops captcha 1988 * tables, destroying all entered Q&A captcha configuration, such 1989 * that when Q&A is configured next the respective tables will be 1990 * created with correct index names. 1991 * 1992 * If you wish to preserve your Q&A captcha configuration, you can 1993 * manually rename indexes to the currently expected name: 1994 * phpbb_captcha_questions_lang_iso => phpbb_captcha_questions_lang 1995 * phpbb_captcha_answers_question_id => phpbb_captcha_answers_qid 1996 * 1997 * Again, this needs to be done only if a board was manually modified 1998 * to fix broken captcha code. 1999 * 2000 if ($db_tools->sql_layer == 'firebird') 2001 { 2002 $changes = array( 2003 'drop_tables' => array( 2004 $table_prefix . 'captcha_questions', 2005 $table_prefix . 'captcha_answers', 2006 $table_prefix . 'qa_confirm', 2007 ), 2008 ); 2009 $statements = $db_tools->perform_schema_changes($changes); 2010 2011 foreach ($statements as $sql) 2012 { 2013 _sql($sql, $errored, $error_ary); 2014 } 2015 } 2016 */ 2017 2018 $no_updates = false; 2019 break; 2020 2021 // No changes from 3.0.9-RC1 to 3.0.9-RC2 2022 case '3.0.9-RC1': 2023 break; 2024 2025 // No changes from 3.0.9-RC2 to 3.0.9-RC3 2026 case '3.0.9-RC2': 2027 break; 2028 2029 // No changes from 3.0.9-RC3 to 3.0.9-RC4 2030 case '3.0.9-RC3': 2031 break; 2032 2033 // No changes from 3.0.9-RC4 to 3.0.9 2034 case '3.0.9-RC4': 2035 break; 2036 2037 // Changes from 3.0.9 to 3.0.10-RC1 2038 case '3.0.9': 2039 if (!isset($config['email_max_chunk_size'])) 2040 { 2041 set_config('email_max_chunk_size', '50'); 2042 } 2043 2044 $no_updates = false; 2045 break; 2046 2047 // No changes from 3.0.10-RC1 to 3.0.10-RC2 2048 case '3.0.10-RC1': 2049 break; 2050 2051 // No changes from 3.0.10-RC2 to 3.0.10-RC3 2052 case '3.0.10-RC2': 2053 break; 2054 2055 // No changes from 3.0.10-RC3 to 3.0.10 2056 case '3.0.10-RC3': 2057 break; 2058 2059 // Changes from 3.0.10 to 3.0.11-RC1 2060 case '3.0.10': 2061 // Updates users having current style a deactivated one 2062 $sql = 'SELECT style_id 2063 FROM ' . STYLES_TABLE . ' 2064 WHERE style_active = 0'; 2065 $result = $db->sql_query($sql); 2066 2067 $deactivated_style_ids = array(); 2068 while ($style_id = $db->sql_fetchfield('style_id', false, $result)) 2069 { 2070 $deactivated_style_ids[] = (int) $style_id; 2071 } 2072 $db->sql_freeresult($result); 2073 2074 if (!empty($deactivated_style_ids)) 2075 { 2076 $sql = 'UPDATE ' . USERS_TABLE . ' 2077 SET user_style = ' . (int) $config['default_style'] .' 2078 WHERE ' . $db->sql_in_set('user_style', $deactivated_style_ids); 2079 _sql($sql, $errored, $error_ary); 2080 } 2081 2082 // Delete orphan private messages 2083 $batch_size = 500; 2084 2085 $sql_array = array( 2086 'SELECT' => 'p.msg_id', 2087 'FROM' => array( 2088 PRIVMSGS_TABLE => 'p', 2089 ), 2090 'LEFT_JOIN' => array( 2091 array( 2092 'FROM' => array(PRIVMSGS_TO_TABLE => 't'), 2093 'ON' => 'p.msg_id = t.msg_id', 2094 ), 2095 ), 2096 'WHERE' => 't.user_id IS NULL', 2097 ); 2098 $sql = $db->sql_build_query('SELECT', $sql_array); 2099 2100 do 2101 { 2102 $result = $db->sql_query_limit($sql, $batch_size); 2103 2104 $delete_pms = array(); 2105 while ($row = $db->sql_fetchrow($result)) 2106 { 2107 $delete_pms[] = (int) $row['msg_id']; 2108 } 2109 $db->sql_freeresult($result); 2110 2111 if (!empty($delete_pms)) 2112 { 2113 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' 2114 WHERE ' . $db->sql_in_set('msg_id', $delete_pms); 2115 _sql($sql, $errored, $error_ary); 2116 } 2117 } 2118 while (sizeof($delete_pms) == $batch_size); 2119 2120 $no_updates = false; 2121 break; 2122 2123 // No changes from 3.0.11-RC1 to 3.0.11-RC2 2124 case '3.0.11-RC1': 2125 break; 2126 2127 // No changes from 3.0.11-RC2 to 3.0.11 2128 case '3.0.11-RC2': 2129 break; 2130 2131 // Changes from 3.0.11 to 3.0.12-RC1 2132 case '3.0.11': 2133 $sql = 'UPDATE ' . MODULES_TABLE . ' 2134 SET module_auth = \'acl_u_sig\' 2135 WHERE module_class = \'ucp\' 2136 AND module_basename = \'profile\' 2137 AND module_mode = \'signature\''; 2138 _sql($sql, $errored, $error_ary); 2139 2140 // Update bots 2141 if (!function_exists('user_delete')) 2142 { 2143 include($phpbb_root_path . 'includes/functions_user.' . $phpEx); 2144 } 2145 2146 $bots_updates = array( 2147 // Bot Deletions 2148 'NG-Search [Bot]' => false, 2149 'Nutch/CVS [Bot]' => false, 2150 'OmniExplorer [Bot]' => false, 2151 'Seekport [Bot]' => false, 2152 'Synoo [Bot]' => false, 2153 'WiseNut [Bot]' => false, 2154 2155 // Bot Updates 2156 // Bot name to bot user agent map 2157 'Baidu [Spider]' => 'Baiduspider', 2158 'Exabot [Bot]' => 'Exabot', 2159 'Voyager [Bot]' => 'voyager/', 2160 'W3C [Validator]' => 'W3C_Validator', 2161 ); 2162 2163 foreach ($bots_updates as $bot_name => $bot_agent) 2164 { 2165 $sql = 'SELECT user_id 2166 FROM ' . USERS_TABLE . ' 2167 WHERE user_type = ' . USER_IGNORE . " 2168 AND username_clean = '" . $db->sql_escape(utf8_clean_string($bot_name)) . "'"; 2169 $result = $db->sql_query($sql); 2170 $bot_user_id = (int) $db->sql_fetchfield('user_id'); 2171 $db->sql_freeresult($result); 2172 2173 if ($bot_user_id) 2174 { 2175 if ($bot_agent === false) 2176 { 2177 $sql = 'DELETE FROM ' . BOTS_TABLE . " 2178 WHERE user_id = $bot_user_id"; 2179 _sql($sql, $errored, $error_ary); 2180 2181 user_delete('remove', $bot_user_id); 2182 } 2183 else 2184 { 2185 $sql = 'UPDATE ' . BOTS_TABLE . " 2186 SET bot_agent = '" . $db->sql_escape($bot_agent) . "' 2187 WHERE user_id = $bot_user_id"; 2188 _sql($sql, $errored, $error_ary); 2189 } 2190 } 2191 } 2192 2193 // Disable receiving pms for bots 2194 $sql = 'SELECT user_id 2195 FROM ' . BOTS_TABLE; 2196 $result = $db->sql_query($sql); 2197 2198 $bot_user_ids = array(); 2199 while ($row = $db->sql_fetchrow($result)) 2200 { 2201 $bot_user_ids[] = (int) $row['user_id']; 2202 } 2203 $db->sql_freeresult($result); 2204 2205 if (!empty($bot_user_ids)) 2206 { 2207 $sql = 'UPDATE ' . USERS_TABLE . ' 2208 SET user_allow_pm = 0 2209 WHERE ' . $db->sql_in_set('user_id', $bot_user_ids); 2210 _sql($sql, $errored, $error_ary); 2211 } 2212 2213 /** 2214 * Update BBCodes that currently use the LOCAL_URL tag 2215 * 2216 * To fix http://tracker.phpbb.com/browse/PHPBB3-8319 we changed 2217 * the second_pass_replace value, so that needs updating for existing ones 2218 */ 2219 $sql = 'SELECT * 2220 FROM ' . BBCODES_TABLE . ' 2221 WHERE bbcode_match ' . $db->sql_like_expression($db->any_char . 'LOCAL_URL' . $db->any_char); 2222 $result = $db->sql_query($sql); 2223 2224 while ($row = $db->sql_fetchrow($result)) 2225 { 2226 if (!class_exists('acp_bbcodes')) 2227 { 2228 phpbb_require_updated('includes/acp/acp_bbcodes.' . $phpEx); 2229 } 2230 $bbcode_match = $row['bbcode_match']; 2231 $bbcode_tpl = $row['bbcode_tpl']; 2232 2233 $acp_bbcodes = new acp_bbcodes(); 2234 $sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl); 2235 2236 $sql = 'UPDATE ' . BBCODES_TABLE . ' 2237 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 2238 WHERE bbcode_id = ' . (int) $row['bbcode_id']; 2239 $db->sql_query($sql); 2240 } 2241 $db->sql_freeresult($result); 2242 2243 $no_updates = false; 2244 break; 2245 2246 // No changes from 3.0.12-RC1 to 3.0.12-RC2 2247 case '3.0.12-RC1': 2248 break; 2249 2250 // No changes from 3.0.12-RC2 to 3.0.12-RC3 2251 case '3.0.12-RC2': 2252 break; 2253 2254 // No changes from 3.0.12-RC3 to 3.0.12 2255 case '3.0.12-RC3': 2256 break; 2257 } 2258 } 2259 2260 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |