Вход Регистрация
Файл: phpBB3/install/install_convert.php
Строк: 1733
<?php
/**
*
* @package install
* @version $Id$
* @copyright (c) 2006 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

/**
*/

if (!defined('IN_INSTALL'))
{
    
// Someone has tried to access the file direct. This is not a good idea, so exit
    
exit;
}

if (!empty(
$setmodules))
{
    
$module[] = array(
        
'module_type'        => 'install',
        
'module_title'        => 'CONVERT',
        
'module_filename'    => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
        
'module_order'        => 20,
        
'module_subs'        => '',
        
'module_stages'        => array('INTRO''SETTINGS''IN_PROGRESS''FINAL'),
        
'module_reqs'        => ''
    
);
}

/**
* Class holding all convertor-specific details.
* @package install
*/
class convert
{
    var 
$options = array();

    var 
$convertor_tag '';
    var 
$src_dbms '';
    var 
$src_dbhost '';
    var 
$src_dbport '';
    var 
$src_dbuser '';
    var 
$src_dbpasswd '';
    var 
$src_dbname '';
    var 
$src_table_prefix '';

    var 
$convertor_data = array();
    var 
$tables = array();
    var 
$config_schema = array();
    var 
$convertor = array();
    var 
$src_truncate_statement 'DELETE FROM ';
    var 
$truncate_statement 'DELETE FROM ';

    var 
$fulltext_search;

    
// Batch size, can be adjusted by the conversion file
    // For big boards a value of 6000 seems to be optimal
    
var $batch_size 2000;
    
// Number of rows to be inserted at once (extended insert) if supported
    // For installations having enough memory a value of 60 may be good.
    
var $num_wait_rows 20;

    
// Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor.
    
var $mysql_convert false;

    var 
$p_master;

    function 
convert(&$p_master)
    {
        
$this->p_master = &$p_master;
    }
}

/**
* Convert class for conversions
* @package install
*/
class install_convert extends module
{
    
/**
    * Variables used while converting, they are accessible from the global variable $convert
    */
    
function install_convert(&$p_master)
    {
        
$this->p_master = &$p_master;
    }

