Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

database_update.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 75.68 KiB


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