Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


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

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

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

install_convert.php

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


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