    function 
main($mode$sub)
    {
        global 
$lang$template$phpbb_root_path$phpEx$cache$config$language$table_prefix;
        global 
$convert;

        
$this->tpl_name 'install_convert';
        
$this->mode $mode;

        
$convert = new convert($this->p_master);

        switch (
$sub)
        {
            case 
'intro':
                
// Try opening config file
                // @todo If phpBB is not installed, we need to do a cut-down installation here
                // For now, we redirect to the installation script instead
                
if (@file_exists($phpbb_root_path 'config.' $phpEx))
                {
                    include(
$phpbb_root_path 'config.' $phpEx);
                }

                if (!
defined('PHPBB_INSTALLED'))
                {
                    
$template->assign_vars(array(
                        
'S_NOT_INSTALLED'        => true,
                        
'TITLE'                    => $lang['BOARD_NOT_INSTALLED'],
                        
'BODY'                    => sprintf($lang['BOARD_NOT_INSTALLED_EXPLAIN'], append_sid($phpbb_root_path 'install/index.' $phpEx'mode=install&amp;language=' $language)),
                    ));

                    return;
                }

                require(
$phpbb_root_path 'config.' $phpEx);
                require(
$phpbb_root_path 'includes/constants.' $phpEx);
                require(
$phpbb_root_path 'includes/db/' $dbms '.' $phpEx);
                require(
$phpbb_root_path 'includes/functions_convert.' $phpEx);

                
$db = new $sql_db();
                
$db->sql_connect($dbhost$dbuser$dbpasswd$dbname$dbportfalsetrue);
                unset(
$dbpasswd);

                
// We need to fill the config to let internal functions correctly work
                
$sql 'SELECT *
                    FROM ' 
CONFIG_TABLE;
                
$result $db->sql_query($sql);

                
$config = array();
                while (
$row $db->sql_fetchrow($result))
                {
                    
$config[$row['config_name']] = $row['config_value'];
                }
                
$db->sql_freeresult($result);

                
// Detect if there is already a conversion in progress at this point and offer to resume
                // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it
                
$new_conversion request_var('new_conv'0);

                if (
$new_conversion)
                {
                    
$config['convert_progress'] = '';
                    
$config['convert_db_server'] = '';
                    
$config['convert_db_user'] = '';
                    
$db->sql_query('DELETE FROM ' CONFIG_TABLE "
                        WHERE config_name = 'convert_progress'
                            OR config_name = 'convert_db_server'
                            OR config_name = 'convert_db_user'"
                    
);
                }

                
// Let's see if there is a conversion in the works...
                
$options = array();
                if (!empty(
$config['convert_progress']) && !empty($config['convert_db_server']) && !empty($config['convert_db_user']) && !empty($config['convert_options']))
                {
                    
$options unserialize($config['convert_progress']);
                    
$options array_merge($optionsunserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
                }

                
// This information should have already been checked once, but do it again for safety
                
if (!empty($options) && !empty($options['tag']) &&
                    isset(
$options['dbms']) &&
                    isset(
$options['dbhost']) &&
                    isset(
$options['dbport']) &&
                    isset(
$options['dbuser']) &&
                    isset(
$options['dbpasswd']) &&
                    isset(
$options['dbname']) &&
                    isset(
$options['table_prefix']))
                {
                    
$this->page_title $lang['CONTINUE_CONVERT'];

                    
$template->assign_vars(array(
                        
'TITLE'            => $lang['CONTINUE_CONVERT'],
                        
'BODY'            => $lang['CONTINUE_CONVERT_BODY'],
                        
'L_NEW'            => $lang['CONVERT_NEW_CONVERSION'],
                        
'L_CONTINUE'    => $lang['CONTINUE_OLD_CONVERSION'],
                        
'S_CONTINUE'    => true,

                        
'U_NEW_ACTION'        => $this->p_master->module_url "?mode={$this->mode}&amp;sub=intro&amp;new_conv=1&amp;language=$language",
                        
'U_CONTINUE_ACTION'    => $this->p_master->module_url "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$options['tag']}{$options['step']}&amp;language=$language",
                    ));

                    return;
                }

                
$this->list_convertors($sub);

            break;

            case 
'settings':
                
$this->get_convert_settings($sub);
            break;

            case 
'in_progress':
                
$this->convert_data($sub);
            break;

            case 
'final':
                
$this->page_title $lang['CONVERT_COMPLETE'];

                
$template->assign_vars(array(
                    
'TITLE'        => $lang['CONVERT_COMPLETE'],
                    
'BODY'        => $lang['CONVERT_COMPLETE_EXPLAIN'],
                ));

                
// If we reached this step (conversion completed) we want to purge the cache and log the user out.
                // This is for making sure the session get not screwed due to the 3.0.x users table being completely new.
                
$cache->purge();

                require(
$phpbb_root_path 'config.' $phpEx);
                require(
$phpbb_root_path 'includes/constants.' $phpEx);
                require(
$phpbb_root_path 'includes/db/' $dbms '.' $phpEx);
                require(
$phpbb_root_path 'includes/functions_convert.' $phpEx);

                
$db = new $sql_db();
                
$db->sql_connect($dbhost$dbuser$dbpasswd$dbname$dbportfalsetrue);
                unset(
$dbpasswd);

                
$sql 'SELECT config_value
                    FROM ' 
CONFIG_TABLE '
                    WHERE config_name = '
search_type'';
                
$result $db->sql_query($sql);

                if (
$db->sql_fetchfield('config_value') != 'fulltext_mysql')
                {
                    
$template->assign_vars(array(
                        
'S_ERROR_BOX'    => true,
                        
'ERROR_TITLE'    => $lang['SEARCH_INDEX_UNCONVERTED'],
                        
'ERROR_MSG'        => $lang['SEARCH_INDEX_UNCONVERTED_EXPLAIN'],
                    ));
                }

                switch (
$db->sql_layer)
                {
                    case 
'sqlite':
                    case 
'firebird':
                        
$db->sql_query('DELETE FROM ' SESSIONS_KEYS_TABLE);
                        
$db->sql_query('DELETE FROM ' SESSIONS_TABLE);
                    break;

                    default:
                        
$db->sql_query('TRUNCATE TABLE ' SESSIONS_KEYS_TABLE);
                        
$db->sql_query('TRUNCATE TABLE ' SESSIONS_TABLE);
                    break;
                }

            break;
        }
    }

    
/**
    * Generate a list of all available conversion modules
    */
    
function list_convertors($sub)
    {
        global 
$lang$language$template$phpbb_root_path$phpEx;

        
$this->page_title $lang['SUB_INTRO'];

        
$template->assign_vars(array(
            
'TITLE'        => $lang['CONVERT_INTRO'],
            
'BODY'        => $lang['CONVERT_INTRO_BODY'],

            
'L_AUTHOR'                    => $lang['AUTHOR'],
            
'L_AVAILABLE_CONVERTORS'    => $lang['AVAILABLE_CONVERTORS'],
            
'L_CONVERT'                    => $lang['CONVERT'],
            
'L_NO_CONVERTORS'            => $lang['NO_CONVERTORS'],
            
'L_OPTIONS'                    => $lang['CONVERT_OPTIONS'],
            
'L_SOFTWARE'                => $lang['SOFTWARE'],
            
'L_VERSION'                    => $lang['VERSION'],

            
'S_LIST'    => true,
        ));

        
$convertors $sort = array();
        
$get_info true;

        
$handle = @opendir('./convertors/');

        if (!
$handle)
        {
            
$this->error('Unable to access the convertors directory'__LINE____FILE__);
        }

        while (
$entry readdir($handle))
        {
            if (
preg_match('/^convert_([a-z0-9_]+).' $phpEx '$/i'$entry$m))
            {
                include(
'./convertors/' $entry);
                if (isset(
$convertor_data))
                {
                    
$sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors);

                    
$convertors[] = array(
                        
'tag'            =>    $m[1],
                        
'forum_name'    =>    $convertor_data['forum_name'],
                        
'version'        =>    $convertor_data['version'],
                        
'dbms'            =>    $convertor_data['dbms'],
                        
'dbhost'        =>    $convertor_data['dbhost'],
                        
'dbport'        =>    $convertor_data['dbport'],
                        
'dbuser'        =>    $convertor_data['dbuser'],
                        
'dbpasswd'        =>    $convertor_data['dbpasswd'],
                        
'dbname'        =>    $convertor_data['dbname'],
                        
'table_prefix'    =>    $convertor_data['table_prefix'],
                        
'author'        =>    $convertor_data['author']
                    );
                }
                unset(
$convertor_data);
            }
        }
        
closedir($handle);

        @
ksort($sort);

        foreach (
$sort as $void => $index)
        {
            
$template->assign_block_vars('convertors', array(
                
'AUTHOR'    => $convertors[$index]['author'],
                
'SOFTWARE'    => $convertors[$index]['forum_name'],
                
'VERSION'    => $convertors[$index]['version'],

                
'U_CONVERT'    => $this->p_master->module_url "?mode={$this->mode}&amp;language=$language&amp;sub=settings&amp;tag=" $convertors[$index]['tag'],
            ));
        }
    }

    
/**
    */
    
function get_convert_settings($sub)
    {
        global 
$lang$language$template$db$phpbb_root_path$phpEx$config$cache;

        require(
$phpbb_root_path 'config.' $phpEx);
        require(
$phpbb_root_path 'includes/constants.' $phpEx);
        require(
$phpbb_root_path 'includes/db/' $dbms '.' $phpEx);
        require(
$phpbb_root_path 'includes/functions_convert.' $phpEx);

        
$db = new $sql_db();
        
$db->sql_connect($dbhost$dbuser$dbpasswd$dbname$dbportfalsetrue);
        unset(
$dbpasswd);

        
$this->page_title $lang['STAGE_SETTINGS'];

        
// We need to fill the config to let internal functions correctly work
        
$sql 'SELECT *
            FROM ' 
CONFIG_TABLE;
        
$result $db->sql_query($sql);

        
$config = array();
        while (
$row $db->sql_fetchrow($result))
        {
            
$config[$row['config_name']] = $row['config_value'];
        }
        
$db->sql_freeresult($result);

        
$convertor_tag request_var('tag''');

        if (empty(
$convertor_tag))
        {
            
$this->p_master->error($lang['NO_CONVERT_SPECIFIED'], __LINE____FILE__);
        }
        
$get_info true;

        
// check security implications of direct inclusion
        
$convertor_tag basename($convertor_tag);
        if (!
file_exists('./convertors/convert_' $convertor_tag '.' $phpEx))
        {
            
$this->p_master->error($lang['CONVERT_NOT_EXIST'], __LINE____FILE__);
        }

        include(
'./convertors/convert_' $convertor_tag '.' $phpEx);

        
// The test_file is a file that should be present in the location of the old board.
        
if (!isset($test_file))
        {
            
$this->p_master->error($lang['DEV_NO_TEST_FILE'], __LINE____FILE__);
        }

        
$submit = (isset($_POST['submit'])) ? true false;

        
$src_dbms            request_var('src_dbms'$convertor_data['dbms']);
        
$src_dbhost            request_var('src_dbhost'$convertor_data['dbhost']);
        
$src_dbport            request_var('src_dbport'$convertor_data['dbport']);
        
$src_dbuser            request_var('src_dbuser'$convertor_data['dbuser']);
        
$src_dbpasswd        request_var('src_dbpasswd'$convertor_data['dbpasswd']);
        
$src_dbname            request_var('src_dbname'$convertor_data['dbname']);
        
$src_table_prefix    request_var('src_table_prefix'$convertor_data['table_prefix']);
        
$forum_path            request_var('forum_path'$convertor_data['forum_path']);
        
$refresh            request_var('refresh'1);

        
// Default URL of the old board
        // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it?
        //        -> We should convert old urls to the new relative urls format
        // $src_url = request_var('src_url', 'Not in use at the moment');

        // strip trailing slash from old forum path
        
$forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path0, -1) : $forum_path;

        
$error = array();
        if (
$submit)
        {
            if (!@
file_exists('./../' $forum_path '/' $test_file))
            {
                
$error[] = sprintf($lang['COULD_NOT_FIND_PATH'], $forum_path);
            }

            
$connect_test false;
            
$available_dbms get_available_dbms(falsetruetrue);

            if (!isset(
$available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE'])
            {
                
$error[] = $lang['INST_ERR_NO_DB'];
                
$connect_test false;
            }
            else
            {
                
$connect_test connect_check_db(true$error$available_dbms[$src_dbms], $src_table_prefix$src_dbhost$src_dbuserhtmlspecialchars_decode($src_dbpasswd), $src_dbname$src_dbporttrue, ($src_dbms == $dbms) ? false truefalse);
            }

            
// The forum prefix of the old and the new forum can only be the same if two different databases are used.
            
if ($src_table_prefix == $table_prefix && $src_dbms == $dbms && $src_dbhost == $dbhost && $src_dbport == $dbport && $src_dbname == $dbname)
            {
                
$error[] = sprintf($lang['TABLE_PREFIX_SAME'], $src_table_prefix);
            }

            
// Check table prefix
            
if (!sizeof($error))
            {
                
// initiate database connection to old db if old and new db differ
                
global $src_db$same_db;
                
$src_db $same_db false;

                if (
$src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser)
                {
                    
$sql_db 'dbal_' $src_dbms;
                    
$src_db = new $sql_db();
                    
$src_db->sql_connect($src_dbhost$src_dbuserhtmlspecialchars_decode($src_dbpasswd), $src_dbname$src_dbportfalsetrue);
                    
$same_db false;
                }
                else
                {
                    
$src_db $db;
                    
$same_db true;
                }

                
$src_db->sql_return_on_error(true);
                
$db->sql_return_on_error(true);

                
// Try to select one row from the first table to see if the prefix is OK
                
$result $src_db->sql_query_limit('SELECT * FROM ' $src_table_prefix $tables[0], 1);

                if (!
$result)
                {
                    
$prefixes = array();

                    
$tables_existing get_tables($src_db);
                    
$tables_existing array_map('strtolower'$tables_existing);
                    foreach (
$tables_existing as $table_name)
                    {
                        
compare_table($tables$table_name$prefixes);
                    }
                    unset(
$tables_existing);

                    foreach (
$prefixes as $prefix => $count)
                    {
                        if (
$count >= sizeof($tables))
                        {
                            
$possible_prefix $prefix;
                            break;
                        }
                    }

                    
$msg '';
                    if (!empty(
$convertor_data['table_prefix']))
                    {
                        
$msg .= sprintf($lang['DEFAULT_PREFIX_IS'], $convertor_data['forum_name'], $convertor_data['table_prefix']);
                    }

                    if (!empty(
$possible_prefix))
                    {
                        
$msg .= '<br />';
                        
$msg .= ($possible_prefix == '*') ? $lang['BLANK_PREFIX_FOUND'] : sprintf($lang['PREFIX_FOUND'], $possible_prefix);
                        
$src_table_prefix = ($possible_prefix == '*') ? '' $possible_prefix;
                    }

                    
$error[] = $msg;
                }
                
$src_db->sql_freeresult($result);
                
$src_db->sql_return_on_error(false);
            }

            if (!
sizeof($error))
            {
                
// Save convertor Status
                
set_config('convert_progress'serialize(array(
                    
'step'            => '',
                    
'table_prefix'    => $src_table_prefix,
                    
'tag'            => $convertor_tag,
                )), 
true);
                
set_config('convert_db_server'serialize(array(
                    
'dbms'            => $src_dbms,
                    
'dbhost'        => $src_dbhost,
                    
'dbport'        => $src_dbport,
                    
'dbname'        => $src_dbname,
                )), 
true);
                
set_config('convert_db_user'serialize(array(
                    
'dbuser'        => $src_dbuser,
                    
'dbpasswd'        => $src_dbpasswd,
                )), 
true);

                
// Save options
                
set_config('convert_options'serialize(array('forum_path' => './../' $forum_path'refresh' => $refresh)), true);

                
$template->assign_block_vars('checks', array(
                    
'TITLE'        => $lang['VERIFY_OPTIONS'],
                    
'RESULT'    => $lang['CONVERT_SETTINGS_VERIFIED'],
                ));

                
$template->assign_vars(array(
                    
'L_SUBMIT'    => $lang['BEGIN_CONVERT'],
//                    'S_HIDDEN'    => $s_hidden_fields,
                    
'U_ACTION'    => $this->p_master->module_url "?mode={$this->mode}&amp;sub=in_progress&amp;tag=$convertor_tag&amp;language=$language",
                ));

                return;
            }
            else
            {
                
$template->assign_block_vars('checks', array(
                    
'TITLE'        => $lang['VERIFY_OPTIONS'],
                    
'RESULT'    => '<b style="color:red">' implode('<br />'$error) . '</b>',
                ));
            }
        } 
// end submit

        
foreach ($this->convert_options as $config_key => $vars)
        {
            if (!
is_array($vars) && strpos($config_key'legend') === false)
            {
                continue;
            }

            if (
strpos($config_key'legend') !== false)
            {
                
$template->assign_block_vars('options', array(
                    
'S_LEGEND'        => true,
                    
'LEGEND'        => $lang[$vars])
                );

                continue;
            }

            
$options = isset($vars['options']) ? $vars['options'] : '';

            
$template->assign_block_vars('options', array(
                
'KEY'            => $config_key,
                
'TITLE'            => $lang[$vars['lang']],
                
'S_EXPLAIN'        => $vars['explain'],
                
'S_LEGEND'        => false,
                
'TITLE_EXPLAIN'    => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
                
'CONTENT'        => $this->p_master->input_field($config_key$vars['type'], $$config_key$options),
                )
            );
        }

        
$template->assign_vars(array(
            
'TITLE'        => $lang['STAGE_SETTINGS'],
            
'BODY'        => $lang['CONV_OPTIONS_BODY'],
            
'L_SUBMIT'    => $lang['BEGIN_CONVERT'],
            
'U_ACTION'    => $this->p_master->module_url "?mode={$this->mode}&amp;sub=settings&amp;tag=$convertor_tag&amp;language=$language",
        ));
    }

    
/**
    * The function which does the actual work (or dispatches it to the relevant places)
    */
    
function convert_data($sub)
    {
        global 
$template$user$phpbb_root_path$phpEx$db$lang$config$cache;
        global 
$convert$convert_row$message_parser$skip_rows$language;

        require(
$phpbb_root_path 'config.' $phpEx);
        require(
$phpbb_root_path 'includes/constants.' $phpEx);
        require(
$phpbb_root_path 'includes/db/' $dbms '.' $phpEx);
        require(
$phpbb_root_path 'includes/functions_convert.' $phpEx);

        
$db = new $sql_db();
        
$db->sql_connect($dbhost$dbuser$dbpasswd$dbname$dbportfalsetrue);
        unset(
$dbpasswd);

        
$sql 'SELECT *
            FROM ' 
CONFIG_TABLE;
        
$result $db->sql_query($sql);

        
$config = array();
        while (
$row $db->sql_fetchrow($result))
        {
            
$config[$row['config_name']] = $row['config_value'];
        }
        
$db->sql_freeresult($result);

        
// Override a couple of config variables for the duration
        
$config['max_quote_depth'] = 0;

        
// @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
        
$config['max_post_chars'] = $config['min_post_chars'] = 0;

        
// Set up a user as well. We _should_ have enough of a database here at this point to do this
        // and it helps for any core code we call
        
$user->session_begin();
        
$user->page $user->extract_current_page($phpbb_root_path);

        
// This is a little bit of a fudge, but it allows the language entries to be available to the
        // core code without us loading them again
        
$user->lang = &$lang;

        
$this->page_title $user->lang['STAGE_IN_PROGRESS'];

        
$convert->options = array();
        if (isset(
$config['convert_progress']))
        {
            
$convert->options unserialize($config['convert_progress']);
            
$convert->options array_merge($convert->optionsunserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
        }

        
// This information should have already been checked once, but do it again for safety
        
if (empty($convert->options) || empty($convert->options['tag']) ||
            !isset(
$convert->options['dbms']) ||
            !isset(
$convert->options['dbhost']) ||
            !isset(
$convert->options['dbport']) ||
            !isset(
$convert->options['dbuser']) ||
            !isset(
$convert->options['dbpasswd']) ||
            !isset(
$convert->options['dbname']) ||
            !isset(
$convert->options['table_prefix']))
        {
            
$this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE____FILE__);
        }

        
// Make some short variables accessible, for easier referencing
        
$convert->convertor_tag basename($convert->options['tag']);
        
$convert->src_dbms $convert->options['dbms'];
        
$convert->src_dbhost $convert->options['dbhost'];
        
$convert->src_dbport $convert->options['dbport'];
        
$convert->src_dbuser $convert->options['dbuser'];
        
$convert->src_dbpasswd $convert->options['dbpasswd'];
        
$convert->src_dbname $convert->options['dbname'];
        
$convert->src_table_prefix $convert->options['table_prefix'];

        
// initiate database connection to old db if old and new db differ
        
global $src_db$same_db;
        
$src_db $same_db null;
        if (
$convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser)
        {
            if (
$convert->src_dbms != $dbms)
            {
                require(
$phpbb_root_path 'includes/db/' $convert->src_dbms '.' $phpEx);
            }
            
$sql_db 'dbal_' $convert->src_dbms;
            
$src_db = new $sql_db();
            
$src_db->sql_connect($convert->src_dbhost$convert->src_dbuserhtmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname$convert->src_dbportfalsetrue);
            
$same_db false;
        }
        else
        {
            
$src_db $db;
            
$same_db true;
        }

        
$convert->mysql_convert false;
        switch (
$src_db->sql_layer)
        {
            case 
'sqlite':
            case 
'firebird':
                
$convert->src_truncate_statement 'DELETE FROM ';
            break;

            
// Thanks MySQL, for silently converting...
            
case 'mysql':
            case 
'mysql4':
                if (
version_compare($src_db->sql_server_info(truefalse), '4.1.3''>='))
                {
                    
$convert->mysql_convert true;
                }
                
$convert->src_truncate_statement 'TRUNCATE TABLE ';
            break;

            case 
'mysqli':
                
$convert->mysql_convert true;
                
$convert->src_truncate_statement 'TRUNCATE TABLE ';
            break;

            default:
                
$convert->src_truncate_statement 'TRUNCATE TABLE ';
            break;
        }

        if (
$convert->mysql_convert && !$same_db)
        {
            
$src_db->sql_query("SET NAMES 'binary'");
        }

        switch (
$db->sql_layer)
        {
            case 
'sqlite':
            case 
'firebird':
                
$convert->truncate_statement 'DELETE FROM ';
            break;

            default:
                
$convert->truncate_statement 'TRUNCATE TABLE ';
            break;
        }

        
$get_info false;

        
// check security implications of direct inclusion
        
if (!file_exists('./convertors/convert_' $convert->convertor_tag '.' $phpEx))
        {
            
$this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE____FILE__);
        }

        if (
file_exists('./convertors/functions_' $convert->convertor_tag '.' $phpEx))
        {
            include(
'./convertors/functions_' $convert->convertor_tag '.' $phpEx);
        }

        
$get_info true;
        include(
'./convertors/convert_' $convert->convertor_tag '.' $phpEx);

        
// Map some variables...
        
$convert->convertor_data $convertor_data;
        
$convert->tables $tables;
        
$convert->config_schema $config_schema;

        
// Now include the real data
        
$get_info false;
        include(
'./convertors/convert_' $convert->convertor_tag '.' $phpEx);

        
$convert->convertor_data $convertor_data;
        
$convert->tables $tables;
        
$convert->config_schema $config_schema;
        
$convert->convertor $convertor;

        
// The test_file is a file that should be present in the location of the old board.
        
if (!file_exists($convert->options['forum_path'] . '/' $test_file))
        {
            
$this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE____FILE__);
        }

        
$search_type basename(trim($config['search_type']));

        
// For conversions we are a bit less strict and set to a search backend we know exist...
        
if (!file_exists($phpbb_root_path 'includes/search/' $search_type '.' $phpEx))
        {
            
$search_type 'fulltext_native';
            
set_config('search_type'$search_type);
        }

