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  ?>