Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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

install_convert.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 62.77 KiB


 0001  <?php
 0002  /**
 0003  *
 0004  * This file is part of the phpBB Forum Software package.
 0005  *
 0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
 0007  * @license GNU General Public License, version 2 (GPL-2.0)
 0008  *
 0009  * For full copyright and license information, please see
 0010  * the docs/CREDITS.txt file.
 0011  *
 0012  */
 0013   
 0014  /**
 0015  */
 0016   
 0017  if (!defined('IN_INSTALL'))
 0018  {
 0019      // Someone has tried to access the file direct. This is not a good idea, so exit
 0020      exit;
 0021  }
 0022   
 0023  if (!empty($setmodules))
 0024  {
 0025      $module[] = array(
 0026          'module_type'        => 'install',
 0027          'module_title'        => 'CONVERT',
 0028          'module_filename'    => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
 0029          'module_order'        => 20,
 0030          'module_subs'        => '',
 0031          'module_stages'        => array('INTRO', 'SETTINGS', 'IN_PROGRESS', 'FINAL'),
 0032          'module_reqs'        => ''
 0033      );
 0034  }
 0035   
 0036  /**
 0037  * Class holding all convertor-specific details.
 0038  */
 0039  class convert
 0040  {
 0041      var $options = array();
 0042   
 0043      var $convertor_tag = '';
 0044      var $src_dbms = '';
 0045      var $src_dbhost = '';
 0046      var $src_dbport = '';
 0047      var $src_dbuser = '';
 0048      var $src_dbpasswd = '';
 0049      var $src_dbname = '';
 0050      var $src_table_prefix = '';
 0051   
 0052      var $convertor_data = array();
 0053      var $tables = array();
 0054      var $config_schema = array();
 0055      var $convertor = array();
 0056      var $src_truncate_statement = 'DELETE FROM ';
 0057      var $truncate_statement = 'DELETE FROM ';
 0058   
 0059      var $fulltext_search;
 0060   
 0061      // Batch size, can be adjusted by the conversion file
 0062      // For big boards a value of 6000 seems to be optimal
 0063      var $batch_size = 2000;
 0064      // Number of rows to be inserted at once (extended insert) if supported
 0065      // For installations having enough memory a value of 60 may be good.
 0066      var $num_wait_rows = 20;
 0067   
 0068      // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor.
 0069      var $mysql_convert = false;
 0070   
 0071      var $p_master;
 0072   
 0073      function convert(&$p_master)
 0074      {
 0075          $this->p_master = &$p_master;
 0076      }
 0077  }
 0078   
 0079  /**
 0080  * Convert class for conversions
 0081  */
 0082  class install_convert extends module
 0083  {
 0084      /** @var array */
 0085      protected $lang;
 0086   
 0087      /** @var string */
 0088      protected $language;
 0089   
 0090      /** @var \phpbb\template\template */
 0091      protected $template;
 0092   
 0093      /** @var string */
 0094      protected $phpbb_root_path;
 0095   
 0096      /** @var string */
 0097      protected $php_ext;
 0098   
 0099      /**
 0100      * Variables used while converting, they are accessible from the global variable $convert
 0101      */
 0102      function install_convert(&$p_master)
 0103      {
 0104          $this->p_master = &$p_master;
 0105      }
 0106   
 0107      function main($mode, $sub)
 0108      {
 0109          global $lang, $template, $phpbb_root_path, $phpEx, $cache, $config, $language, $table_prefix;
 0110          global $convert, $request, $phpbb_container, $phpbb_config_php_file;
 0111   
 0112          $this->tpl_name = 'install_convert';
 0113          $this->mode = $mode;
 0114          $this->lang = $lang;
 0115          $this->language = $language;
 0116          $this->template = $template;
 0117          $this->phpbb_root_path = $phpbb_root_path;
 0118          $this->php_ext = $phpEx;
 0119   
 0120          if (!$this->check_phpbb_installed())
 0121          {
 0122              return;
 0123          }
 0124   
 0125          $convert = new convert($this->p_master);
 0126   
 0127          // Enable super globals to prevent issues with the new \phpbb\request\request object
 0128          $request->enable_super_globals();
 0129          // Create a normal container now
 0130          $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
 0131          $phpbb_container = $phpbb_container_builder->get_container();
 0132   
 0133          // Create cache
 0134          $cache = $phpbb_container->get('cache');
 0135   
 0136          switch ($sub)
 0137          {
 0138              case 'intro':
 0139                  extract($phpbb_config_php_file->get_all());
 0140   
 0141                  require($phpbb_root_path . 'includes/constants.' . $phpEx);
 0142                  require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
 0143   
 0144                  $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
 0145   
 0146                  $db = new $dbms();
 0147                  $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
 0148                  unset($dbpasswd);
 0149   
 0150                  // We need to fill the config to let internal functions correctly work
 0151                  $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
 0152                  set_config(null, null, null, $config);
 0153                  set_config_count(null, null, null, $config);
 0154   
 0155                  // Detect if there is already a conversion in progress at this point and offer to resume
 0156                  // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it
 0157                  $new_conversion = request_var('new_conv', 0);
 0158   
 0159                  if ($new_conversion)
 0160                  {
 0161                      $config['convert_progress'] = '';
 0162                      $config['convert_db_server'] = '';
 0163                      $config['convert_db_user'] = '';
 0164                      $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
 0165                          WHERE config_name = 'convert_progress'
 0166                              OR config_name = 'convert_db_server'
 0167                              OR config_name = 'convert_db_user'"
 0168                      );
 0169                  }
 0170   
 0171                  // Let's see if there is a conversion in the works...
 0172                  $options = array();
 0173                  if (!empty($config['convert_progress']) && !empty($config['convert_db_server']) && !empty($config['convert_db_user']) && !empty($config['convert_options']))
 0174                  {
 0175                      $options = unserialize($config['convert_progress']);
 0176                      $options = array_merge($options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
 0177                  }
 0178   
 0179                  // This information should have already been checked once, but do it again for safety
 0180                  if (!empty($options) && !empty($options['tag']) &&
 0181                      isset($options['dbms']) &&
 0182                      isset($options['dbhost']) &&
 0183                      isset($options['dbport']) &&
 0184                      isset($options['dbuser']) &&
 0185                      isset($options['dbpasswd']) &&
 0186                      isset($options['dbname']) &&
 0187                      isset($options['table_prefix']))
 0188                  {
 0189                      $this->page_title = $lang['CONTINUE_CONVERT'];
 0190   
 0191                      $template->assign_vars(array(
 0192                          'TITLE'            => $lang['CONTINUE_CONVERT'],
 0193                          'BODY'            => $lang['CONTINUE_CONVERT_BODY'],
 0194                          'L_NEW'            => $lang['CONVERT_NEW_CONVERSION'],
 0195                          'L_CONTINUE'    => $lang['CONTINUE_OLD_CONVERSION'],
 0196                          'S_CONTINUE'    => true,
 0197   
 0198                          'U_NEW_ACTION'        => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=intro&amp;new_conv=1&amp;language=$language",
 0199                          'U_CONTINUE_ACTION'    => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$options['tag']}{$options['step']}&amp;language=$language",
 0200                      ));
 0201   
 0202                      return;
 0203                  }
 0204   
 0205                  $this->list_convertors($sub);
 0206   
 0207              break;
 0208   
 0209              case 'settings':
 0210                  $this->get_convert_settings($sub);
 0211              break;
 0212   
 0213              case 'in_progress':
 0214                  $this->convert_data($sub);
 0215              break;
 0216   
 0217              case 'final':
 0218                  $this->page_title = $lang['CONVERT_COMPLETE'];
 0219   
 0220                  $template->assign_vars(array(
 0221                      'TITLE'        => $lang['CONVERT_COMPLETE'],
 0222                      'BODY'        => $lang['CONVERT_COMPLETE_EXPLAIN'],
 0223                  ));
 0224   
 0225                  // If we reached this step (conversion completed) we want to purge the cache and log the user out.
 0226                  // This is for making sure the session get not screwed due to the 3.0.x users table being completely new.
 0227                  $cache->purge();
 0228   
 0229                  extract($phpbb_config_php_file->get_all());
 0230   
 0231                  require($phpbb_root_path . 'includes/constants.' . $phpEx);
 0232                  require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
 0233   
 0234                  $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
 0235   
 0236                  $db = new $dbms();
 0237                  $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
 0238                  unset($dbpasswd);
 0239   
 0240                  $sql = 'SELECT config_value
 0241                      FROM ' . CONFIG_TABLE . '
 0242                      WHERE config_name = \'search_type\'';
 0243                  $result = $db->sql_query($sql);
 0244   
 0245                  if ($db->sql_fetchfield('config_value') != 'fulltext_mysql')
 0246                  {
 0247                      $template->assign_vars(array(
 0248                          'S_ERROR_BOX'    => true,
 0249                          'ERROR_TITLE'    => $lang['SEARCH_INDEX_UNCONVERTED'],
 0250                          'ERROR_MSG'        => $lang['SEARCH_INDEX_UNCONVERTED_EXPLAIN'],
 0251                      ));
 0252                  }
 0253   
 0254                  switch ($db->get_sql_layer())
 0255                  {
 0256                      case 'sqlite':
 0257                      case 'sqlite3':
 0258                          $db->sql_query('DELETE FROM ' . SESSIONS_KEYS_TABLE);
 0259                          $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
 0260                      break;
 0261   
 0262                      default:
 0263                          $db->sql_query('TRUNCATE TABLE ' . SESSIONS_KEYS_TABLE);
 0264                          $db->sql_query('TRUNCATE TABLE ' . SESSIONS_TABLE);
 0265                      break;
 0266                  }
 0267   
 0268              break;
 0269          }
 0270      }
 0271   
 0272      /**
 0273      * Check whether phpBB is installed.
 0274      * Assigns error template vars if not installed.
 0275      *
 0276      * @return bool Returns true if phpBB is installed.
 0277      */
 0278      public function check_phpbb_installed()
 0279      {
 0280          if (phpbb_check_installation_exists($this->phpbb_root_path, $this->php_ext))
 0281          {
 0282              return true;
 0283          }
 0284   
 0285          $this->page_title = 'BOARD_NOT_INSTALLED';
 0286          $install_url = append_sid($this->phpbb_root_path . 'install/index.' . $this->php_ext, 'mode=install&amp;language=' . $this->language);
 0287   
 0288          $this->template->assign_vars(array(
 0289              'S_NOT_INSTALLED'        => true,
 0290              'BODY'                    => sprintf($this->lang['BOARD_NOT_INSTALLED_EXPLAIN'], $install_url),
 0291          ));
 0292   
 0293          return false;
 0294      }
 0295   
 0296      /**
 0297      * Generate a list of all available conversion modules
 0298      */
 0299      function list_convertors($sub)
 0300      {
 0301          global $lang, $language, $template, $phpbb_root_path, $phpEx;
 0302   
 0303          $this->page_title = $lang['SUB_INTRO'];
 0304   
 0305          $template->assign_vars(array(
 0306              'TITLE'        => $lang['CONVERT_INTRO'],
 0307              'BODY'        => $lang['CONVERT_INTRO_BODY'],
 0308   
 0309              'L_AUTHOR'                    => $lang['AUTHOR'],
 0310              'L_AVAILABLE_CONVERTORS'    => $lang['AVAILABLE_CONVERTORS'],
 0311              'L_CONVERT'                    => $lang['CONVERT'],
 0312              'L_NO_CONVERTORS'            => $lang['NO_CONVERTORS'],
 0313              'L_OPTIONS'                    => $lang['CONVERT_OPTIONS'],
 0314              'L_SOFTWARE'                => $lang['SOFTWARE'],
 0315              'L_VERSION'                    => $lang['VERSION'],
 0316   
 0317              'S_LIST'    => true,
 0318          ));
 0319   
 0320          $convertors = $sort = array();
 0321          $get_info = true;
 0322   
 0323          $handle = @opendir('./convertors/');
 0324   
 0325          if (!$handle)
 0326          {
 0327              $this->error('Unable to access the convertors directory', __LINE__, __FILE__);
 0328          }
 0329   
 0330          while ($entry = readdir($handle))
 0331          {
 0332              if (preg_match('/^convert_([a-z0-9_]+).' . $phpEx . '$/i', $entry, $m))
 0333              {
 0334                  include('./convertors/' . $entry);
 0335                  if (isset($convertor_data))
 0336                  {
 0337                      $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors);
 0338   
 0339                      $convertors[] = array(
 0340                          'tag'            =>    $m[1],
 0341                          'forum_name'    =>    $convertor_data['forum_name'],
 0342                          'version'        =>    $convertor_data['version'],
 0343                          'dbms'            =>    $convertor_data['dbms'],
 0344                          'dbhost'        =>    $convertor_data['dbhost'],
 0345                          'dbport'        =>    $convertor_data['dbport'],
 0346                          'dbuser'        =>    $convertor_data['dbuser'],
 0347                          'dbpasswd'        =>    $convertor_data['dbpasswd'],
 0348                          'dbname'        =>    $convertor_data['dbname'],
 0349                          'table_prefix'    =>    $convertor_data['table_prefix'],
 0350                          'author'        =>    $convertor_data['author']
 0351                      );
 0352                  }
 0353                  unset($convertor_data);
 0354              }
 0355          }
 0356          closedir($handle);
 0357   
 0358          @ksort($sort);
 0359   
 0360          foreach ($sort as $void => $index)
 0361          {
 0362              $template->assign_block_vars('convertors', array(
 0363                  'AUTHOR'    => $convertors[$index]['author'],
 0364                  'SOFTWARE'    => $convertors[$index]['forum_name'],
 0365                  'VERSION'    => $convertors[$index]['version'],
 0366   
 0367                  'U_CONVERT'    => $this->p_master->module_url . "?mode={$this->mode}&amp;language=$language&amp;sub=settings&amp;tag=" . $convertors[$index]['tag'],
 0368              ));
 0369          }
 0370      }
 0371   
 0372      /**
 0373      */
 0374      function get_convert_settings($sub)
 0375      {
 0376          global $lang, $language, $template, $db, $phpbb_root_path, $phpEx, $config, $cache, $phpbb_config_php_file;
 0377   
 0378          extract($phpbb_config_php_file->get_all());
 0379   
 0380          require($phpbb_root_path . 'includes/constants.' . $phpEx);
 0381          require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
 0382   
 0383          $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
 0384   
 0385          $db = new $dbms();
 0386          $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
 0387          unset($dbpasswd);
 0388   
 0389          $this->page_title = $lang['STAGE_SETTINGS'];
 0390   
 0391          // We need to fill the config to let internal functions correctly work
 0392          $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
 0393          set_config(null, null, null, $config);
 0394          set_config_count(null, null, null, $config);
 0395   
 0396          $convertor_tag = request_var('tag', '');
 0397   
 0398          if (empty($convertor_tag))
 0399          {
 0400              $this->p_master->error($lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
 0401          }
 0402          $get_info = true;
 0403   
 0404          // check security implications of direct inclusion
 0405          $convertor_tag = basename($convertor_tag);
 0406          if (!file_exists('./convertors/convert_' . $convertor_tag . '.' . $phpEx))
 0407          {
 0408              $this->p_master->error($lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
 0409          }
 0410   
 0411          include('./convertors/convert_' . $convertor_tag . '.' . $phpEx);
 0412   
 0413          // The test_file is a file that should be present in the location of the old board.
 0414          if (!isset($test_file))
 0415          {
 0416              $this->p_master->error($lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
 0417          }
 0418   
 0419          $submit = (isset($_POST['submit'])) ? true : false;
 0420   
 0421          $src_dbms            = request_var('src_dbms', $convertor_data['dbms']);
 0422          $src_dbhost            = request_var('src_dbhost', $convertor_data['dbhost']);
 0423          $src_dbport            = request_var('src_dbport', $convertor_data['dbport']);
 0424          $src_dbuser            = request_var('src_dbuser', $convertor_data['dbuser']);
 0425          $src_dbpasswd        = request_var('src_dbpasswd', $convertor_data['dbpasswd']);
 0426          $src_dbname            = request_var('src_dbname', $convertor_data['dbname']);
 0427          $src_table_prefix    = request_var('src_table_prefix', $convertor_data['table_prefix']);
 0428          $forum_path            = request_var('forum_path', $convertor_data['forum_path']);
 0429          $refresh            = request_var('refresh', 1);
 0430   
 0431          // Default URL of the old board
 0432          // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it?
 0433          //        -> We should convert old urls to the new relative urls format
 0434          // $src_url = request_var('src_url', 'Not in use at the moment');
 0435   
 0436          // strip trailing slash from old forum path
 0437          $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path;
 0438   
 0439          $error = array();
 0440          if ($submit)
 0441          {
 0442              if (!@file_exists('./../' . $forum_path . '/' . $test_file))
 0443              {
 0444                  $error[] = sprintf($lang['COULD_NOT_FIND_PATH'], $forum_path);
 0445              }
 0446   
 0447              $connect_test = false;
 0448              $available_dbms = get_available_dbms(false, true, true);
 0449   
 0450              if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE'])
 0451              {
 0452                  $error[] = $lang['INST_ERR_NO_DB'];
 0453                  $connect_test = false;
 0454              }
 0455              else
 0456              {
 0457                  $connect_test = connect_check_db(true, $error, $available_dbms[$src_dbms], $src_table_prefix, $src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, true, ($src_dbms == $dbms) ? false : true, false);
 0458              }
 0459   
 0460              // The forum prefix of the old and the new forum can only be the same if two different databases are used.
 0461              if ($src_table_prefix == $table_prefix && $src_dbms == $dbms && $src_dbhost == $dbhost && $src_dbport == $dbport && $src_dbname == $dbname)
 0462              {
 0463                  $error[] = sprintf($lang['TABLE_PREFIX_SAME'], $src_table_prefix);
 0464              }
 0465   
 0466              $src_dbms = $phpbb_config_php_file->convert_30_dbms_to_31($src_dbms);
 0467   
 0468              // Check table prefix
 0469              if (!sizeof($error))
 0470              {
 0471                  // initiate database connection to old db if old and new db differ
 0472                  global $src_db, $same_db;
 0473                  $src_db = $same_db = false;
 0474   
 0475                  if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser)
 0476                  {
 0477                      $src_db = new $src_dbms();
 0478                      $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true);
 0479                      $same_db = false;
 0480                  }
 0481                  else
 0482                  {
 0483                      $src_db = $db;
 0484                      $same_db = true;
 0485                  }
 0486   
 0487                  $src_db->sql_return_on_error(true);
 0488                  $db->sql_return_on_error(true);
 0489   
 0490                  // Try to select one row from the first table to see if the prefix is OK
 0491                  $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1);
 0492   
 0493                  if (!$result)
 0494                  {
 0495                      $prefixes = array();
 0496   
 0497                      $tables_existing = get_tables($src_db);
 0498                      $tables_existing = array_map('strtolower', $tables_existing);
 0499                      foreach ($tables_existing as $table_name)
 0500                      {
 0501                          compare_table($tables, $table_name, $prefixes);
 0502                      }
 0503                      unset($tables_existing);
 0504   
 0505                      foreach ($prefixes as $prefix => $count)
 0506                      {
 0507                          if ($count >= sizeof($tables))
 0508                          {
 0509                              $possible_prefix = $prefix;
 0510                              break;
 0511                          }
 0512                      }
 0513   
 0514                      $msg = '';
 0515                      if (!empty($convertor_data['table_prefix']))
 0516                      {
 0517                          $msg .= sprintf($lang['DEFAULT_PREFIX_IS'], $convertor_data['forum_name'], $convertor_data['table_prefix']);
 0518                      }
 0519   
 0520                      if (!empty($possible_prefix))
 0521                      {
 0522                          $msg .= '<br />';
 0523                          $msg .= ($possible_prefix == '*') ? $lang['BLANK_PREFIX_FOUND'] : sprintf($lang['PREFIX_FOUND'], $possible_prefix);
 0524                          $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix;
 0525                      }
 0526   
 0527                      $error[] = $msg;
 0528                  }
 0529                  $src_db->sql_freeresult($result);
 0530                  $src_db->sql_return_on_error(false);
 0531              }
 0532   
 0533              if (!sizeof($error))
 0534              {
 0535                  // Save convertor Status
 0536                  set_config('convert_progress', serialize(array(
 0537                      'step'            => '',
 0538                      'table_prefix'    => $src_table_prefix,
 0539                      'tag'            => $convertor_tag,
 0540                  )), true);
 0541                  set_config('convert_db_server', serialize(array(
 0542                      'dbms'            => $src_dbms,
 0543                      'dbhost'        => $src_dbhost,
 0544                      'dbport'        => $src_dbport,
 0545                      'dbname'        => $src_dbname,
 0546                  )), true);
 0547                  set_config('convert_db_user', serialize(array(
 0548                      'dbuser'        => $src_dbuser,
 0549                      'dbpasswd'        => $src_dbpasswd,
 0550                  )), true);
 0551   
 0552                  // Save options
 0553                  set_config('convert_options', serialize(array('forum_path' => './../' . $forum_path, 'refresh' => $refresh)), true);
 0554   
 0555                  $template->assign_block_vars('checks', array(
 0556                      'TITLE'        => $lang['VERIFY_OPTIONS'],
 0557                      'RESULT'    => $lang['CONVERT_SETTINGS_VERIFIED'],
 0558                  ));
 0559   
 0560                  $template->assign_vars(array(
 0561                      'L_SUBMIT'    => $lang['BEGIN_CONVERT'],
 0562  //                    'S_HIDDEN'    => $s_hidden_fields,
 0563                      'U_ACTION'    => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag=$convertor_tag&amp;language=$language",
 0564                  ));
 0565   
 0566                  return;
 0567              }
 0568              else
 0569              {
 0570                  $template->assign_block_vars('checks', array(
 0571                      'TITLE'        => $lang['VERIFY_OPTIONS'],
 0572                      'RESULT'    => '<b style="color:red">' . implode('<br />', $error) . '</b>',
 0573                  ));
 0574              }
 0575          } // end submit
 0576   
 0577          foreach ($this->convert_options as $config_key => $vars)
 0578          {
 0579              if (!is_array($vars) && strpos($config_key, 'legend') === false)
 0580              {
 0581                  continue;
 0582              }
 0583   
 0584              if (strpos($config_key, 'legend') !== false)
 0585              {
 0586                  $template->assign_block_vars('options', array(
 0587                      'S_LEGEND'        => true,
 0588                      'LEGEND'        => $lang[$vars])
 0589                  );
 0590   
 0591                  continue;
 0592              }
 0593   
 0594              $options = isset($vars['options']) ? $vars['options'] : '';
 0595   
 0596              $template->assign_block_vars('options', array(
 0597                  'KEY'            => $config_key,
 0598                  'TITLE'            => $lang[$vars['lang']],
 0599                  'S_EXPLAIN'        => $vars['explain'],
 0600                  'S_LEGEND'        => false,
 0601                  'TITLE_EXPLAIN'    => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
 0602                  'CONTENT'        => $this->p_master->input_field($config_key, $vars['type'], $$config_key, $options),
 0603                  )
 0604              );
 0605          }
 0606   
 0607          $template->assign_vars(array(
 0608              'TITLE'        => $lang['STAGE_SETTINGS'],
 0609              'BODY'        => $lang['CONV_OPTIONS_BODY'],
 0610              'L_SUBMIT'    => $lang['BEGIN_CONVERT'],
 0611              'U_ACTION'    => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=settings&amp;tag=$convertor_tag&amp;language=$language",
 0612          ));
 0613      }
 0614   
 0615      /**
 0616      * The function which does the actual work (or dispatches it to the relevant places)
 0617      */
 0618      function convert_data($sub)
 0619      {
 0620          global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
 0621          global $convert, $convert_row, $message_parser, $skip_rows, $language;
 0622          global $request, $phpbb_config_php_file;
 0623   
 0624          extract($phpbb_config_php_file->get_all());
 0625   
 0626          require($phpbb_root_path . 'includes/constants.' . $phpEx);
 0627          require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
 0628   
 0629          $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
 0630   
 0631          $db = new $dbms();
 0632          $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
 0633          unset($dbpasswd);
 0634   
 0635          // We need to fill the config to let internal functions correctly work
 0636          $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null, CONFIG_TABLE);
 0637          set_config(null, null, null, $config);
 0638          set_config_count(null, null, null, $config);
 0639   
 0640          // Override a couple of config variables for the duration
 0641          $config['max_quote_depth'] = 0;
 0642   
 0643          // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
 0644          $config['max_post_chars'] = $config['min_post_chars'] = 0;
 0645   
 0646          // Set up a user as well. We _should_ have enough of a database here at this point to do this
 0647          // and it helps for any core code we call
 0648          $user->session_begin();
 0649          $user->page = $user->extract_current_page($phpbb_root_path);
 0650   
 0651          // This is a little bit of a fudge, but it allows the language entries to be available to the
 0652          // core code without us loading them again
 0653          $user->lang = &$lang;
 0654   
 0655          $this->page_title = $user->lang['STAGE_IN_PROGRESS'];
 0656   
 0657          $convert->options = array();
 0658          if (isset($config['convert_progress']))
 0659          {
 0660              $convert->options = unserialize($config['convert_progress']);
 0661              $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
 0662          }
 0663   
 0664          // This information should have already been checked once, but do it again for safety
 0665          if (empty($convert->options) || empty($convert->options['tag']) ||
 0666              !isset($convert->options['dbms']) ||
 0667              !isset($convert->options['dbhost']) ||
 0668              !isset($convert->options['dbport']) ||
 0669              !isset($convert->options['dbuser']) ||
 0670              !isset($convert->options['dbpasswd']) ||
 0671              !isset($convert->options['dbname']) ||
 0672              !isset($convert->options['table_prefix']))
 0673          {
 0674              $this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
 0675          }
 0676   
 0677          // Make some short variables accessible, for easier referencing
 0678          $convert->convertor_tag = basename($convert->options['tag']);
 0679          $convert->src_dbms = $convert->options['dbms'];
 0680          $convert->src_dbhost = $convert->options['dbhost'];
 0681          $convert->src_dbport = $convert->options['dbport'];
 0682          $convert->src_dbuser = $convert->options['dbuser'];
 0683          $convert->src_dbpasswd = $convert->options['dbpasswd'];
 0684          $convert->src_dbname = $convert->options['dbname'];
 0685          $convert->src_table_prefix = $convert->options['table_prefix'];
 0686   
 0687          // initiate database connection to old db if old and new db differ
 0688          global $src_db, $same_db;
 0689          $src_db = $same_db = null;
 0690          if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser)
 0691          {
 0692              $dbms = $convert->src_dbms;
 0693              $src_db = new $dbms();
 0694              $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
 0695              $same_db = false;
 0696          }
 0697          else
 0698          {
 0699              $src_db = $db;
 0700              $same_db = true;
 0701          }
 0702   
 0703          $convert->mysql_convert = false;
 0704          switch ($src_db->sql_layer)
 0705          {
 0706              case 'sqlite':
 0707              case 'sqlite3':
 0708                  $convert->src_truncate_statement = 'DELETE FROM ';
 0709              break;
 0710   
 0711              // Thanks MySQL, for silently converting...
 0712              case 'mysql':
 0713              case 'mysql4':
 0714                  if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>='))
 0715                  {
 0716                      $convert->mysql_convert = true;
 0717                  }
 0718                  $convert->src_truncate_statement = 'TRUNCATE TABLE ';
 0719              break;
 0720   
 0721              case 'mysqli':
 0722                  $convert->mysql_convert = true;
 0723                  $convert->src_truncate_statement = 'TRUNCATE TABLE ';
 0724              break;
 0725   
 0726              default:
 0727                  $convert->src_truncate_statement = 'TRUNCATE TABLE ';
 0728              break;
 0729          }
 0730   
 0731          if ($convert->mysql_convert && !$same_db)
 0732          {
 0733              $src_db->sql_query("SET NAMES 'binary'");
 0734          }
 0735   
 0736          switch ($db->get_sql_layer())
 0737          {
 0738              case 'sqlite':
 0739              case 'sqlite3':
 0740                  $convert->truncate_statement = 'DELETE FROM ';
 0741              break;
 0742   
 0743              default:
 0744                  $convert->truncate_statement = 'TRUNCATE TABLE ';
 0745              break;
 0746          }
 0747   
 0748          $get_info = false;
 0749   
 0750          // check security implications of direct inclusion
 0751          if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx))
 0752          {
 0753              $this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
 0754          }
 0755   
 0756          if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx))
 0757          {
 0758              include('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx);
 0759          }
 0760   
 0761          $get_info = true;
 0762          include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
 0763   
 0764          // Map some variables...
 0765          $convert->convertor_data = $convertor_data;
 0766          $convert->tables = $tables;
 0767          $convert->config_schema = $config_schema;
 0768   
 0769          // Now include the real data
 0770          $get_info = false;
 0771          include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
 0772   
 0773          $convert->convertor_data = $convertor_data;
 0774          $convert->tables = $tables;
 0775          $convert->config_schema = $config_schema;
 0776          $convert->convertor = $convertor;
 0777   
 0778          // The test_file is a file that should be present in the location of the old board.
 0779          if (!file_exists($convert->options['forum_path'] . '/' . $test_file))
 0780          {
 0781              $this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__);
 0782          }
 0783   
 0784          $search_type = $config['search_type'];
 0785   
 0786          // For conversions we are a bit less strict and set to a search backend we know exist...
 0787          if (!class_exists($search_type))
 0788          {
 0789              $search_type = '\phpbb\search\fulltext_native';
 0790              set_config('search_type', $search_type);
 0791          }
 0792   
 0793          if (!class_exists($search_type))
 0794          {
 0795              trigger_error('NO_SUCH_SEARCH_MODULE');
 0796          }
 0797   
 0798          $error = false;
 0799          $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
 0800   
 0801          if ($error)
 0802          {
 0803              trigger_error($error);
 0804          }
 0805   
 0806          include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
 0807          $message_parser = new parse_message();
 0808   
 0809          $jump = request_var('jump', 0);
 0810          $final_jump = request_var('final_jump', 0);
 0811          $sync_batch = request_var('sync_batch', -1);
 0812          $last_statement = request_var('last', 0);
 0813   
 0814          // We are running sync...
 0815          if ($sync_batch >= 0)
 0816          {
 0817              $this->sync_forums($sync_batch);
 0818              return;
 0819          }
 0820   
 0821          if ($jump)
 0822          {
 0823              $this->jump($jump, $last_statement);
 0824              return;
 0825          }
 0826   
 0827          if ($final_jump)
 0828          {
 0829              $this->final_jump($final_jump);
 0830              return;
 0831          }
 0832   
 0833          $current_table = request_var('current_table', 0);
 0834          $old_current_table = min(-1, $current_table - 1);
 0835          $skip_rows = request_var('skip_rows', 0);
 0836   
 0837          if (!$current_table && !$skip_rows)
 0838          {
 0839              if (!$request->variable('confirm', false))
 0840              {
 0841                  // If avatars / ranks / smilies folders are specified make sure they are writable
 0842                  $bad_folders = array();
 0843   
 0844                  $local_paths = array(
 0845                      'avatar_path'            => path($config['avatar_path']),
 0846                      'avatar_gallery_path'    => path($config['avatar_gallery_path']),
 0847                      'icons_path'            => path($config['icons_path']),
 0848                      'ranks_path'            => path($config['ranks_path']),
 0849                      'smilies_path'            => path($config['smilies_path'])
 0850                  );
 0851   
 0852                  foreach ($local_paths as $folder => $local_path)
 0853                  {
 0854                      if (isset($convert->convertor[$folder]))
 0855                      {
 0856                          if (empty($convert->convertor['test_file']))
 0857                          {
 0858                              // test_file is mandantory at the moment so this should never be reached, but just in case...
 0859                              $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
 0860                          }
 0861   
 0862                          if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path))
 0863                          {
 0864                              if (!$local_path)
 0865                              {
 0866                                  $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
 0867                              }
 0868                              else
 0869                              {
 0870                                  $bad_folders[] = $local_path;
 0871                              }
 0872                          }
 0873                      }
 0874                  }
 0875   
 0876                  if (sizeof($bad_folders))
 0877                  {
 0878                      $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
 0879                      sort($bad_folders);
 0880                      $this->p_master->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true);
 0881   
 0882                      $template->assign_vars(array(
 0883                          'L_SUBMIT'    => $user->lang['INSTALL_TEST'],
 0884                          'U_ACTION'    => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}&amp;language=$language",
 0885                      ));
 0886                      return;
 0887                  }
 0888   
 0889                  // Grab all the tables used in convertor
 0890                  $missing_tables = $tables_list = $aliases = array();
 0891   
 0892                  foreach ($convert->convertor['schema'] as $schema)
 0893                  {
 0894                      // Skip those not used (because of addons/plugins not detected)
 0895                      if (!$schema['target'])
 0896                      {
 0897                          continue;
 0898                      }
 0899   
 0900                      foreach ($schema as $key => $val)
 0901                      {
 0902                          // we're dealing with an array like:
 0903                          // array('forum_status',            'forums.forum_status',                'is_item_locked')
 0904                          if (is_int($key) && !empty($val[1]))
 0905                          {
 0906                              $temp_data = $val[1];
 0907                              if (!is_array($temp_data))
 0908                              {
 0909                                  $temp_data = array($temp_data);
 0910                              }
 0911   
 0912                              foreach ($temp_data as $val)
 0913                              {
 0914                                  if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $val, $m))
 0915                                  {
 0916                                      $table = $convert->src_table_prefix . $m[1];
 0917                                      $tables_list[$table] = $table;
 0918   
 0919                                      if (!empty($m[3]))
 0920                                      {
 0921                                          $aliases[] = $convert->src_table_prefix . $m[3];
 0922                                      }
 0923                                  }
 0924                              }
 0925                          }
 0926                          // 'left_join'        => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1'
 0927                          else if ($key == 'left_join')
 0928                          {
 0929                              // Convert the value if it wasn't an array already.
 0930                              if (!is_array($val))
 0931                              {
 0932                                  $val = array($val);
 0933                              }
 0934   
 0935                              for ($j = 0; $j < sizeof($val); ++$j)
 0936                              {
 0937                                  if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m))
 0938                                  {
 0939                                      $table = $convert->src_table_prefix . $m[1];
 0940                                      $tables_list[$table] = $table;
 0941   
 0942                                      if (!empty($m[2]))
 0943                                      {
 0944                                          $aliases[] = $convert->src_table_prefix . $m[2];
 0945                                      }
 0946                                  }
 0947                              }
 0948                          }
 0949                      }
 0950                  }
 0951   
 0952                  // Remove aliased tables from $tables_list
 0953                  foreach ($aliases as $alias)
 0954                  {
 0955                      unset($tables_list[$alias]);
 0956                  }
 0957   
 0958                  // Check if the tables that we need exist
 0959                  $src_db->sql_return_on_error(true);
 0960                  foreach ($tables_list as $table => $null)
 0961                  {
 0962                      $sql = 'SELECT 1 FROM ' . $table;
 0963                      $_result = $src_db->sql_query_limit($sql, 1);
 0964   
 0965                      if (!$_result)
 0966                      {
 0967                          $missing_tables[] = $table;
 0968                      }
 0969                      $src_db->sql_freeresult($_result);
 0970                  }
 0971                  $src_db->sql_return_on_error(false);
 0972   
 0973                  // Throw an error if some tables are missing
 0974                  // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again
 0975   
 0976                  if (sizeof($missing_tables) == sizeof($tables_list))
 0977                  {
 0978                      $this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
 0979                  }
 0980                  else if (sizeof($missing_tables))
 0981                  {
 0982                      $this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
 0983                  }
 0984   
 0985                  $url = $this->save_convert_progress('&amp;confirm=1');
 0986                  $msg = $user->lang['PRE_CONVERT_COMPLETE'];
 0987   
 0988                  if ($convert->convertor_data['author_notes'])
 0989                  {
 0990                      $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
 0991                  }
 0992   
 0993                  $template->assign_vars(array(
 0994                      'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 0995                      'L_MESSAGE'        => $msg,
 0996                      'U_ACTION'        => $url,
 0997                  ));
 0998   
 0999                  return;
 1000              } // if (!$request->variable('confirm', false)))
 1001   
 1002              $template->assign_block_vars('checks', array(
 1003                  'S_LEGEND'        => true,
 1004                  'LEGEND'        => $user->lang['STARTING_CONVERT'],
 1005              ));
 1006   
 1007              // Convert the config table and load the settings of the old board
 1008              if (!empty($convert->config_schema))
 1009              {
 1010                  restore_config($convert->config_schema);
 1011   
 1012                  // Override a couple of config variables for the duration
 1013                  $config['max_quote_depth'] = 0;
 1014   
 1015                  // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
 1016                  $config['max_post_chars'] = $config['min_post_chars'] = 0;
 1017              }
 1018   
 1019              $template->assign_block_vars('checks', array(
 1020                  'TITLE'        => $user->lang['CONFIG_CONVERT'],
 1021                  'RESULT'    => $user->lang['DONE'],
 1022              ));
 1023   
 1024              // Now process queries and execute functions that have to be executed prior to the conversion
 1025              if (!empty($convert->convertor['execute_first']))
 1026              {
 1027                  // @codingStandardsIgnoreStart
 1028                  eval($convert->convertor['execute_first']);
 1029                  // @codingStandardsIgnoreEnd
 1030              }
 1031   
 1032              if (!empty($convert->convertor['query_first']))
 1033              {
 1034                  if (!is_array($convert->convertor['query_first']))
 1035                  {
 1036                      $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
 1037                  }
 1038                  else if (!is_array($convert->convertor['query_first'][0]))
 1039                  {
 1040                      $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
 1041                  }
 1042   
 1043                  foreach ($convert->convertor['query_first'] as $query_first)
 1044                  {
 1045                      if ($query_first[0] == 'src')
 1046                      {
 1047                          if ($convert->mysql_convert && $same_db)
 1048                          {
 1049                              $src_db->sql_query("SET NAMES 'binary'");
 1050                          }
 1051   
 1052                          $src_db->sql_query($query_first[1]);
 1053   
 1054                          if ($convert->mysql_convert && $same_db)
 1055                          {
 1056                              $src_db->sql_query("SET NAMES 'utf8'");
 1057                          }
 1058                      }
 1059                      else
 1060                      {
 1061                          $db->sql_query($query_first[1]);
 1062                      }
 1063                  }
 1064              }
 1065   
 1066              $template->assign_block_vars('checks', array(
 1067                  'TITLE'        => $user->lang['PREPROCESS_STEP'],
 1068                  'RESULT'    => $user->lang['DONE'],
 1069              ));
 1070          } // if (!$current_table && !$skip_rows)
 1071   
 1072          $template->assign_block_vars('checks', array(
 1073              'S_LEGEND'        => true,
 1074              'LEGEND'        => $user->lang['FILLING_TABLES'],
 1075          ));
 1076   
 1077          // This loop takes one target table and processes it
 1078          while ($current_table < sizeof($convert->convertor['schema']))
 1079          {
 1080              $schema = $convert->convertor['schema'][$current_table];
 1081   
 1082              // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
 1083              if (empty($schema['target']))
 1084              {
 1085                  $current_table++;
 1086                  continue;
 1087              }
 1088   
 1089              $template->assign_block_vars('checks', array(
 1090                  'TITLE'    => sprintf($user->lang['FILLING_TABLE'], $schema['target']),
 1091              ));
 1092   
 1093              // This is only the case when we first start working on the tables.
 1094              if (!$skip_rows)
 1095              {
 1096                  // process execute_first and query_first for this table...
 1097                  if (!empty($schema['execute_first']))
 1098                  {
 1099                      // @codingStandardsIgnoreStart
 1100                      eval($schema['execute_first']);
 1101                      // @codingStandardsIgnoreEnd
 1102                  }
 1103   
 1104                  if (!empty($schema['query_first']))
 1105                  {
 1106                      if (!is_array($schema['query_first']))
 1107                      {
 1108                          $schema['query_first'] = array('target', array($schema['query_first']));
 1109                      }
 1110                      else if (!is_array($schema['query_first'][0]))
 1111                      {
 1112                          $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
 1113                      }
 1114   
 1115                      foreach ($schema['query_first'] as $query_first)
 1116                      {
 1117                          if ($query_first[0] == 'src')
 1118                          {
 1119                              if ($convert->mysql_convert && $same_db)
 1120                              {
 1121                                  $src_db->sql_query("SET NAMES 'binary'");
 1122                              }
 1123                              $src_db->sql_query($query_first[1]);
 1124                              if ($convert->mysql_convert && $same_db)
 1125                              {
 1126                                  $src_db->sql_query("SET NAMES 'utf8'");
 1127                              }
 1128                          }
 1129                          else
 1130                          {
 1131                              $db->sql_query($query_first[1]);
 1132                          }
 1133                      }
 1134                  }
 1135   
 1136                  if (!empty($schema['autoincrement']))
 1137                  {
 1138                      switch ($db->get_sql_layer())
 1139                      {
 1140                          case 'postgres':
 1141                              $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
 1142                          break;
 1143   
 1144                          case 'oracle':
 1145                              $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
 1146                              $row = $db->sql_fetchrow($result);
 1147                              $db->sql_freeresult($result);
 1148   
 1149                              $largest_id = (int) $row['max_id'];
 1150   
 1151                              if ($largest_id)
 1152                              {
 1153                                  $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
 1154                                  $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
 1155                              }
 1156                          break;
 1157                      }
 1158                  }
 1159              }
 1160   
 1161              // Process execute_always for this table
 1162              // This is for code which needs to be executed on every pass of this table if
 1163              // it gets split because of time restrictions
 1164              if (!empty($schema['execute_always']))
 1165              {
 1166                  // @codingStandardsIgnoreStart
 1167                  eval($schema['execute_always']);
 1168                  // @codingStandardsIgnoreEnd
 1169              }
 1170   
 1171              //
 1172              // Set up some variables
 1173              //
 1174              // $waiting_rows    holds rows for multirows insertion (MySQL only)
 1175              // $src_tables        holds unique tables with aliases to select from
 1176              // $src_fields        will quickly refer source fields (or aliases) corresponding to the current index
 1177              // $select_fields    holds the names of the fields to retrieve
 1178              //
 1179   
 1180              $sql_data = array(
 1181                  'source_fields'        => array(),
 1182                  'target_fields'        => array(),
 1183                  'source_tables'        => array(),
 1184                  'select_fields'        => array(),
 1185              );
 1186   
 1187              // This statement is building the keys for later insertion.
 1188              $insert_query = $this->build_insert_query($schema, $sql_data, $current_table);
 1189   
 1190              // If no source table is affected, we skip the table
 1191              if (empty($sql_data['source_tables']))
 1192              {
 1193                  $skip_rows = 0;
 1194                  $current_table++;
 1195                  continue;
 1196              }
 1197   
 1198              $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : '';
 1199   
 1200              $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']);
 1201   
 1202              // Where
 1203              $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : '';
 1204   
 1205              // Group By
 1206              if (!empty($schema['group_by']))
 1207              {
 1208                  $schema['group_by'] = array($schema['group_by']);
 1209                  foreach ($sql_data['select_fields'] as $select)
 1210                  {
 1211                      $alias = strpos(strtolower($select), ' as ');
 1212                      $select = ($alias) ? substr($select, 0, $alias) : $select;
 1213                      if (!in_array($select, $schema['group_by']))
 1214                      {
 1215                          $schema['group_by'][] = $select;
 1216                      }
 1217                  }
 1218              }
 1219              $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : '';
 1220   
 1221              // Having
 1222              $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : '';
 1223   
 1224              // Order By
 1225              if (empty($schema['order_by']) && !empty($schema['primary']))
 1226              {
 1227                  $schema['order_by'] = $schema['primary'];
 1228              }
 1229              $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : '';
 1230   
 1231              // Counting basically holds the amount of rows processed.
 1232              $counting = -1;
 1233              $batch_time = 0;
 1234   
 1235              while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time()))
 1236              {
 1237                  $old_current_table = $current_table;
 1238   
 1239                  $rows = '';
 1240                  $waiting_rows = array();
 1241   
 1242                  if (!empty($batch_time))
 1243                  {
 1244                      $mtime = explode(' ', microtime());
 1245                      $mtime = $mtime[0] + $mtime[1];
 1246                      $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | ";
 1247                  }
 1248   
 1249                  $template->assign_block_vars('checks', array(
 1250                      'TITLE'        => "skip_rows = $skip_rows",
 1251                      'RESULT'    => $rows . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''),
 1252                  ));
 1253   
 1254                  $mtime = explode(' ', microtime());
 1255                  $batch_time = $mtime[0] + $mtime[1];
 1256   
 1257                  if ($convert->mysql_convert && $same_db)
 1258                  {
 1259                      $src_db->sql_query("SET NAMES 'binary'");
 1260                  }
 1261   
 1262                  // Take skip rows into account and only fetch batch_size amount of rows
 1263                  $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows);
 1264   
 1265                  if ($convert->mysql_convert && $same_db)
 1266                  {
 1267                      $src_db->sql_query("SET NAMES 'utf8'");
 1268                  }
 1269   
 1270                  // This loop processes each row
 1271                  $counting = 0;
 1272   
 1273                  $convert->row = $convert_row = array();
 1274   
 1275                  if (!empty($schema['autoincrement']))
 1276                  {
 1277                      switch ($db->get_sql_layer())
 1278                      {
 1279                          case 'mssql':
 1280                          case 'mssql_odbc':
 1281                          case 'mssqlnative':
 1282                              $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON');
 1283                          break;
 1284                      }
 1285                  }
 1286   
 1287                  // Now handle the rows until time is over or no more rows to process...
 1288                  while ($counting === 0 || still_on_time())
 1289                  {
 1290                      $convert_row = $src_db->sql_fetchrow($___result);
 1291   
 1292                      if (!$convert_row)
 1293                      {
 1294                          // move to the next batch or table
 1295                          break;
 1296                      }
 1297   
 1298                      // With this we are able to always save the last state
 1299                      $convert->row = $convert_row;
 1300   
 1301                      // Increment the counting variable, it stores the number of rows we have processed
 1302                      $counting++;
 1303   
 1304                      $insert_values = array();
 1305   
 1306                      $sql_flag = $this->process_row($schema, $sql_data, $insert_values);
 1307   
 1308                      if ($sql_flag === true)
 1309                      {
 1310                          switch ($db->get_sql_layer())
 1311                          {
 1312                              // If MySQL, we'll wait to have num_wait_rows rows to submit at once
 1313                              case 'mysql':
 1314                              case 'mysql4':
 1315                              case 'mysqli':
 1316                                  $waiting_rows[] = '(' . implode(', ', $insert_values) . ')';
 1317   
 1318                                  if (sizeof($waiting_rows) >= $convert->num_wait_rows)
 1319                                  {
 1320                                      $errored = false;
 1321   
 1322                                      $db->sql_return_on_error(true);
 1323   
 1324                                      if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
 1325                                      {
 1326                                          $errored = true;
 1327                                      }
 1328                                      $db->sql_return_on_error(false);
 1329   
 1330                                      if ($errored)
 1331                                      {
 1332                                          $db->sql_return_on_error(true);
 1333   
 1334                                          // Because it errored out we will try to insert the rows one by one... most of the time this
 1335                                          // is caused by duplicate entries - but we also do not want to miss one...
 1336                                          foreach ($waiting_rows as $waiting_sql)
 1337                                          {
 1338                                              if (!$db->sql_query($insert_query . $waiting_sql))
 1339                                              {
 1340                                                  $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
 1341                                              }
 1342                                          }
 1343   
 1344                                          $db->sql_return_on_error(false);
 1345                                      }
 1346   
 1347                                      $waiting_rows = array();
 1348                                  }
 1349   
 1350                              break;
 1351   
 1352                              default:
 1353                                  $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')';
 1354   
 1355                                  $db->sql_return_on_error(true);
 1356   
 1357                                  if (!$db->sql_query($insert_sql))
 1358                                  {
 1359                                      $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
 1360                                  }
 1361                                  $db->sql_return_on_error(false);
 1362   
 1363                                  $waiting_rows = array();
 1364   
 1365                              break;
 1366                          }
 1367                      }
 1368   
 1369                      $skip_rows++;
 1370                  }
 1371                  $src_db->sql_freeresult($___result);
 1372   
 1373                  // We might still have some rows waiting
 1374                  if (sizeof($waiting_rows))
 1375                  {
 1376                      $errored = false;
 1377                      $db->sql_return_on_error(true);
 1378   
 1379                      if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
 1380                      {
 1381                          $errored = true;
 1382                      }
 1383                      $db->sql_return_on_error(false);
 1384   
 1385                      if ($errored)
 1386                      {
 1387                          $db->sql_return_on_error(true);
 1388   
 1389                          // Because it errored out we will try to insert the rows one by one... most of the time this
 1390                          // is caused by duplicate entries - but we also do not want to miss one...
 1391                          foreach ($waiting_rows as $waiting_sql)
 1392                          {
 1393                              $db->sql_query($insert_query . $waiting_sql);
 1394                              $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
 1395                          }
 1396   
 1397                          $db->sql_return_on_error(false);
 1398                      }
 1399   
 1400                      $waiting_rows = array();
 1401                  }
 1402   
 1403                  if (!empty($schema['autoincrement']))
 1404                  {
 1405                      switch ($db->get_sql_layer())
 1406                      {
 1407                          case 'mssql':
 1408                          case 'mssql_odbc':
 1409                          case 'mssqlnative':
 1410                              $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF');
 1411                          break;
 1412   
 1413                          case 'postgres':
 1414                              $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
 1415                          break;
 1416   
 1417                          case 'oracle':
 1418                              $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
 1419                              $row = $db->sql_fetchrow($result);
 1420                              $db->sql_freeresult($result);
 1421   
 1422                              $largest_id = (int) $row['max_id'];
 1423   
 1424                              if ($largest_id)
 1425                              {
 1426                                  $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
 1427                                  $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
 1428                              }
 1429                          break;
 1430                      }
 1431                  }
 1432              }
 1433   
 1434              // When we reach this point, either the current table has been processed or we're running out of time.
 1435              if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG')*/)
 1436              {
 1437                  $skip_rows = 0;
 1438                  $current_table++;
 1439              }
 1440              else
 1441              {/*
 1442                  if (still_on_time() && $counting < $convert->batch_size)
 1443                  {
 1444                      $skip_rows = 0;
 1445                      $current_table++;
 1446                  }*/
 1447   
 1448                  // Looks like we ran out of time.
 1449                  $url = $this->save_convert_progress('&amp;current_table=' . $current_table . '&amp;skip_rows=' . $skip_rows);
 1450   
 1451                  $current_table++;
 1452  //                $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows));
 1453   
 1454                  $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema']));
 1455   
 1456                  $template->assign_vars(array(
 1457                      'L_MESSAGE'        => $msg,
 1458                      'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 1459                      'U_ACTION'        => $url,
 1460                  ));
 1461   
 1462                  $this->meta_refresh($url);
 1463                  return;
 1464              }
 1465          }
 1466   
 1467          // Process execute_last then we'll be done
 1468          $url = $this->save_convert_progress('&amp;jump=1');
 1469   
 1470          $template->assign_vars(array(
 1471              'L_SUBMIT'        => $user->lang['FINAL_STEP'],
 1472              'U_ACTION'        => $url,
 1473          ));
 1474   
 1475          $this->meta_refresh($url);
 1476          return;
 1477      }
 1478   
 1479      /**
 1480      * Sync function being executed at the middle, some functions need to be executed after a successful sync.
 1481      */
 1482      function sync_forums($sync_batch)
 1483      {
 1484          global $template, $user, $db, $phpbb_root_path, $phpEx, $config, $cache;
 1485          global $convert;
 1486   
 1487          $template->assign_block_vars('checks', array(
 1488              'S_LEGEND'    => true,
 1489              'LEGEND'    => $user->lang['SYNC_TOPICS'],
 1490          ));
 1491   
 1492          $batch_size = $convert->batch_size;
 1493   
 1494          $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value
 1495              FROM ' . TOPICS_TABLE;
 1496          $result = $db->sql_query($sql);
 1497          $row = $db->sql_fetchrow($result);
 1498          $db->sql_freeresult($result);
 1499   
 1500          // Set values of minimum/maximum primary value for this table.
 1501          $primary_min = $row['min_value'];
 1502          $primary_max = $row['max_value'];
 1503   
 1504          if ($sync_batch == 0)
 1505          {
 1506              $sync_batch = (int) $primary_min;
 1507          }
 1508   
 1509          if ($sync_batch == 0)
 1510          {
 1511              $sync_batch = 1;
 1512          }
 1513   
 1514          // Fetch a batch of rows, process and insert them.
 1515          while ($sync_batch <= $primary_max && still_on_time())
 1516          {
 1517              $end = ($sync_batch + $batch_size - 1);
 1518   
 1519              // Sync all topics in batch mode...
 1520              sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true);
 1521   
 1522              $template->assign_block_vars('checks', array(
 1523                  'TITLE'        => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''),
 1524                  'RESULT'    => $user->lang['DONE'],
 1525              ));
 1526   
 1527              $sync_batch += $batch_size;
 1528          }
 1529   
 1530          if ($sync_batch >= $primary_max)
 1531          {
 1532              $url = $this->save_convert_progress('&amp;final_jump=1');
 1533   
 1534              $template->assign_vars(array(
 1535                  'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 1536                  'U_ACTION'        => $url,
 1537              ));
 1538   
 1539              $this->meta_refresh($url);
 1540              return;
 1541          }
 1542          else
 1543          {
 1544              $sync_batch--;
 1545          }
 1546   
 1547          $url = $this->save_convert_progress('&amp;sync_batch=' . $sync_batch);
 1548   
 1549          $template->assign_vars(array(
 1550              'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 1551              'U_ACTION'        => $url,
 1552          ));
 1553   
 1554          $this->meta_refresh($url);
 1555          return;
 1556      }
 1557   
 1558      /**
 1559      * Save the convertor status
 1560      */
 1561      function save_convert_progress($step)
 1562      {
 1563          global $convert, $language;
 1564   
 1565          // Save convertor Status
 1566          set_config('convert_progress', serialize(array(
 1567              'step'            => $step,
 1568              'table_prefix'    => $convert->src_table_prefix,
 1569              'tag'            => $convert->convertor_tag,
 1570          )), true);
 1571   
 1572          set_config('convert_db_server', serialize(array(
 1573              'dbms'            => $convert->src_dbms,
 1574              'dbhost'        => $convert->src_dbhost,
 1575              'dbport'        => $convert->src_dbport,
 1576              'dbname'        => $convert->src_dbname,
 1577          )), true);
 1578   
 1579          set_config('convert_db_user', serialize(array(
 1580              'dbuser'        => $convert->src_dbuser,
 1581              'dbpasswd'        => $convert->src_dbpasswd,
 1582          )), true);
 1583   
 1584          return $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}$step&amp;language=$language";
 1585      }
 1586   
 1587      /**
 1588      * Finish conversion, the last function to be called.
 1589      */
 1590      function finish_conversion()
 1591      {
 1592          global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user, $template;
 1593          global $cache, $auth, $phpbb_container, $phpbb_log;
 1594   
 1595          $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
 1596              WHERE config_name = 'convert_progress'
 1597                  OR config_name = 'convert_options'
 1598                  OR config_name = 'convert_db_server'
 1599                  OR config_name = 'convert_db_user'");
 1600          $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
 1601   
 1602          @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx);
 1603          phpbb_cache_moderators($db, $cache, $auth);
 1604   
 1605          // And finally, add a note to the log
 1606          $phpbb_log = $phpbb_container->get('log');
 1607          add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']);
 1608   
 1609          $url = $this->p_master->module_url . "?mode={$this->mode}&amp;sub=final&amp;language=$language";
 1610   
 1611          $template->assign_vars(array(
 1612              'L_SUBMIT'        => $user->lang['FINAL_STEP'],
 1613              'U_ACTION'        => $url,
 1614          ));
 1615   
 1616          $this->meta_refresh($url);
 1617          return;
 1618      }
 1619   
 1620      /**
 1621      * This function marks the steps after syncing
 1622      */
 1623      function final_jump($final_jump)
 1624      {
 1625          global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
 1626          global $convert;
 1627   
 1628          $template->assign_block_vars('checks', array(
 1629              'S_LEGEND'    => true,
 1630              'LEGEND'    => $user->lang['PROCESS_LAST'],
 1631          ));
 1632   
 1633          if ($final_jump == 1)
 1634          {
 1635              $db->sql_return_on_error(true);
 1636   
 1637              update_topics_posted();
 1638   
 1639              $template->assign_block_vars('checks', array(
 1640                  'TITLE'        => $user->lang['UPDATE_TOPICS_POSTED'],
 1641                  'RESULT'    => $user->lang['DONE'],
 1642              ));
 1643   
 1644              if ($db->get_sql_error_triggered())
 1645              {
 1646                  $template->assign_vars(array(
 1647                      'S_ERROR_BOX'    => true,
 1648                      'ERROR_TITLE'    => $user->lang['UPDATE_TOPICS_POSTED'],
 1649                      'ERROR_MSG'        => $user->lang['UPDATE_TOPICS_POSTED_ERR'],
 1650                  ));
 1651              }
 1652              $db->sql_return_on_error(false);
 1653   
 1654              $this->finish_conversion();
 1655              return;
 1656          }
 1657      }
 1658   
 1659      /**
 1660      * This function marks the steps before syncing (jump=1)
 1661      */
 1662      function jump($jump, $last_statement)
 1663      {
 1664          global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
 1665          global $convert;
 1666   
 1667          $template->assign_block_vars('checks', array(
 1668              'S_LEGEND'    => true,
 1669              'LEGEND'    => $user->lang['PROCESS_LAST'],
 1670          ));
 1671   
 1672          if ($jump == 1)
 1673          {
 1674              // Execute 'last' statements/queries
 1675              if (!empty($convert->convertor['execute_last']))
 1676              {
 1677                  if (!is_array($convert->convertor['execute_last']))
 1678                  {
 1679                      // @codingStandardsIgnoreStart
 1680                      eval($convert->convertor['execute_last']);
 1681                      // @codingStandardsIgnoreEnd
 1682                  }
 1683                  else
 1684                  {
 1685                      while ($last_statement < sizeof($convert->convertor['execute_last']))
 1686                      {
 1687                          // @codingStandardsIgnoreStart
 1688                          eval($convert->convertor['execute_last'][$last_statement]);
 1689                          // @codingStandardsIgnoreEnd
 1690   
 1691                          $template->assign_block_vars('checks', array(
 1692                              'TITLE'        => $convert->convertor['execute_last'][$last_statement],
 1693                              'RESULT'    => $user->lang['DONE'],
 1694                          ));
 1695   
 1696                          $last_statement++;
 1697                          $url = $this->save_convert_progress('&amp;jump=1&amp;last=' . $last_statement);
 1698   
 1699                          $percentage = ($last_statement == 0) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement));
 1700                          $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($convert->convertor['execute_last']), $percentage);
 1701   
 1702                          $template->assign_vars(array(
 1703                              'L_SUBMIT'        => $user->lang['CONTINUE_LAST'],
 1704                              'L_MESSAGE'        => $msg,
 1705                              'U_ACTION'        => $url,
 1706                          ));
 1707   
 1708                          $this->meta_refresh($url);
 1709                          return;
 1710                      }
 1711                  }
 1712              }
 1713   
 1714              if (!empty($convert->convertor['query_last']))
 1715              {
 1716                  if (!is_array($convert->convertor['query_last']))
 1717                  {
 1718                      $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last']));
 1719                  }
 1720                  else if (!is_array($convert->convertor['query_last'][0]))
 1721                  {
 1722                      $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1]));
 1723                  }
 1724   
 1725                  foreach ($convert->convertor['query_last'] as $query_last)
 1726                  {
 1727                      if ($query_last[0] == 'src')
 1728                      {
 1729                          if ($convert->mysql_convert && $same_db)
 1730                          {
 1731                              $src_db->sql_query("SET NAMES 'binary'");
 1732                          }
 1733   
 1734                          $src_db->sql_query($query_last[1]);
 1735   
 1736                          if ($convert->mysql_convert && $same_db)
 1737                          {
 1738                              $src_db->sql_query("SET NAMES 'utf8'");
 1739                          }
 1740                      }
 1741                      else
 1742                      {
 1743                          $db->sql_query($query_last[1]);
 1744                      }
 1745                  }
 1746              }
 1747   
 1748              // Sanity check
 1749              $db->sql_return_on_error(false);
 1750              $src_db->sql_return_on_error(false);
 1751   
 1752              fix_empty_primary_groups();
 1753   
 1754              $sql = 'SELECT MIN(user_regdate) AS board_startdate
 1755                  FROM ' . USERS_TABLE;
 1756              $result = $db->sql_query($sql);
 1757              $row = $db->sql_fetchrow($result);
 1758              $db->sql_freeresult($result);
 1759   
 1760              if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0))
 1761              {
 1762                  set_config('board_startdate', $row['board_startdate']);
 1763                  $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS);
 1764              }
 1765   
 1766              update_dynamic_config();
 1767   
 1768              $template->assign_block_vars('checks', array(
 1769                  'TITLE'        => $user->lang['CLEAN_VERIFY'],
 1770                  'RESULT'    => $user->lang['DONE'],
 1771              ));
 1772   
 1773              $url = $this->save_convert_progress('&amp;jump=2');
 1774   
 1775              $template->assign_vars(array(
 1776                  'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 1777                  'U_ACTION'        => $url,
 1778              ));
 1779   
 1780              $this->meta_refresh($url);
 1781              return;
 1782          }
 1783   
 1784          if ($jump == 2)
 1785          {
 1786              $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''");
 1787   
 1788              // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics.
 1789              // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing)
 1790              sync('forum', '', '', false, true);
 1791              $cache->destroy('sql', FORUMS_TABLE);
 1792   
 1793              $template->assign_block_vars('checks', array(
 1794                  'TITLE'        => $user->lang['SYNC_FORUMS'],
 1795                  'RESULT'    => $user->lang['DONE'],
 1796              ));
 1797   
 1798              // Continue with synchronizing the forums...
 1799              $url = $this->save_convert_progress('&amp;sync_batch=0');
 1800   
 1801              $template->assign_vars(array(
 1802                  'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
 1803                  'U_ACTION'        => $url,
 1804              ));
 1805   
 1806              $this->meta_refresh($url);
 1807              return;
 1808          }
 1809      }
 1810   
 1811      function build_insert_query(&$schema, &$sql_data, $current_table)
 1812      {
 1813          global $db, $user;
 1814          global $convert;
 1815   
 1816          // Can we use IGNORE with this DBMS?
 1817          $sql_ignore = (strpos($db->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? 'IGNORE ' : '';
 1818          $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' (';
 1819   
 1820          $aliases = array();
 1821   
 1822          $sql_data = array(
 1823              'source_fields'        => array(),
 1824              'target_fields'        => array(),
 1825              'source_tables'        => array(),
 1826              'select_fields'        => array(),
 1827          );
 1828   
 1829          foreach ($schema as $key => $val)
 1830          {
 1831              // Example: array('group_name',                'extension_groups.group_name',        'htmlspecialchars'),
 1832              if (is_int($key))
 1833              {
 1834                  if (!empty($val[0]))
 1835                  {
 1836                      // Target fields
 1837                      $sql_data['target_fields'][$val[0]] = $key;
 1838                      $insert_query .= $val[0] . ', ';
 1839                  }
 1840   
 1841                  if (!is_array($val[1]))
 1842                  {
 1843                      $val[1] = array($val[1]);
 1844                  }
 1845   
 1846                  foreach ($val[1] as $valkey => $value_1)
 1847                  {
 1848                      // This should cover about any case:
 1849                      //
 1850                      // table.field                    => SELECT table.field                FROM table
 1851                      // table.field AS alias            => SELECT table.field    AS alias    FROM table
 1852                      // table.field AS table2.alias    => SELECT table2.field    AS alias    FROM table table2
 1853                      // table.field AS table2.field    => SELECT table2.field                FROM table table2
 1854                      //
 1855                      if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m))
 1856                      {
 1857                          // There is 'AS ...' in the field names
 1858                          if (!empty($m[3]))
 1859                          {
 1860                              $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6];
 1861   
 1862                              // Table alias: store it then replace the source table with it
 1863                              if (!empty($m[5]) && $m[5] != $m[1])
 1864                              {
 1865                                  $aliases[$m[5]] = $m[1];
 1866                                  $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1);
 1867                              }
 1868                          }
 1869                          else
 1870                          {
 1871                              // No table alias
 1872                              $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1];
 1873                          }
 1874   
 1875                          $sql_data['select_fields'][$value_1] = $value_1;
 1876                          $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2];
 1877                      }
 1878                  }
 1879              }
 1880              else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having')
 1881              {
 1882                  if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m))
 1883                  {
 1884                      foreach ($m[1] as $value)
 1885                      {
 1886                          $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value;
 1887                      }
 1888                  }
 1889              }
 1890          }
 1891   
 1892          // Add the aliases to the list of tables
 1893          foreach ($aliases as $alias => $table)
 1894          {
 1895              $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias;
 1896          }
 1897   
 1898          // 'left_join'        => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id',
 1899          if (!empty($schema['left_join']))
 1900          {
 1901              if (!is_array($schema['left_join']))
 1902              {
 1903                  $schema['left_join'] = array($schema['left_join']);
 1904              }
 1905   
 1906              foreach ($schema['left_join'] as $left_join)
 1907              {
 1908                  // This won't handle concatened LEFT JOINs
 1909                  if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m))
 1910                  {
 1911                      $this->p_master->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__);
 1912                  }
 1913   
 1914                  if (!empty($aliases[$m[2]]))
 1915                  {
 1916                      if (!empty($m[3]))
 1917                      {
 1918                          $this->p_master->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__);
 1919                      }
 1920   
 1921                      $m[2] = $aliases[$m[2]];
 1922                      $m[3] = $m[2];
 1923                  }
 1924   
 1925                  $right_table = $convert->src_table_prefix . $m[2];
 1926                  if (!empty($m[3]))
 1927                  {
 1928                      unset($sql_data['source_tables'][$m[3]]);
 1929                  }
 1930                  else if ($m[2] != $m[1])
 1931                  {
 1932                      unset($sql_data['source_tables'][$m[2]]);
 1933                  }
 1934   
 1935                  if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false)
 1936                  {
 1937                      $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table";
 1938                  }
 1939                  else
 1940                  {
 1941                      $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table";
 1942                  }
 1943   
 1944                  if (!empty($m[3]))
 1945                  {
 1946                      unset($sql_data['source_tables'][$m[3]]);
 1947                      $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3];
 1948                  }
 1949                  else if (!empty($convert->src_table_prefix))
 1950                  {
 1951                      $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2];
 1952                  }
 1953                  $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5];
 1954              }
 1955          }
 1956   
 1957          // Remove ", " from the end of the insert query
 1958          $insert_query = substr($insert_query, 0, -2) . ') VALUES ';
 1959   
 1960          return $insert_query;
 1961      }
 1962   
 1963      /**
 1964      * Function for processing the currently handled row
 1965      */
 1966      function process_row(&$schema, &$sql_data, &$insert_values)
 1967      {
 1968          global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache;
 1969          global $convert, $convert_row;
 1970   
 1971          $sql_flag = false;
 1972   
 1973          foreach ($schema as $key => $fields)
 1974          {
 1975              // We are only interested in the lines with:
 1976              // array('comment', 'attachments_desc.comment', 'htmlspecialchars'),
 1977              if (is_int($key))
 1978              {
 1979                  if (!is_array($fields[1]))
 1980                  {
 1981                      $fields[1] = array($fields[1]);
 1982                  }
 1983   
 1984                  $firstkey_set = false;
 1985                  $firstkey = 0;
 1986   
 1987                  foreach ($fields[1] as $inner_key => $inner_value)
 1988                  {
 1989                      if (!$firstkey_set)
 1990                      {
 1991                          $firstkey = $inner_key;
 1992                          $firstkey_set = true;
 1993                      }
 1994   
 1995                      $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : '';
 1996   
 1997                      if (!empty($src_field))
 1998                      {
 1999                          $fields[1][$inner_key] = $convert->row[$src_field];
 2000                      }
 2001                  }
 2002   
 2003                  if (!empty($fields[0]))
 2004                  {
 2005                      // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE.
 2006                      // If a function has already set it to FALSE it won't change it.
 2007                      if ($sql_flag === false)
 2008                      {
 2009                          $sql_flag = true;
 2010                      }
 2011   
 2012                      // No function assigned?
 2013                      if (empty($fields[2]))
 2014                      {
 2015                          $value = $fields[1][$firstkey];
 2016                      }
 2017                      else if (is_array($fields[2]))
 2018                      {
 2019                          // Execute complex function/eval/typecast
 2020                          $value = $fields[1];
 2021   
 2022                          foreach ($fields[2] as $type => $execution)
 2023                          {
 2024                              if (strpos($type, 'typecast') === 0)
 2025                              {
 2026                                  if (!is_array($value))
 2027                                  {
 2028                                      $value = array($value);
 2029                                  }
 2030                                  $value = $value[0];
 2031                                  settype($value, $execution);
 2032                              }
 2033                              else if (strpos($type, 'function') === 0)
 2034                              {
 2035                                  if (!is_array($value))
 2036                                  {
 2037                                      $value = array($value);
 2038                                  }
 2039   
 2040                                  $value = call_user_func_array($execution, $value);
 2041                              }
 2042                              else if (strpos($type, 'execute') === 0)
 2043                              {
 2044                                  if (!is_array($value))
 2045                                  {
 2046                                      $value = array($value);
 2047                                  }
 2048   
 2049                                  $execution = str_replace('{RESULT}', '$value', $execution);
 2050                                  $execution = str_replace('{VALUE}', '$value', $execution);
 2051                                  // @codingStandardsIgnoreStart
 2052                                  eval($execution);
 2053                                  // @codingStandardsIgnoreEnd
 2054                              }
 2055                          }
 2056                      }
 2057                      else
 2058                      {
 2059                          $value = call_user_func_array($fields[2], $fields[1]);
 2060                      }
 2061   
 2062                      if (is_null($value))
 2063                      {
 2064                          $value = '';
 2065                      }
 2066   
 2067                      $insert_values[] = $db->_sql_validate_value($value);
 2068                  }
 2069                  else if (!empty($fields[2]))
 2070                  {
 2071                      if (is_array($fields[2]))
 2072                      {
 2073                          // Execute complex function/eval/typecast
 2074                          $value = '';
 2075   
 2076                          foreach ($fields[2] as $type => $execution)
 2077                          {
 2078                              if (strpos($type, 'typecast') === 0)
 2079                              {
 2080                                  $value = settype($value, $execution);
 2081                              }
 2082                              else if (strpos($type, 'function') === 0)
 2083                              {
 2084                                  if (!is_array($value))
 2085                                  {
 2086                                      $value = array($value);
 2087                                  }
 2088   
 2089                                  $value = call_user_func_array($execution, $value);
 2090                              }
 2091                              else if (strpos($type, 'execute') === 0)
 2092                              {
 2093                                  if (!is_array($value))
 2094                                  {
 2095                                      $value = array($value);
 2096                                  }
 2097   
 2098                                  $execution = str_replace('{RESULT}', '$value', $execution);
 2099                                  $execution = str_replace('{VALUE}', '$value', $execution);
 2100                                  // @codingStandardsIgnoreStart
 2101                                  eval($execution);
 2102                                  // @codingStandardsIgnoreEnd
 2103                              }
 2104                          }
 2105                      }
 2106                      else
 2107                      {
 2108                          call_user_func_array($fields[2], $fields[1]);
 2109                      }
 2110                  }
 2111              }
 2112          }
 2113   
 2114          return $sql_flag;
 2115      }
 2116   
 2117      /**
 2118      * Own meta refresh function to be able to change the global time used
 2119      */
 2120      function meta_refresh($url)
 2121      {
 2122          global $convert, $template;
 2123   
 2124          if ($convert->options['refresh'])
 2125          {
 2126              // Because we should not rely on correct settings, we simply use the relative path here directly.
 2127              $template->assign_vars(array(
 2128                  'S_REFRESH'    => true,
 2129                  'META'        => '<meta http-equiv="refresh" content="5; url=' . $url . '" />')
 2130              );
 2131          }
 2132      }
 2133   
 2134      /**
 2135      * The information below will be used to build the input fields presented to the user
 2136      */
 2137      var $convert_options = array(
 2138          'legend1'            => 'SPECIFY_OPTIONS',
 2139          'src_dbms'            => array('lang' => 'DBMS',            'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\', true)', 'explain' => false),
 2140          'src_dbhost'        => array('lang' => 'DB_HOST',        'type' => 'text:25:100', 'explain' => true),
 2141          'src_dbport'        => array('lang' => 'DB_PORT',        'type' => 'text:25:100', 'explain' => true),
 2142          'src_dbname'        => array('lang' => 'DB_NAME',        'type' => 'text:25:100', 'explain' => false),
 2143          'src_dbuser'        => array('lang' => 'DB_USERNAME',    'type' => 'text:25:100', 'explain' => false),
 2144          'src_dbpasswd'        => array('lang' => 'DB_PASSWORD',    'type' => 'password:25:100', 'explain' => false),
 2145          'src_table_prefix'    => array('lang' => 'TABLE_PREFIX',    'type' => 'text:25:100', 'explain' => false),
 2146          //'src_url'            => array('lang' => 'FORUM_ADDRESS',    'type' => 'text:50:100', 'explain' => true),
 2147          'forum_path'        => array('lang' => 'FORUM_PATH',    'type' => 'text:25:100', 'explain' => true),
 2148          'refresh'            => array('lang' => 'REFRESH_PAGE',    'type' => 'radio:yes_no', 'explain' => true),
 2149      );
 2150  }
 2151