        if (!
file_exists($phpbb_root_path 'includes/search/' $search_type '.' $phpEx))
        {
            
trigger_error('NO_SUCH_SEARCH_MODULE');
        }

        require(
$phpbb_root_path 'includes/search/' $search_type '.' $phpEx);

        
$error false;
        
$convert->fulltext_search = new $search_type($error);

        if (
$error)
        {
            
trigger_error($error);
        }

        include(
$phpbb_root_path 'includes/message_parser.' $phpEx);
        
$message_parser = new parse_message();

        
$jump request_var('jump'0);
        
$final_jump request_var('final_jump'0);
        
$sync_batch request_var('sync_batch', -1);
        
$last_statement request_var('last'0);

        
// We are running sync...
        
if ($sync_batch >= 0)
        {
            
$this->sync_forums($sync_batch);
            return;
        }

        if (
$jump)
        {
            
$this->jump($jump$last_statement);
            return;
        }

        if (
$final_jump)
        {
            
$this->final_jump($final_jump);
            return;
        }

        
$current_table request_var('current_table'0);
        
$old_current_table min(-1$current_table 1);
        
$skip_rows request_var('skip_rows'0);

        if (!
$current_table && !$skip_rows)
        {
            if (empty(
$_REQUEST['confirm']))
            {
                
// If avatars / ranks / smilies folders are specified make sure they are writable
                
$bad_folders = array();

                
$local_paths = array(
                    
'avatar_path'            => path($config['avatar_path']),
                    
'avatar_gallery_path'    => path($config['avatar_gallery_path']),
                    
'icons_path'            => path($config['icons_path']),
                    
'ranks_path'            => path($config['ranks_path']),
                    
'smilies_path'            => path($config['smilies_path'])
                );

                foreach (
$local_paths as $folder => $local_path)
                {
                    if (isset(
$convert->convertor[$folder]))
                    {
                        if (empty(
$convert->convertor['test_file']))
                        {
                            
// test_file is mandantory at the moment so this should never be reached, but just in case...
                            
$this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE____FILE__);
                        }

                        if (!
$local_path || !phpbb_is_writable($phpbb_root_path $local_path))
                        {
                            if (!
$local_path)
                            {
                                
$bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
                            }
                            else
                            {
                                
$bad_folders[] = $local_path;
                            }
                        }
                    }
                }

                if (
sizeof($bad_folders))
                {
                    
$msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
                    
sort($bad_folders);
                    
$this->p_master->error(sprintf($msgimplode('<br />'$bad_folders)), __LINE____FILE__true);

                    
$template->assign_vars(array(
                        
'L_SUBMIT'    => $user->lang['INSTALL_TEST'],
                        
'U_ACTION'    => $this->p_master->module_url "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}&amp;language=$language",
                    ));
                    return;
                }

                
// Grab all the tables used in convertor
                
$missing_tables $tables_list $aliases = array();

                foreach (
$convert->convertor['schema'] as $schema)
                {
                    
// Skip those not used (because of addons/plugins not detected)
                    
if (!$schema['target'])
                    {
                        continue;
                    }

                    foreach (
$schema as $key => $val)
                    {
                        
// we're dealing with an array like:
                        // array('forum_status',            'forums.forum_status',                'is_item_locked')
                        
if (is_int($key) && !empty($val[1]))
                        {
                            
$temp_data $val[1];
                            if (!
is_array($temp_data))
                            {
                                
$temp_data = array($temp_data);
                            }

                            foreach (
$temp_data as $val)
                            {
                                if (
preg_match('/([a-z0-9_]+).([a-z0-9_]+))* ?A?S? ?([a-z0-9_]*?).?([a-z0-9_]*)$/i'$val$m))
                                {
                                    
$table $convert->src_table_prefix $m[1];
                                    
$tables_list[$table] = $table;

                                    if (!empty(
$m[3]))
                                    {
                                        
$aliases[] = $convert->src_table_prefix $m[3];
                                    }
                                }
                            }
                        }
                        
// 'left_join'        => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1'
                        
else if ($key == 'left_join')
                        {
                            
// Convert the value if it wasn't an array already.
                            
if (!is_array($val))
                            {
                                
$val = array($val);
                            }

                            for (
$j 0$j sizeof($val); ++$j)
                            {
                                if (
preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i'$val[$j], $m))
                                {
                                    
$table $convert->src_table_prefix $m[1];
                                    
$tables_list[$table] = $table;

                                    if (!empty(
$m[2]))
                                    {
                                        
$aliases[] = $convert->src_table_prefix $m[2];
                                    }
                                }
                            }
                        }
                    }
                }

                
// Remove aliased tables from $tables_list
                
foreach ($aliases as $alias)
                {
                    unset(
$tables_list[$alias]);
                }

                
// Check if the tables that we need exist
                
$src_db->sql_return_on_error(true);
                foreach (
$tables_list as $table => $null)
                {
                    
$sql 'SELECT 1 FROM ' $table;
                    
$_result $src_db->sql_query_limit($sql1);

                    if (!
$_result)
                    {
                        
$missing_tables[] = $table;
                    }
                    
$src_db->sql_freeresult($_result);
                }
                
$src_db->sql_return_on_error(false);

                
// Throw an error if some tables are missing
                // 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

                
if (sizeof($missing_tables) == sizeof($tables_list))
                {
                    
$this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' $user->lang['CHECK_TABLE_PREFIX'], __LINE____FILE__);
                }
                else if (
sizeof($missing_tables))
                {
                    
$this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode(', '$missing_tables)) . '<br /><br />' $user->lang['CHECK_TABLE_PREFIX'], __LINE____FILE__);
                }

                
$url $this->save_convert_progress('&amp;confirm=1');
                
$msg $user->lang['PRE_CONVERT_COMPLETE'];

                if (
$convert->convertor_data['author_notes'])
                {
                    
$msg .= '</p><p>' sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
                }

                
$template->assign_vars(array(
                    
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
                    
'L_MESSAGE'        => $msg,
                    
'U_ACTION'        => $url,
                ));

                return;
            } 
// if (empty($_REQUEST['confirm']))

            
$template->assign_block_vars('checks', array(
                
'S_LEGEND'        => true,
                
'LEGEND'        => $user->lang['STARTING_CONVERT'],
            ));

            
// Convert the config table and load the settings of the old board
            
if (!empty($convert->config_schema))
            {
                
restore_config($convert->config_schema);

                
// Override a couple of config variables for the duration
                
$config['max_quote_depth'] = 0;

                
// @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
                
$config['max_post_chars'] = $config['min_post_chars'] = 0;
            }

            
$template->assign_block_vars('checks', array(
                
'TITLE'        => $user->lang['CONFIG_CONVERT'],
                
'RESULT'    => $user->lang['DONE'],
            ));

            
// Now process queries and execute functions that have to be executed prior to the conversion
            
if (!empty($convert->convertor['execute_first']))
            {
                eval(
$convert->convertor['execute_first']);
            }

            if (!empty(
$convert->convertor['query_first']))
            {
                if (!
is_array($convert->convertor['query_first']))
                {
                    
$convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
                }
                else if (!
is_array($convert->convertor['query_first'][0]))
                {
                    
$convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
                }

                foreach (
$convert->convertor['query_first'] as $query_first)
                {
                    if (
$query_first[0] == 'src')
                    {
                        if (
$convert->mysql_convert && $same_db)
                        {
                            
$src_db->sql_query("SET NAMES 'binary'");
                        }

                        
$src_db->sql_query($query_first[1]);

                        if (
$convert->mysql_convert && $same_db)
                        {
                            
$src_db->sql_query("SET NAMES 'utf8'");
                        }
                    }
                    else
                    {
                        
$db->sql_query($query_first[1]);
                    }
                }
            }

            
$template->assign_block_vars('checks', array(
                
'TITLE'        => $user->lang['PREPROCESS_STEP'],
                
'RESULT'    => $user->lang['DONE'],
            ));
        } 
// if (!$current_table && !$skip_rows)

        
$template->assign_block_vars('checks', array(
            
'S_LEGEND'        => true,
            
'LEGEND'        => $user->lang['FILLING_TABLES'],
        ));

        
// This loop takes one target table and processes it
        
while ($current_table sizeof($convert->convertor['schema']))
        {
            
$schema $convert->convertor['schema'][$current_table];

            
// The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
            
if (empty($schema['target']))
            {
                
$current_table++;
                continue;
            }

            
$template->assign_block_vars('checks', array(
                
'TITLE'    => sprintf($user->lang['FILLING_TABLE'], $schema['target']),
            ));

            
// This is only the case when we first start working on the tables.
            
if (!$skip_rows)
            {
                
// process execute_first and query_first for this table...
                
if (!empty($schema['execute_first']))
                {
                    eval(
$schema['execute_first']);
                }

                if (!empty(
$schema['query_first']))
                {
                    if (!
is_array($schema['query_first']))
                    {
                        
$schema['query_first'] = array('target', array($schema['query_first']));
                    }
                    else if (!
is_array($schema['query_first'][0]))
                    {
                        
$schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
                    }

                    foreach (
$schema['query_first'] as $query_first)
                    {
                        if (
$query_first[0] == 'src')
                        {
                            if (
$convert->mysql_convert && $same_db)
                            {
                                
$src_db->sql_query("SET NAMES 'binary'");
                            }
                            
$src_db->sql_query($query_first[1]);
                            if (
$convert->mysql_convert && $same_db)
                            {
                                
$src_db->sql_query("SET NAMES 'utf8'");
                            }
                        }
                        else
                        {
                            
$db->sql_query($query_first[1]);
                        }
                    }
                }

                if (!empty(
$schema['autoincrement']))
                {
                    switch (
$db->sql_layer)
                    {
                        case 
'postgres':
                            
$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'] . '));');
                        break;

                        case 
'oracle':
                            
$result $db->sql_query('SELECT MAX(' $schema['autoincrement'] . ') as max_id FROM ' $schema['target']);
                            
$row $db->sql_fetchrow($result);
                            
$db->sql_freeresult($result);

                            
$largest_id = (int) $row['max_id'];

                            if (
$largest_id)
                            {
                                
$db->sql_query('DROP SEQUENCE ' $schema['target'] . '_seq');
                                
$db->sql_query('CREATE SEQUENCE ' $schema['target'] . '_seq START WITH ' . ($largest_id 1));
                            }
                        break;
                    }
                }
            }

            
// Process execute_always for this table
            // This is for code which needs to be executed on every pass of this table if
            // it gets split because of time restrictions
            
if (!empty($schema['execute_always']))
            {
                eval(
$schema['execute_always']);
            }

            
//
            // Set up some variables
            //
            // $waiting_rows    holds rows for multirows insertion (MySQL only)
            // $src_tables        holds unique tables with aliases to select from
            // $src_fields        will quickly refer source fields (or aliases) corresponding to the current index
            // $select_fields    holds the names of the fields to retrieve
            //

            
$sql_data = array(
                
'source_fields'        => array(),
                
'target_fields'        => array(),
                
'source_tables'        => array(),
                
'select_fields'        => array(),
            );

            
// This statement is building the keys for later insertion.
            
$insert_query $this->build_insert_query($schema$sql_data$current_table);

            
// If no source table is affected, we skip the table
            
if (empty($sql_data['source_tables']))
            {
                
$skip_rows 0;
                
$current_table++;
                continue;
            }

            
$distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' '';

            
$sql 'SELECT ' $distinct implode(', '$sql_data['select_fields']) . " nFROM " implode(', '$sql_data['source_tables']);

            
// Where
            
$sql .= (!empty($schema['where'])) ? "nWHERE (" $schema['where'] . ')' '';

            
// Group By
            
if (!empty($schema['group_by']))
            {
                
$schema['group_by'] = array($schema['group_by']);
                foreach (
$sql_data['select_fields'] as $select)
                {
                    
$alias strpos(strtolower($select), ' as ');
                    
$select = ($alias) ? substr($select0$alias) : $select;
                    if (!
in_array($select$schema['group_by']))
                    {
                        
$schema['group_by'][] = $select;
                    }
                }
            }
            
$sql .= (!empty($schema['group_by'])) ? "nGROUP BY " implode(', '$schema['group_by']) : '';

            
// Having
            
$sql .= (!empty($schema['having'])) ? "nHAVING " $schema['having'] : '';

            
// Order By
            
if (empty($schema['order_by']) && !empty($schema['primary']))
            {
                
$schema['order_by'] = $schema['primary'];
            }
            
$sql .= (!empty($schema['order_by'])) ? "nORDER BY " $schema['order_by'] : '';

            
// Counting basically holds the amount of rows processed.
            
$counting = -1;
            
$batch_time 0;

            while (
$counting === -|| ($counting >= $convert->batch_size && still_on_time()))
            {
                
$old_current_table $current_table;

                
$rows '';
                
$waiting_rows = array();

                if (!empty(
$batch_time))
                {
                    
$mtime explode(' 'microtime());
                    
$mtime $mtime[0] + $mtime[1];
                    
$rows ceil($counting/($mtime $batch_time)) . " rows/s ($counting rows) | ";
                }

                
$template->assign_block_vars('checks', array(
                    
'TITLE'        => "skip_rows = $skip_rows",
                    
'RESULT'    => $rows . ((defined('DEBUG_EXTRA') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' $user->lang['KIB'] : ''),
                ));

                
$mtime explode(' 'microtime());
                
$batch_time $mtime[0] + $mtime[1];

                if (
$convert->mysql_convert && $same_db)
                {
                    
$src_db->sql_query("SET NAMES 'binary'");
                }

                
// Take skip rows into account and only fetch batch_size amount of rows
                
$___result $src_db->sql_query_limit($sql$convert->batch_size$skip_rows);

                if (
$convert->mysql_convert && $same_db)
                {
                    
$src_db->sql_query("SET NAMES 'utf8'");
                }

                
// This loop processes each row
                
$counting 0;

                
$convert->row $convert_row = array();

                if (!empty(
$schema['autoincrement']))
                {
                    switch (
$db->sql_layer)
                    {
                        case 
'mssql':
                        case 
'mssql_odbc':
                        case 
'mssqlnative':
                            
$db->sql_query('SET IDENTITY_INSERT ' $schema['target'] . ' ON');
                        break;
                    }
                }

                
// Now handle the rows until time is over or no more rows to process...
                
while ($counting === || still_on_time())
                {
                    
$convert_row $src_db->sql_fetchrow($___result);

                    if (!
$convert_row)
                    {
                        
// move to the next batch or table
                        
break;
                    }

                    
// With this we are able to always save the last state
                    
$convert->row $convert_row;

                    
// Increment the counting variable, it stores the number of rows we have processed
                    
$counting++;

                    
$insert_values = array();

                    
$sql_flag $this->process_row($schema$sql_data$insert_values);

                    if (
$sql_flag === true)
                    {
                        switch (
$db->sql_layer)
                        {
                            
// If MySQL, we'll wait to have num_wait_rows rows to submit at once
                            
case 'mysql':
                            case 
'mysql4':
                            case 
'mysqli':
                                
$waiting_rows[] = '(' implode(', '$insert_values) . ')';

                                if (
sizeof($waiting_rows) >= $convert->num_wait_rows)
                                {
                                    
$errored false;

                                    
$db->sql_return_on_error(true);

                                    if (!
$db->sql_query($insert_query implode(', '$waiting_rows)))
                                    {
                                        
$errored true;
                                    }
                                    
$db->sql_return_on_error(false);

                                    if (
$errored)
                                    {
                                        
$db->sql_return_on_error(true);

                                        
// Because it errored out we will try to insert the rows one by one... most of the time this
                                        // is caused by duplicate entries - but we also do not want to miss one...
                                        
foreach ($waiting_rows as $waiting_sql)
                                        {
                                            if (!
$db->sql_query($insert_query $waiting_sql))
                                            {
                                                
$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);
                                            }
                                        }

                                        
$db->sql_return_on_error(false);
                                    }

                                    
$waiting_rows = array();
                                }

                            break;

                            default:
                                
$insert_sql $insert_query '(' implode(', '$insert_values) . ')';

                                
$db->sql_return_on_error(true);

                                if (!
$db->sql_query($insert_sql))
                                {
                                    
$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);
                                }
                                
$db->sql_return_on_error(false);

                                
$waiting_rows = array();

                            break;
                        }
                    }

                    
$skip_rows++;
                }
                
$src_db->sql_freeresult($___result);

                
// We might still have some rows waiting
                
if (sizeof($waiting_rows))
                {
                    
$errored false;
                    
$db->sql_return_on_error(true);

                    if (!
$db->sql_query($insert_query implode(', '$waiting_rows)))
                    {
                        
$errored true;
                    }
                    
$db->sql_return_on_error(false);

                    if (
$errored)
                    {
                        
$db->sql_return_on_error(true);

                        
// Because it errored out we will try to insert the rows one by one... most of the time this
                        // is caused by duplicate entries - but we also do not want to miss one...
                        
foreach ($waiting_rows as $waiting_sql)
                        {
                            
$db->sql_query($insert_query $waiting_sql);
                            
$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);
                        }

                        
$db->sql_return_on_error(false);
                    }

                    
$waiting_rows = array();
                }

                if (!empty(
$schema['autoincrement']))
                {
                    switch (
$db->sql_layer)
                    {
                        case 
'mssql':
                        case 
'mssql_odbc':
                        case 
'mssqlnative':
                            
$db->sql_query('SET IDENTITY_INSERT ' $schema['target'] . ' OFF');
                        break;

                        case 
'postgres':
                            
$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'] . '));');
                        break;

                        case 
'oracle':
                            
$result $db->sql_query('SELECT MAX(' $schema['autoincrement'] . ') as max_id FROM ' $schema['target']);
                            
$row $db->sql_fetchrow($result);
                            
$db->sql_freeresult($result);

                            
$largest_id = (int) $row['max_id'];

                            if (
$largest_id)
                            {
                                
$db->sql_query('DROP SEQUENCE ' $schema['target'] . '_seq');
                                
$db->sql_query('CREATE SEQUENCE ' $schema['target'] . '_seq START WITH ' . ($largest_id 1));
                            }
                        break;
                    }
                }
            }

            
// When we reach this point, either the current table has been processed or we're running out of time.
            
if (still_on_time() && $counting $convert->batch_size/* && !defined('DEBUG_EXTRA')*/)
            {
                
$skip_rows 0;
                
$current_table++;
            }
            else
            {
/*
                if (still_on_time() && $counting < $convert->batch_size)
                {
                    $skip_rows = 0;
                    $current_table++;
                }*/

                // Looks like we ran out of time.
                
$url $this->save_convert_progress('&amp;current_table=' $current_table '&amp;skip_rows=' $skip_rows);

                
$current_table++;
//                $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows));

                
$msg sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_tablesizeof($convert->convertor['schema']));

                
$template->assign_vars(array(
                    
'L_MESSAGE'        => $msg,
                    
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
                    
'U_ACTION'        => $url,
                ));

                
$this->meta_refresh($url);
                return;
            }
        }

        
// Process execute_last then we'll be done
        
$url $this->save_convert_progress('&amp;jump=1');

        
$template->assign_vars(array(
            
'L_SUBMIT'        => $user->lang['FINAL_STEP'],
            
'U_ACTION'        => $url,
        ));

        
$this->meta_refresh($url);
        return;
    }

    
/**
    * Sync function being executed at the middle, some functions need to be executed after a successful sync.
    */
    
function sync_forums($sync_batch)
    {
        global 
$template$user$db$phpbb_root_path$phpEx$config$cache;
        global 
$convert;

        
$template->assign_block_vars('checks', array(
            
'S_LEGEND'    => true,
            
'LEGEND'    => $user->lang['SYNC_TOPICS'],
        ));

        
$batch_size $convert->batch_size;

        
$sql 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value
            FROM ' 
TOPICS_TABLE;
        
$result $db->sql_query($sql);
        
$row $db->sql_fetchrow($result);
        
$db->sql_freeresult($result);

        
// Set values of minimum/maximum primary value for this table.
        
$primary_min $row['min_value'];
        
$primary_max $row['max_value'];

        if (
$sync_batch == 0)
        {
            
$sync_batch = (int) $primary_min;
        }

        if (
$sync_batch == 0)
        {
            
$sync_batch 1;
        }

        
// Fetch a batch of rows, process and insert them.
        
while ($sync_batch <= $primary_max && still_on_time())
        {
            
$end = ($sync_batch $batch_size 1);

            
// Sync all topics in batch mode...
            
sync('topic_approved''range''topic_id BETWEEN ' $sync_batch ' AND ' $endtruefalse);
            
sync('topic''range''topic_id BETWEEN ' $sync_batch ' AND ' $endtruetrue);

            
$template->assign_block_vars('checks', array(
                
'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) . ' ' $user->lang['KIB'] . ']' ''),
                
'RESULT'    => $user->lang['DONE'],
            ));

            
$sync_batch += $batch_size;
        }

        if (
$sync_batch >= $primary_max)
        {
            
$url $this->save_convert_progress('&amp;final_jump=1');

            
$template->assign_vars(array(
                
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
                
'U_ACTION'        => $url,
            ));

            
$this->meta_refresh($url);
            return;
        }
        else
        {
            
$sync_batch--;
        }

        
$url $this->save_convert_progress('&amp;sync_batch=' $sync_batch);

        
$template->assign_vars(array(
            
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
            
'U_ACTION'        => $url,
        ));

        
$this->meta_refresh($url);
        return;
    }

    
/**
    * Save the convertor status
    */
    
function save_convert_progress($step)
    {
        global 
$convert$language;

        
// Save convertor Status
        
set_config('convert_progress'serialize(array(
            
'step'            => $step,
            
'table_prefix'    => $convert->src_table_prefix,
            
'tag'            => $convert->convertor_tag,
        )), 
true);

        
set_config('convert_db_server'serialize(array(
            
'dbms'            => $convert->src_dbms,
            
'dbhost'        => $convert->src_dbhost,
            
'dbport'        => $convert->src_dbport,
            
'dbname'        => $convert->src_dbname,
        )), 
true);

        
set_config('convert_db_user'serialize(array(
            
'dbuser'        => $convert->src_dbuser,
            
'dbpasswd'        => $convert->src_dbpasswd,
        )), 
true);

        return 
$this->p_master->module_url "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}$step&amp;language=$language";
    }

    
/**
    * Finish conversion, the last function to be called.
    */
    
function finish_conversion()
    {
        global 
$db$phpbb_root_path$phpEx$convert$config$language$user$template;

        
$db->sql_query('DELETE FROM ' CONFIG_TABLE "
            WHERE config_name = 'convert_progress'
                OR config_name = 'convert_options'
                OR config_name = 'convert_db_server'
                OR config_name = 'convert_db_user'"
);
        
$db->sql_query('DELETE FROM ' SESSIONS_TABLE);

        @
unlink($phpbb_root_path 'cache/data_global.' $phpEx);
        
cache_moderators();

        
// And finally, add a note to the log
        
add_log('admin''LOG_INSTALL_CONVERTED'$convert->convertor_data['forum_name'], $config['version']);

        
$url $this->p_master->module_url "?mode={$this->mode}&amp;sub=final&amp;language=$language";

        
$template->assign_vars(array(
            
'L_SUBMIT'        => $user->lang['FINAL_STEP'],
            
'U_ACTION'        => $url,
        ));

        
$this->meta_refresh($url);
        return;
    }

    
/**
    * This function marks the steps after syncing
    */
    
function final_jump($final_jump)
    {
        global 
$template$user$src_db$same_db$db$phpbb_root_path$phpEx$config$cache;
        global 
$convert;

        
$template->assign_block_vars('checks', array(
            
'S_LEGEND'    => true,
            
'LEGEND'    => $user->lang['PROCESS_LAST'],
        ));

        if (
$final_jump == 1)
        {
            
$db->sql_return_on_error(true);

            
update_topics_posted();

            
$template->assign_block_vars('checks', array(
                
'TITLE'        => $user->lang['UPDATE_TOPICS_POSTED'],
                
'RESULT'    => $user->lang['DONE'],
            ));

            if (
$db->sql_error_triggered)
            {
                
$template->assign_vars(array(
                    
'S_ERROR_BOX'    => true,
                    
'ERROR_TITLE'    => $user->lang['UPDATE_TOPICS_POSTED'],
                    
'ERROR_MSG'        => $user->lang['UPDATE_TOPICS_POSTED_ERR'],
                ));
            }
            
$db->sql_return_on_error(false);

            
$this->finish_conversion();
            return;
        }
    }

    
/**
    * This function marks the steps before syncing (jump=1)
    */
    
function jump($jump$last_statement)
    {
        global 
$template$user$src_db$same_db$db$phpbb_root_path$phpEx$config$cache;
        global 
$convert;

        
$template->assign_block_vars('checks', array(
            
'S_LEGEND'    => true,
            
'LEGEND'    => $user->lang['PROCESS_LAST'],
        ));

        if (
$jump == 1)
        {
            
// Execute 'last' statements/queries
            
if (!empty($convert->convertor['execute_last']))
            {
                if (!
is_array($convert->convertor['execute_last']))
                {
                    eval(
$convert->convertor['execute_last']);
                }
                else
                {
                    while (
$last_statement sizeof($convert->convertor['execute_last']))
                    {
                        eval(
$convert->convertor['execute_last'][$last_statement]);

                        
$template->assign_block_vars('checks', array(
                            
'TITLE'        => $convert->convertor['execute_last'][$last_statement],
                            
'RESULT'    => $user->lang['DONE'],
                        ));

                        
$last_statement++;
                        
$url $this->save_convert_progress('&amp;jump=1&amp;last=' $last_statement);

                        
$percentage = ($last_statement == 0) ? floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement));
                        
$msg sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statementsizeof($convert->convertor['execute_last']), $percentage);

                        
$template->assign_vars(array(
                            
'L_SUBMIT'        => $user->lang['CONTINUE_LAST'],
                            
'L_MESSAGE'        => $msg,
                            
'U_ACTION'        => $url,
                        ));

                        
$this->meta_refresh($url);
                        return;
                    }
                }
            }

            if (!empty(
$convert->convertor['query_last']))
            {
                if (!
is_array($convert->convertor['query_last']))
                {
                    
$convert->convertor['query_last'] = array('target', array($convert->convertor['query_last']));
                }
                else if (!
is_array($convert->convertor['query_last'][0]))
                {
                    
$convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1]));
                }

                foreach (
$convert->convertor['query_last'] as $query_last)
                {
                    if (
$query_last[0] == 'src')
                    {
                        if (
$convert->mysql_convert && $same_db)
                        {
                            
$src_db->sql_query("SET NAMES 'binary'");
                        }

                        
$src_db->sql_query($query_last[1]);

                        if (
$convert->mysql_convert && $same_db)
                        {
                            
$src_db->sql_query("SET NAMES 'utf8'");
                        }
                    }
                    else
                    {
                        
$db->sql_query($query_last[1]);
                    }
                }
            }

            
// Sanity check
            
$db->sql_return_on_error(false);
            
$src_db->sql_return_on_error(false);

            
fix_empty_primary_groups();

            
$sql 'SELECT MIN(user_regdate) AS board_startdate
                FROM ' 
USERS_TABLE;
            
$result $db->sql_query($sql);
            
$row $db->sql_fetchrow($result);
            
$db->sql_freeresult($result);

            if (!isset(
$config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0))
            {
                
set_config('board_startdate'$row['board_startdate']);
                
$db->sql_query('UPDATE ' USERS_TABLE ' SET user_regdate = ' $row['board_startdate'] . ' WHERE user_id = ' ANONYMOUS);
            }

            
update_dynamic_config();

            
$template->assign_block_vars('checks', array(
                
'TITLE'        => $user->lang['CLEAN_VERIFY'],
                
'RESULT'    => $user->lang['DONE'],
            ));

            
$url $this->save_convert_progress('&amp;jump=2');

            
$template->assign_vars(array(
                
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
                
'U_ACTION'        => $url,
            ));

            
$this->meta_refresh($url);
            return;
        }

        if (
$jump == 2)
        {
            
$db->sql_query('UPDATE ' USERS_TABLE " SET user_permissions = ''");

            
// TODO: sync() is likely going to bomb out on forums with a considerable amount of topics.
            // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing)
            
sync('forum'''''falsetrue);
            
$cache->destroy('sql'FORUMS_TABLE);

            
$template->assign_block_vars('checks', array(
                
'TITLE'        => $user->lang['SYNC_FORUMS'],
                
'RESULT'    => $user->lang['DONE'],
            ));

            
// Continue with synchronizing the forums...
            
$url $this->save_convert_progress('&amp;sync_batch=0');

            
$template->assign_vars(array(
                
'L_SUBMIT'        => $user->lang['CONTINUE_CONVERT'],
                
'U_ACTION'        => $url,
            ));

            
$this->meta_refresh($url);
            return;
        }
    }

    function 
build_insert_query(&$schema, &$sql_data$current_table)
    {
        global 
$db$user;
        global 
$convert;

        
// Can we use IGNORE with this DBMS?
        
$sql_ignore = (strpos($db->sql_layer'mysql') === && !defined('DEBUG_EXTRA')) ? 'IGNORE ' '';
        
$insert_query 'INSERT ' $sql_ignore 'INTO ' $schema['target'] . ' (';

        
$aliases = array();

        
$sql_data = array(
            
'source_fields'        => array(),
            
'target_fields'        => array(),
            
'source_tables'        => array(),
            
'select_fields'        => array(),
        );

        foreach (
$schema as $key => $val)
        {
            
// Example: array('group_name',                'extension_groups.group_name',        'htmlspecialchars'),
            
if (is_int($key))
            {
                if (!empty(
$val[0]))
                {
                    
// Target fields
                    
$sql_data['target_fields'][$val[0]] = $key;
                    
$insert_query .= $val[0] . ', ';
                }

                if (!
is_array($val[1]))
                {
                    
$val[1] = array($val[1]);
                }

                foreach (
$val[1] as $valkey => $value_1)
                {
                    
// This should cover about any case:
                    //
                    // table.field                    => SELECT table.field                FROM table
                    // table.field AS alias            => SELECT table.field    AS alias    FROM table
                    // table.field AS table2.alias    => SELECT table2.field    AS alias    FROM table table2
                    // table.field AS table2.field    => SELECT table2.field                FROM table table2
                    //
                    
if (preg_match('/^([a-z0-9_]+).([a-z0-9_]+)( +AS +(([a-z0-9_]+?).)?([a-z0-9_]+))?$/i'$value_1$m))
                    {
                        
// There is 'AS ...' in the field names
                        
if (!empty($m[3]))
                        {
                            
$value_1 = ($m[2] == $m[6]) ? $m[1] . '.' $m[2] : $m[1] . '.' $m[2] . ' AS ' $m[6];

                            
// Table alias: store it then replace the source table with it
                            
if (!empty($m[5]) && $m[5] != $m[1])
                            {
                                
$aliases[$m[5]] = $m[1];
                                
$value_1 str_replace($m[1] . '.' $m[2], $m[5] . '.' $m[2], $value_1);
                            }
                        }
                        else
                        {
                            
// No table alias
                            
$sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix $m[1] . ' ' $m[1];
                        }

                        
$sql_data['select_fields'][$value_1] = $value_1;
                        
$sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2];
                    }
                }
            }
            else if (
$key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having')
            {
                if (@
preg_match_all('/([a-z0-9_]+).([a-z0-9_]+)/i'$val$m))
                {
                    foreach (
$m[1] as $value)
                    {
                        
$sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value $convert->src_table_prefix $value ' ' $value;
                    }
                }
            }
        }

        
// Add the aliases to the list of tables
        
foreach ($aliases as $alias => $table)
        {
            
$sql_data['source_tables'][$alias] = $convert->src_table_prefix $table ' ' $alias;
        }

        
// 'left_join'        => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id',
        
if (!empty($schema['left_join']))
        {
            if (!
is_array($schema['left_join']))
            {
                
$schema['left_join'] = array($schema['left_join']);
            }

            foreach (
$schema['left_join'] as $left_join)
            {
                
// This won't handle concatened LEFT JOINs
                
if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i'$left_join$m))
                {
                    
$this->p_master->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN'$left_join$current_table$schema['target']), __LINE____FILE__);
                }

                if (!empty(
$aliases[$m[2]]))
                {
                    if (!empty(
$m[3]))
                    {
                        
$this->p_master->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE____FILE__);
                    }

                    
$m[2] = $aliases[$m[2]];
                    
$m[3] = $m[2];
                }

                
$right_table $convert->src_table_prefix $m[2];
                if (!empty(
$m[3]))
                {
                    unset(
$sql_data['source_tables'][$m[3]]);
                }
                else if (
$m[2] != $m[1])
                {
                    unset(
$sql_data['source_tables'][$m[2]]);
                }

                if (
strpos($sql_data['source_tables'][$m[1]], "nLEFT JOIN") !== false)
                {
                    
$sql_data['source_tables'][$m[1]] = '(' $sql_data['source_tables'][$m[1]] . ")nLEFT JOIN $right_table";
                }
                else
                {
                    
$sql_data['source_tables'][$m[1]] .= "nLEFT JOIN $right_table";
                }

                if (!empty(
$m[3]))
                {
                    unset(
$sql_data['source_tables'][$m[3]]);
                    
$sql_data['source_tables'][$m[1]] .= ' AS ' $m[3];
                }
                else if (!empty(
$convert->src_table_prefix))
                {
                    
$sql_data['source_tables'][$m[1]] .= ' AS ' $m[2];
                }
                
$sql_data['source_tables'][$m[1]] .= ' ' $m[4] . $m[5];
            }
        }

        
// Remove ", " from the end of the insert query
        
$insert_query substr($insert_query0, -2) . ') VALUES ';

        return 
$insert_query;
    }

    
/**
    * Function for processing the currently handled row
    */
    
function process_row(&$schema, &$sql_data, &$insert_values)
    {
        global 
$template$user$phpbb_root_path$phpEx$db$lang$config$cache;
        global 
$convert$convert_row;

        
$sql_flag false;

        foreach (
$schema as $key => $fields)
        {
            
// We are only interested in the lines with:
            // array('comment', 'attachments_desc.comment', 'htmlspecialchars'),
            
if (is_int($key))
            {
                if (!
is_array($fields[1]))
                {
                    
$fields[1] = array($fields[1]);
                }

                
$firstkey_set false;
                
$firstkey 0;

                foreach (
$fields[1] as $inner_key => $inner_value)
                {
                    if (!
$firstkey_set)
                    {
                        
$firstkey $inner_key;
                        
$firstkey_set true;
                    }

                    
$src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : '';

                    if (!empty(
$src_field))
                    {
                        
$fields[1][$inner_key] = $convert->row[$src_field];
                    }
                }

                if (!empty(
$fields[0]))
                {
                    
// We have a target field, if we haven't set $sql_flag yet it will be set to TRUE.
                    // If a function has already set it to FALSE it won't change it.
                    
if ($sql_flag === false)
                    {
                        
$sql_flag true;
                    }

                    
// No function assigned?
                    
if (empty($fields[2]))
                    {
                        
$value $fields[1][$firstkey];
                    }
                    else if (
is_array($fields[2]))
                    {
                        
// Execute complex function/eval/typecast
                        
$value $fields[1];

                        foreach (
$fields[2] as $type => $execution)
                        {
                            if (
strpos($type'typecast') === 0)
                            {
                                if (!
is_array($value))
                                {
                                    
$value = array($value);
                                }
                                
$value $value[0];
                                
settype($value$execution);
                            }
                            else if (
strpos($type'function') === 0)
                            {
                                if (!
is_array($value))
                                {
                                    
$value = array($value);
                                }

                                
$value call_user_func_array($execution$value);
                            }
                            else if (
strpos($type'execute') === 0)
                            {
                                if (!
is_array($value))
                                {
                                    
$value = array($value);
                                }

                                
$execution str_replace('{RESULT}''$value'$execution);
                                
$execution str_replace('{VALUE}''$value'$execution);
                                eval(
$execution);
                            }
                        }
                    }
                    else
                    {
                        
$value call_user_func_array($fields[2], $fields[1]);
                    }

                    if (
is_null($value))
                    {
                        
$value '';
                    }

                    
$insert_values[] = $db->_sql_validate_value($value);
                }
                else if (!empty(
$fields[2]))
                {
                    if (
is_array($fields[2]))
                    {
                        
// Execute complex function/eval/typecast
                        
$value '';

                        foreach (
$fields[2] as $type => $execution)
                        {
                            if (
strpos($type'typecast') === 0)
                            {
                                
$value settype($value$execution);
                            }
                            else if (
strpos($type'function') === 0)
                            {
                                if (!
is_array($value))
                                {
                                    
$value = array($value);
                                }

                                
$value call_user_func_array($execution$value);
                            }
                            else if (
strpos($type'execute') === 0)
                            {
                                if (!
is_array($value))
                                {
                                    
$value = array($value);
                                }

                                
$execution str_replace('{RESULT}''$value'$execution);
                                
$execution str_replace('{VALUE}''$value'$execution);
                                eval(
$execution);
                            }
                        }
                    }
                    else
                    {
                        
call_user_func_array($fields[2], $fields[1]);
                    }
                }
            }
        }

        return 
$sql_flag;
    }

    
/**
    * Own meta refresh function to be able to change the global time used
    */
    
function meta_refresh($url)
    {
        global 
$convert$template;

        if (
$convert->options['refresh'])
        {
            
// Because we should not rely on correct settings, we simply use the relative path here directly.
            
$template->assign_vars(array(
                
'S_REFRESH'    => true,
                
'META'        => '<meta http-equiv="refresh" content="5; url=' $url '" />')
            );
        }
    }

    
/**
    * The information below will be used to build the input fields presented to the user
    */
    
var $convert_options = array(
        
'legend1'            => 'SPECIFY_OPTIONS',
        
'src_dbms'            => array('lang' => 'DBMS',            'type' => 'select''options' => 'dbms_select('{VALUE}', true)''explain' => false),
        
'src_dbhost'        => array('lang' => 'DB_HOST',        'type' => 'text:25:100''explain' => true),
        
'src_dbport'        => array('lang' => 'DB_PORT',        'type' => 'text:25:100''explain' => true),
        
'src_dbname'        => array('lang' => 'DB_NAME',        'type' => 'text:25:100''explain' => false),
        
'src_dbuser'        => array('lang' => 'DB_USERNAME',    'type' => 'text:25:100''explain' => false),
        
'src_dbpasswd'        => array('lang' => 'DB_PASSWORD',    'type' => 'password:25:100''explain' => false),
        
'src_table_prefix'    => array('lang' => 'TABLE_PREFIX',    'type' => 'text:25:100''explain' => false),
        
//'src_url'            => array('lang' => 'FORUM_ADDRESS',    'type' => 'text:50:100', 'explain' => true),
        
'forum_path'        => array('lang' => 'FORUM_PATH',    'type' => 'text:25:100''explain' => true),
        
'refresh'            => array('lang' => 'REFRESH_PAGE',    'type' => 'radio:yes_no''explain' => true),
    );
}

?>
Онлайн: 3
Реклама