aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/install
diff options
context:
space:
mode:
authorMate Bartus <mate.bartus@gmail.com>2015-06-30 16:36:34 +0200
committerMate Bartus <mate.bartus@gmail.com>2015-07-08 01:28:10 +0200
commit10f6716566fce9d9c38f3dd99419595b2a1cba4c (patch)
tree435a7a88bea17219187c271e38f2b07a677223aa /phpBB/install
parent249345d9cc6d6bff380436d6e05f24918d762c0d (diff)
downloadforums-10f6716566fce9d9c38f3dd99419595b2a1cba4c.tar
forums-10f6716566fce9d9c38f3dd99419595b2a1cba4c.tar.gz
forums-10f6716566fce9d9c38f3dd99419595b2a1cba4c.tar.bz2
forums-10f6716566fce9d9c38f3dd99419595b2a1cba4c.tar.xz
forums-10f6716566fce9d9c38f3dd99419595b2a1cba4c.zip
[ticket/13740] Restore original install folder
This reverts commit 934e2821f1cef5e2e21ad6d96f7beb45647ed81c. PHPBB3-13740
Diffstat (limited to 'phpBB/install')
-rw-r--r--phpBB/install/app.php79
-rw-r--r--phpBB/install/convertors/convert_phpbb20.php975
-rw-r--r--phpBB/install/convertors/functions_phpbb20.php1984
-rw-r--r--phpBB/install/data/confusables.php645
-rw-r--r--phpBB/install/database_update.php267
-rw-r--r--phpBB/install/index.php867
-rw-r--r--phpBB/install/install_convert.php2153
-rw-r--r--phpBB/install/install_install.php2368
-rw-r--r--phpBB/install/install_main.php78
-rw-r--r--phpBB/install/install_update.php1790
-rwxr-xr-xphpBB/install/phpbbcli.php68
-rw-r--r--phpBB/install/phpinfo.php14
-rw-r--r--phpBB/install/schemas/index.htm10
-rw-r--r--phpBB/install/schemas/oracle_schema.sql37
-rw-r--r--phpBB/install/schemas/postgres_schema.sql80
-rw-r--r--phpBB/install/schemas/schema_data.sql821
16 files changed, 12089 insertions, 147 deletions
diff --git a/phpBB/install/app.php b/phpBB/install/app.php
deleted file mode 100644
index 75b28fa092..0000000000
--- a/phpBB/install/app.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- *
- * This file is part of the phpBB Forum Software package.
- *
- * @copyright (c) phpBB Limited <https://www.phpbb.com>
- * @license GNU General Public License, version 2 (GPL-2.0)
- *
- * For full copyright and license information, please see
- * the docs/CREDITS.txt file.
- *
- */
-
-/**
- * @ignore
- */
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-define('PHPBB_ENVIRONMENT', 'production');
-$phpbb_root_path = '../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-//
-// Let's do the common.php logic
-//
-require($phpbb_root_path . 'includes/startup.' . $phpEx);
-require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
-
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include files
-require($phpbb_root_path . 'includes/functions.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
-include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_user.' . $phpEx);
-require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
-$phpbb_installer_container = $phpbb_installer_container_builder
- ->with_environment('installer')
- ->without_extensions()
- ->get_container();
-
-// Path to templates
-$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
-$paths = array_filter($paths, 'is_dir');
-
-/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
-$phpbb_filesystem = $phpbb_installer_container->get('filesystem');
-
-/** @var \phpbb\template\template $template */
-$template = $phpbb_installer_container->get('template');
-$template->set_custom_style(array(
- array(
- 'name' => 'adm',
- 'ext_path' => 'adm/style/',
- ),
-), $paths);
-
-/** @var \phpbb\language\language $language */
-$language = $phpbb_installer_container->get('language');
-$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
-
-/* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */
-$http_kernel = $phpbb_installer_container->get('http_kernel');
-
-/* @var $symfony_request \phpbb\symfony_request */
-$symfony_request = $phpbb_installer_container->get('symfony_request');
-$response = $http_kernel->handle($symfony_request);
-$response->send();
-$http_kernel->terminate($symfony_request, $response);
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
new file mode 100644
index 0000000000..a19bb2504b
--- /dev/null
+++ b/phpBB/install/convertors/convert_phpbb20.php
@@ -0,0 +1,975 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+* NOTE to potential convertor authors. Please use this file to get
+* familiar with the structure since we added some bare explanations here.
+*
+* Since this file gets included more than once on one page you are not able to add functions to it.
+* Instead use a functions_ file.
+*
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
+extract($phpbb_config_php_file->get_all());
+unset($dbpasswd);
+
+$dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+/**
+* $convertor_data provides some basic information about this convertor which is
+* used on the initial list of convertors and to populate the default settings
+*/
+$convertor_data = array(
+ 'forum_name' => 'phpBB 2.0.x',
+ 'version' => '1.0.3',
+ 'phpbb_version' => '3.1.5',
+ 'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>',
+ 'dbms' => $dbms,
+ 'dbhost' => $dbhost,
+ 'dbport' => $dbport,
+ 'dbuser' => $dbuser,
+ 'dbpasswd' => '',
+ 'dbname' => $dbname,
+ 'table_prefix' => 'phpbb_',
+ 'forum_path' => '../forums',
+ 'author_notes' => '',
+);
+
+/**
+* $tables is a list of the tables (minus prefix) which we expect to find in the
+* source forum. It is used to guess the prefix if the specified prefix is incorrect
+*/
+$tables = array(
+ 'auth_access',
+ 'banlist',
+ 'categories',
+ 'disallow',
+ 'forum_prune',
+ 'forums',
+ 'groups',
+ 'posts',
+ 'posts_text',
+ 'privmsgs',
+ 'privmsgs_text',
+ 'ranks',
+ 'smilies',
+ 'topics',
+ 'topics_watch',
+ 'user_group',
+ 'users',
+ 'vote_desc',
+ 'vote_results',
+ 'vote_voters',
+ 'words'
+);
+
+/**
+* $config_schema details how the board configuration information is stored in the source forum.
+*
+* 'table_format' can take the value 'file' to indicate a config file. In this case array_name
+* is set to indicate the name of the array the config values are stored in
+* Example of using a file:
+* $config_schema = array(
+* 'table_format' => 'file',
+* 'filename' => 'NAME OF FILE', // If the file is not in the root directory, the path needs to be added with no leading slash
+* 'array_name' => 'NAME OF ARRAY', // Only used if the configuration file stores the setting in an array.
+* 'settings' => array(
+* 'board_email' => 'SUPPORT_EMAIL', // target config name => source target name
+* )
+* );
+* 'table_format' can be an array if the values are stored in a table which is an assosciative array
+* (as per phpBB 2.0.x)
+* If left empty, values are assumed to be stored in a table where each config setting is
+* a column (as per phpBB 1.x)
+*
+* In either of the latter cases 'table_name' indicates the name of the table in the database
+*
+* 'settings' is an array which maps the name of the config directive in the source forum
+* to the config directive in phpBB3. It can either be a direct mapping or use a function.
+* Please note that the contents of the old config value are passed to the function, therefore
+* an in-built function requiring the variable passed by reference is not able to be used. Since
+* empty() is such a function we created the function is_empty() to be used instead.
+*/
+$config_schema = array(
+ 'table_name' => 'config',
+ 'table_format' => array('config_name' => 'config_value'),
+ 'settings' => array(
+ 'allow_bbcode' => 'allow_bbcode',
+ 'allow_smilies' => 'allow_smilies',
+ 'allow_sig' => 'allow_sig',
+ 'allow_namechange' => 'allow_namechange',
+ 'allow_avatar_local' => 'allow_avatar_local',
+ 'allow_avatar_remote' => 'allow_avatar_remote',
+ 'allow_avatar_upload' => 'allow_avatar_upload',
+ 'board_disable' => 'board_disable',
+ 'sitename' => 'phpbb_set_encoding(sitename)',
+ 'site_desc' => 'phpbb_set_encoding(site_desc)',
+ 'session_length' => 'session_length',
+ 'board_email_sig' => 'phpbb_set_encoding(board_email_sig)',
+ 'posts_per_page' => 'posts_per_page',
+ 'topics_per_page' => 'topics_per_page',
+ 'enable_confirm' => 'enable_confirm',
+ 'board_email_form' => 'board_email_form',
+ 'override_user_style' => 'override_user_style',
+ 'hot_threshold' => 'hot_threshold',
+ 'max_poll_options' => 'max_poll_options',
+ 'max_sig_chars' => 'max_sig_chars',
+ 'pm_max_msgs' => 'max_inbox_privmsgs',
+ 'smtp_delivery' => 'smtp_delivery',
+ 'smtp_host' => 'smtp_host',
+ 'smtp_username' => 'smtp_username',
+ 'smtp_password' => 'smtp_password',
+ 'require_activation' => 'require_activation',
+ 'flood_interval' => 'flood_interval',
+ 'avatar_filesize' => 'avatar_filesize',
+ 'avatar_max_width' => 'avatar_max_width',
+ 'avatar_max_height' => 'avatar_max_height',
+ 'default_dateformat' => 'phpbb_set_encoding(default_dateformat)',
+ 'board_timezone' => 'phpbb_convert_timezone(board_timezone)',
+ 'allow_privmsg' => 'not(privmsg_disable)',
+ 'gzip_compress' => 'gzip_compress',
+ 'coppa_enable' => '!is_empty(coppa_mail)',
+ 'coppa_fax' => 'coppa_fax',
+ 'coppa_mail' => 'coppa_mail',
+ 'record_online_users' => 'record_online_users',
+ 'record_online_date' => 'record_online_date',
+ 'board_startdate' => 'board_startdate',
+ )
+);
+
+/**
+* $test_file is the name of a file which is present on the source
+* forum which can be used to check that the path specified by the
+* user was correct
+*/
+$test_file = 'modcp.php';
+
+/**
+* If this is set then we are not generating the first page of information but getting the conversion information.
+*/
+if (!$get_info)
+{
+ // Test to see if the birthday MOD is installed on the source forum
+ // Niels' birthday mod
+ if (get_config_value('birthday_required') !== false || get_config_value('bday_require') !== false)
+ {
+ define('MOD_BIRTHDAY', true);
+ }
+
+ // TerraFrost's validated birthday mod
+ if (get_config_value('bday_require') !== false)
+ {
+ define('MOD_BIRTHDAY_TERRA', true);
+ }
+
+ // Test to see if the attachment MOD is installed on the source forum
+ // If it is, we will convert this data as well
+ $src_db->sql_return_on_error(true);
+
+ $sql = "SELECT config_value
+ FROM {$convert->src_table_prefix}attachments_config
+ WHERE config_name = 'upload_dir'";
+ $result = $src_db->sql_query($sql);
+
+ if ($result && $row = $src_db->sql_fetchrow($result))
+ {
+ // Here the constant is defined
+ define('MOD_ATTACHMENT', true);
+
+ // Here i add more tables to be checked in the old forum
+ $tables += array(
+ 'attachments',
+ 'attachments_desc',
+ 'extensions',
+ 'extension_groups'
+ );
+
+ $src_db->sql_freeresult($result);
+ }
+ else if ($result)
+ {
+ $src_db->sql_freeresult($result);
+ }
+
+
+ /**
+ * Tests for further MODs can be included here.
+ * Please use constants for this, prefixing them with MOD_
+ */
+
+ $src_db->sql_return_on_error(false);
+
+ // Now let us set a temporary config variable for user id incrementing
+ $sql = "SELECT user_id
+ FROM {$convert->src_table_prefix}users
+ WHERE user_id = 1";
+ $result = $src_db->sql_query($sql);
+ $user_id = (int) $src_db->sql_fetchfield('user_id');
+ $src_db->sql_freeresult($result);
+
+ // If there is a user id 1, we need to increment user ids. :/
+ if ($user_id === 1)
+ {
+ // Try to get the maximum user id possible...
+ $sql = "SELECT MAX(user_id) AS max_user_id
+ FROM {$convert->src_table_prefix}users";
+ $result = $src_db->sql_query($sql);
+ $user_id = (int) $src_db->sql_fetchfield('max_user_id');
+ $src_db->sql_freeresult($result);
+
+ $config->set('increment_user_id', ($user_id + 1), false);
+ }
+ else
+ {
+ $config->set('increment_user_id', 0, false);
+ }
+
+ // Overwrite maximum avatar width/height
+ @define('DEFAULT_AVATAR_X_CUSTOM', get_config_value('avatar_max_width'));
+ @define('DEFAULT_AVATAR_Y_CUSTOM', get_config_value('avatar_max_height'));
+
+ // additional table used only during conversion
+ @define('USERCONV_TABLE', $table_prefix . 'userconv');
+
+/**
+* Description on how to use the convertor framework.
+*
+* 'schema' Syntax Description
+* -> 'target' => Target Table. If not specified the next table will be handled
+* -> 'primary' => Primary Key. If this is specified then this table is processed in batches
+* -> 'query_first' => array('target' or 'src', Query to execute before beginning the process
+* (if more than one then specified as array))
+* -> 'function_first' => Function to execute before beginning the process (if more than one then specified as array)
+* (This is mostly useful if variables need to be given to the converting process)
+* -> 'test_file' => This is not used at the moment but should be filled with a file from the old installation
+*
+* // DB Functions
+* 'distinct' => Add DISTINCT to the select query
+* 'where' => Add WHERE to the select query
+* 'group_by' => Add GROUP BY to the select query
+* 'left_join' => Add LEFT JOIN to the select query (if more than one joins specified as array)
+* 'having' => Add HAVING to the select query
+*
+* // DB INSERT array
+* This one consist of three parameters
+* First Parameter:
+* The key need to be filled within the target table
+* If this is empty, the target table gets not assigned the source value
+* Second Parameter:
+* Source value. If the first parameter is specified, it will be assigned this value.
+* If the first parameter is empty, this only gets added to the select query
+* Third Parameter:
+* Custom Function. Function to execute while storing source value into target table.
+* The functions return value get stored.
+* The function parameter consist of the value of the second parameter.
+*
+* types:
+* - empty string == execute nothing
+* - string == function to execute
+* - array == complex execution instructions
+*
+* Complex execution instructions:
+* @todo test complex execution instructions - in theory they will work fine
+*
+* By defining an array as the third parameter you are able to define some statements to be executed. The key
+* is defining what to execute, numbers can be appended...
+*
+* 'function' => execute function
+* 'execute' => run code, whereby all occurrences of {VALUE} get replaced by the last returned value.
+* The result *must* be assigned/stored to {RESULT}.
+* 'typecast' => typecast value
+*
+* The returned variables will be made always available to the next function to continue to work with.
+*
+* example (variable inputted is an integer of 1):
+*
+* array(
+* 'function1' => 'increment_by_one', // returned variable is 2
+* 'typecast' => 'string', // typecast variable to be a string
+* 'execute' => '{RESULT} = {VALUE} . ' is good';', // returned variable is '2 is good'
+* 'function2' => 'replace_good_with_bad', // returned variable is '2 is bad'
+* ),
+*
+*/
+
+ $convertor = array(
+ 'test_file' => 'viewtopic.php',
+
+ 'avatar_path' => get_config_value('avatar_path') . '/',
+ 'avatar_gallery_path' => get_config_value('avatar_gallery_path') . '/',
+ 'smilies_path' => get_config_value('smilies_path') . '/',
+ 'upload_path' => (defined('MOD_ATTACHMENT')) ? phpbb_get_files_dir() . '/' : '',
+ 'thumbnails' => (defined('MOD_ATTACHMENT')) ? array('thumbs/', 't_') : '',
+ 'ranks_path' => false, // phpBB 2.0.x had no config value for a ranks path
+
+ // We empty some tables to have clean data available
+ 'query_first' => array(
+ array('target', $convert->truncate_statement . SEARCH_RESULTS_TABLE),
+ array('target', $convert->truncate_statement . SEARCH_WORDLIST_TABLE),
+ array('target', $convert->truncate_statement . SEARCH_WORDMATCH_TABLE),
+ array('target', $convert->truncate_statement . LOG_TABLE),
+ ),
+
+// with this you are able to import all attachment files on the fly. For large boards this is not an option, therefore commented out by default.
+// Instead every file gets copied while processing the corresponding attachment entry.
+// if (defined("MOD_ATTACHMENT")) { import_attachment_files(); phpbb_copy_thumbnails(); }
+
+ // phpBB2 allowed some similar usernames to coexist which would have the same
+ // username_clean in phpBB3 which is not possible, so we'll give the admin a list
+ // of user ids and usernames and let him deicde what he wants to do with them
+ 'execute_first' => '
+ phpbb_create_userconv_table();
+ import_avatar_gallery();
+ if (defined("MOD_ATTACHMENT")) phpbb_import_attach_config();
+ phpbb_insert_forums();
+ ',
+
+ 'execute_last' => array('
+ add_bots();
+ ', '
+ update_folder_pm_count();
+ ', '
+ update_unread_count();
+ ', (defined('MOD_ATTACHMENT')) ? '
+ phpbb_attachment_extension_group_name();
+ ' : '
+ ', '
+ phpbb_convert_authentication(\'start\');
+ ', '
+ phpbb_convert_authentication(\'first\');
+ ', '
+ phpbb_convert_authentication(\'second\');
+ ', '
+ phpbb_convert_authentication(\'third\');
+ '),
+
+ 'schema' => array(
+ array(
+ 'target' => USERCONV_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . USERCONV_TABLE),
+
+
+ array('user_id', 'users.user_id', ''),
+ array('username_clean', 'users.username', array('function1' => 'phpbb_set_encoding', 'function2' => 'utf8_clean_string')),
+ ),
+
+ array(
+ 'target' => (defined('MOD_ATTACHMENT')) ? ATTACHMENTS_TABLE : '',
+ 'primary' => 'attachments.attach_id',
+ 'query_first' => (defined('MOD_ATTACHMENT')) ? array('target', $convert->truncate_statement . ATTACHMENTS_TABLE) : '',
+ 'autoincrement' => 'attach_id',
+
+ array('attach_id', 'attachments.attach_id', ''),
+ array('post_msg_id', 'attachments.post_id', ''),
+ array('topic_id', 'posts.topic_id', ''),
+ array('in_message', 0, ''),
+ array('is_orphan', 0, ''),
+ array('poster_id', 'attachments.user_id_1 AS poster_id', 'phpbb_user_id'),
+ array('physical_filename', 'attachments_desc.physical_filename', 'import_attachment'),
+ array('real_filename', 'attachments_desc.real_filename', 'phpbb_set_encoding'),
+ array('download_count', 'attachments_desc.download_count', ''),
+ array('attach_comment', 'attachments_desc.comment', array('function1' => 'phpbb_set_encoding', 'function2' => 'utf8_htmlspecialchars')),
+ array('extension', 'attachments_desc.extension', ''),
+ array('mimetype', 'attachments_desc.mimetype', ''),
+ array('filesize', 'attachments_desc.filesize', ''),
+ array('filetime', 'attachments_desc.filetime', ''),
+ array('thumbnail', 'attachments_desc.thumbnail', ''),
+
+ 'where' => 'attachments_desc.attach_id = attachments.attach_id AND attachments.privmsgs_id = 0 AND posts.post_id = attachments.post_id',
+ 'group_by' => 'attachments.attach_id'
+ ),
+
+ array(
+ 'target' => (defined('MOD_ATTACHMENT')) ? ATTACHMENTS_TABLE : '',
+ 'primary' => 'attachments.attach_id',
+ 'autoincrement' => 'attach_id',
+
+ array('attach_id', 'attachments.attach_id', ''),
+ array('post_msg_id', 'attachments.privmsgs_id', ''),
+ array('topic_id', 0, ''),
+ array('in_message', 1, ''),
+ array('is_orphan', 0, ''),
+ array('poster_id', 'attachments.user_id_1 AS poster_id', 'phpbb_user_id'),
+ array('physical_filename', 'attachments_desc.physical_filename', 'import_attachment'),
+ array('real_filename', 'attachments_desc.real_filename', 'phpbb_set_encoding'),
+ array('download_count', 'attachments_desc.download_count', ''),
+ array('attach_comment', 'attachments_desc.comment', array('function1' => 'phpbb_set_encoding', 'function2' => 'utf8_htmlspecialchars')),
+ array('extension', 'attachments_desc.extension', ''),
+ array('mimetype', 'attachments_desc.mimetype', ''),
+ array('filesize', 'attachments_desc.filesize', ''),
+ array('filetime', 'attachments_desc.filetime', ''),
+ array('thumbnail', 'attachments_desc.thumbnail', ''),
+
+ 'where' => 'attachments_desc.attach_id = attachments.attach_id AND attachments.post_id = 0',
+ 'group_by' => 'attachments.attach_id'
+ ),
+
+ array(
+ 'target' => (defined('MOD_ATTACHMENT')) ? EXTENSIONS_TABLE : '',
+ 'query_first' => (defined('MOD_ATTACHMENT')) ? array('target', $convert->truncate_statement . EXTENSIONS_TABLE) : '',
+ 'autoincrement' => 'extension_id',
+
+ array('extension_id', 'extensions.ext_id', ''),
+ array('group_id', 'extensions.group_id', ''),
+ array('extension', 'extensions.extension', ''),
+ ),
+
+ array(
+ 'target' => (defined('MOD_ATTACHMENT')) ? EXTENSION_GROUPS_TABLE : '',
+ 'query_first' => (defined('MOD_ATTACHMENT')) ? array('target', $convert->truncate_statement . EXTENSION_GROUPS_TABLE) : '',
+ 'autoincrement' => 'group_id',
+
+ array('group_id', 'extension_groups.group_id', ''),
+ array('group_name', 'extension_groups.group_name', array('function1' => 'phpbb_set_encoding', 'function2' => 'utf8_htmlspecialchars')),
+ array('cat_id', 'extension_groups.cat_id', 'phpbb_attachment_category'),
+ array('allow_group', 'extension_groups.allow_group', ''),
+ array('download_mode', 1, ''),
+ array('upload_icon', '', ''),
+ array('max_filesize', 'extension_groups.max_filesize', ''),
+ array('allowed_forums', 'extension_groups.forum_permissions', 'phpbb_attachment_forum_perms'),
+ array('allow_in_pm', 1, ''),
+ ),
+
+ array(
+ 'target' => BANLIST_TABLE,
+ 'execute_first' => 'phpbb_check_username_collisions();',
+ 'query_first' => array('target', $convert->truncate_statement . BANLIST_TABLE),
+
+ array('ban_ip', 'banlist.ban_ip', 'decode_ban_ip'),
+ array('ban_userid', 'banlist.ban_userid', 'phpbb_user_id'),
+ array('ban_email', 'banlist.ban_email', ''),
+ array('ban_reason', '', ''),
+ array('ban_give_reason', '', ''),
+
+ 'where' => "banlist.ban_ip NOT LIKE '%.%'",
+ ),
+
+ array(
+ 'target' => BANLIST_TABLE,
+
+ array('ban_ip', 'banlist.ban_ip', ''),
+ array('ban_userid', 0, ''),
+ array('ban_email', '', ''),
+ array('ban_reason', '', ''),
+ array('ban_give_reason', '', ''),
+
+ 'where' => "banlist.ban_ip LIKE '%.%'",
+ ),
+
+ array(
+ 'target' => DISALLOW_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . DISALLOW_TABLE),
+
+ array('disallow_username', 'disallow.disallow_username', 'phpbb_disallowed_username'),
+ ),
+
+ array(
+ 'target' => RANKS_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . RANKS_TABLE),
+ 'autoincrement' => 'rank_id',
+
+ array('rank_id', 'ranks.rank_id', ''),
+ array('rank_title', 'ranks.rank_title', array('function1' => 'phpbb_set_default_encoding', 'function2' => 'utf8_htmlspecialchars')),
+ array('rank_min', 'ranks.rank_min', array('typecast' => 'int', 'execute' => '{RESULT} = ({VALUE}[0] < 0) ? 0 : {VALUE}[0];')),
+ array('rank_special', 'ranks.rank_special', ''),
+ array('rank_image', 'ranks.rank_image', 'import_rank'),
+ ),
+
+ array(
+ 'target' => TOPICS_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . TOPICS_TABLE),
+ 'primary' => 'topics.topic_id',
+ 'autoincrement' => 'topic_id',
+
+ array('topic_id', 'topics.topic_id', ''),
+ array('forum_id', 'topics.forum_id', ''),
+ array('icon_id', 0, ''),
+ array('topic_poster', 'topics.topic_poster AS poster_id', 'phpbb_user_id'),
+ array('topic_attachment', ((defined('MOD_ATTACHMENT')) ? 'topics.topic_attachment' : 0), ''),
+ array('topic_title', 'topics.topic_title', 'phpbb_set_encoding'),
+ array('topic_time', 'topics.topic_time', ''),
+ array('topic_views', 'topics.topic_views', ''),
+ array('topic_posts_approved', 'topics.topic_replies', 'phpbb_topic_replies_to_posts'),
+ array('topic_posts_unapproved', 0, ''),
+ array('topic_posts_softdeleted',0, ''),
+ array('topic_last_post_id', 'topics.topic_last_post_id', ''),
+ array('topic_status', 'topics.topic_status', 'is_topic_locked'),
+ array('topic_moved_id', 0, ''),
+ array('topic_type', 'topics.topic_type', 'phpbb_convert_topic_type'),
+ array('topic_first_post_id', 'topics.topic_first_post_id', ''),
+ array('topic_last_view_time', 'posts.post_time', 'intval'),
+ array('topic_visibility', ITEM_APPROVED, ''),
+
+ array('poll_title', 'vote_desc.vote_text', array('function1' => 'null_to_str', 'function2' => 'phpbb_set_encoding', 'function3' => 'htmlspecialchars_decode', 'function4' => 'utf8_htmlspecialchars')),
+ array('poll_start', 'vote_desc.vote_start', 'null_to_zero'),
+ array('poll_length', 'vote_desc.vote_length', 'null_to_zero'),
+ array('poll_max_options', 1, ''),
+ array('poll_vote_change', 0, ''),
+
+ 'left_join' => array ( 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1',
+ 'topics LEFT JOIN posts ON topics.topic_last_post_id = posts.post_id',
+ ),
+ 'where' => 'topics.topic_moved_id = 0',
+ ),
+
+ array(
+ 'target' => TOPICS_TABLE,
+ 'primary' => 'topics.topic_id',
+ 'autoincrement' => 'topic_id',
+
+ array('topic_id', 'topics.topic_id', ''),
+ array('forum_id', 'topics.forum_id', ''),
+ array('icon_id', 0, ''),
+ array('topic_poster', 'topics.topic_poster AS poster_id', 'phpbb_user_id'),
+ array('topic_attachment', ((defined('MOD_ATTACHMENT')) ? 'topics.topic_attachment' : 0), ''),
+ array('topic_title', 'topics.topic_title', 'phpbb_set_encoding'),
+ array('topic_time', 'topics.topic_time', ''),
+ array('topic_views', 'topics.topic_views', ''),
+ array('topic_posts_approved', 'topics.topic_replies', 'phpbb_topic_replies_to_posts'),
+ array('topic_posts_unapproved', 0, ''),
+ array('topic_posts_softdeleted',0, ''),
+ array('topic_last_post_id', 'topics.topic_last_post_id', ''),
+ array('topic_status', ITEM_MOVED, ''),
+ array('topic_moved_id', 'topics.topic_moved_id', ''),
+ array('topic_type', 'topics.topic_type', 'phpbb_convert_topic_type'),
+ array('topic_first_post_id', 'topics.topic_first_post_id', ''),
+ array('topic_visibility', ITEM_APPROVED, ''),
+
+ array('poll_title', 'vote_desc.vote_text', array('function1' => 'null_to_str', 'function2' => 'phpbb_set_encoding', 'function3' => 'htmlspecialchars_decode', 'function4' => 'utf8_htmlspecialchars')),
+ array('poll_start', 'vote_desc.vote_start', 'null_to_zero'),
+ array('poll_length', 'vote_desc.vote_length', 'null_to_zero'),
+ array('poll_max_options', 1, ''),
+ array('poll_vote_change', 0, ''),
+
+ 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1',
+ 'where' => 'topics.topic_moved_id <> 0',
+ ),
+
+ array(
+ 'target' => TOPICS_WATCH_TABLE,
+ 'primary' => 'topics_watch.topic_id',
+ 'query_first' => array('target', $convert->truncate_statement . TOPICS_WATCH_TABLE),
+
+ array('topic_id', 'topics_watch.topic_id', ''),
+ array('user_id', 'topics_watch.user_id', 'phpbb_user_id'),
+ array('notify_status', 'topics_watch.notify_status', ''),
+ ),
+
+ array(
+ 'target' => SMILIES_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . SMILIES_TABLE),
+ 'autoincrement' => 'smiley_id',
+
+ array('smiley_id', 'smilies.smilies_id', ''),
+ array('code', 'smilies.code', array('function1' => 'phpbb_smilie_html_decode', 'function2' => 'phpbb_set_encoding', 'function3' => 'utf8_htmlspecialchars')),
+ array('emotion', 'smilies.emoticon', 'phpbb_set_encoding'),
+ array('smiley_url', 'smilies.smile_url', 'import_smiley'),
+ array('smiley_width', 'smilies.smile_url', 'get_smiley_width'),
+ array('smiley_height', 'smilies.smile_url', 'get_smiley_height'),
+ array('smiley_order', 'smilies.smilies_id', ''),
+ array('display_on_posting', 'smilies.smilies_id', 'get_smiley_display'),
+
+ 'order_by' => 'smilies.smilies_id ASC',
+ ),
+
+ array(
+ 'target' => POLL_OPTIONS_TABLE,
+ 'primary' => 'vote_results.vote_option_id',
+ 'query_first' => array('target', $convert->truncate_statement . POLL_OPTIONS_TABLE),
+
+ array('poll_option_id', 'vote_results.vote_option_id', ''),
+ array('topic_id', 'vote_desc.topic_id', ''),
+ array('', 'topics.topic_poster AS poster_id', 'phpbb_user_id'),
+ array('poll_option_text', 'vote_results.vote_option_text', array('function1' => 'phpbb_set_encoding', 'function2' => 'htmlspecialchars_decode', 'function3' => 'utf8_htmlspecialchars')),
+ array('poll_option_total', 'vote_results.vote_result', ''),
+
+ 'where' => 'vote_results.vote_id = vote_desc.vote_id',
+ 'left_join' => 'vote_desc LEFT JOIN topics ON topics.topic_id = vote_desc.topic_id',
+ ),
+
+ array(
+ 'target' => POLL_VOTES_TABLE,
+ 'primary' => 'vote_desc.topic_id',
+ 'query_first' => array('target', $convert->truncate_statement . POLL_VOTES_TABLE),
+
+ array('poll_option_id', VOTE_CONVERTED, ''),
+ array('topic_id', 'vote_desc.topic_id', ''),
+ array('vote_user_id', 'vote_voters.vote_user_id', 'phpbb_user_id'),
+ array('vote_user_ip', 'vote_voters.vote_user_ip', 'decode_ip'),
+
+ 'where' => 'vote_voters.vote_id = vote_desc.vote_id',
+ ),
+
+ array(
+ 'target' => WORDS_TABLE,
+ 'primary' => 'words.word_id',
+ 'query_first' => array('target', $convert->truncate_statement . WORDS_TABLE),
+ 'autoincrement' => 'word_id',
+
+ array('word_id', 'words.word_id', ''),
+ array('word', 'words.word', 'phpbb_set_encoding'),
+ array('replacement', 'words.replacement', 'phpbb_set_encoding'),
+ ),
+
+ array(
+ 'target' => POSTS_TABLE,
+ 'primary' => 'posts.post_id',
+ 'autoincrement' => 'post_id',
+ 'query_first' => array('target', $convert->truncate_statement . POSTS_TABLE),
+ 'execute_first' => '
+ $config["max_post_chars"] = 0;
+ $config["min_post_chars"] = 0;
+ $config["max_quote_depth"] = 0;
+ ',
+
+ array('post_id', 'posts.post_id', ''),
+ array('topic_id', 'posts.topic_id', ''),
+ array('forum_id', 'posts.forum_id', ''),
+ array('poster_id', 'posts.poster_id', 'phpbb_user_id'),
+ array('icon_id', 0, ''),
+ array('poster_ip', 'posts.poster_ip', 'decode_ip'),
+ array('post_time', 'posts.post_time', ''),
+ array('enable_bbcode', 'posts.enable_bbcode', ''),
+ array('', 'posts.enable_html', ''),
+ array('enable_smilies', 'posts.enable_smilies', ''),
+ array('enable_sig', 'posts.enable_sig', ''),
+ array('enable_magic_url', 1, ''),
+ array('post_username', 'posts.post_username', 'phpbb_set_encoding'),
+ array('post_subject', 'posts_text.post_subject', 'phpbb_set_encoding'),
+ array('post_attachment', ((defined('MOD_ATTACHMENT')) ? 'posts.post_attachment' : 0), ''),
+ array('post_edit_time', 'posts.post_edit_time', array('typecast' => 'int')),
+ array('post_edit_count', 'posts.post_edit_count', ''),
+ array('post_edit_reason', '', ''),
+ array('post_edit_user', '', 'phpbb_post_edit_user'),
+ array('post_visibility', ITEM_APPROVED, ''),
+
+ array('bbcode_uid', 'posts.post_time', 'make_uid'),
+ array('post_text', 'posts_text.post_text', 'phpbb_prepare_message'),
+ array('', 'posts_text.bbcode_uid AS old_bbcode_uid', ''),
+ array('bbcode_bitfield', '', 'get_bbcode_bitfield'),
+ array('post_checksum', '', ''),
+
+ // Commented out inline search indexing, this takes up a LOT of time. :D
+ // @todo We either need to enable this or call the rebuild search functionality post convert
+/* array('', '', 'search_indexing'),
+ array('', 'posts_text.post_text AS message', ''),
+ array('', 'posts_text.post_subject AS title', ''),*/
+
+ 'where' => 'posts.post_id = posts_text.post_id'
+ ),
+
+ array(
+ 'target' => PRIVMSGS_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+ 'autoincrement' => 'msg_id',
+ 'query_first' => array(
+ array('target', $convert->truncate_statement . PRIVMSGS_TABLE),
+ array('target', $convert->truncate_statement . PRIVMSGS_RULES_TABLE),
+ ),
+
+ 'execute_first' => '
+ $config["max_post_chars"] = 0;
+ $config["min_post_chars"] = 0;
+ $config["max_quote_depth"] = 0;
+ ',
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('root_level', 0, ''),
+ array('author_id', 'privmsgs.privmsgs_from_userid AS poster_id', 'phpbb_user_id'),
+ array('icon_id', 0, ''),
+ array('author_ip', 'privmsgs.privmsgs_ip', 'decode_ip'),
+ array('message_time', 'privmsgs.privmsgs_date', ''),
+ array('enable_bbcode', 'privmsgs.privmsgs_enable_bbcode AS enable_bbcode', ''),
+ array('', 'privmsgs.privmsgs_enable_html AS enable_html', ''),
+ array('enable_smilies', 'privmsgs.privmsgs_enable_smilies AS enable_smilies', ''),
+ array('enable_magic_url', 1, ''),
+ array('enable_sig', 'privmsgs.privmsgs_attach_sig', ''),
+ array('message_subject', 'privmsgs.privmsgs_subject', 'phpbb_set_encoding'), // Already specialchared in 2.0.x
+ array('message_attachment', ((defined('MOD_ATTACHMENT')) ? 'privmsgs.privmsgs_attachment' : 0), ''),
+ array('message_edit_reason', '', ''),
+ array('message_edit_user', 0, ''),
+ array('message_edit_time', 0, ''),
+ array('message_edit_count', 0, ''),
+
+ array('bbcode_uid', 'privmsgs.privmsgs_date AS post_time', 'make_uid'),
+ array('message_text', 'privmsgs_text.privmsgs_text', 'phpbb_prepare_message'),
+ array('', 'privmsgs_text.privmsgs_bbcode_uid AS old_bbcode_uid', ''),
+ array('bbcode_bitfield', '', 'get_bbcode_bitfield'),
+ array('to_address', 'privmsgs.privmsgs_to_userid', 'phpbb_privmsgs_to_userid'),
+ array('bcc_address', '', ''),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id'
+ ),
+
+ array(
+ 'target' => PRIVMSGS_FOLDER_TABLE,
+ 'primary' => 'users.user_id',
+ 'query_first' => array('target', $convert->truncate_statement . PRIVMSGS_FOLDER_TABLE),
+
+ array('user_id', 'users.user_id', 'phpbb_user_id'),
+ array('folder_name', $user->lang['CONV_SAVED_MESSAGES'], ''),
+ array('pm_count', 0, ''),
+
+ 'where' => 'users.user_id <> -1',
+ ),
+
+ // Inbox
+ array(
+ 'target' => PRIVMSGS_TO_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+ 'query_first' => array('target', $convert->truncate_statement . PRIVMSGS_TO_TABLE),
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('user_id', 'privmsgs.privmsgs_to_userid', 'phpbb_user_id'),
+ array('author_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('pm_deleted', 0, ''),
+ array('pm_new', 'privmsgs.privmsgs_type', 'phpbb_new_pm'),
+ array('pm_unread', 'privmsgs.privmsgs_type', 'phpbb_unread_pm'),
+ array('pm_replied', 0, ''),
+ array('pm_marked', 0, ''),
+ array('pm_forwarded', 0, ''),
+ array('folder_id', PRIVMSGS_INBOX, ''),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id
+ AND (privmsgs.privmsgs_type = 0 OR privmsgs.privmsgs_type = 1 OR privmsgs.privmsgs_type = 5)',
+ ),
+
+ // Outbox
+ array(
+ 'target' => PRIVMSGS_TO_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('user_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('author_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('pm_deleted', 0, ''),
+ array('pm_new', 0, ''),
+ array('pm_unread', 0, ''),
+ array('pm_replied', 0, ''),
+ array('pm_marked', 0, ''),
+ array('pm_forwarded', 0, ''),
+ array('folder_id', PRIVMSGS_OUTBOX, ''),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id
+ AND (privmsgs.privmsgs_type = 1 OR privmsgs.privmsgs_type = 5)',
+ ),
+
+ // Sentbox
+ array(
+ 'target' => PRIVMSGS_TO_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('user_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('author_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('pm_deleted', 0, ''),
+ array('pm_new', 'privmsgs.privmsgs_type', 'phpbb_new_pm'),
+ array('pm_unread', 'privmsgs.privmsgs_type', 'phpbb_unread_pm'),
+ array('pm_replied', 0, ''),
+ array('pm_marked', 0, ''),
+ array('pm_forwarded', 0, ''),
+ array('folder_id', PRIVMSGS_SENTBOX, ''),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id
+ AND privmsgs.privmsgs_type = 2',
+ ),
+
+ // Savebox (SAVED IN)
+ array(
+ 'target' => PRIVMSGS_TO_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('user_id', 'privmsgs.privmsgs_to_userid', 'phpbb_user_id'),
+ array('author_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('pm_deleted', 0, ''),
+ array('pm_new', 'privmsgs.privmsgs_type', 'phpbb_new_pm'),
+ array('pm_unread', 'privmsgs.privmsgs_type', 'phpbb_unread_pm'),
+ array('pm_replied', 0, ''),
+ array('pm_marked', 0, ''),
+ array('pm_forwarded', 0, ''),
+ array('folder_id', 'privmsgs.privmsgs_to_userid', 'phpbb_get_savebox_id'),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id
+ AND privmsgs.privmsgs_type = 3',
+ ),
+
+ // Savebox (SAVED OUT)
+ array(
+ 'target' => PRIVMSGS_TO_TABLE,
+ 'primary' => 'privmsgs.privmsgs_id',
+
+ array('msg_id', 'privmsgs.privmsgs_id', ''),
+ array('user_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('author_id', 'privmsgs.privmsgs_from_userid', 'phpbb_user_id'),
+ array('pm_deleted', 0, ''),
+ array('pm_new', 'privmsgs.privmsgs_type', 'phpbb_new_pm'),
+ array('pm_unread', 'privmsgs.privmsgs_type', 'phpbb_unread_pm'),
+ array('pm_replied', 0, ''),
+ array('pm_marked', 0, ''),
+ array('pm_forwarded', 0, ''),
+ array('folder_id', 'privmsgs.privmsgs_from_userid', 'phpbb_get_savebox_id'),
+
+ 'where' => 'privmsgs.privmsgs_id = privmsgs_text.privmsgs_text_id
+ AND privmsgs.privmsgs_type = 4',
+ ),
+
+ array(
+ 'target' => GROUPS_TABLE,
+ 'autoincrement' => 'group_id',
+ 'query_first' => array(
+ array('target', $convert->truncate_statement . GROUPS_TABLE),
+ array('target', $convert->truncate_statement . TEAMPAGE_TABLE),
+ ),
+
+ array('group_id', 'groups.group_id', ''),
+ array('group_type', 'groups.group_type', 'phpbb_convert_group_type'),
+ array('group_display', 0, ''),
+ array('group_legend', 0, ''),
+ array('group_name', 'groups.group_name', 'phpbb_convert_group_name'), // phpbb_set_encoding called in phpbb_convert_group_name
+ array('group_desc', 'groups.group_description', 'phpbb_set_encoding'),
+
+ 'where' => 'groups.group_single_user = 0',
+ ),
+
+ array(
+ 'target' => USER_GROUP_TABLE,
+ 'query_first' => array('target', $convert->truncate_statement . USER_GROUP_TABLE),
+ 'execute_first' => '
+ add_default_groups();
+ add_groups_to_teampage();
+ ',
+
+ array('group_id', 'groups.group_id', ''),
+ array('user_id', 'groups.group_moderator', 'phpbb_user_id'),
+ array('group_leader', 1, ''),
+ array('user_pending', 0, ''),
+
+ 'where' => 'groups.group_single_user = 0 AND groups.group_moderator <> 0',
+ ),
+
+ array(
+ 'target' => USER_GROUP_TABLE,
+
+ array('group_id', 'user_group.group_id', ''),
+ array('user_id', 'user_group.user_id', 'phpbb_user_id'),
+ array('group_leader', 0, ''),
+ array('user_pending', 'user_group.user_pending', ''),
+
+ 'where' => 'user_group.group_id = groups.group_id AND groups.group_single_user = 0 AND groups.group_moderator <> user_group.user_id',
+ ),
+
+ array(
+ 'target' => USERS_TABLE,
+ 'primary' => 'users.user_id',
+ 'autoincrement' => 'user_id',
+ 'query_first' => array(
+ array('target', 'DELETE FROM ' . USERS_TABLE . ' WHERE user_id <> ' . ANONYMOUS),
+ array('target', $convert->truncate_statement . BOTS_TABLE),
+ array('target', $convert->truncate_statement . USER_NOTIFICATIONS_TABLE),
+ ),
+
+ 'execute_last' => '
+ remove_invalid_users();
+ ',
+
+ array('user_id', 'users.user_id', 'phpbb_user_id'),
+ array('', 'users.user_id AS poster_id', 'phpbb_user_id'),
+ array('user_type', 'users.user_active', 'set_user_type'),
+ array('group_id', 'users.user_level', 'phpbb_set_primary_group'),
+ array('user_regdate', 'users.user_regdate', ''),
+ array('username', 'users.username', 'phpbb_set_default_encoding'), // recode to utf8 with default lang
+ array('username_clean', 'users.username', array('function1' => 'phpbb_set_default_encoding', 'function2' => 'utf8_clean_string')),
+ array('user_password', 'users.user_password', 'phpbb_convert_password_hash'),
+ array('user_posts', 'users.user_posts', 'intval'),
+ array('user_email', 'users.user_email', 'strtolower'),
+ array('user_email_hash', 'users.user_email', 'gen_email_hash'),
+ array('user_birthday', ((defined('MOD_BIRTHDAY')) ? 'users.user_birthday' : ''), 'phpbb_get_birthday'),
+ array('user_lastvisit', 'users.user_lastvisit', 'intval'),
+ array('user_lastmark', 'users.user_lastvisit', 'intval'),
+ array('user_lang', $config['default_lang'], ''),
+ array('', 'users.user_lang', ''),
+ array('user_timezone', 'users.user_timezone', 'phpbb_convert_timezone'),
+ array('user_dateformat', 'users.user_dateformat', array('function1' => 'phpbb_set_encoding', 'function2' => 'fill_dateformat')),
+ array('user_inactive_reason', '', 'phpbb_inactive_reason'),
+ array('user_inactive_time', '', 'phpbb_inactive_time'),
+
+ array('user_jabber', '', ''),
+ array('user_rank', 'users.user_rank', 'intval'),
+ array('user_permissions', '', ''),
+
+ array('user_avatar', 'users.user_avatar', 'phpbb_import_avatar'),
+ array('user_avatar_type', 'users.user_avatar_type', 'phpbb_avatar_type'),
+ array('user_avatar_width', 'users.user_avatar', 'phpbb_get_avatar_width'),
+ array('user_avatar_height', 'users.user_avatar', 'phpbb_get_avatar_height'),
+
+ array('user_new_privmsg', 'users.user_new_privmsg', ''),
+ array('user_unread_privmsg', 0, ''), //'users.user_unread_privmsg'
+ array('user_last_privmsg', 'users.user_last_privmsg', 'intval'),
+ array('user_emailtime', 'users.user_emailtime', 'null_to_zero'),
+ array('user_notify', 'users.user_notify', 'intval'),
+ array('user_notify_pm', 'users.user_notify_pm', 'intval'),
+ array('user_notify_type', NOTIFY_EMAIL, ''),
+ array('user_allow_pm', 'users.user_allow_pm', 'intval'),
+ array('user_allow_viewonline', 'users.user_allow_viewonline', 'intval'),
+ array('user_allow_viewemail', 'users.user_viewemail', 'intval'),
+ array('user_actkey', 'users.user_actkey', ''),
+ array('user_newpasswd', '', ''), // Users need to re-request their password...
+ array('user_style', $config['default_style'], ''),
+
+ array('user_options', '', 'set_user_options'),
+ array('', 'users.user_popup_pm AS popuppm', ''),
+ array('', 'users.user_allowhtml AS html', ''),
+ array('', 'users.user_allowbbcode AS bbcode', ''),
+ array('', 'users.user_allowsmile AS smile', ''),
+ array('', 'users.user_attachsig AS attachsig',''),
+
+ array('user_sig_bbcode_uid', 'users.user_regdate', 'make_uid'),
+ array('user_sig', 'users.user_sig', 'phpbb_prepare_message'),
+ array('', 'users.user_sig_bbcode_uid AS old_bbcode_uid', ''),
+ array('user_sig_bbcode_bitfield', '', 'get_bbcode_bitfield'),
+ array('', 'users.user_regdate AS post_time', ''),
+
+ array('', 'users.user_notify_pm', 'phpbb_add_notification_options'),
+
+ 'where' => 'users.user_id <> -1',
+ ),
+
+ array(
+ 'target' => PROFILE_FIELDS_DATA_TABLE,
+ 'primary' => 'users.user_id',
+ 'query_first' => array(
+ array('target', $convert->truncate_statement . PROFILE_FIELDS_DATA_TABLE),
+ ),
+
+ array('user_id', 'users.user_id', 'phpbb_user_id'),
+ array('pf_phpbb_occupation', 'users.user_occ', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_interests', 'users.user_interests', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_location', 'users.user_from', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_icq', 'users.user_icq', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_wlm', 'users.user_msnm', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_yahoo', 'users.user_yim', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_aol', 'users.user_aim', array('function1' => 'phpbb_set_encoding')),
+ array('pf_phpbb_website', 'users.user_website', 'validate_website'),
+
+ 'where' => 'users.user_id <> -1',
+ ),
+ ),
+ );
+}
diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php
new file mode 100644
index 0000000000..48cff426b8
--- /dev/null
+++ b/phpBB/install/convertors/functions_phpbb20.php
@@ -0,0 +1,1984 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Helper functions for phpBB 2.0.x to phpBB 3.1.x conversion
+*/
+
+/**
+* Set forum flags - only prune old polls by default
+*/
+function phpbb_forum_flags()
+{
+ // Set forum flags
+ $forum_flags = 0;
+
+ // FORUM_FLAG_LINK_TRACK
+ $forum_flags += 0;
+
+ // FORUM_FLAG_PRUNE_POLL
+ $forum_flags += FORUM_FLAG_PRUNE_POLL;
+
+ // FORUM_FLAG_PRUNE_ANNOUNCE
+ $forum_flags += 0;
+
+ // FORUM_FLAG_PRUNE_STICKY
+ $forum_flags += 0;
+
+ // FORUM_FLAG_ACTIVE_TOPICS
+ $forum_flags += 0;
+
+ // FORUM_FLAG_POST_REVIEW
+ $forum_flags += FORUM_FLAG_POST_REVIEW;
+
+ return $forum_flags;
+}
+
+/**
+* Insert/Convert forums
+*/
+function phpbb_insert_forums()
+{
+ global $db, $src_db, $same_db, $convert, $user, $config;
+
+ $db->sql_query($convert->truncate_statement . FORUMS_TABLE);
+
+ // Determine the highest id used within the old forums table (we add the categories after the forum ids)
+ $sql = 'SELECT MAX(forum_id) AS max_forum_id
+ FROM ' . $convert->src_table_prefix . 'forums';
+ $result = $src_db->sql_query($sql);
+ $max_forum_id = (int) $src_db->sql_fetchfield('max_forum_id');
+ $src_db->sql_freeresult($result);
+
+ $max_forum_id++;
+
+ // pruning disabled globally?
+ $sql = "SELECT config_value
+ FROM {$convert->src_table_prefix}config
+ WHERE config_name = 'prune_enable'";
+ $result = $src_db->sql_query($sql);
+ $prune_enabled = (int) $src_db->sql_fetchfield('config_value');
+ $src_db->sql_freeresult($result);
+
+ // Insert categories
+ $sql = 'SELECT cat_id, cat_title
+ FROM ' . $convert->src_table_prefix . 'categories
+ ORDER BY cat_order';
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $result = $src_db->sql_query($sql);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ switch ($db->get_sql_layer())
+ {
+ case 'mssql':
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $db->sql_query('SET IDENTITY_INSERT ' . FORUMS_TABLE . ' ON');
+ break;
+ }
+
+ $cats_added = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $sql_ary = array(
+ 'forum_id' => (int) $max_forum_id,
+ 'forum_name' => ($row['cat_title']) ? htmlspecialchars(phpbb_set_default_encoding($row['cat_title']), ENT_COMPAT, 'UTF-8') : $user->lang['CATEGORY'],
+ 'parent_id' => 0,
+ 'forum_parents' => '',
+ 'forum_desc' => '',
+ 'forum_type' => FORUM_CAT,
+ 'forum_status' => ITEM_UNLOCKED,
+ 'forum_rules' => '',
+ );
+
+ $sql = 'SELECT MAX(right_id) AS right_id
+ FROM ' . FORUMS_TABLE;
+ $_result = $db->sql_query($sql);
+ $cat_row = $db->sql_fetchrow($_result);
+ $db->sql_freeresult($_result);
+
+ $sql_ary['left_id'] = (int) ($cat_row['right_id'] + 1);
+ $sql_ary['right_id'] = (int) ($cat_row['right_id'] + 2);
+
+ $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
+ $db->sql_query($sql);
+
+ $cats_added[$row['cat_id']] = $max_forum_id;
+ $max_forum_id++;
+ }
+ $src_db->sql_freeresult($result);
+
+ // There may be installations having forums with non-existant category ids.
+ // We try to catch them and add them to an "unknown" category instead of leaving them out.
+ $sql = 'SELECT cat_id
+ FROM ' . $convert->src_table_prefix . 'forums
+ GROUP BY cat_id';
+ $result = $src_db->sql_query($sql);
+
+ $unknown_cat_id = false;
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ // Catch those categories not been added before
+ if (!isset($cats_added[$row['cat_id']]))
+ {
+ $unknown_cat_id = true;
+ }
+ }
+ $src_db->sql_freeresult($result);
+
+ // Is there at least one category not known?
+ if ($unknown_cat_id === true)
+ {
+ $unknown_cat_id = 'ghost';
+
+ $sql_ary = array(
+ 'forum_id' => (int) $max_forum_id,
+ 'forum_name' => (string) $user->lang['CATEGORY'],
+ 'parent_id' => 0,
+ 'forum_parents' => '',
+ 'forum_desc' => '',
+ 'forum_type' => FORUM_CAT,
+ 'forum_status' => ITEM_UNLOCKED,
+ 'forum_rules' => '',
+ );
+
+ $sql = 'SELECT MAX(right_id) AS right_id
+ FROM ' . FORUMS_TABLE;
+ $_result = $db->sql_query($sql);
+ $cat_row = $db->sql_fetchrow($_result);
+ $db->sql_freeresult($_result);
+
+ $sql_ary['left_id'] = (int) ($cat_row['right_id'] + 1);
+ $sql_ary['right_id'] = (int) ($cat_row['right_id'] + 2);
+
+ $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
+ $db->sql_query($sql);
+
+ $cats_added[$unknown_cat_id] = $max_forum_id;
+ $max_forum_id++;
+ }
+
+ // Now insert the forums
+ $sql = 'SELECT f.forum_id, f.forum_name, f.cat_id, f.forum_desc, f.forum_status, f.prune_enable, f.prune_next, fp.prune_days, fp.prune_freq FROM ' . $convert->src_table_prefix . 'forums f
+ LEFT JOIN ' . $convert->src_table_prefix . 'forum_prune fp ON f.forum_id = fp.forum_id
+ GROUP BY f.forum_id, f.forum_name, f.cat_id, f.forum_desc, f.forum_status, f.prune_enable, f.prune_next, f.forum_order, fp.prune_days, fp.prune_freq
+ ORDER BY f.cat_id, f.forum_order';
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $result = $src_db->sql_query($sql);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ // Some might have forums here with an id not being "possible"...
+ // To be somewhat friendly we "change" the category id for those to a previously created ghost category
+ if (!isset($cats_added[$row['cat_id']]) && $unknown_cat_id !== false)
+ {
+ $row['cat_id'] = $unknown_cat_id;
+ }
+
+ if (!isset($cats_added[$row['cat_id']]))
+ {
+ continue;
+ }
+
+ // Define the new forums sql ary
+ $sql_ary = array(
+ 'forum_id' => (int) $row['forum_id'],
+ 'forum_name' => htmlspecialchars(phpbb_set_default_encoding($row['forum_name']), ENT_COMPAT, 'UTF-8'),
+ 'parent_id' => (int) $cats_added[$row['cat_id']],
+ 'forum_parents' => '',
+ 'forum_desc' => htmlspecialchars(phpbb_set_default_encoding($row['forum_desc']), ENT_COMPAT, 'UTF-8'),
+ 'forum_type' => FORUM_POST,
+ 'forum_status' => is_item_locked($row['forum_status']),
+ 'enable_prune' => ($prune_enabled) ? (int) $row['prune_enable'] : 0,
+ 'prune_next' => (int) null_to_zero($row['prune_next']),
+ 'prune_days' => (int) null_to_zero($row['prune_days']),
+ 'prune_viewed' => 0,
+ 'prune_freq' => (int) null_to_zero($row['prune_freq']),
+
+ 'forum_flags' => phpbb_forum_flags(),
+ 'forum_options' => 0,
+
+ // Default values
+ 'forum_desc_bitfield' => '',
+ 'forum_desc_options' => 7,
+ 'forum_desc_uid' => '',
+ 'forum_link' => '',
+ 'forum_password' => '',
+ 'forum_style' => 0,
+ 'forum_image' => '',
+ 'forum_rules' => '',
+ 'forum_rules_link' => '',
+ 'forum_rules_bitfield' => '',
+ 'forum_rules_options' => 7,
+ 'forum_rules_uid' => '',
+ 'forum_topics_per_page' => 0,
+ 'forum_posts_approved' => 0,
+ 'forum_posts_unapproved' => 0,
+ 'forum_posts_softdeleted' => 0,
+ 'forum_topics_approved' => 0,
+ 'forum_topics_unapproved' => 0,
+ 'forum_topics_softdeleted' => 0,
+ 'forum_last_post_id' => 0,
+ 'forum_last_poster_id' => 0,
+ 'forum_last_post_subject' => '',
+ 'forum_last_post_time' => 0,
+ 'forum_last_poster_name' => '',
+ 'forum_last_poster_colour' => '',
+ 'display_on_index' => 1,
+ 'enable_indexing' => 1,
+ 'enable_icons' => 0,
+ );
+
+ // Now add the forums with proper left/right ids
+ $sql = 'SELECT left_id, right_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $cats_added[$row['cat_id']];
+ $_result = $db->sql_query($sql);
+ $cat_row = $db->sql_fetchrow($_result);
+ $db->sql_freeresult($_result);
+
+ $sql = 'UPDATE ' . FORUMS_TABLE . '
+ SET left_id = left_id + 2, right_id = right_id + 2
+ WHERE left_id > ' . $cat_row['right_id'];
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . FORUMS_TABLE . '
+ SET right_id = right_id + 2
+ WHERE ' . $cat_row['left_id'] . ' BETWEEN left_id AND right_id';
+ $db->sql_query($sql);
+
+ $sql_ary['left_id'] = (int) $cat_row['right_id'];
+ $sql_ary['right_id'] = (int) ($cat_row['right_id'] + 1);
+
+ $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
+ $db->sql_query($sql);
+ }
+ $src_db->sql_freeresult($result);
+
+ switch ($db->get_sql_layer())
+ {
+ case 'postgres':
+ $db->sql_query("SELECT SETVAL('" . FORUMS_TABLE . "_seq',(select case when max(forum_id)>0 then max(forum_id)+1 else 1 end from " . FORUMS_TABLE . '));');
+ break;
+
+ case 'mssql':
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $db->sql_query('SET IDENTITY_INSERT ' . FORUMS_TABLE . ' OFF');
+ break;
+
+ case 'oracle':
+ $result = $db->sql_query('SELECT MAX(forum_id) as max_id FROM ' . FORUMS_TABLE);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $largest_id = (int) $row['max_id'];
+
+ if ($largest_id)
+ {
+ $db->sql_query('DROP SEQUENCE ' . FORUMS_TABLE . '_seq');
+ $db->sql_query('CREATE SEQUENCE ' . FORUMS_TABLE . '_seq START WITH ' . ($largest_id + 1));
+ }
+ break;
+ }
+}
+
+/**
+* Function for recoding text with the default language
+*
+* @param string $text text to recode to utf8
+* @param bool $grab_user_lang if set to true the function tries to use $convert_row['user_lang'] (and falls back to $convert_row['poster_id']) instead of the boards default language
+*/
+function phpbb_set_encoding($text, $grab_user_lang = true)
+{
+ global $lang_enc_array, $convert_row;
+ global $convert, $phpEx;
+
+ /*static $lang_enc_array = array(
+ 'korean' => 'euc-kr',
+ 'serbian' => 'windows-1250',
+ 'polish' => 'iso-8859-2',
+ 'kurdish' => 'windows-1254',
+ 'slovak' => 'Windows-1250',
+ 'russian' => 'windows-1251',
+ 'estonian' => 'iso-8859-4',
+ 'chinese_simplified' => 'gb2312',
+ 'macedonian' => 'windows-1251',
+ 'azerbaijani' => 'UTF-8',
+ 'romanian' => 'iso-8859-2',
+ 'romanian_diacritice' => 'iso-8859-2',
+ 'lithuanian' => 'windows-1257',
+ 'turkish' => 'iso-8859-9',
+ 'ukrainian' => 'windows-1251',
+ 'japanese' => 'shift_jis',
+ 'hungarian' => 'ISO-8859-2',
+ 'romanian_no_diacritics' => 'iso-8859-2',
+ 'mongolian' => 'UTF-8',
+ 'slovenian' => 'windows-1250',
+ 'bosnian' => 'windows-1250',
+ 'czech' => 'Windows-1250',
+ 'farsi' => 'Windows-1256',
+ 'croatian' => 'windows-1250',
+ 'greek' => 'iso-8859-7',
+ 'russian_tu' => 'windows-1251',
+ 'sakha' => 'UTF-8',
+ 'serbian_cyrillic' => 'windows-1251',
+ 'bulgarian' => 'windows-1251',
+ 'chinese_traditional_taiwan' => 'big5',
+ 'chinese_traditional' => 'big5',
+ 'arabic' => 'windows-1256',
+ 'hebrew' => 'WINDOWS-1255',
+ 'thai' => 'windows-874',
+ //'chinese_traditional_taiwan' => 'utf-8' // custom modified, we may have to do an include :-(
+ );*/
+
+ if (empty($lang_enc_array))
+ {
+ $lang_enc_array = array();
+ }
+
+ $get_lang = trim(get_config_value('default_lang'));
+
+ // Do we need the users language encoding?
+ if ($grab_user_lang && !empty($convert_row))
+ {
+ if (!empty($convert_row['user_lang']))
+ {
+ $get_lang = trim($convert_row['user_lang']);
+ }
+ else if (!empty($convert_row['poster_id']))
+ {
+ global $src_db, $same_db;
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $sql = 'SELECT user_lang
+ FROM ' . $convert->src_table_prefix . 'users
+ WHERE user_id = ' . (int) $convert_row['poster_id'];
+ $result = $src_db->sql_query($sql);
+ $get_lang = (string) $src_db->sql_fetchfield('user_lang');
+ $src_db->sql_freeresult($result);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ $get_lang = (!trim($get_lang)) ? trim(get_config_value('default_lang')) : trim($get_lang);
+ }
+ }
+
+ if (!isset($lang_enc_array[$get_lang]))
+ {
+ $filename = $convert->options['forum_path'] . '/language/lang_' . $get_lang . '/lang_main.' . $phpEx;
+
+ if (!file_exists($filename))
+ {
+ $get_lang = trim(get_config_value('default_lang'));
+ }
+
+ if (!isset($lang_enc_array[$get_lang]))
+ {
+ include($convert->options['forum_path'] . '/language/lang_' . $get_lang . '/lang_main.' . $phpEx);
+ $lang_enc_array[$get_lang] = $lang['ENCODING'];
+ unset($lang);
+ }
+ }
+
+ $encoding = $lang_enc_array[$get_lang];
+
+ return utf8_recode($text, $lang_enc_array[$get_lang]);
+}
+
+/**
+* Same as phpbb_set_encoding, but forcing boards default language
+*/
+function phpbb_set_default_encoding($text)
+{
+ return phpbb_set_encoding($text, false);
+}
+
+/**
+* Convert Birthday from Birthday MOD to phpBB Format
+*/
+function phpbb_get_birthday($birthday = '')
+{
+ if (defined('MOD_BIRTHDAY_TERRA'))
+ {
+ $birthday = (string) $birthday;
+
+ // stored as month, day, year
+ if (!$birthday)
+ {
+ return ' 0- 0- 0';
+ }
+
+ // We use the original mod code to retrieve the birthday (not ideal)
+ preg_match('/(..)(..)(....)/', sprintf('%08d', $birthday), $birthday_parts);
+
+ $month = $birthday_parts[1];
+ $day = $birthday_parts[2];
+ $year = $birthday_parts[3];
+
+ return sprintf('%2d-%2d-%4d', $day, $month, $year);
+ }
+ else
+ {
+ $birthday = (int) $birthday;
+
+ if (!$birthday || $birthday == 999999)
+ {
+ return ' 0- 0- 0';
+ }
+
+ // The birthday mod from niels is using this code to transform to day/month/year
+ return sprintf('%2d-%2d-%4d', gmdate('j', $birthday * 86400 + 1), gmdate('n', $birthday * 86400 + 1), gmdate('Y', $birthday * 86400 + 1));
+ }
+}
+
+/**
+* Return correct user id value
+* Everyone's id will be one higher to allow the guest/anonymous user to have a positive id as well
+*/
+function phpbb_user_id($user_id)
+{
+ global $config;
+
+ // Increment user id if the old forum is having a user with the id 1
+ if (!isset($config['increment_user_id']))
+ {
+ global $src_db, $same_db, $convert;
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ // Now let us set a temporary config variable for user id incrementing
+ $sql = "SELECT user_id
+ FROM {$convert->src_table_prefix}users
+ WHERE user_id = 1";
+ $result = $src_db->sql_query($sql);
+ $id = (int) $src_db->sql_fetchfield('user_id');
+ $src_db->sql_freeresult($result);
+
+ // Try to get the maximum user id possible...
+ $sql = "SELECT MAX(user_id) AS max_user_id
+ FROM {$convert->src_table_prefix}users";
+ $result = $src_db->sql_query($sql);
+ $max_id = (int) $src_db->sql_fetchfield('max_user_id');
+ $src_db->sql_freeresult($result);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ // If there is a user id 1, we need to increment user ids. :/
+ if ($id === 1)
+ {
+ $config->set('increment_user_id', ($max_id + 1), false);
+ $config['increment_user_id'] = $max_id + 1;
+ }
+ else
+ {
+ $config->set('increment_user_id', 0, false);
+ $config['increment_user_id'] = 0;
+ }
+ }
+
+ // If the old user id is -1 in 2.0.x it is the anonymous user...
+ if ($user_id == -1)
+ {
+ return ANONYMOUS;
+ }
+
+ if (!empty($config['increment_user_id']) && $user_id == 1)
+ {
+ return $config['increment_user_id'];
+ }
+
+ // A user id of 0 can happen, for example within the ban table if no user is banned...
+ // Within the posts and topics table this can be "dangerous" but is the fault of the user
+ // having mods installed (a poster id of 0 is not possible in 2.0.x).
+ // Therefore, we return the user id "as is".
+
+ return (int) $user_id;
+}
+
+/**
+* Return correct user id value
+* Everyone's id will be one higher to allow the guest/anonymous user to have a positive id as well
+*/
+function phpbb_topic_replies_to_posts($num_replies)
+{
+ return (int) $num_replies + 1;
+}
+
+/* Copy additional table fields from old forum to new forum if user wants this (for Mod compatibility for example)
+function phpbb_copy_table_fields()
+{
+}
+*/
+
+/**
+* Convert authentication
+* user, group and forum table has to be filled in order to work
+*/
+function phpbb_convert_authentication($mode)
+{
+ global $db, $src_db, $same_db, $convert, $user, $config, $cache;
+
+ if ($mode == 'start')
+ {
+ $db->sql_query($convert->truncate_statement . ACL_USERS_TABLE);
+ $db->sql_query($convert->truncate_statement . ACL_GROUPS_TABLE);
+
+ // What we will do is handling all 2.0.x admins as founder to replicate what is common in 2.0.x.
+ // After conversion the main admin need to make sure he is removing permissions and the founder status if wanted.
+
+ // Grab user ids of users with user_level of ADMIN
+ $sql = "SELECT user_id
+ FROM {$convert->src_table_prefix}users
+ WHERE user_level = 1
+ ORDER BY user_regdate ASC";
+ $result = $src_db->sql_query($sql);
+
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $user_id = (int) phpbb_user_id($row['user_id']);
+ // Set founder admin...
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_type = ' . USER_FOUNDER . "
+ WHERE user_id = $user_id";
+ $db->sql_query($sql);
+ }
+ $src_db->sql_freeresult($result);
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $db->sql_escape('BOTS') . "'";
+ $result = $db->sql_query($sql);
+ $bot_group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+ }
+
+ // Grab forum auth information
+ $sql = "SELECT *
+ FROM {$convert->src_table_prefix}forums";
+ $result = $src_db->sql_query($sql);
+
+ $forum_access = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $forum_access[$row['forum_id']] = $row;
+ }
+ $src_db->sql_freeresult($result);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+ // Grab user auth information from 2.0.x board
+ $sql = "SELECT ug.user_id, aa.*
+ FROM {$convert->src_table_prefix}auth_access aa, {$convert->src_table_prefix}user_group ug, {$convert->src_table_prefix}groups g, {$convert->src_table_prefix}forums f
+ WHERE g.group_id = aa.group_id
+ AND g.group_single_user = 1
+ AND ug.group_id = g.group_id
+ AND f.forum_id = aa.forum_id";
+ $result = $src_db->sql_query($sql);
+
+ $user_access = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $user_access[$row['forum_id']][] = $row;
+ }
+ $src_db->sql_freeresult($result);
+
+ // Grab group auth information
+ $sql = "SELECT g.group_id, aa.*
+ FROM {$convert->src_table_prefix}auth_access aa, {$convert->src_table_prefix}groups g
+ WHERE g.group_id = aa.group_id
+ AND g.group_single_user <> 1";
+ $result = $src_db->sql_query($sql);
+
+ $group_access = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $group_access[$row['forum_id']][] = $row;
+ }
+ $src_db->sql_freeresult($result);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ // Add Forum Access List
+ $auth_map = array(
+ 'auth_view' => array('f_', 'f_list'),
+ 'auth_read' => array('f_read', 'f_search'),
+ 'auth_post' => array('f_post', 'f_bbcode', 'f_smilies', 'f_img', 'f_sigs', 'f_postcount', 'f_report', 'f_subscribe', 'f_print', 'f_email'),
+ 'auth_reply' => 'f_reply',
+ 'auth_edit' => 'f_edit',
+ 'auth_delete' => 'f_delete',
+ 'auth_pollcreate' => 'f_poll',
+ 'auth_vote' => 'f_vote',
+ 'auth_announce' => 'f_announce',
+ 'auth_sticky' => 'f_sticky',
+ 'auth_attachments' => array('f_attach', 'f_download'),
+ 'auth_download' => 'f_download',
+ );
+
+ // Define the ACL constants used in 2.0 to make the code slightly more readable
+ define('AUTH_ALL', 0);
+ define('AUTH_REG', 1);
+ define('AUTH_ACL', 2);
+ define('AUTH_MOD', 3);
+ define('AUTH_ADMIN', 5);
+
+ // A mapping of the simple permissions used by 2.0
+ $simple_auth_ary = array(
+ 'public' => array(
+ 'auth_view' => AUTH_ALL,
+ 'auth_read' => AUTH_ALL,
+ 'auth_post' => AUTH_ALL,
+ 'auth_reply' => AUTH_ALL,
+ 'auth_edit' => AUTH_REG,
+ 'auth_delete' => AUTH_REG,
+ 'auth_sticky' => AUTH_MOD,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_REG,
+ 'auth_pollcreate' => AUTH_REG,
+ ),
+ 'registered' => array(
+ 'auth_view' => AUTH_ALL,
+ 'auth_read' => AUTH_ALL,
+ 'auth_post' => AUTH_REG,
+ 'auth_reply' => AUTH_REG,
+ 'auth_edit' => AUTH_REG,
+ 'auth_delete' => AUTH_REG,
+ 'auth_sticky' => AUTH_MOD,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_REG,
+ 'auth_pollcreate' => AUTH_REG,
+ ),
+ 'registered_hidden' => array(
+ 'auth_view' => AUTH_REG,
+ 'auth_read' => AUTH_REG,
+ 'auth_post' => AUTH_REG,
+ 'auth_reply' => AUTH_REG,
+ 'auth_edit' => AUTH_REG,
+ 'auth_delete' => AUTH_REG,
+ 'auth_sticky' => AUTH_MOD,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_REG,
+ 'auth_pollcreate' => AUTH_REG,
+ ),
+ 'private' => array(
+ 'auth_view' => AUTH_ALL,
+ 'auth_read' => AUTH_ACL,
+ 'auth_post' => AUTH_ACL,
+ 'auth_reply' => AUTH_ACL,
+ 'auth_edit' => AUTH_ACL,
+ 'auth_delete' => AUTH_ACL,
+ 'auth_sticky' => AUTH_ACL,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_ACL,
+ 'auth_pollcreate' => AUTH_ACL,
+ ),
+ 'private_hidden' => array(
+ 'auth_view' => AUTH_ACL,
+ 'auth_read' => AUTH_ACL,
+ 'auth_post' => AUTH_ACL,
+ 'auth_reply' => AUTH_ACL,
+ 'auth_edit' => AUTH_ACL,
+ 'auth_delete' => AUTH_ACL,
+ 'auth_sticky' => AUTH_ACL,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_ACL,
+ 'auth_pollcreate' => AUTH_ACL,
+ ),
+ 'moderator' => array(
+ 'auth_view' => AUTH_ALL,
+ 'auth_read' => AUTH_MOD,
+ 'auth_post' => AUTH_MOD,
+ 'auth_reply' => AUTH_MOD,
+ 'auth_edit' => AUTH_MOD,
+ 'auth_delete' => AUTH_MOD,
+ 'auth_sticky' => AUTH_MOD,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_MOD,
+ 'auth_pollcreate' => AUTH_MOD,
+ ),
+ 'moderator_hidden' => array(
+ 'auth_view' => AUTH_MOD,
+ 'auth_read' => AUTH_MOD,
+ 'auth_post' => AUTH_MOD,
+ 'auth_reply' => AUTH_MOD,
+ 'auth_edit' => AUTH_MOD,
+ 'auth_delete' => AUTH_MOD,
+ 'auth_sticky' => AUTH_MOD,
+ 'auth_announce' => AUTH_MOD,
+ 'auth_vote' => AUTH_MOD,
+ 'auth_pollcreate' => AUTH_MOD,
+ ),
+ );
+
+ if ($mode == 'start')
+ {
+ user_group_auth('guests', 'SELECT user_id, {GUESTS} FROM ' . USERS_TABLE . ' WHERE user_id = ' . ANONYMOUS, false);
+ user_group_auth('registered', 'SELECT user_id, {REGISTERED} FROM ' . USERS_TABLE . ' WHERE user_id <> ' . ANONYMOUS . " AND group_id <> $bot_group_id", false);
+
+ // Selecting from old table
+ if (!empty($config['increment_user_id']))
+ {
+ $auth_sql = 'SELECT user_id, {ADMINISTRATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1 AND user_id <> 1';
+ user_group_auth('administrators', $auth_sql, true);
+
+ $auth_sql = 'SELECT ' . $config['increment_user_id'] . ' as user_id, {ADMINISTRATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1 AND user_id = 1';
+ user_group_auth('administrators', $auth_sql, true);
+ }
+ else
+ {
+ $auth_sql = 'SELECT user_id, {ADMINISTRATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1';
+ user_group_auth('administrators', $auth_sql, true);
+ }
+
+ if (!empty($config['increment_user_id']))
+ {
+ $auth_sql = 'SELECT user_id, {GLOBAL_MODERATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1 AND user_id <> 1';
+ user_group_auth('global_moderators', $auth_sql, true);
+
+ $auth_sql = 'SELECT ' . $config['increment_user_id'] . ' as user_id, {GLOBAL_MODERATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1 AND user_id = 1';
+ user_group_auth('global_moderators', $auth_sql, true);
+ }
+ else
+ {
+ $auth_sql = 'SELECT user_id, {GLOBAL_MODERATORS} FROM ' . $convert->src_table_prefix . 'users WHERE user_level = 1';
+ user_group_auth('global_moderators', $auth_sql, true);
+ }
+ }
+ else if ($mode == 'first')
+ {
+ // Go through all 2.0.x forums
+ foreach ($forum_access as $forum)
+ {
+ $new_forum_id = (int) $forum['forum_id'];
+
+ // Administrators have full access to all forums whatever happens
+ mass_auth('group_role', $new_forum_id, 'administrators', 'FORUM_FULL');
+
+ $matched_type = '';
+ foreach ($simple_auth_ary as $key => $auth_levels)
+ {
+ $matched = 1;
+ foreach ($auth_levels as $k => $level)
+ {
+ if ($forum[$k] != $auth_levels[$k])
+ {
+ $matched = 0;
+ }
+ }
+
+ if ($matched)
+ {
+ $matched_type = $key;
+ break;
+ }
+ }
+
+ switch ($matched_type)
+ {
+ case 'public':
+ mass_auth('group_role', $new_forum_id, 'guests', 'FORUM_LIMITED');
+ mass_auth('group_role', $new_forum_id, 'registered', 'FORUM_LIMITED_POLLS');
+ mass_auth('group_role', $new_forum_id, 'bots', 'FORUM_BOT');
+ break;
+
+ case 'registered':
+ mass_auth('group_role', $new_forum_id, 'guests', 'FORUM_READONLY');
+ mass_auth('group_role', $new_forum_id, 'bots', 'FORUM_BOT');
+
+ // no break;
+
+ case 'registered_hidden':
+ mass_auth('group_role', $new_forum_id, 'registered', 'FORUM_POLLS');
+ break;
+
+ case 'private':
+ case 'private_hidden':
+ case 'moderator':
+ case 'moderator_hidden':
+ default:
+ // The permissions don't match a simple set, so we're going to have to map them directly
+
+ // No post approval for all, in 2.0.x this feature does not exist
+ mass_auth('group', $new_forum_id, 'guests', 'f_noapprove', ACL_YES);
+ mass_auth('group', $new_forum_id, 'registered', 'f_noapprove', ACL_YES);
+
+ // Go through authentication map
+ foreach ($auth_map as $old_auth_key => $new_acl)
+ {
+ // If old authentication key does not exist we continue
+ // This is helpful for mods adding additional authentication fields, we need to add them to the auth_map array
+ if (!isset($forum[$old_auth_key]))
+ {
+ continue;
+ }
+
+ // Now set the new ACL correctly
+ switch ($forum[$old_auth_key])
+ {
+ // AUTH_ALL
+ case AUTH_ALL:
+ mass_auth('group', $new_forum_id, 'guests', $new_acl, ACL_YES);
+ mass_auth('group', $new_forum_id, 'bots', $new_acl, ACL_YES);
+ mass_auth('group', $new_forum_id, 'registered', $new_acl, ACL_YES);
+ break;
+
+ // AUTH_REG
+ case AUTH_REG:
+ mass_auth('group', $new_forum_id, 'registered', $new_acl, ACL_YES);
+ break;
+
+ // AUTH_ACL
+ case AUTH_ACL:
+ // Go through the old group access list for this forum
+ if (isset($group_access[$forum['forum_id']]))
+ {
+ foreach ($group_access[$forum['forum_id']] as $index => $access)
+ {
+ // We only check for ACL_YES equivalence entry
+ if (isset($access[$old_auth_key]) && $access[$old_auth_key] == 1)
+ {
+ mass_auth('group', $new_forum_id, (int) $access['group_id'], $new_acl, ACL_YES);
+ }
+ }
+ }
+
+ if (isset($user_access[$forum['forum_id']]))
+ {
+ foreach ($user_access[$forum['forum_id']] as $index => $access)
+ {
+ // We only check for ACL_YES equivalence entry
+ if (isset($access[$old_auth_key]) && $access[$old_auth_key] == 1)
+ {
+ mass_auth('user', $new_forum_id, (int) phpbb_user_id($access['user_id']), $new_acl, ACL_YES);
+ }
+ }
+ }
+ break;
+
+ // AUTH_MOD
+ case AUTH_MOD:
+ if (isset($group_access[$forum['forum_id']]))
+ {
+ foreach ($group_access[$forum['forum_id']] as $index => $access)
+ {
+ // We only check for ACL_YES equivalence entry
+ if (isset($access[$old_auth_key]) && $access[$old_auth_key] == 1)
+ {
+ mass_auth('group', $new_forum_id, (int) $access['group_id'], $new_acl, ACL_YES);
+ }
+ }
+ }
+
+ if (isset($user_access[$forum['forum_id']]))
+ {
+ foreach ($user_access[$forum['forum_id']] as $index => $access)
+ {
+ // We only check for ACL_YES equivalence entry
+ if (isset($access[$old_auth_key]) && $access[$old_auth_key] == 1)
+ {
+ mass_auth('user', $new_forum_id, (int) phpbb_user_id($access['user_id']), $new_acl, ACL_YES);
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if ($mode == 'second')
+ {
+ // Assign permission roles and other default permissions
+
+ // guests having u_download and u_search ability
+ $db->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) SELECT ' . get_group_id('guests') . ', 0, auth_option_id, 0, 1 FROM ' . ACL_OPTIONS_TABLE . " WHERE auth_option IN ('u_', 'u_download', 'u_search')");
+
+ // administrators/global mods having full user features
+ mass_auth('group_role', 0, 'administrators', 'USER_FULL');
+ mass_auth('group_role', 0, 'global_moderators', 'USER_FULL');
+
+ // By default all converted administrators are given full access
+ mass_auth('group_role', 0, 'administrators', 'ADMIN_FULL');
+
+ // All registered users are assigned the standard user role
+ mass_auth('group_role', 0, 'registered', 'USER_STANDARD');
+ mass_auth('group_role', 0, 'registered_coppa', 'USER_STANDARD');
+
+ // Instead of administrators being global moderators we give the MOD_FULL role to global mods (admins already assigned to this group)
+ mass_auth('group_role', 0, 'global_moderators', 'MOD_FULL');
+
+ // And now those who have had their avatar rights removed get assigned a more restrictive role
+ $sql = 'SELECT user_id FROM ' . $convert->src_table_prefix . 'users
+ WHERE user_allowavatar = 0
+ AND user_id > 0';
+ $result = $src_db->sql_query($sql);
+
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ mass_auth('user_role', 0, (int) phpbb_user_id($row['user_id']), 'USER_NOAVATAR');
+ }
+ $src_db->sql_freeresult($result);
+
+ // And the same for those who have had their PM rights removed
+ $sql = 'SELECT user_id FROM ' . $convert->src_table_prefix . 'users
+ WHERE user_allow_pm = 0
+ AND user_id > 0';
+ $result = $src_db->sql_query($sql);
+
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ mass_auth('user_role', 0, (int) phpbb_user_id($row['user_id']), 'USER_NOPM');
+ }
+ $src_db->sql_freeresult($result);
+ }
+ else if ($mode == 'third')
+ {
+ // And now the moderators
+ // We make sure that they have at least standard access to the forums they moderate in addition to the moderating permissions
+
+ $mod_post_map = array(
+ 'auth_announce' => 'f_announce',
+ 'auth_sticky' => 'f_sticky'
+ );
+
+ foreach ($user_access as $forum_id => $access_map)
+ {
+ $forum_id = (int) $forum_id;
+
+ foreach ($access_map as $access)
+ {
+ if (isset($access['auth_mod']) && $access['auth_mod'] == 1)
+ {
+ mass_auth('user_role', $forum_id, (int) phpbb_user_id($access['user_id']), 'MOD_STANDARD');
+ mass_auth('user_role', $forum_id, (int) phpbb_user_id($access['user_id']), 'FORUM_STANDARD');
+ foreach ($mod_post_map as $old => $new)
+ {
+ if (isset($forum_access[$forum_id]) && isset($forum_access[$forum_id][$old]) && $forum_access[$forum_id][$old] == AUTH_MOD)
+ {
+ mass_auth('user', $forum_id, (int) phpbb_user_id($access['user_id']), $new, ACL_YES);
+ }
+ }
+ }
+ }
+ }
+
+ foreach ($group_access as $forum_id => $access_map)
+ {
+ $forum_id = (int) $forum_id;
+
+ foreach ($access_map as $access)
+ {
+ if (isset($access['auth_mod']) && $access['auth_mod'] == 1)
+ {
+ mass_auth('group_role', $forum_id, (int) $access['group_id'], 'MOD_STANDARD');
+ mass_auth('group_role', $forum_id, (int) $access['group_id'], 'FORUM_STANDARD');
+ foreach ($mod_post_map as $old => $new)
+ {
+ if (isset($forum_access[$forum_id]) && isset($forum_access[$forum_id][$old]) && $forum_access[$forum_id][$old] == AUTH_MOD)
+ {
+ mass_auth('group', $forum_id, (int) $access['group_id'], $new, ACL_YES);
+ }
+ }
+ }
+ }
+ }
+
+ // We grant everyone readonly access to the categories to ensure that the forums are visible
+ $sql = 'SELECT forum_id, forum_name, parent_id, left_id, right_id
+ FROM ' . FORUMS_TABLE . '
+ ORDER BY left_id ASC';
+ $result = $db->sql_query($sql);
+
+ $parent_forums = $forums = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ if ($row['parent_id'] == 0)
+ {
+ mass_auth('group_role', $row['forum_id'], 'administrators', 'FORUM_FULL');
+ mass_auth('group_role', $row['forum_id'], 'global_moderators', 'FORUM_FULL');
+ $parent_forums[] = $row;
+ }
+ else
+ {
+ $forums[] = $row;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ global $auth;
+
+ // Let us see which groups have access to these forums...
+ foreach ($parent_forums as $row)
+ {
+ // Get the children
+ $branch = $forum_ids = array();
+
+ foreach ($forums as $key => $_row)
+ {
+ if ($_row['left_id'] > $row['left_id'] && $_row['left_id'] < $row['right_id'])
+ {
+ $branch[] = $_row;
+ $forum_ids[] = $_row['forum_id'];
+ continue;
+ }
+ }
+
+ if (sizeof($forum_ids))
+ {
+ // Now make sure the user is able to read these forums
+ $hold_ary = $auth->acl_group_raw_data(false, 'f_list', $forum_ids);
+
+ if (empty($hold_ary))
+ {
+ continue;
+ }
+
+ foreach ($hold_ary as $g_id => $f_id_ary)
+ {
+ $set_group = false;
+
+ foreach ($f_id_ary as $f_id => $auth_ary)
+ {
+ foreach ($auth_ary as $auth_option => $setting)
+ {
+ if ($setting == ACL_YES)
+ {
+ $set_group = true;
+ break 2;
+ }
+ }
+ }
+
+ if ($set_group)
+ {
+ mass_auth('group', $row['forum_id'], $g_id, 'f_list', ACL_YES);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+* Set primary group.
+* Really simple and only based on user_level (remaining groups will be assigned later)
+*/
+function phpbb_set_primary_group($user_level)
+{
+ global $convert_row;
+
+ if ($user_level == 1)
+ {
+ return get_group_id('administrators');
+ }
+/* else if ($user_level == 2)
+ {
+ return get_group_id('global_moderators');
+ }
+ else if ($user_level == 0 && $convert_row['user_active'])*/
+ else if ($convert_row['user_active'])
+ {
+ return get_group_id('registered');
+ }
+
+ return 0;
+}
+
+/**
+* Convert the group name, making sure to avoid conflicts with 3.0 special groups
+*/
+function phpbb_convert_group_name($group_name)
+{
+ $default_groups = array(
+ 'GUESTS',
+ 'REGISTERED',
+ 'REGISTERED_COPPA',
+ 'GLOBAL_MODERATORS',
+ 'ADMINISTRATORS',
+ 'BOTS',
+ );
+
+ if (in_array(strtoupper($group_name), $default_groups))
+ {
+ return 'phpBB2 - ' . $group_name;
+ }
+
+ return phpbb_set_default_encoding($group_name);
+}
+
+/**
+* Convert the group type constants
+*/
+function phpbb_convert_group_type($group_type)
+{
+ switch ($group_type)
+ {
+ case 0:
+ return GROUP_OPEN;
+ break;
+
+ case 1:
+ return GROUP_CLOSED;
+ break;
+
+ case 2:
+ return GROUP_HIDDEN;
+ break;
+ }
+
+ // Never return GROUP_SPECIAL here, because only phpBB3's default groups are allowed to have this type set.
+ return GROUP_HIDDEN;
+}
+
+/**
+* Convert the topic type constants
+*/
+function phpbb_convert_topic_type($topic_type)
+{
+ switch ($topic_type)
+ {
+ case 0:
+ return POST_NORMAL;
+ break;
+
+ case 1:
+ return POST_STICKY;
+ break;
+
+ case 2:
+ return POST_ANNOUNCE;
+ break;
+
+ case 3:
+ return POST_GLOBAL;
+ break;
+ }
+
+ return POST_NORMAL;
+}
+
+function phpbb_replace_size($matches)
+{
+ return '[size=' . min(200, ceil(100.0 * (((double) $matches[1])/12.0))) . ':' . $matches[2] . ']';
+}
+
+/**
+* Reparse the message stripping out the bbcode_uid values and adding new ones and setting the bitfield
+* @todo What do we want to do about HTML in messages - currently it gets converted to the entities, but there may be some objections to this
+*/
+function phpbb_prepare_message($message)
+{
+ global $phpbb_root_path, $phpEx, $db, $convert, $user, $config, $cache, $convert_row, $message_parser;
+
+ if (!$message)
+ {
+ $convert->row['mp_bbcode_bitfield'] = $convert_row['mp_bbcode_bitfield'] = 0;
+ return '';
+ }
+
+ // Decode phpBB 2.0.x Message
+ if (isset($convert->row['old_bbcode_uid']) && $convert->row['old_bbcode_uid'] != '')
+ {
+ // Adjust size...
+ if (strpos($message, '[size=') !== false)
+ {
+ $message = preg_replace_callback('/\[size=(\d*):(' . $convert->row['old_bbcode_uid'] . ')\]/', 'phpbb_replace_size', $message);
+ }
+
+ $message = preg_replace('/\:(([a-z0-9]:)?)' . $convert->row['old_bbcode_uid'] . '/s', '', $message);
+ }
+
+ if (strpos($message, '[quote=') !== false)
+ {
+ $message = preg_replace('/\[quote="(.*?)"\]/s', '[quote=&quot;\1&quot;]', $message);
+ $message = preg_replace('/\[quote=\\\"(.*?)\\\"\]/s', '[quote=&quot;\1&quot;]', $message);
+
+ // let's hope that this solves more problems than it causes. Deal with escaped quotes.
+ $message = str_replace('\"', '&quot;', $message);
+ $message = str_replace('\&quot;', '&quot;', $message);
+ }
+
+ // Already the new user id ;)
+ $user_id = $convert->row['poster_id'];
+
+ $message = str_replace('<br />', "\n", $message);
+ $message = str_replace('<', '&lt;', $message);
+ $message = str_replace('>', '&gt;', $message);
+
+ // make the post UTF-8
+ $message = phpbb_set_encoding($message);
+
+ $message_parser->warn_msg = array(); // Reset the errors from the previous message
+ $message_parser->bbcode_uid = make_uid($convert->row['post_time']);
+ $message_parser->message = $message;
+ unset($message);
+
+ // Make sure options are set.
+// $enable_html = (!isset($row['enable_html'])) ? false : $row['enable_html'];
+ $enable_bbcode = (!isset($convert->row['enable_bbcode'])) ? true : $convert->row['enable_bbcode'];
+ $enable_smilies = (!isset($convert->row['enable_smilies'])) ? true : $convert->row['enable_smilies'];
+ $enable_magic_url = (!isset($convert->row['enable_magic_url'])) ? true : $convert->row['enable_magic_url'];
+
+ // parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post')
+ $message_parser->parse($enable_bbcode, $enable_magic_url, $enable_smilies);
+
+ if (sizeof($message_parser->warn_msg))
+ {
+ $msg_id = isset($convert->row['post_id']) ? $convert->row['post_id'] : $convert->row['privmsgs_id'];
+ $convert->p_master->error('<span style="color:red">' . $user->lang['POST_ID'] . ': ' . $msg_id . ' ' . $user->lang['CONV_ERROR_MESSAGE_PARSER'] . ': <br /><br />' . implode('<br />', $message_parser->warn_msg), __LINE__, __FILE__, true);
+ }
+
+ $convert->row['mp_bbcode_bitfield'] = $convert_row['mp_bbcode_bitfield'] = $message_parser->bbcode_bitfield;
+
+ $message = $message_parser->message;
+ unset($message_parser->message);
+
+ return $message;
+}
+
+/**
+* Return the bitfield calculated by the previous function
+*/
+function get_bbcode_bitfield()
+{
+ global $convert_row;
+
+ return $convert_row['mp_bbcode_bitfield'];
+}
+
+/**
+* Determine the last user to edit a post
+* In practice we only tracked edits by the original poster in 2.0.x so this will only be set if they had edited their own post
+*/
+function phpbb_post_edit_user()
+{
+ global $convert_row, $config;
+
+ if (isset($convert_row['post_edit_count']))
+ {
+ return phpbb_user_id($convert_row['poster_id']);
+ }
+
+ return 0;
+}
+
+/**
+* Obtain the path to uploaded files on the 2.0.x forum
+* This is only used if the Attachment MOD was installed
+*/
+function phpbb_get_files_dir()
+{
+ if (!defined('MOD_ATTACHMENT'))
+ {
+ return;
+ }
+
+ global $src_db, $same_db, $convert, $user, $config, $cache;
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+ $sql = 'SELECT config_value AS upload_dir
+ FROM ' . $convert->src_table_prefix . "attachments_config
+ WHERE config_name = 'upload_dir'";
+ $result = $src_db->sql_query($sql);
+ $upload_path = $src_db->sql_fetchfield('upload_dir');
+ $src_db->sql_freeresult($result);
+
+ $sql = 'SELECT config_value AS ftp_upload
+ FROM ' . $convert->src_table_prefix . "attachments_config
+ WHERE config_name = 'allow_ftp_upload'";
+ $result = $src_db->sql_query($sql);
+ $ftp_upload = (int) $src_db->sql_fetchfield('ftp_upload');
+ $src_db->sql_freeresult($result);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ if ($ftp_upload)
+ {
+ $convert->p_master->error($user->lang['CONV_ERROR_ATTACH_FTP_DIR'], __LINE__, __FILE__);
+ }
+
+ return $upload_path;
+}
+
+/**
+* Copy thumbnails of uploaded images from the 2.0.x forum
+* This is only used if the Attachment MOD was installed
+*/
+function phpbb_copy_thumbnails()
+{
+ global $db, $convert, $user, $config, $cache, $phpbb_root_path;
+
+ $src_path = $convert->options['forum_path'] . '/' . phpbb_get_files_dir() . '/thumbs/';
+
+ if ($handle = @opendir($src_path))
+ {
+ while ($entry = readdir($handle))
+ {
+ if ($entry[0] == '.')
+ {
+ continue;
+ }
+
+ if (is_dir($src_path . $entry))
+ {
+ continue;
+ }
+ else
+ {
+ copy_file($src_path . $entry, $config['upload_path'] . '/' . preg_replace('/^t_/', 'thumb_', $entry));
+ @unlink($phpbb_root_path . $config['upload_path'] . '/thumbs/' . $entry);
+ }
+ }
+ closedir($handle);
+ }
+}
+
+/**
+* Convert the attachment category constants
+* This is only used if the Attachment MOD was installed
+*/
+function phpbb_attachment_category($cat_id)
+{
+ switch ($cat_id)
+ {
+ case 1:
+ return ATTACHMENT_CATEGORY_IMAGE;
+ break;
+
+ case 2:
+ return ATTACHMENT_CATEGORY_WM;
+ break;
+
+ case 3:
+ return ATTACHMENT_CATEGORY_FLASH;
+ break;
+ }
+
+ return ATTACHMENT_CATEGORY_NONE;
+}
+
+/**
+* Convert the attachment extension names
+* This is only used if the Attachment MOD was installed
+*/
+function phpbb_attachment_extension_group_name()
+{
+ global $db, $phpbb_root_path, $phpEx;
+
+ // Update file extension group names to use language strings.
+ $sql = 'SELECT lang_dir
+ FROM ' . LANG_TABLE;
+ $result = $db->sql_query($sql);
+
+ $extension_groups_updated = array();
+ while ($lang_dir = $db->sql_fetchfield('lang_dir'))
+ {
+ $lang_dir = basename($lang_dir);
+ $lang_file = $phpbb_root_path . 'language/' . $lang_dir . '/acp/attachments.' . $phpEx;
+
+ if (!file_exists($lang_file))
+ {
+ continue;
+ }
+
+ $lang = array();
+ include($lang_file);
+
+ foreach ($lang as $lang_key => $lang_val)
+ {
+ if (isset($extension_groups_updated[$lang_key]) || strpos($lang_key, 'EXT_GROUP_') !== 0)
+ {
+ continue;
+ }
+
+ $sql_ary = array(
+ 'group_name' => substr($lang_key, 10), // Strip off 'EXT_GROUP_'
+ );
+
+ $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
+ WHERE group_name = '" . $db->sql_escape($lang_val) . "'";
+ $db->sql_query($sql);
+
+ $extension_groups_updated[$lang_key] = true;
+ }
+ }
+ $db->sql_freeresult($result);
+}
+
+/**
+* Obtain list of forums in which different attachment categories can be used
+*/
+function phpbb_attachment_forum_perms($forum_permissions)
+{
+ if (empty($forum_permissions))
+ {
+ return '';
+ }
+
+ // Decode forum permissions
+ $forum_ids = array();
+
+ $one_char_encoding = '#';
+ $two_char_encoding = '.';
+
+ $auth_len = 1;
+ for ($pos = 0; $pos < strlen($forum_permissions); $pos += $auth_len)
+ {
+ $forum_auth = substr($forum_permissions, $pos, 1);
+ if ($forum_auth == $one_char_encoding)
+ {
+ $auth_len = 1;
+ continue;
+ }
+ else if ($forum_auth == $two_char_encoding)
+ {
+ $auth_len = 2;
+ $pos--;
+ continue;
+ }
+
+ $forum_auth = substr($forum_permissions, $pos, $auth_len);
+ $forum_id = base64_unpack($forum_auth);
+
+ $forum_ids[] = (int) $forum_id;
+ }
+
+ if (sizeof($forum_ids))
+ {
+ return attachment_forum_perms($forum_ids);
+ }
+
+ return '';
+}
+
+/**
+* Convert the avatar type constants
+*/
+function phpbb_avatar_type($type)
+{
+ switch ($type)
+ {
+ case 1:
+ return AVATAR_UPLOAD;
+ break;
+
+ case 2:
+ return AVATAR_REMOTE;
+ break;
+
+ case 3:
+ return AVATAR_GALLERY;
+ break;
+ }
+
+ return 0;
+}
+
+
+/**
+* Just undos the replacing of '<' and '>'
+*/
+function phpbb_smilie_html_decode($code)
+{
+ $code = str_replace('&lt;', '<', $code);
+ return str_replace('&gt;', '>', $code);
+}
+
+/**
+* Transfer avatars, copying the image if it was uploaded
+*/
+function phpbb_import_avatar($user_avatar)
+{
+ global $convert_row;
+
+ if (!$convert_row['user_avatar_type'])
+ {
+ return '';
+ }
+ else if ($convert_row['user_avatar_type'] == 1)
+ {
+ // Uploaded avatar
+ return import_avatar($user_avatar, false, $convert_row['user_id']);
+ }
+ else if ($convert_row['user_avatar_type'] == 2)
+ {
+ // Remote avatar
+ return $user_avatar;
+ }
+ else if ($convert_row['user_avatar_type'] == 3)
+ {
+ // Gallery avatar
+ return $user_avatar;
+ }
+
+ return '';
+}
+
+
+/**
+* Find out about the avatar's dimensions
+*/
+function phpbb_get_avatar_height($user_avatar)
+{
+ global $convert_row;
+
+ if (empty($convert_row['user_avatar_type']))
+ {
+ return 0;
+ }
+ return get_avatar_height($user_avatar, 'phpbb_avatar_type', $convert_row['user_avatar_type']);
+}
+
+
+/**
+* Find out about the avatar's dimensions
+*/
+function phpbb_get_avatar_width($user_avatar)
+{
+ global $convert_row;
+
+ if (empty($convert_row['user_avatar_type']))
+ {
+ return 0;
+ }
+
+ return get_avatar_width($user_avatar, 'phpbb_avatar_type', $convert_row['user_avatar_type']);
+}
+
+
+/**
+* Calculate the correct to_address field for private messages
+*/
+function phpbb_privmsgs_to_userid($to_userid)
+{
+ global $config;
+
+ return 'u_' . phpbb_user_id($to_userid);
+}
+
+/**
+* Calculate whether a private message was unread using the bitfield
+*/
+function phpbb_unread_pm($pm_type)
+{
+ return ($pm_type == 5) ? 1 : 0;
+}
+
+/**
+* Calculate whether a private message was new using the bitfield
+*/
+function phpbb_new_pm($pm_type)
+{
+ return ($pm_type == 1) ? 1 : 0;
+}
+
+/**
+* Obtain the folder_id for the custom folder created to replace the savebox from 2.0.x (used to store saved private messages)
+*/
+function phpbb_get_savebox_id($user_id)
+{
+ global $db;
+
+ $user_id = phpbb_user_id($user_id);
+
+ // Only one custom folder, check only one
+ $sql = 'SELECT folder_id
+ FROM ' . PRIVMSGS_FOLDER_TABLE . '
+ WHERE user_id = ' . $user_id;
+ $result = $db->sql_query_limit($sql, 1);
+ $folder_id = (int) $db->sql_fetchfield('folder_id');
+ $db->sql_freeresult($result);
+
+ return $folder_id;
+}
+
+/**
+* Transfer attachment specific configuration options
+* These were not stored in the main config table on 2.0.x
+* This is only used if the Attachment MOD was installed
+*/
+function phpbb_import_attach_config()
+{
+ global $db, $src_db, $same_db, $convert, $config;
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'binary'");
+ }
+
+ $sql = 'SELECT *
+ FROM ' . $convert->src_table_prefix . 'attachments_config';
+ $result = $src_db->sql_query($sql);
+
+ if ($convert->mysql_convert && $same_db)
+ {
+ $src_db->sql_query("SET NAMES 'utf8'");
+ }
+
+ $attach_config = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $attach_config[$row['config_name']] = $row['config_value'];
+ }
+ $src_db->sql_freeresult($result);
+
+ $config->set('allow_attachments', 1);
+
+ // old attachment mod? Must be very old if this entry do not exist...
+ if (!empty($attach_config['display_order']))
+ {
+ $config->set('display_order', $attach_config['display_order']);
+ }
+ $config->set('max_filesize', $attach_config['max_filesize']);
+ $config->set('max_filesize_pm', $attach_config['max_filesize_pm']);
+ $config->set('attachment_quota', $attach_config['attachment_quota']);
+ $config->set('max_attachments', $attach_config['max_attachments']);
+ $config->set('max_attachments_pm', $attach_config['max_attachments_pm']);
+ $config->set('allow_pm_attach', $attach_config['allow_pm_attach']);
+
+ $config->set('img_display_inlined', $attach_config['img_display_inlined']);
+ $config->set('img_max_width', $attach_config['img_max_width']);
+ $config->set('img_max_height', $attach_config['img_max_height']);
+ $config->set('img_link_width', $attach_config['img_link_width']);
+ $config->set('img_link_height', $attach_config['img_link_height']);
+ $config->set('img_create_thumbnail', $attach_config['img_create_thumbnail']);
+ $config->set('img_max_thumb_width', 400);
+ $config->set('img_min_thumb_filesize', $attach_config['img_min_thumb_filesize']);
+ $config->set('img_imagick', $attach_config['img_imagick']);
+}
+
+/**
+* Calculate the date a user became inactive
+*/
+function phpbb_inactive_time()
+{
+ global $convert_row;
+
+ if ($convert_row['user_active'])
+ {
+ return 0;
+ }
+
+ if ($convert_row['user_lastvisit'])
+ {
+ return $convert_row['user_lastvisit'];
+ }
+
+ return $convert_row['user_regdate'];
+}
+
+/**
+* Calculate the reason a user became inactive
+* We can't actually tell the difference between a manual deactivation and one for profile changes
+* from the data available to assume the latter
+*/
+function phpbb_inactive_reason()
+{
+ global $convert_row;
+
+ if ($convert_row['user_active'])
+ {
+ return 0;
+ }
+
+ if ($convert_row['user_lastvisit'])
+ {
+ return INACTIVE_PROFILE;
+ }
+
+ return INACTIVE_REGISTER;
+}
+
+/**
+* Adjust 2.0.x disallowed names to 3.0.x format
+*/
+function phpbb_disallowed_username($username)
+{
+ // Replace * with %
+ $username = phpbb_set_default_encoding(str_replace('*', '%', $username));
+ return utf8_htmlspecialchars($username);
+}
+
+/**
+* Checks whether there are any usernames on the old board that would map to the same
+* username_clean on phpBB3. Prints out a list if any exist and exits.
+*/
+function phpbb_create_userconv_table()
+{
+ global $db, $src_db, $convert, $table_prefix, $user, $lang;
+
+ $map_dbms = '';
+ switch ($db->get_sql_layer())
+ {
+ case 'mysql':
+ $map_dbms = 'mysql_40';
+ break;
+
+ case 'mysql4':
+ if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
+ {
+ $map_dbms = 'mysql_41';
+ }
+ else
+ {
+ $map_dbms = 'mysql_40';
+ }
+ break;
+
+ case 'mysqli':
+ $map_dbms = 'mysql_41';
+ break;
+
+ case 'mssql':
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $map_dbms = 'mssql';
+ break;
+
+ default:
+ $map_dbms = $db->get_sql_layer();
+ break;
+ }
+
+ // create a temporary table in which we store the clean usernames
+ $drop_sql = 'DROP TABLE ' . USERCONV_TABLE;
+ switch ($map_dbms)
+ {
+ case 'mssql':
+ $create_sql = 'CREATE TABLE [' . USERCONV_TABLE . '] (
+ [user_id] [int] NOT NULL ,
+ [username_clean] [varchar] (255) DEFAULT (\'\') NOT NULL
+ )';
+ break;
+
+ case 'mysql_40':
+ $create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
+ user_id mediumint(8) NOT NULL,
+ username_clean blob NOT NULL
+ )';
+ break;
+
+ case 'mysql_41':
+ $create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
+ user_id mediumint(8) NOT NULL,
+ username_clean varchar(255) DEFAULT \'\' NOT NULL
+ ) CHARACTER SET `utf8` COLLATE `utf8_bin`';
+ break;
+
+ case 'oracle':
+ $create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
+ user_id number(8) NOT NULL,
+ username_clean varchar2(255) DEFAULT \'\'
+ )';
+ break;
+
+ case 'postgres':
+ $create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
+ user_id INT4 DEFAULT \'0\',
+ username_clean varchar_ci DEFAULT \'\' NOT NULL
+ )';
+ break;
+
+ case 'sqlite':
+ case 'sqlite3':
+ $create_sql = 'CREATE TABLE ' . USERCONV_TABLE . ' (
+ user_id INTEGER NOT NULL DEFAULT \'0\',
+ username_clean varchar(255) NOT NULL DEFAULT \'\'
+ )';
+ break;
+ }
+
+ $db->sql_return_on_error(true);
+ $db->sql_query($drop_sql);
+ $db->sql_return_on_error(false);
+ $db->sql_query($create_sql);
+}
+
+function phpbb_check_username_collisions()
+{
+ global $db, $src_db, $convert, $table_prefix, $user, $lang;
+
+ // now find the clean version of the usernames that collide
+ $sql = 'SELECT username_clean
+ FROM ' . USERCONV_TABLE .'
+ GROUP BY username_clean
+ HAVING COUNT(user_id) > 1';
+ $result = $db->sql_query($sql);
+
+ $colliding_names = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $colliding_names[] = $row['username_clean'];
+ }
+ $db->sql_freeresult($result);
+
+ // there was at least one collision, the admin will have to solve it before conversion can continue
+ if (sizeof($colliding_names))
+ {
+ $sql = 'SELECT user_id, username_clean
+ FROM ' . USERCONV_TABLE . '
+ WHERE ' . $db->sql_in_set('username_clean', $colliding_names);
+ $result = $db->sql_query($sql);
+ unset($colliding_names);
+
+ $colliding_user_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $colliding_user_ids[(int) $row['user_id']] = $row['username_clean'];
+ }
+ $db->sql_freeresult($result);
+
+ $sql = 'SELECT username, user_id, user_posts
+ FROM ' . $convert->src_table_prefix . 'users
+ WHERE ' . $src_db->sql_in_set('user_id', array_keys($colliding_user_ids));
+ $result = $src_db->sql_query($sql);
+
+ $colliding_users = array();
+ while ($row = $src_db->sql_fetchrow($result))
+ {
+ $row['user_id'] = (int) $row['user_id'];
+ if (isset($colliding_user_ids[$row['user_id']]))
+ {
+ $colliding_users[$colliding_user_ids[$row['user_id']]][] = $row;
+ }
+ }
+ $src_db->sql_freeresult($result);
+ unset($colliding_user_ids);
+
+ $list = '';
+ foreach ($colliding_users as $username_clean => $users)
+ {
+ $list .= sprintf($user->lang['COLLIDING_CLEAN_USERNAME'], $username_clean) . "<br />\n";
+ foreach ($users as $i => $row)
+ {
+ $list .= sprintf($user->lang['COLLIDING_USER'], $row['user_id'], phpbb_set_default_encoding($row['username']), $row['user_posts']) . "<br />\n";
+ }
+ }
+
+ $lang['INST_ERR_FATAL'] = $user->lang['CONV_ERR_FATAL'];
+ $convert->p_master->error('<span style="color:red">' . $user->lang['COLLIDING_USERNAMES_FOUND'] . '</span></b><br /><br />' . $list . '<b>', __LINE__, __FILE__);
+ }
+
+ $drop_sql = 'DROP TABLE ' . USERCONV_TABLE;
+ $db->sql_query($drop_sql);
+}
+
+function phpbb_convert_timezone($timezone)
+{
+ global $config, $db, $phpbb_root_path, $phpEx, $table_prefix;
+
+ $factory = new \phpbb\db\tools\factory();
+ $timezone_migration = new \phpbb\db\migration\data\v310\timezone($config, $db, $factory->get($db), $phpbb_root_path, $phpEx, $table_prefix);
+ return $timezone_migration->convert_phpbb30_timezone($timezone, 0);
+}
+
+function phpbb_add_notification_options($user_notify_pm)
+{
+ global $convert_row, $db;
+
+ $user_id = phpbb_user_id($convert_row['user_id']);
+ if ($user_id == ANONYMOUS)
+ {
+ return;
+ }
+
+ $rows = array();
+
+ $rows[] = array(
+ 'item_type' => 'post',
+ 'item_id' => 0,
+ 'user_id' => (int) $user_id,
+ 'notify' => 1,
+ 'method' => 'email',
+ );
+ $rows[] = array(
+ 'item_type' => 'topic',
+ 'item_id' => 0,
+ 'user_id' => (int) $user_id,
+ 'notify' => 1,
+ 'method' => 'email',
+ );
+ if ($user_notify_pm)
+ {
+ $rows[] = array(
+ 'item_type' => 'pm',
+ 'item_id' => 0,
+ 'user_id' => (int) $user_id,
+ 'notify' => 1,
+ 'method' => 'email',
+ );
+ }
+
+ $sql = $db->sql_multi_insert(USER_NOTIFICATIONS_TABLE, $rows);
+}
+
+function phpbb_convert_password_hash($hash)
+{
+ global $phpbb_container;
+
+ /* @var $manager \phpbb\passwords\manager */
+ $manager = $phpbb_container->get('passwords.manager');
+ $hash = $manager->hash($hash, '$H$');
+
+ return '$CP$' . $hash;
+}
diff --git a/phpBB/install/data/confusables.php b/phpBB/install/data/confusables.php
new file mode 100644
index 0000000000..992207c1ef
--- /dev/null
+++ b/phpBB/install/data/confusables.php
@@ -0,0 +1,645 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+function utf8_new_case_fold($text, $option = 'full')
+{
+ static $uniarray = array();
+ global $phpbb_root_path, $phpEx;
+
+ // common is always set
+ if (!isset($uniarray['c']))
+ {
+ $uniarray['c'] = include($phpbb_root_path . 'includes/utf/data/case_fold_c.' . $phpEx);
+ }
+
+ // only set full if we need to
+ if ($option === 'full' && !isset($uniarray['f']))
+ {
+ $uniarray['f'] = include($phpbb_root_path . 'includes/utf/data/case_fold_f.' . $phpEx);
+ }
+
+ // only set simple if we need to
+ if ($option !== 'full' && !isset($uniarray['s']))
+ {
+ $uniarray['s'] = include($phpbb_root_path . 'includes/utf/data/case_fold_s.' . $phpEx);
+ }
+
+ // common is always replaced
+ $text = strtr($text, $uniarray['c']);
+
+ if ($option === 'full')
+ {
+ // full replaces a character with multiple characters
+ $text = strtr($text, $uniarray['f']);
+ }
+ else
+ {
+ // simple replaces a character with another character
+ $text = strtr($text, $uniarray['s']);
+ }
+
+ return $text;
+}
+
+function utf8_new_case_fold_nfkc($text, $option = 'full')
+{
+ static $fc_nfkc_closure = array(
+ "\xCD\xBA" => "\x20\xCE\xB9",
+ "\xCF\x92" => "\xCF\x85",
+ "\xCF\x93" => "\xCF\x8D",
+ "\xCF\x94" => "\xCF\x8B",
+ "\xCF\xB2" => "\xCF\x83",
+ "\xCF\xB9" => "\xCF\x83",
+ "\xE1\xB4\xAC" => "\x61",
+ "\xE1\xB4\xAD" => "\xC3\xA6",
+ "\xE1\xB4\xAE" => "\x62",
+ "\xE1\xB4\xB0" => "\x64",
+ "\xE1\xB4\xB1" => "\x65",
+ "\xE1\xB4\xB2" => "\xC7\x9D",
+ "\xE1\xB4\xB3" => "\x67",
+ "\xE1\xB4\xB4" => "\x68",
+ "\xE1\xB4\xB5" => "\x69",
+ "\xE1\xB4\xB6" => "\x6A",
+ "\xE1\xB4\xB7" => "\x6B",
+ "\xE1\xB4\xB8" => "\x6C",
+ "\xE1\xB4\xB9" => "\x6D",
+ "\xE1\xB4\xBA" => "\x6E",
+ "\xE1\xB4\xBC" => "\x6F",
+ "\xE1\xB4\xBD" => "\xC8\xA3",
+ "\xE1\xB4\xBE" => "\x70",
+ "\xE1\xB4\xBF" => "\x72",
+ "\xE1\xB5\x80" => "\x74",
+ "\xE1\xB5\x81" => "\x75",
+ "\xE1\xB5\x82" => "\x77",
+ "\xE2\x82\xA8" => "\x72\x73",
+ "\xE2\x84\x82" => "\x63",
+ "\xE2\x84\x83" => "\xC2\xB0\x63",
+ "\xE2\x84\x87" => "\xC9\x9B",
+ "\xE2\x84\x89" => "\xC2\xB0\x66",
+ "\xE2\x84\x8B" => "\x68",
+ "\xE2\x84\x8C" => "\x68",
+ "\xE2\x84\x8D" => "\x68",
+ "\xE2\x84\x90" => "\x69",
+ "\xE2\x84\x91" => "\x69",
+ "\xE2\x84\x92" => "\x6C",
+ "\xE2\x84\x95" => "\x6E",
+ "\xE2\x84\x96" => "\x6E\x6F",
+ "\xE2\x84\x99" => "\x70",
+ "\xE2\x84\x9A" => "\x71",
+ "\xE2\x84\x9B" => "\x72",
+ "\xE2\x84\x9C" => "\x72",
+ "\xE2\x84\x9D" => "\x72",
+ "\xE2\x84\xA0" => "\x73\x6D",
+ "\xE2\x84\xA1" => "\x74\x65\x6C",
+ "\xE2\x84\xA2" => "\x74\x6D",
+ "\xE2\x84\xA4" => "\x7A",
+ "\xE2\x84\xA8" => "\x7A",
+ "\xE2\x84\xAC" => "\x62",
+ "\xE2\x84\xAD" => "\x63",
+ "\xE2\x84\xB0" => "\x65",
+ "\xE2\x84\xB1" => "\x66",
+ "\xE2\x84\xB3" => "\x6D",
+ "\xE2\x84\xBB" => "\x66\x61\x78",
+ "\xE2\x84\xBE" => "\xCE\xB3",
+ "\xE2\x84\xBF" => "\xCF\x80",
+ "\xE2\x85\x85" => "\x64",
+ "\xE3\x89\x90" => "\x70\x74\x65",
+ "\xE3\x8B\x8C" => "\x68\x67",
+ "\xE3\x8B\x8E" => "\x65\x76",
+ "\xE3\x8B\x8F" => "\x6C\x74\x64",
+ "\xE3\x8D\xB1" => "\x68\x70\x61",
+ "\xE3\x8D\xB3" => "\x61\x75",
+ "\xE3\x8D\xB5" => "\x6F\x76",
+ "\xE3\x8D\xBA" => "\x69\x75",
+ "\xE3\x8E\x80" => "\x70\x61",
+ "\xE3\x8E\x81" => "\x6E\x61",
+ "\xE3\x8E\x82" => "\xCE\xBC\x61",
+ "\xE3\x8E\x83" => "\x6D\x61",
+ "\xE3\x8E\x84" => "\x6B\x61",
+ "\xE3\x8E\x85" => "\x6B\x62",
+ "\xE3\x8E\x86" => "\x6D\x62",
+ "\xE3\x8E\x87" => "\x67\x62",
+ "\xE3\x8E\x8A" => "\x70\x66",
+ "\xE3\x8E\x8B" => "\x6E\x66",
+ "\xE3\x8E\x8C" => "\xCE\xBC\x66",
+ "\xE3\x8E\x90" => "\x68\x7A",
+ "\xE3\x8E\x91" => "\x6B\x68\x7A",
+ "\xE3\x8E\x92" => "\x6D\x68\x7A",
+ "\xE3\x8E\x93" => "\x67\x68\x7A",
+ "\xE3\x8E\x94" => "\x74\x68\x7A",
+ "\xE3\x8E\xA9" => "\x70\x61",
+ "\xE3\x8E\xAA" => "\x6B\x70\x61",
+ "\xE3\x8E\xAB" => "\x6D\x70\x61",
+ "\xE3\x8E\xAC" => "\x67\x70\x61",
+ "\xE3\x8E\xB4" => "\x70\x76",
+ "\xE3\x8E\xB5" => "\x6E\x76",
+ "\xE3\x8E\xB6" => "\xCE\xBC\x76",
+ "\xE3\x8E\xB7" => "\x6D\x76",
+ "\xE3\x8E\xB8" => "\x6B\x76",
+ "\xE3\x8E\xB9" => "\x6D\x76",
+ "\xE3\x8E\xBA" => "\x70\x77",
+ "\xE3\x8E\xBB" => "\x6E\x77",
+ "\xE3\x8E\xBC" => "\xCE\xBC\x77",
+ "\xE3\x8E\xBD" => "\x6D\x77",
+ "\xE3\x8E\xBE" => "\x6B\x77",
+ "\xE3\x8E\xBF" => "\x6D\x77",
+ "\xE3\x8F\x80" => "\x6B\xCF\x89",
+ "\xE3\x8F\x81" => "\x6D\xCF\x89",
+ "\xE3\x8F\x83" => "\x62\x71",
+ "\xE3\x8F\x86" => "\x63\xE2\x88\x95\x6B\x67",
+ "\xE3\x8F\x87" => "\x63\x6F\x2E",
+ "\xE3\x8F\x88" => "\x64\x62",
+ "\xE3\x8F\x89" => "\x67\x79",
+ "\xE3\x8F\x8B" => "\x68\x70",
+ "\xE3\x8F\x8D" => "\x6B\x6B",
+ "\xE3\x8F\x8E" => "\x6B\x6D",
+ "\xE3\x8F\x97" => "\x70\x68",
+ "\xE3\x8F\x99" => "\x70\x70\x6D",
+ "\xE3\x8F\x9A" => "\x70\x72",
+ "\xE3\x8F\x9C" => "\x73\x76",
+ "\xE3\x8F\x9D" => "\x77\x62",
+ "\xE3\x8F\x9E" => "\x76\xE2\x88\x95\x6D",
+ "\xE3\x8F\x9F" => "\x61\xE2\x88\x95\x6D",
+ "\xF0\x9D\x90\x80" => "\x61",
+ "\xF0\x9D\x90\x81" => "\x62",
+ "\xF0\x9D\x90\x82" => "\x63",
+ "\xF0\x9D\x90\x83" => "\x64",
+ "\xF0\x9D\x90\x84" => "\x65",
+ "\xF0\x9D\x90\x85" => "\x66",
+ "\xF0\x9D\x90\x86" => "\x67",
+ "\xF0\x9D\x90\x87" => "\x68",
+ "\xF0\x9D\x90\x88" => "\x69",
+ "\xF0\x9D\x90\x89" => "\x6A",
+ "\xF0\x9D\x90\x8A" => "\x6B",
+ "\xF0\x9D\x90\x8B" => "\x6C",
+ "\xF0\x9D\x90\x8C" => "\x6D",
+ "\xF0\x9D\x90\x8D" => "\x6E",
+ "\xF0\x9D\x90\x8E" => "\x6F",
+ "\xF0\x9D\x90\x8F" => "\x70",
+ "\xF0\x9D\x90\x90" => "\x71",
+ "\xF0\x9D\x90\x91" => "\x72",
+ "\xF0\x9D\x90\x92" => "\x73",
+ "\xF0\x9D\x90\x93" => "\x74",
+ "\xF0\x9D\x90\x94" => "\x75",
+ "\xF0\x9D\x90\x95" => "\x76",
+ "\xF0\x9D\x90\x96" => "\x77",
+ "\xF0\x9D\x90\x97" => "\x78",
+ "\xF0\x9D\x90\x98" => "\x79",
+ "\xF0\x9D\x90\x99" => "\x7A",
+ "\xF0\x9D\x90\xB4" => "\x61",
+ "\xF0\x9D\x90\xB5" => "\x62",
+ "\xF0\x9D\x90\xB6" => "\x63",
+ "\xF0\x9D\x90\xB7" => "\x64",
+ "\xF0\x9D\x90\xB8" => "\x65",
+ "\xF0\x9D\x90\xB9" => "\x66",
+ "\xF0\x9D\x90\xBA" => "\x67",
+ "\xF0\x9D\x90\xBB" => "\x68",
+ "\xF0\x9D\x90\xBC" => "\x69",
+ "\xF0\x9D\x90\xBD" => "\x6A",
+ "\xF0\x9D\x90\xBE" => "\x6B",
+ "\xF0\x9D\x90\xBF" => "\x6C",
+ "\xF0\x9D\x91\x80" => "\x6D",
+ "\xF0\x9D\x91\x81" => "\x6E",
+ "\xF0\x9D\x91\x82" => "\x6F",
+ "\xF0\x9D\x91\x83" => "\x70",
+ "\xF0\x9D\x91\x84" => "\x71",
+ "\xF0\x9D\x91\x85" => "\x72",
+ "\xF0\x9D\x91\x86" => "\x73",
+ "\xF0\x9D\x91\x87" => "\x74",
+ "\xF0\x9D\x91\x88" => "\x75",
+ "\xF0\x9D\x91\x89" => "\x76",
+ "\xF0\x9D\x91\x8A" => "\x77",
+ "\xF0\x9D\x91\x8B" => "\x78",
+ "\xF0\x9D\x91\x8C" => "\x79",
+ "\xF0\x9D\x91\x8D" => "\x7A",
+ "\xF0\x9D\x91\xA8" => "\x61",
+ "\xF0\x9D\x91\xA9" => "\x62",
+ "\xF0\x9D\x91\xAA" => "\x63",
+ "\xF0\x9D\x91\xAB" => "\x64",
+ "\xF0\x9D\x91\xAC" => "\x65",
+ "\xF0\x9D\x91\xAD" => "\x66",
+ "\xF0\x9D\x91\xAE" => "\x67",
+ "\xF0\x9D\x91\xAF" => "\x68",
+ "\xF0\x9D\x91\xB0" => "\x69",
+ "\xF0\x9D\x91\xB1" => "\x6A",
+ "\xF0\x9D\x91\xB2" => "\x6B",
+ "\xF0\x9D\x91\xB3" => "\x6C",
+ "\xF0\x9D\x91\xB4" => "\x6D",
+ "\xF0\x9D\x91\xB5" => "\x6E",
+ "\xF0\x9D\x91\xB6" => "\x6F",
+ "\xF0\x9D\x91\xB7" => "\x70",
+ "\xF0\x9D\x91\xB8" => "\x71",
+ "\xF0\x9D\x91\xB9" => "\x72",
+ "\xF0\x9D\x91\xBA" => "\x73",
+ "\xF0\x9D\x91\xBB" => "\x74",
+ "\xF0\x9D\x91\xBC" => "\x75",
+ "\xF0\x9D\x91\xBD" => "\x76",
+ "\xF0\x9D\x91\xBE" => "\x77",
+ "\xF0\x9D\x91\xBF" => "\x78",
+ "\xF0\x9D\x92\x80" => "\x79",
+ "\xF0\x9D\x92\x81" => "\x7A",
+ "\xF0\x9D\x92\x9C" => "\x61",
+ "\xF0\x9D\x92\x9E" => "\x63",
+ "\xF0\x9D\x92\x9F" => "\x64",
+ "\xF0\x9D\x92\xA2" => "\x67",
+ "\xF0\x9D\x92\xA5" => "\x6A",
+ "\xF0\x9D\x92\xA6" => "\x6B",
+ "\xF0\x9D\x92\xA9" => "\x6E",
+ "\xF0\x9D\x92\xAA" => "\x6F",
+ "\xF0\x9D\x92\xAB" => "\x70",
+ "\xF0\x9D\x92\xAC" => "\x71",
+ "\xF0\x9D\x92\xAE" => "\x73",
+ "\xF0\x9D\x92\xAF" => "\x74",
+ "\xF0\x9D\x92\xB0" => "\x75",
+ "\xF0\x9D\x92\xB1" => "\x76",
+ "\xF0\x9D\x92\xB2" => "\x77",
+ "\xF0\x9D\x92\xB3" => "\x78",
+ "\xF0\x9D\x92\xB4" => "\x79",
+ "\xF0\x9D\x92\xB5" => "\x7A",
+ "\xF0\x9D\x93\x90" => "\x61",
+ "\xF0\x9D\x93\x91" => "\x62",
+ "\xF0\x9D\x93\x92" => "\x63",
+ "\xF0\x9D\x93\x93" => "\x64",
+ "\xF0\x9D\x93\x94" => "\x65",
+ "\xF0\x9D\x93\x95" => "\x66",
+ "\xF0\x9D\x93\x96" => "\x67",
+ "\xF0\x9D\x93\x97" => "\x68",
+ "\xF0\x9D\x93\x98" => "\x69",
+ "\xF0\x9D\x93\x99" => "\x6A",
+ "\xF0\x9D\x93\x9A" => "\x6B",
+ "\xF0\x9D\x93\x9B" => "\x6C",
+ "\xF0\x9D\x93\x9C" => "\x6D",
+ "\xF0\x9D\x93\x9D" => "\x6E",
+ "\xF0\x9D\x93\x9E" => "\x6F",
+ "\xF0\x9D\x93\x9F" => "\x70",
+ "\xF0\x9D\x93\xA0" => "\x71",
+ "\xF0\x9D\x93\xA1" => "\x72",
+ "\xF0\x9D\x93\xA2" => "\x73",
+ "\xF0\x9D\x93\xA3" => "\x74",
+ "\xF0\x9D\x93\xA4" => "\x75",
+ "\xF0\x9D\x93\xA5" => "\x76",
+ "\xF0\x9D\x93\xA6" => "\x77",
+ "\xF0\x9D\x93\xA7" => "\x78",
+ "\xF0\x9D\x93\xA8" => "\x79",
+ "\xF0\x9D\x93\xA9" => "\x7A",
+ "\xF0\x9D\x94\x84" => "\x61",
+ "\xF0\x9D\x94\x85" => "\x62",
+ "\xF0\x9D\x94\x87" => "\x64",
+ "\xF0\x9D\x94\x88" => "\x65",
+ "\xF0\x9D\x94\x89" => "\x66",
+ "\xF0\x9D\x94\x8A" => "\x67",
+ "\xF0\x9D\x94\x8D" => "\x6A",
+ "\xF0\x9D\x94\x8E" => "\x6B",
+ "\xF0\x9D\x94\x8F" => "\x6C",
+ "\xF0\x9D\x94\x90" => "\x6D",
+ "\xF0\x9D\x94\x91" => "\x6E",
+ "\xF0\x9D\x94\x92" => "\x6F",
+ "\xF0\x9D\x94\x93" => "\x70",
+ "\xF0\x9D\x94\x94" => "\x71",
+ "\xF0\x9D\x94\x96" => "\x73",
+ "\xF0\x9D\x94\x97" => "\x74",
+ "\xF0\x9D\x94\x98" => "\x75",
+ "\xF0\x9D\x94\x99" => "\x76",
+ "\xF0\x9D\x94\x9A" => "\x77",
+ "\xF0\x9D\x94\x9B" => "\x78",
+ "\xF0\x9D\x94\x9C" => "\x79",
+ "\xF0\x9D\x94\xB8" => "\x61",
+ "\xF0\x9D\x94\xB9" => "\x62",
+ "\xF0\x9D\x94\xBB" => "\x64",
+ "\xF0\x9D\x94\xBC" => "\x65",
+ "\xF0\x9D\x94\xBD" => "\x66",
+ "\xF0\x9D\x94\xBE" => "\x67",
+ "\xF0\x9D\x95\x80" => "\x69",
+ "\xF0\x9D\x95\x81" => "\x6A",
+ "\xF0\x9D\x95\x82" => "\x6B",
+ "\xF0\x9D\x95\x83" => "\x6C",
+ "\xF0\x9D\x95\x84" => "\x6D",
+ "\xF0\x9D\x95\x86" => "\x6F",
+ "\xF0\x9D\x95\x8A" => "\x73",
+ "\xF0\x9D\x95\x8B" => "\x74",
+ "\xF0\x9D\x95\x8C" => "\x75",
+ "\xF0\x9D\x95\x8D" => "\x76",
+ "\xF0\x9D\x95\x8E" => "\x77",
+ "\xF0\x9D\x95\x8F" => "\x78",
+ "\xF0\x9D\x95\x90" => "\x79",
+ "\xF0\x9D\x95\xAC" => "\x61",
+ "\xF0\x9D\x95\xAD" => "\x62",
+ "\xF0\x9D\x95\xAE" => "\x63",
+ "\xF0\x9D\x95\xAF" => "\x64",
+ "\xF0\x9D\x95\xB0" => "\x65",
+ "\xF0\x9D\x95\xB1" => "\x66",
+ "\xF0\x9D\x95\xB2" => "\x67",
+ "\xF0\x9D\x95\xB3" => "\x68",
+ "\xF0\x9D\x95\xB4" => "\x69",
+ "\xF0\x9D\x95\xB5" => "\x6A",
+ "\xF0\x9D\x95\xB6" => "\x6B",
+ "\xF0\x9D\x95\xB7" => "\x6C",
+ "\xF0\x9D\x95\xB8" => "\x6D",
+ "\xF0\x9D\x95\xB9" => "\x6E",
+ "\xF0\x9D\x95\xBA" => "\x6F",
+ "\xF0\x9D\x95\xBB" => "\x70",
+ "\xF0\x9D\x95\xBC" => "\x71",
+ "\xF0\x9D\x95\xBD" => "\x72",
+ "\xF0\x9D\x95\xBE" => "\x73",
+ "\xF0\x9D\x95\xBF" => "\x74",
+ "\xF0\x9D\x96\x80" => "\x75",
+ "\xF0\x9D\x96\x81" => "\x76",
+ "\xF0\x9D\x96\x82" => "\x77",
+ "\xF0\x9D\x96\x83" => "\x78",
+ "\xF0\x9D\x96\x84" => "\x79",
+ "\xF0\x9D\x96\x85" => "\x7A",
+ "\xF0\x9D\x96\xA0" => "\x61",
+ "\xF0\x9D\x96\xA1" => "\x62",
+ "\xF0\x9D\x96\xA2" => "\x63",
+ "\xF0\x9D\x96\xA3" => "\x64",
+ "\xF0\x9D\x96\xA4" => "\x65",
+ "\xF0\x9D\x96\xA5" => "\x66",
+ "\xF0\x9D\x96\xA6" => "\x67",
+ "\xF0\x9D\x96\xA7" => "\x68",
+ "\xF0\x9D\x96\xA8" => "\x69",
+ "\xF0\x9D\x96\xA9" => "\x6A",
+ "\xF0\x9D\x96\xAA" => "\x6B",
+ "\xF0\x9D\x96\xAB" => "\x6C",
+ "\xF0\x9D\x96\xAC" => "\x6D",
+ "\xF0\x9D\x96\xAD" => "\x6E",
+ "\xF0\x9D\x96\xAE" => "\x6F",
+ "\xF0\x9D\x96\xAF" => "\x70",
+ "\xF0\x9D\x96\xB0" => "\x71",
+ "\xF0\x9D\x96\xB1" => "\x72",
+ "\xF0\x9D\x96\xB2" => "\x73",
+ "\xF0\x9D\x96\xB3" => "\x74",
+ "\xF0\x9D\x96\xB4" => "\x75",
+ "\xF0\x9D\x96\xB5" => "\x76",
+ "\xF0\x9D\x96\xB6" => "\x77",
+ "\xF0\x9D\x96\xB7" => "\x78",
+ "\xF0\x9D\x96\xB8" => "\x79",
+ "\xF0\x9D\x96\xB9" => "\x7A",
+ "\xF0\x9D\x97\x94" => "\x61",
+ "\xF0\x9D\x97\x95" => "\x62",
+ "\xF0\x9D\x97\x96" => "\x63",
+ "\xF0\x9D\x97\x97" => "\x64",
+ "\xF0\x9D\x97\x98" => "\x65",
+ "\xF0\x9D\x97\x99" => "\x66",
+ "\xF0\x9D\x97\x9A" => "\x67",
+ "\xF0\x9D\x97\x9B" => "\x68",
+ "\xF0\x9D\x97\x9C" => "\x69",
+ "\xF0\x9D\x97\x9D" => "\x6A",
+ "\xF0\x9D\x97\x9E" => "\x6B",
+ "\xF0\x9D\x97\x9F" => "\x6C",
+ "\xF0\x9D\x97\xA0" => "\x6D",
+ "\xF0\x9D\x97\xA1" => "\x6E",
+ "\xF0\x9D\x97\xA2" => "\x6F",
+ "\xF0\x9D\x97\xA3" => "\x70",
+ "\xF0\x9D\x97\xA4" => "\x71",
+ "\xF0\x9D\x97\xA5" => "\x72",
+ "\xF0\x9D\x97\xA6" => "\x73",
+ "\xF0\x9D\x97\xA7" => "\x74",
+ "\xF0\x9D\x97\xA8" => "\x75",
+ "\xF0\x9D\x97\xA9" => "\x76",
+ "\xF0\x9D\x97\xAA" => "\x77",
+ "\xF0\x9D\x97\xAB" => "\x78",
+ "\xF0\x9D\x97\xAC" => "\x79",
+ "\xF0\x9D\x97\xAD" => "\x7A",
+ "\xF0\x9D\x98\x88" => "\x61",
+ "\xF0\x9D\x98\x89" => "\x62",
+ "\xF0\x9D\x98\x8A" => "\x63",
+ "\xF0\x9D\x98\x8B" => "\x64",
+ "\xF0\x9D\x98\x8C" => "\x65",
+ "\xF0\x9D\x98\x8D" => "\x66",
+ "\xF0\x9D\x98\x8E" => "\x67",
+ "\xF0\x9D\x98\x8F" => "\x68",
+ "\xF0\x9D\x98\x90" => "\x69",
+ "\xF0\x9D\x98\x91" => "\x6A",
+ "\xF0\x9D\x98\x92" => "\x6B",
+ "\xF0\x9D\x98\x93" => "\x6C",
+ "\xF0\x9D\x98\x94" => "\x6D",
+ "\xF0\x9D\x98\x95" => "\x6E",
+ "\xF0\x9D\x98\x96" => "\x6F",
+ "\xF0\x9D\x98\x97" => "\x70",
+ "\xF0\x9D\x98\x98" => "\x71",
+ "\xF0\x9D\x98\x99" => "\x72",
+ "\xF0\x9D\x98\x9A" => "\x73",
+ "\xF0\x9D\x98\x9B" => "\x74",
+ "\xF0\x9D\x98\x9C" => "\x75",
+ "\xF0\x9D\x98\x9D" => "\x76",
+ "\xF0\x9D\x98\x9E" => "\x77",
+ "\xF0\x9D\x98\x9F" => "\x78",
+ "\xF0\x9D\x98\xA0" => "\x79",
+ "\xF0\x9D\x98\xA1" => "\x7A",
+ "\xF0\x9D\x98\xBC" => "\x61",
+ "\xF0\x9D\x98\xBD" => "\x62",
+ "\xF0\x9D\x98\xBE" => "\x63",
+ "\xF0\x9D\x98\xBF" => "\x64",
+ "\xF0\x9D\x99\x80" => "\x65",
+ "\xF0\x9D\x99\x81" => "\x66",
+ "\xF0\x9D\x99\x82" => "\x67",
+ "\xF0\x9D\x99\x83" => "\x68",
+ "\xF0\x9D\x99\x84" => "\x69",
+ "\xF0\x9D\x99\x85" => "\x6A",
+ "\xF0\x9D\x99\x86" => "\x6B",
+ "\xF0\x9D\x99\x87" => "\x6C",
+ "\xF0\x9D\x99\x88" => "\x6D",
+ "\xF0\x9D\x99\x89" => "\x6E",
+ "\xF0\x9D\x99\x8A" => "\x6F",
+ "\xF0\x9D\x99\x8B" => "\x70",
+ "\xF0\x9D\x99\x8C" => "\x71",
+ "\xF0\x9D\x99\x8D" => "\x72",
+ "\xF0\x9D\x99\x8E" => "\x73",
+ "\xF0\x9D\x99\x8F" => "\x74",
+ "\xF0\x9D\x99\x90" => "\x75",
+ "\xF0\x9D\x99\x91" => "\x76",
+ "\xF0\x9D\x99\x92" => "\x77",
+ "\xF0\x9D\x99\x93" => "\x78",
+ "\xF0\x9D\x99\x94" => "\x79",
+ "\xF0\x9D\x99\x95" => "\x7A",
+ "\xF0\x9D\x99\xB0" => "\x61",
+ "\xF0\x9D\x99\xB1" => "\x62",
+ "\xF0\x9D\x99\xB2" => "\x63",
+ "\xF0\x9D\x99\xB3" => "\x64",
+ "\xF0\x9D\x99\xB4" => "\x65",
+ "\xF0\x9D\x99\xB5" => "\x66",
+ "\xF0\x9D\x99\xB6" => "\x67",
+ "\xF0\x9D\x99\xB7" => "\x68",
+ "\xF0\x9D\x99\xB8" => "\x69",
+ "\xF0\x9D\x99\xB9" => "\x6A",
+ "\xF0\x9D\x99\xBA" => "\x6B",
+ "\xF0\x9D\x99\xBB" => "\x6C",
+ "\xF0\x9D\x99\xBC" => "\x6D",
+ "\xF0\x9D\x99\xBD" => "\x6E",
+ "\xF0\x9D\x99\xBE" => "\x6F",
+ "\xF0\x9D\x99\xBF" => "\x70",
+ "\xF0\x9D\x9A\x80" => "\x71",
+ "\xF0\x9D\x9A\x81" => "\x72",
+ "\xF0\x9D\x9A\x82" => "\x73",
+ "\xF0\x9D\x9A\x83" => "\x74",
+ "\xF0\x9D\x9A\x84" => "\x75",
+ "\xF0\x9D\x9A\x85" => "\x76",
+ "\xF0\x9D\x9A\x86" => "\x77",
+ "\xF0\x9D\x9A\x87" => "\x78",
+ "\xF0\x9D\x9A\x88" => "\x79",
+ "\xF0\x9D\x9A\x89" => "\x7A",
+ "\xF0\x9D\x9A\xA8" => "\xCE\xB1",
+ "\xF0\x9D\x9A\xA9" => "\xCE\xB2",
+ "\xF0\x9D\x9A\xAA" => "\xCE\xB3",
+ "\xF0\x9D\x9A\xAB" => "\xCE\xB4",
+ "\xF0\x9D\x9A\xAC" => "\xCE\xB5",
+ "\xF0\x9D\x9A\xAD" => "\xCE\xB6",
+ "\xF0\x9D\x9A\xAE" => "\xCE\xB7",
+ "\xF0\x9D\x9A\xAF" => "\xCE\xB8",
+ "\xF0\x9D\x9A\xB0" => "\xCE\xB9",
+ "\xF0\x9D\x9A\xB1" => "\xCE\xBA",
+ "\xF0\x9D\x9A\xB2" => "\xCE\xBB",
+ "\xF0\x9D\x9A\xB3" => "\xCE\xBC",
+ "\xF0\x9D\x9A\xB4" => "\xCE\xBD",
+ "\xF0\x9D\x9A\xB5" => "\xCE\xBE",
+ "\xF0\x9D\x9A\xB6" => "\xCE\xBF",
+ "\xF0\x9D\x9A\xB7" => "\xCF\x80",
+ "\xF0\x9D\x9A\xB8" => "\xCF\x81",
+ "\xF0\x9D\x9A\xB9" => "\xCE\xB8",
+ "\xF0\x9D\x9A\xBA" => "\xCF\x83",
+ "\xF0\x9D\x9A\xBB" => "\xCF\x84",
+ "\xF0\x9D\x9A\xBC" => "\xCF\x85",
+ "\xF0\x9D\x9A\xBD" => "\xCF\x86",
+ "\xF0\x9D\x9A\xBE" => "\xCF\x87",
+ "\xF0\x9D\x9A\xBF" => "\xCF\x88",
+ "\xF0\x9D\x9B\x80" => "\xCF\x89",
+ "\xF0\x9D\x9B\x93" => "\xCF\x83",
+ "\xF0\x9D\x9B\xA2" => "\xCE\xB1",
+ "\xF0\x9D\x9B\xA3" => "\xCE\xB2",
+ "\xF0\x9D\x9B\xA4" => "\xCE\xB3",
+ "\xF0\x9D\x9B\xA5" => "\xCE\xB4",
+ "\xF0\x9D\x9B\xA6" => "\xCE\xB5",
+ "\xF0\x9D\x9B\xA7" => "\xCE\xB6",
+ "\xF0\x9D\x9B\xA8" => "\xCE\xB7",
+ "\xF0\x9D\x9B\xA9" => "\xCE\xB8",
+ "\xF0\x9D\x9B\xAA" => "\xCE\xB9",
+ "\xF0\x9D\x9B\xAB" => "\xCE\xBA",
+ "\xF0\x9D\x9B\xAC" => "\xCE\xBB",
+ "\xF0\x9D\x9B\xAD" => "\xCE\xBC",
+ "\xF0\x9D\x9B\xAE" => "\xCE\xBD",
+ "\xF0\x9D\x9B\xAF" => "\xCE\xBE",
+ "\xF0\x9D\x9B\xB0" => "\xCE\xBF",
+ "\xF0\x9D\x9B\xB1" => "\xCF\x80",
+ "\xF0\x9D\x9B\xB2" => "\xCF\x81",
+ "\xF0\x9D\x9B\xB3" => "\xCE\xB8",
+ "\xF0\x9D\x9B\xB4" => "\xCF\x83",
+ "\xF0\x9D\x9B\xB5" => "\xCF\x84",
+ "\xF0\x9D\x9B\xB6" => "\xCF\x85",
+ "\xF0\x9D\x9B\xB7" => "\xCF\x86",
+ "\xF0\x9D\x9B\xB8" => "\xCF\x87",
+ "\xF0\x9D\x9B\xB9" => "\xCF\x88",
+ "\xF0\x9D\x9B\xBA" => "\xCF\x89",
+ "\xF0\x9D\x9C\x8D" => "\xCF\x83",
+ "\xF0\x9D\x9C\x9C" => "\xCE\xB1",
+ "\xF0\x9D\x9C\x9D" => "\xCE\xB2",
+ "\xF0\x9D\x9C\x9E" => "\xCE\xB3",
+ "\xF0\x9D\x9C\x9F" => "\xCE\xB4",
+ "\xF0\x9D\x9C\xA0" => "\xCE\xB5",
+ "\xF0\x9D\x9C\xA1" => "\xCE\xB6",
+ "\xF0\x9D\x9C\xA2" => "\xCE\xB7",
+ "\xF0\x9D\x9C\xA3" => "\xCE\xB8",
+ "\xF0\x9D\x9C\xA4" => "\xCE\xB9",
+ "\xF0\x9D\x9C\xA5" => "\xCE\xBA",
+ "\xF0\x9D\x9C\xA6" => "\xCE\xBB",
+ "\xF0\x9D\x9C\xA7" => "\xCE\xBC",
+ "\xF0\x9D\x9C\xA8" => "\xCE\xBD",
+ "\xF0\x9D\x9C\xA9" => "\xCE\xBE",
+ "\xF0\x9D\x9C\xAA" => "\xCE\xBF",
+ "\xF0\x9D\x9C\xAB" => "\xCF\x80",
+ "\xF0\x9D\x9C\xAC" => "\xCF\x81",
+ "\xF0\x9D\x9C\xAD" => "\xCE\xB8",
+ "\xF0\x9D\x9C\xAE" => "\xCF\x83",
+ "\xF0\x9D\x9C\xAF" => "\xCF\x84",
+ "\xF0\x9D\x9C\xB0" => "\xCF\x85",
+ "\xF0\x9D\x9C\xB1" => "\xCF\x86",
+ "\xF0\x9D\x9C\xB2" => "\xCF\x87",
+ "\xF0\x9D\x9C\xB3" => "\xCF\x88",
+ "\xF0\x9D\x9C\xB4" => "\xCF\x89",
+ "\xF0\x9D\x9D\x87" => "\xCF\x83",
+ "\xF0\x9D\x9D\x96" => "\xCE\xB1",
+ "\xF0\x9D\x9D\x97" => "\xCE\xB2",
+ "\xF0\x9D\x9D\x98" => "\xCE\xB3",
+ "\xF0\x9D\x9D\x99" => "\xCE\xB4",
+ "\xF0\x9D\x9D\x9A" => "\xCE\xB5",
+ "\xF0\x9D\x9D\x9B" => "\xCE\xB6",
+ "\xF0\x9D\x9D\x9C" => "\xCE\xB7",
+ "\xF0\x9D\x9D\x9D" => "\xCE\xB8",
+ "\xF0\x9D\x9D\x9E" => "\xCE\xB9",
+ "\xF0\x9D\x9D\x9F" => "\xCE\xBA",
+ "\xF0\x9D\x9D\xA0" => "\xCE\xBB",
+ "\xF0\x9D\x9D\xA1" => "\xCE\xBC",
+ "\xF0\x9D\x9D\xA2" => "\xCE\xBD",
+ "\xF0\x9D\x9D\xA3" => "\xCE\xBE",
+ "\xF0\x9D\x9D\xA4" => "\xCE\xBF",
+ "\xF0\x9D\x9D\xA5" => "\xCF\x80",
+ "\xF0\x9D\x9D\xA6" => "\xCF\x81",
+ "\xF0\x9D\x9D\xA7" => "\xCE\xB8",
+ "\xF0\x9D\x9D\xA8" => "\xCF\x83",
+ "\xF0\x9D\x9D\xA9" => "\xCF\x84",
+ "\xF0\x9D\x9D\xAA" => "\xCF\x85",
+ "\xF0\x9D\x9D\xAB" => "\xCF\x86",
+ "\xF0\x9D\x9D\xAC" => "\xCF\x87",
+ "\xF0\x9D\x9D\xAD" => "\xCF\x88",
+ "\xF0\x9D\x9D\xAE" => "\xCF\x89",
+ "\xF0\x9D\x9E\x81" => "\xCF\x83",
+ "\xF0\x9D\x9E\x90" => "\xCE\xB1",
+ "\xF0\x9D\x9E\x91" => "\xCE\xB2",
+ "\xF0\x9D\x9E\x92" => "\xCE\xB3",
+ "\xF0\x9D\x9E\x93" => "\xCE\xB4",
+ "\xF0\x9D\x9E\x94" => "\xCE\xB5",
+ "\xF0\x9D\x9E\x95" => "\xCE\xB6",
+ "\xF0\x9D\x9E\x96" => "\xCE\xB7",
+ "\xF0\x9D\x9E\x97" => "\xCE\xB8",
+ "\xF0\x9D\x9E\x98" => "\xCE\xB9",
+ "\xF0\x9D\x9E\x99" => "\xCE\xBA",
+ "\xF0\x9D\x9E\x9A" => "\xCE\xBB",
+ "\xF0\x9D\x9E\x9B" => "\xCE\xBC",
+ "\xF0\x9D\x9E\x9C" => "\xCE\xBD",
+ "\xF0\x9D\x9E\x9D" => "\xCE\xBE",
+ "\xF0\x9D\x9E\x9E" => "\xCE\xBF",
+ "\xF0\x9D\x9E\x9F" => "\xCF\x80",
+ "\xF0\x9D\x9E\xA0" => "\xCF\x81",
+ "\xF0\x9D\x9E\xA1" => "\xCE\xB8",
+ "\xF0\x9D\x9E\xA2" => "\xCF\x83",
+ "\xF0\x9D\x9E\xA3" => "\xCF\x84",
+ "\xF0\x9D\x9E\xA4" => "\xCF\x85",
+ "\xF0\x9D\x9E\xA5" => "\xCF\x86",
+ "\xF0\x9D\x9E\xA6" => "\xCF\x87",
+ "\xF0\x9D\x9E\xA7" => "\xCF\x88",
+ "\xF0\x9D\x9E\xA8" => "\xCF\x89",
+ "\xF0\x9D\x9E\xBB" => "\xCF\x83",
+ "\xF0\x9D\x9F\x8A" => "\xCF\x9D",
+ );
+ global $phpbb_root_path, $phpEx;
+
+ // do the case fold
+ $text = utf8_new_case_fold($text, $option);
+
+ // convert to NFKC
+ $text = Normalizer::normalize($text, Normalizer::NFKC);
+
+ // FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt
+ $text = strtr($text, $fc_nfkc_closure);
+
+ return $text;
+}
+
+return array('¡'=>'i','ǃ'=>'!','α'=>'a',' '=>' ','­'=>'','۝'=>'','܏'=>'','᠆'=>'','᠎'=>'','​'=>'','‌'=>'','‍'=>'','
'=>'','
'=>'','⁠'=>'','⁡'=>'','⁢'=>'','⁣'=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'',''=>'','𝅳'=>'','𝅴'=>'','𝅵'=>'','𝅶'=>'','𝅷'=>'','𝅸'=>'','𝅹'=>'','𝅺'=>'','۬'=>'۟','̓'=>'̓','ُ'=>'̓','֜'=>'́','́'=>'́','݇'=>'́','॔'=>'́','̀'=>'̀','॓'=>'̀','̌'=>'̆','̑'=>'̂','֯'=>'̊','ஂ'=>'̊','ํ'=>'̊','ໍ'=>'̊','ံ'=>'̊','ំ'=>'̊','៓'=>'̊','゚'=>'̊','゚'=>'̊','ͦ'=>'̊','͂'=>'̃','ׄ'=>'̇','ֹ'=>'̇','ׂ'=>'̇','ׁ'=>'̇','݁'=>'̇','ं'=>'̇','ਂ'=>'̇','ં'=>'̇','்'=>'̇','̅'=>'̄','〬'=>'̉','̱'=>'̠','॒'=>'̠','̧'=>'̡','̦'=>'̡','̨'=>'̢','़'=>'̣','়'=>'̣','਼'=>'̣','઼'=>'̣','଼'=>'̣','͇'=>'̳','̶'=>'̵','ﱞ'=>'ﹲّ','ﱟ'=>'ﹴّ','ﳲ'=>'ﹷّ','ﱠ'=>'ﹶّ','ﳳ'=>'ﹹّ','ﱡ'=>'ﹸّ','ﳴ'=>'ﹻّ','ﱢ'=>'ﹺّ','ﱣ'=>'ﹼٰ','ٴ'=>'ٔ','݂'=>'ܼ','౦'=>'o','೦'=>'o','゙'=>'゙',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','`'=>'`','`'=>'`','῀'=>'˜','^'=>'^','︿'=>'^','_'=>'_','﹍'=>'_','﹎'=>'_','﹏'=>'_','⌇'=>'︴','-'=>'-','‐'=>'-','‑'=>'-','‒'=>'-','–'=>'-','﹘'=>'-','∼'=>'⁓','・'=>'・','•'=>'・',','=>',','‚'=>',','٬'=>'،','、'=>'、',';'=>';',';'=>';',':'=>':','։'=>':','︰'=>':','׃'=>':','⩴'=>'::=','.'=>'.','․'=>'.','܂'=>'.','‥'=>'..','…'=>'...','。'=>'。','·'=>'·','‧'=>'·','∙'=>'·','⋅'=>'·','ᐧ'=>'·','ᔯ'=>'·4','ᐌ'=>'·ᐁ','ᐎ'=>'·ᐃ','ᐐ'=>'·ᐄ','ᐒ'=>'·ᐅ','ᐔ'=>'·ᐆ','ᐗ'=>'·ᐊ','ᐙ'=>'·ᐋ','ᐷ'=>'·ᐳ','ᑀ'=>'·ᐳ','ᑂ'=>'·ᐴ','ᑄ'=>'·ᐸ','ᑆ'=>'·ᐹ','ᑗ'=>'·ᑌ','ᑙ'=>'·ᑎ','ᑛ'=>'·ᑏ','ᑔ'=>'·ᑐ','ᑝ'=>'·ᑐ','ᑟ'=>'·ᑑ','ᑡ'=>'·ᑕ','ᑣ'=>'·ᑖ','ᑴ'=>'·ᑫ','ᑸ'=>'·ᑮ','ᑼ'=>'·ᑰ','ᑾ'=>'·ᑲ','ᒀ'=>'·ᑳ','ᒒ'=>'·ᒉ','ᒔ'=>'·ᒋ','ᒖ'=>'·ᒌ','ᒚ'=>'·ᒎ','ᒜ'=>'·ᒐ','ᒞ'=>'·ᒑ','ᒬ'=>'·ᒣ','ᒮ'=>'·ᒥ','ᒰ'=>'·ᒦ','ᒲ'=>'·ᒧ','ᒴ'=>'·ᒨ','ᒶ'=>'·L','ᒸ'=>'·ᒫ','ᓉ'=>'·ᓀ','ᓋ'=>'·ᓇ','ᓍ'=>'·ᓈ','ᓜ'=>'·ᓓ','ᓞ'=>'·ᓕ','ᓠ'=>'·ᓖ','ᓢ'=>'·ᓗ','ᓤ'=>'·ᓘ','ᓦ'=>'·ᓚ','ᓨ'=>'·ᓛ','ᓶ'=>'·ᓭ','ᓸ'=>'·ᓯ','ᓺ'=>'·ᓰ','ᓼ'=>'·ᓱ','ᓾ'=>'·ᓲ','ᔀ'=>'·ᓴ','ᔂ'=>'·ᓵ','ᔗ'=>'·ᔐ','ᔙ'=>'·ᔑ','ᔛ'=>'·ᔒ','ᔝ'=>'·ᔓ','ᔟ'=>'·ᔔ','ᔡ'=>'·ᔕ','ᔣ'=>'·ᔖ','ᔱ'=>'·ᔨ','ᔳ'=>'·ᔩ','ᔵ'=>'·ᔪ','ᔷ'=>'·ᔫ','ᔹ'=>'·ᔭ','ᔻ'=>'·ᔮ','ᕎ'=>'·ᕌ','ᕛ'=>'·ᕚ','ᕨ'=>'·ᕧ','('=>'(','⑴'=>'(1)','⒧'=>'(l)','⑽'=>'(10)','⑾'=>'(11)','⑿'=>'(12)','⒀'=>'(13)','⒁'=>'(14)','⒂'=>'(15)','⒃'=>'(16)','⒄'=>'(17)','⒅'=>'(18)','⒆'=>'(19)','⑵'=>'(2)','⒇'=>'(20)','⑶'=>'(3)','⑷'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','⑻'=>'(8)','⑼'=>'(9)','⒜'=>'(a)','⒝'=>'(b)','⒞'=>'(c)','⒟'=>'(d)','⒠'=>'(e)','⒡'=>'(f)','⒢'=>'(g)','⒣'=>'(h)','⒤'=>'(i)','⒥'=>'(j)','⒦'=>'(k)','⒨'=>'(m)','⒩'=>'(n)','⒪'=>'(o)','⒫'=>'(p)','⒬'=>'(q)','⒭'=>'(r)','⒮'=>'(s)','⒯'=>'(t)','⒰'=>'(u)','⒱'=>'(v)','⒲'=>'(w)','⒳'=>'(x)','⒴'=>'(y)','⒵'=>'(z)','㈀'=>'(ᄀ)','㈎'=>'(가)','㈁'=>'(ᄂ)','㈏'=>'(나)','㈂'=>'(ᄃ)','㈐'=>'(다)','㈃'=>'(ᄅ)','㈑'=>'(라)','㈄'=>'(ᄆ)','㈒'=>'(마)','㈅'=>'(ᄇ)','㈓'=>'(바)','㈆'=>'(ᄉ)','㈔'=>'(사)','㈇'=>'(ᄋ)','㈕'=>'(아)','㈝'=>'(오전)','㈞'=>'(오후)','㈈'=>'(ᄌ)','㈖'=>'(자)','㈜'=>'(주)','㈉'=>'(ᄎ)','㈗'=>'(차)','㈊'=>'(ᄏ)','㈘'=>'(카)','㈋'=>'(ᄐ)','㈙'=>'(타)','㈌'=>'(ᄑ)','㈚'=>'(파)','㈍'=>'(ᄒ)','㈛'=>'(하)','㈠'=>'(一)','㈦'=>'(七)','㈢'=>'(三)','㈨'=>'(九)','㈡'=>'(二)','㈤'=>'(五)','㈹'=>'(代)','㈽'=>'(企)','㉁'=>'(休)','㈧'=>'(八)','㈥'=>'(六)','㈸'=>'(労)','㈩'=>'(十)','㈿'=>'(協)','㈴'=>'(名)','㈺'=>'(呼)','㈣'=>'(四)','㈯'=>'(土)','㈻'=>'(学)','㈰'=>'(日)','㈪'=>'(月)','㈲'=>'(有)','㈭'=>'(木)','㈱'=>'(株)','㈬'=>'(水)','㈫'=>'(火)','㈵'=>'(特)','㈼'=>'(監)','㈳'=>'(社)','㈷'=>'(祝)','㉀'=>'(祭)','㉂'=>'(自)','㉃'=>'(至)','㈶'=>'(財)','㈾'=>'(資)','㈮'=>'(金)',')'=>')','['=>'[','〔'=>'[',']'=>']','〕'=>']','{'=>'{','}'=>'}','⦅'=>'⦅','⦆'=>'⦆','「'=>'「','」'=>'」','@'=>'@','*'=>'*','/'=>'/','⁄'=>'/','∕'=>'/','\'=>'\\','&'=>'&','#'=>'#','%'=>'%','‶'=>'‵‵','‷'=>'‵‵‵','༌'=>'་','´'=>'ʹ','΄'=>'ʹ','´'=>'ʹ','\''=>'ʹ','''=>'ʹ','′'=>'ʹ','׳'=>'ʹ','ʹ'=>'ʹ','ˊ'=>'ʹ','"'=>'ʹʹ','"'=>'ʹʹ','″'=>'ʹʹ','〃'=>'ʹʹ','״'=>'ʹʹ','ʺ'=>'ʹʹ','‴'=>'ʹʹʹ','⁗'=>'ʹʹʹʹ','¯'=>'ˉ',' ̄'=>'ˉ','‾'=>'ˉ','﹉'=>'ˉ','﹊'=>'ˉ','﹋'=>'ˉ','﹌'=>'ˉ','˚'=>'°','௵'=>'௳','←'=>'←','→'=>'→','↑'=>'↑','↓'=>'↓','↵'=>'↲','⨡'=>'↾','𝛛'=>'∂','𝜕'=>'∂','𝝏'=>'∂','𝞉'=>'∂','𝟃'=>'∂','𝛁'=>'∇','𝛻'=>'∇','𝜵'=>'∇','𝝯'=>'∇','𝞩'=>'∇','+'=>'+','﬩'=>'+','‹'=>'<','<'=>'<','='=>'=','⩵'=>'==','⩶'=>'===','›'=>'>','>'=>'>','¬'=>'¬','¦'=>'¦','〜'=>'~','~'=>'~','﹨'=>'∖','⋀'=>'∧','⋁'=>'∨','⋂'=>'∩','⋃'=>'∪','∯'=>'∮∮','∰'=>'∮∮∮','≣'=>'≡','♁'=>'⊕','☉'=>'⊙','⟂'=>'⊥','▷'=>'⊲','⨝'=>'⋈','⨽'=>'⌙','☸'=>'⎈','⎮'=>'⎥','│'=>'│','▐'=>'▌','■'=>'■','☐'=>'□','○'=>'○','⦾'=>'◎','〛'=>'⟧','〈'=>'⟨','〈'=>'⟨','〉'=>'⟩','〉'=>'⟩','⧙'=>'⦚','〶'=>'〒','ー'=>'ー','¢'=>'¢','$'=>'$','£'=>'£','¥'=>'Y̵','₩'=>'W̵','0'=>'0','𝟎'=>'0','𝟘'=>'0','𝟢'=>'0','𝟬'=>'0','𝟶'=>'0','০'=>'0','୦'=>'0','௦'=>'0','᠐'=>'0','〇'=>'0','𝐎'=>'0','𝑂'=>'0','𝑶'=>'0','𝒪'=>'0','𝓞'=>'0','𝔒'=>'0','𝕆'=>'0','𝕺'=>'0','𝖮'=>'0','𝗢'=>'0','𝘖'=>'0','𝙊'=>'0','𝙾'=>'0','𝚶'=>'0','𝛰'=>'0','𝜪'=>'0','𝝤'=>'0','𝞞'=>'0','ⵔ'=>'0','ഠ'=>'0','⊖'=>'0̵','𝚯'=>'0̵','𝚹'=>'0̵','𝛩'=>'0̵','𝛳'=>'0̵','𝜣'=>'0̵','𝜭'=>'0̵','𝝝'=>'0̵','𝝧'=>'0̵','𝞗'=>'0̵','𝞡'=>'0̵','ⴱ'=>'0̵','Ꮎ'=>'0̵','۰'=>'٠','᭜'=>'᭐','㍘'=>'0点','1'=>'1','𝟏'=>'1','𝟙'=>'1','𝟣'=>'1','𝟭'=>'1','𝟷'=>'1','ℐ'=>'1','ℑ'=>'1','𝐈'=>'1','𝐼'=>'1','𝑰'=>'1','𝓘'=>'1','𝕀'=>'1','𝕴'=>'1','𝖨'=>'1','𝗜'=>'1','𝘐'=>'1','𝙄'=>'1','𝙸'=>'1','l'=>'l','l'=>'l','ⅼ'=>'1','ℓ'=>'l','𝐥'=>'l','𝑙'=>'l','𝒍'=>'l','𝓁'=>'l','𝓵'=>'l','𝔩'=>'l','𝕝'=>'l','𝖑'=>'l','𝗅'=>'l','𝗹'=>'l','𝘭'=>'l','𝙡'=>'l','𝚕'=>'l','𝚰'=>'l','𝛪'=>'l','𝜤'=>'l','𝝞'=>'l','𝞘'=>'l','①'=>'➀','ɭ'=>'l̢','ɫ'=>'l̴','ƚ'=>'l̵','ł'=>'l̷','۱'=>'١','⒈'=>'1.','ŀ'=>'l·','ᒷ'=>'1·','⑩'=>'➉','⒑'=>'10.','㏩'=>'10日','㋉'=>'10月','㍢'=>'10点','⒒'=>'11.','㏪'=>'11日','㋊'=>'11月','㍣'=>'11点','⒓'=>'12.','㏫'=>'12日','㋋'=>'12月','㍤'=>'12点','⒔'=>'13.','㏬'=>'13日','㍥'=>'13点','⒕'=>'14.','㏭'=>'14日','㍦'=>'14点','⒖'=>'15.','㏮'=>'15日','㍧'=>'15点','⒗'=>'16.','㏯'=>'16日','㍨'=>'16点','⒘'=>'17.','㏰'=>'17日','㍩'=>'17点','⒙'=>'18.','㏱'=>'18日','㍪'=>'18点','⒚'=>'19.','㏲'=>'19日','㍫'=>'19点','lj'=>'lj','㏠'=>'1日','㋀'=>'1月','㍙'=>'1点','2'=>'2','𝟐'=>'2','𝟚'=>'2','𝟤'=>'2','𝟮'=>'2','𝟸'=>'2','ᒿ'=>'2','②'=>'➁','۲'=>'٢','⒉'=>'2.','⒛'=>'20.','㏳'=>'20日','㍬'=>'20点','㏴'=>'21日','㍭'=>'21点','㏵'=>'22日','㍮'=>'22点','㏶'=>'23日','㍯'=>'23点','㏷'=>'24日','㍰'=>'24点','㏸'=>'25日','㏹'=>'26日','㏺'=>'27日','㏻'=>'28日','㏼'=>'29日','㏡'=>'2日','㋁'=>'2月','㍚'=>'2点','3'=>'3','𝟑'=>'3','𝟛'=>'3','𝟥'=>'3','𝟯'=>'3','𝟹'=>'3','③'=>'➂','۳'=>'٣','⒊'=>'3.','㏽'=>'30日','㏾'=>'31日','㏢'=>'3日','㋂'=>'3月','㍛'=>'3点','4'=>'4','𝟒'=>'4','𝟜'=>'4','𝟦'=>'4','𝟰'=>'4','𝟺'=>'4','Ꮞ'=>'4','④'=>'➃','⒋'=>'4.','ᔰ'=>'4·','㏣'=>'4日','㋃'=>'4月','㍜'=>'4点','5'=>'5','𝟓'=>'5','𝟝'=>'5','𝟧'=>'5','𝟱'=>'5','𝟻'=>'5','⑤'=>'➄','⒌'=>'5.','㏤'=>'5日','㋄'=>'5月','㍝'=>'5点','6'=>'6','𝟔'=>'6','𝟞'=>'6','𝟨'=>'6','𝟲'=>'6','𝟼'=>'6','б'=>'6','⑥'=>'➅','⒍'=>'6.','㏥'=>'6日','㋅'=>'6月','㍞'=>'6点','7'=>'7','𝟕'=>'7','𝟟'=>'7','𝟩'=>'7','𝟳'=>'7','𝟽'=>'7','⑦'=>'➆','۷'=>'٧','⒎'=>'7.','㏦'=>'7日','㋆'=>'7月','㍟'=>'7点','ଃ'=>'8','৪'=>'8','੪'=>'8','8'=>'8','𝟖'=>'8','𝟠'=>'8','𝟪'=>'8','𝟴'=>'8','𝟾'=>'8','ȣ'=>'8','⑧'=>'➇','۸'=>'٨','⒏'=>'8.','㏧'=>'8日','㋇'=>'8月','㍠'=>'8点','੧'=>'9','୨'=>'9','৭'=>'9','9'=>'9','𝟗'=>'9','𝟡'=>'9','𝟫'=>'9','𝟵'=>'9','𝟿'=>'9','⑨'=>'➈','۹'=>'٩','⒐'=>'9.','㏨'=>'9日','㋈'=>'9月','㍡'=>'9点','a'=>'a','𝐚'=>'a','𝑎'=>'a','𝒂'=>'a','𝒶'=>'a','𝓪'=>'a','𝔞'=>'a','𝕒'=>'a','𝖆'=>'a','𝖺'=>'a','𝗮'=>'a','𝘢'=>'a','𝙖'=>'a','𝚊'=>'a','℀'=>'a/c','℁'=>'a/s','æ'=>'ae','b'=>'b','𝐛'=>'b','𝑏'=>'b','𝒃'=>'b','𝒷'=>'b','𝓫'=>'b','𝔟'=>'b','𝕓'=>'b','𝖇'=>'b','𝖻'=>'b','𝗯'=>'b','𝘣'=>'b','𝙗'=>'b','𝚋'=>'b','ɓ'=>'b̔','ƃ'=>'b̄','ƀ'=>'b̵','c'=>'c','ⅽ'=>'c','𝐜'=>'c','𝑐'=>'c','𝒄'=>'c','𝒸'=>'c','𝓬'=>'c','𝔠'=>'c','𝕔'=>'c','𝖈'=>'c','𝖼'=>'c','𝗰'=>'c','𝘤'=>'c','𝙘'=>'c','𝚌'=>'c','𝛓'=>'c','𝜍'=>'c','𝝇'=>'c','𝞁'=>'c','𝞻'=>'c','℅'=>'c/o','℆'=>'c/u','d'=>'d','ⅾ'=>'d','ⅆ'=>'d','𝐝'=>'d','𝑑'=>'d','𝒅'=>'d','𝒹'=>'d','𝓭'=>'d','𝔡'=>'d','𝕕'=>'d','𝖉'=>'d','𝖽'=>'d','𝗱'=>'d','𝘥'=>'d','𝙙'=>'d','𝚍'=>'d','ɗ'=>'d̔','ƌ'=>'d̄','ɖ'=>'d̢','đ'=>'d̵','dz'=>'dz','dž'=>'dž','e'=>'e','ℯ'=>'e','ⅇ'=>'e','𝐞'=>'e','𝑒'=>'e','𝒆'=>'e','𝓮'=>'e','𝔢'=>'e','𝕖'=>'e','𝖊'=>'e','𝖾'=>'e','𝗲'=>'e','𝘦'=>'e','𝙚'=>'e','𝚎'=>'e','ⴹ'=>'E','ə'=>'ǝ','ɚ'=>'ǝ˞','⋴'=>'ɛ','𝛆'=>'ɛ','𝛜'=>'ɛ','𝜀'=>'ɛ','𝜖'=>'ɛ','𝜺'=>'ɛ','𝝐'=>'ɛ','𝝴'=>'ɛ','𝞊'=>'ɛ','𝞮'=>'ɛ','𝟄'=>'ɛ','f'=>'f','𝐟'=>'f','𝑓'=>'f','𝒇'=>'f','𝒻'=>'f','𝓯'=>'f','𝔣'=>'f','𝕗'=>'f','𝖋'=>'f','𝖿'=>'f','𝗳'=>'f','𝘧'=>'f','𝙛'=>'f','𝚏'=>'f','ƒ'=>'f̡','g'=>'g','ℊ'=>'g','𝐠'=>'g','𝑔'=>'g','𝒈'=>'g','𝓰'=>'g','𝔤'=>'g','𝕘'=>'g','𝖌'=>'g','𝗀'=>'g','𝗴'=>'g','𝘨'=>'g','𝙜'=>'g','𝚐'=>'g','ɡ'=>'g','ɠ'=>'g̔','ǥ'=>'g̵','h'=>'h','ℎ'=>'h','𝐡'=>'h','𝒉'=>'h','𝒽'=>'h','𝓱'=>'h','𝔥'=>'h','𝕙'=>'h','𝖍'=>'h','𝗁'=>'h','𝗵'=>'h','𝘩'=>'h','𝙝'=>'h','𝚑'=>'h','ɦ'=>'h̔','ħ'=>'h̵','ℏ'=>'h̵','῾'=>'ʻ','‘'=>'ʻ','‛'=>'ʻ','ʽ'=>'ʻ','⍳'=>'i','i'=>'i','ⅰ'=>'i','ℹ'=>'i','ⅈ'=>'i','𝐢'=>'i','𝑖'=>'i','𝒊'=>'i','𝒾'=>'i','𝓲'=>'i','𝔦'=>'i','𝕚'=>'i','𝖎'=>'i','𝗂'=>'i','𝗶'=>'i','𝘪'=>'i','𝙞'=>'i','𝚒'=>'i','ı'=>'i','𝚤'=>'i','ɪ'=>'i','ɩ'=>'i','𝛊'=>'i','𝜄'=>'i','𝜾'=>'i','𝝸'=>'i','𝞲'=>'i','ɨ'=>'i̵','ⅱ'=>'ii','ⅲ'=>'iii','ij'=>'ij','ⅳ'=>'iv','ⅸ'=>'ix','j'=>'j','ⅉ'=>'j','𝐣'=>'j','𝑗'=>'j','𝒋'=>'j','𝒿'=>'j','𝓳'=>'j','𝔧'=>'j','𝕛'=>'j','𝖏'=>'j','𝗃'=>'j','𝗷'=>'j','𝘫'=>'j','𝙟'=>'j','𝚓'=>'j','ϳ'=>'j','𝚥'=>'ȷ','k'=>'k','𝐤'=>'k','𝑘'=>'k','𝒌'=>'k','𝓀'=>'k','𝓴'=>'k','𝔨'=>'k','𝕜'=>'k','𝖐'=>'k','𝗄'=>'k','𝗸'=>'k','𝘬'=>'k','𝙠'=>'k','𝚔'=>'k','ƙ'=>'k̔','m'=>'m','ⅿ'=>'m','𝐦'=>'m','𝑚'=>'m','𝒎'=>'m','𝓂'=>'m','𝓶'=>'m','𝔪'=>'m','𝕞'=>'m','𝖒'=>'m','𝗆'=>'m','𝗺'=>'m','𝘮'=>'m','𝙢'=>'m','𝚖'=>'m','ɱ'=>'m̡','n'=>'n','𝐧'=>'n','𝑛'=>'n','𝒏'=>'n','𝓃'=>'n','𝓷'=>'n','𝔫'=>'n','𝕟'=>'n','𝖓'=>'n','𝗇'=>'n','𝗻'=>'n','𝘯'=>'n','𝙣'=>'n','𝚗'=>'n','𝐍'=>'N','𝑁'=>'N','𝑵'=>'N','𝒩'=>'N','𝓝'=>'N','𝔑'=>'N','𝕹'=>'N','𝖭'=>'N','𝗡'=>'N','𝘕'=>'N','𝙉'=>'N','𝙽'=>'N','𝚴'=>'N','𝛮'=>'N','𝜨'=>'N','𝝢'=>'N','𝞜'=>'N','ɲ'=>'ņ','ɳ'=>'n̢','ƞ'=>'n̩','𝛈'=>'n̩','𝜂'=>'n̩','𝜼'=>'n̩','𝝶'=>'n̩','𝞰'=>'n̩','nj'=>'nj','o'=>'o','ℴ'=>'o','𝐨'=>'o','𝑜'=>'o','𝒐'=>'o','𝓸'=>'o','𝔬'=>'o','𝕠'=>'o','𝖔'=>'o','𝗈'=>'o','𝗼'=>'o','𝘰'=>'o','𝙤'=>'o','𝚘'=>'o','ᴏ'=>'o','𝛐'=>'o','𝜊'=>'o','𝝄'=>'o','𝝾'=>'o','𝞸'=>'o','ɵ'=>'o̵','ǿ'=>'ó̵','ø'=>'o̷','œ'=>'oe','ơ'=>'oʼ','⍴'=>'p','p'=>'p','𝐩'=>'p','𝑝'=>'p','𝒑'=>'p','𝓅'=>'p','𝓹'=>'p','𝔭'=>'p','𝕡'=>'p','𝖕'=>'p','𝗉'=>'p','𝗽'=>'p','𝘱'=>'p','𝙥'=>'p','𝚙'=>'p','𝛒'=>'p','𝛠'=>'p','𝜌'=>'p','𝜚'=>'p','𝝆'=>'p','𝝔'=>'p','𝞀'=>'p','𝞎'=>'p','𝞺'=>'p','𝟈'=>'p','ƥ'=>'p̔','q'=>'q','𝐪'=>'q','𝑞'=>'q','𝒒'=>'q','𝓆'=>'q','𝓺'=>'q','𝔮'=>'q','𝕢'=>'q','𝖖'=>'q','𝗊'=>'q','𝗾'=>'q','𝘲'=>'q','𝙦'=>'q','𝚚'=>'q','𝐐'=>'Q','𝑄'=>'Q','𝑸'=>'Q','𝒬'=>'Q','𝓠'=>'Q','𝔔'=>'Q','𝕼'=>'Q','𝖰'=>'Q','𝗤'=>'Q','𝘘'=>'Q','𝙌'=>'Q','𝚀'=>'Q','ʠ'=>'q̔','𝛋'=>'ĸ','𝛞'=>'ĸ','𝜅'=>'ĸ','𝜘'=>'ĸ','𝜿'=>'ĸ','𝝒'=>'ĸ','𝝹'=>'ĸ','𝞌'=>'ĸ','𝞳'=>'ĸ','𝟆'=>'ĸ','r'=>'r','𝐫'=>'r','𝑟'=>'r','𝒓'=>'r','𝓇'=>'r','𝓻'=>'r','𝔯'=>'r','𝕣'=>'r','𝖗'=>'r','𝗋'=>'r','𝗿'=>'r','𝘳'=>'r','𝙧'=>'r','𝚛'=>'r','ɽ'=>'r̢','ɼ'=>'r̩','s'=>'s','𝐬'=>'s','𝑠'=>'s','𝒔'=>'s','𝓈'=>'s','𝓼'=>'s','𝔰'=>'s','𝕤'=>'s','𝖘'=>'s','𝗌'=>'s','𝘀'=>'s','𝘴'=>'s','𝙨'=>'s','𝚜'=>'s','ƽ'=>'s','ʂ'=>'s̢','∫'=>'ʃ','∬'=>'ʃʃ','∭'=>'ʃʃʃ','⨌'=>'ʃʃʃʃ','t'=>'t','𝐭'=>'t','𝑡'=>'t','𝒕'=>'t','𝓉'=>'t','𝓽'=>'t','𝔱'=>'t','𝕥'=>'t','𝖙'=>'t','𝗍'=>'t','𝘁'=>'t','𝘵'=>'t','𝙩'=>'t','𝚝'=>'t','𝑇'=>'T','𝑻'=>'T','𝒯'=>'T','𝓣'=>'T','𝔗'=>'T','𝕋'=>'T','𝕿'=>'T','𝖳'=>'T','𝗧'=>'T','𝘛'=>'T','𝙏'=>'T','𝚃'=>'T','𝚻'=>'T','𝛵'=>'T','𝜯'=>'T','𝝩'=>'T','𝞣'=>'T','ƭ'=>'t̔','ț'=>'ţ','ƫ'=>'ţ','ŧ'=>'t̵','u'=>'u','𝐮'=>'u','𝑢'=>'u','𝒖'=>'u','𝓊'=>'u','𝓾'=>'u','𝔲'=>'u','𝕦'=>'u','𝖚'=>'u','𝗎'=>'u','𝘂'=>'u','𝘶'=>'u','𝙪'=>'u','𝚞'=>'u','ʊ'=>'u','ʋ'=>'u','𝛖'=>'u','𝜐'=>'u','𝝊'=>'u','𝞄'=>'u','𝞾'=>'u','𝑈'=>'U','𝑼'=>'U','𝒰'=>'U','𝓤'=>'U','𝔘'=>'U','𝕌'=>'U','𝖀'=>'U','𝖴'=>'U','𝗨'=>'U','𝘜'=>'U','𝙐'=>'U','𝚄'=>'U','v'=>'v','ⅴ'=>'v','𝐯'=>'v','𝑣'=>'v','𝒗'=>'v','𝓋'=>'v','𝓿'=>'v','𝔳'=>'v','𝕧'=>'v','𝖛'=>'v','𝗏'=>'v','𝘃'=>'v','𝘷'=>'v','𝙫'=>'v','𝚟'=>'v','𝛎'=>'v','𝜈'=>'v','𝝂'=>'v','𝝼'=>'v','𝞶'=>'v','ⅵ'=>'vi','ⅶ'=>'vii','ⅷ'=>'viii','ɯ'=>'w','w'=>'w','𝐰'=>'w','𝑤'=>'w','𝒘'=>'w','𝓌'=>'w','𝔀'=>'w','𝔴'=>'w','𝕨'=>'w','𝖜'=>'w','𝗐'=>'w','𝘄'=>'w','𝘸'=>'w','𝙬'=>'w','𝚠'=>'w','𝑊'=>'W','𝑾'=>'W','𝒲'=>'W','𝓦'=>'W','𝔚'=>'W','𝕎'=>'W','𝖂'=>'W','𝖶'=>'W','𝗪'=>'W','𝘞'=>'W','𝙒'=>'W','𝚆'=>'W','×'=>'x','x'=>'x','ⅹ'=>'x','𝐱'=>'x','𝑥'=>'x','𝒙'=>'x','𝓍'=>'x','𝔁'=>'x','𝔵'=>'x','𝕩'=>'x','𝖝'=>'x','𝗑'=>'x','𝘅'=>'x','𝘹'=>'x','𝙭'=>'x','𝚡'=>'x','᙭'=>'X','𝑋'=>'X','𝑿'=>'X','𝒳'=>'X','𝓧'=>'X','𝔛'=>'X','𝕏'=>'X','𝖃'=>'X','𝖷'=>'X','𝗫'=>'X','𝘟'=>'X','𝙓'=>'X','𝚇'=>'X','𝚾'=>'X','𝛸'=>'X','𝜲'=>'X','𝝬'=>'X','𝞦'=>'X','ⅺ'=>'xi','ⅻ'=>'xii','y'=>'y','𝐲'=>'y','𝑦'=>'y','𝒚'=>'y','𝓎'=>'y','𝔂'=>'y','𝔶'=>'y','𝕪'=>'y','𝖞'=>'y','𝗒'=>'y','𝘆'=>'y','𝘺'=>'y','𝙮'=>'y','𝚢'=>'y','ƴ'=>'y̔','z'=>'z','𝐳'=>'z','𝑧'=>'z','𝒛'=>'z','𝓏'=>'z','𝔃'=>'z','𝔷'=>'z','𝕫'=>'z','𝖟'=>'z','𝗓'=>'z','𝘇'=>'z','𝘻'=>'z','𝙯'=>'z','𝚣'=>'z','ȥ'=>'z̡','ʐ'=>'z̢','ƶ'=>'z̵','ȝ'=>'ʒ','?'=>'ʔ','?'=>'ʔ','⁇'=>'ʔʔ','⁈'=>'ʔǃ','᾽'=>'ʼ','᾿'=>'ʼ','’'=>'ʼ','ʾ'=>'ʼ','!'=>'ǃ','!'=>'ǃ','⁉'=>'ǃʔ','‼'=>'ǃǃ','⍺'=>'α','𝛂'=>'α','𝛼'=>'α','𝜶'=>'α','𝝰'=>'α','𝞪'=>'α','𝛃'=>'β','𝛽'=>'β','𝜷'=>'β','𝝱'=>'β','𝞫'=>'β','ℽ'=>'γ','𝛄'=>'γ','𝛾'=>'γ','𝜸'=>'γ','𝝲'=>'γ','𝞬'=>'γ','𝛅'=>'δ','𝛿'=>'δ','𝜹'=>'δ','𝝳'=>'δ','𝞭'=>'δ','𝟋'=>'ϝ','𝛇'=>'ζ','𝜁'=>'ζ','𝜻'=>'ζ','𝝵'=>'ζ','𝞯'=>'ζ','⍬'=>'θ','𝛉'=>'θ','𝛝'=>'θ','𝜃'=>'θ','𝜗'=>'θ','𝜽'=>'θ','𝝑'=>'θ','𝝷'=>'θ','𝞋'=>'θ','𝞱'=>'θ','𝟅'=>'θ','𝛌'=>'λ','𝜆'=>'λ','𝝀'=>'λ','𝝺'=>'λ','𝞴'=>'λ','𝛬'=>'Λ','𝜦'=>'Λ','𝝠'=>'Λ','𝞚'=>'Λ','𝛍'=>'μ','𝜇'=>'μ','𝝁'=>'μ','𝝻'=>'μ','𝞵'=>'μ','𝛏'=>'ξ','𝜉'=>'ξ','𝝃'=>'ξ','𝝽'=>'ξ','𝞷'=>'ξ','𝛯'=>'Ξ','𝜩'=>'Ξ','𝝣'=>'Ξ','𝞝'=>'Ξ','ℼ'=>'π','𝛑'=>'π','𝛡'=>'π','𝜋'=>'π','𝜛'=>'π','𝝅'=>'π','𝝕'=>'π','𝝿'=>'π','𝞏'=>'π','𝞹'=>'π','𝟉'=>'π','ᴨ'=>'π','∏'=>'Π','𝚷'=>'Π','𝛱'=>'Π','𝜫'=>'Π','𝝥'=>'Π','𝞟'=>'Π','𝛔'=>'σ','𝜎'=>'σ','𝝈'=>'σ','𝞂'=>'σ','𝞼'=>'σ','𝛕'=>'τ','𝜏'=>'τ','𝝉'=>'τ','𝞃'=>'τ','𝞽'=>'τ','𝐘'=>'Y','𝑌'=>'Y','𝒀'=>'Y','𝒴'=>'Y','𝓨'=>'Y','𝔜'=>'Y','𝕐'=>'Y','𝖄'=>'Y','𝖸'=>'Y','𝗬'=>'Y','𝘠'=>'Y','𝙔'=>'Y','𝚈'=>'Y','𝚼'=>'Y','𝛶'=>'Y','𝜰'=>'Y','𝝪'=>'Y','𝞤'=>'Y','𝛗'=>'φ','𝛟'=>'φ','𝜑'=>'φ','𝜙'=>'φ','𝝋'=>'φ','𝝓'=>'φ','𝞅'=>'φ','𝞍'=>'φ','𝞿'=>'φ','𝟇'=>'φ','𝛷'=>'Φ','𝜱'=>'Φ','𝝫'=>'Φ','𝞥'=>'Φ','𝛘'=>'χ','𝜒'=>'χ','𝝌'=>'χ','𝞆'=>'χ','𝟀'=>'χ','𝛙'=>'ψ','𝜓'=>'ψ','𝝍'=>'ψ','𝞇'=>'ψ','𝟁'=>'ψ','𝛹'=>'Ψ','𝜳'=>'Ψ','𝝭'=>'Ψ','𝞧'=>'Ψ','⍵'=>'ω','𝛚'=>'ω','𝜔'=>'ω','𝝎'=>'ω','𝞈'=>'ω','𝟂'=>'ω','ӕ'=>'ae','ғ'=>'r̵','ґ'=>'rᑊ','җ'=>'ж̩','ҙ'=>'з̡','ӏ'=>'i','ҋ'=>'й̡','қ'=>'ĸ̩','ҟ'=>'ĸ̵','ᴫ'=>'л','ӆ'=>'л̡','ӎ'=>'м̡','ӊ'=>'н̡','ӈ'=>'н̡','ң'=>'н̩','ө'=>'o̵','ѳ'=>'o̵','ҫ'=>'c̡','ҭ'=>'т̩','ү'=>'y','ұ'=>'y̵','ћ'=>'h̵','ѽ'=>'ѡ҃','ӌ'=>'ҷ','ҿ'=>'ҽ̢','ҍ'=>'Ь̵','զ'=>'q','ռ'=>'n','ℵ'=>'א','ﬡ'=>'א','אָ'=>'אַ','אּ'=>'אַ','ﭏ'=>'אל','ℶ'=>'ב','ℷ'=>'ג','ℸ'=>'ד','ﬢ'=>'ד','ﬣ'=>'ה','ﬤ'=>'כ','ﬥ'=>'ל','ﬦ'=>'ם','ﬠ'=>'ע','ﬧ'=>'ר','ﬨ'=>'ת','ﺀ'=>'ء','ﺂ'=>'آ','ﺁ'=>'آ','ﺄ'=>'أ','ﺃ'=>'أ','ٵ'=>'أ','ﭑ'=>'ٱ','ﭐ'=>'ٱ','ﺆ'=>'ؤ','ﺅ'=>'ؤ','ٶ'=>'ؤ','ﺈ'=>'إ','ﺇ'=>'إ','ﺋ'=>'ئ','ﺌ'=>'ئ','ﺊ'=>'ئ','ﺉ'=>'ئ','ﯫ'=>'ئا','ﯪ'=>'ئا','ﯸ'=>'ئٻ','ﯷ'=>'ئٻ','ﯶ'=>'ئٻ','ﲗ'=>'ئج','ﰀ'=>'ئج','ﲘ'=>'ئح','ﰁ'=>'ئح','ﲙ'=>'ئخ','ﱤ'=>'ئر','ﱥ'=>'ئز','ﲚ'=>'ئم','ﳟ'=>'ئم','ﱦ'=>'ئم','ﰂ'=>'ئم','ﱧ'=>'ئن','ﲛ'=>'ئه','ﳠ'=>'ئه','ﯭ'=>'ئه','ﯬ'=>'ئه','ﯯ'=>'ئو','ﯮ'=>'ئو','ﯳ'=>'ئۆ','ﯲ'=>'ئۆ','ﯱ'=>'ئۇ','ﯰ'=>'ئۇ','ﯵ'=>'ئۈ','ﯴ'=>'ئۈ','ﯻ'=>'ئى','ﯺ'=>'ئى','ﱨ'=>'ئى','ﯹ'=>'ئى','ﰃ'=>'ئى','ﱩ'=>'ئى','ﰄ'=>'ئى','ﺎ'=>'ا','ﺍ'=>'ا','ﴼ'=>'اً','ﴽ'=>'اً','ﷳ'=>'اكبر','ﷲ'=>'الله','ﺑ'=>'ب','ﺒ'=>'ب','ﺐ'=>'ب','ﺏ'=>'ب','ﲜ'=>'بج','ﰅ'=>'بج','ﲝ'=>'بح','ﰆ'=>'بح','ﷂ'=>'بحى','ﲞ'=>'بخ','ﰇ'=>'بخ','ﶞ'=>'بخى','ﱪ'=>'بر','ﱫ'=>'بز','ﲟ'=>'بم','ﳡ'=>'بم','ﱬ'=>'بم','ﰈ'=>'بم','ﱭ'=>'بن','ﲠ'=>'به','ﳢ'=>'به','ﱮ'=>'بى','ﰉ'=>'بى','ﱯ'=>'بى','ﰊ'=>'بى','ﭔ'=>'ٻ','ﭕ'=>'ٻ','ﭓ'=>'ٻ','ﭒ'=>'ٻ','ې'=>'ٻ','ﯦ'=>'ٻ','ﯧ'=>'ٻ','ﯥ'=>'ٻ','ﯤ'=>'ٻ','ﭘ'=>'پ','ﭙ'=>'پ','ﭗ'=>'پ','ﭖ'=>'پ','ﭜ'=>'ڀ','ﭝ'=>'ڀ','ﭛ'=>'ڀ','ﭚ'=>'ڀ','ﺔ'=>'ة','ﺓ'=>'ة','ﺗ'=>'ت','ﺘ'=>'ت','ﺖ'=>'ت','ﺕ'=>'ت','ﲡ'=>'تج','ﰋ'=>'تج','ﵐ'=>'تجم','ﶠ'=>'تجى','ﶟ'=>'تجى','ﲢ'=>'تح','ﰌ'=>'تح','ﵒ'=>'تحج','ﵑ'=>'تحج','ﵓ'=>'تحم','ﲣ'=>'تخ','ﰍ'=>'تخ','ﵔ'=>'تخم','ﶢ'=>'تخى','ﶡ'=>'تخى','ﱰ'=>'تر','ﱱ'=>'تز','ﲤ'=>'تم','ﳣ'=>'تم','ﱲ'=>'تم','ﰎ'=>'تم','ﵕ'=>'تمج','ﵖ'=>'تمح','ﵗ'=>'تمخ','ﶤ'=>'تمى','ﶣ'=>'تمى','ﱳ'=>'تن','ﲥ'=>'ته','ﳤ'=>'ته','ﱴ'=>'تى','ﰏ'=>'تى','ﱵ'=>'تى','ﰐ'=>'تى','ﺛ'=>'ث','ﺜ'=>'ث','ﺚ'=>'ث','ﺙ'=>'ث','ﰑ'=>'ثج','ﱶ'=>'ثر','ﱷ'=>'ثز','ﲦ'=>'ثم','ﳥ'=>'ثم','ﱸ'=>'ثم','ﰒ'=>'ثم','ﱹ'=>'ثن','ﳦ'=>'ثه','ﱺ'=>'ثى','ﰓ'=>'ثى','ﱻ'=>'ثى','ﰔ'=>'ثى','ﭨ'=>'ٹ','ﭩ'=>'ٹ','ﭧ'=>'ٹ','ﭦ'=>'ٹ','ڻ'=>'ٹ','ﮢ'=>'ٹ','ﮣ'=>'ٹ','ﮡ'=>'ٹ','ﮠ'=>'ٹ','ﭠ'=>'ٺ','ﭡ'=>'ٺ','ﭟ'=>'ٺ','ﭞ'=>'ٺ','ﭤ'=>'ٿ','ﭥ'=>'ٿ','ﭣ'=>'ٿ','ﭢ'=>'ٿ','ﺟ'=>'ج','ﺠ'=>'ج','ﺞ'=>'ج','ﺝ'=>'ج','ﲧ'=>'جح','ﰕ'=>'جح','ﶦ'=>'جحى','ﶾ'=>'جحى','ﷻ'=>'جل جلاله','ﲨ'=>'جم','ﰖ'=>'جم','ﵙ'=>'جمح','ﵘ'=>'جمح','ﶧ'=>'جمى','ﶥ'=>'جمى','ﴝ'=>'جى','ﴁ'=>'جى','ﴞ'=>'جى','ﴂ'=>'جى','ﭸ'=>'ڃ','ﭹ'=>'ڃ','ﭷ'=>'ڃ','ﭶ'=>'ڃ','ﭴ'=>'ڄ','ﭵ'=>'ڄ','ﭳ'=>'ڄ','ﭲ'=>'ڄ','ﭼ'=>'چ','ﭽ'=>'چ','ﭻ'=>'چ','ﭺ'=>'چ','ﮀ'=>'ڇ','ﮁ'=>'ڇ','ﭿ'=>'ڇ','ﭾ'=>'ڇ','ﺣ'=>'ح','ﺤ'=>'ح','ﺢ'=>'ح','ﺡ'=>'ح','ﲩ'=>'حج','ﰗ'=>'حج','ﶿ'=>'حجى','ﲪ'=>'حم','ﰘ'=>'حم','ﵛ'=>'حمى','ﵚ'=>'حمى','ﴛ'=>'حى','ﳿ'=>'حى','ﴜ'=>'حى','ﴀ'=>'حى','ﺧ'=>'خ','ﺨ'=>'خ','ﺦ'=>'خ','ﺥ'=>'خ','ﲫ'=>'خج','ﰙ'=>'خج','ﰚ'=>'خح','ﲬ'=>'خم','ﰛ'=>'خم','ﴟ'=>'خى','ﴃ'=>'خى','ﴠ'=>'خى','ﴄ'=>'خى','ﺪ'=>'د','ﺩ'=>'د','ﺬ'=>'ذ','ﺫ'=>'ذ','ﱛ'=>'ذٰ','ﮉ'=>'ڈ','ﮈ'=>'ڈ','ﮅ'=>'ڌ','ﮄ'=>'ڌ','ﮃ'=>'ڍ','ﮂ'=>'ڍ','ﮇ'=>'ڎ','ﮆ'=>'ڎ','ﺮ'=>'ر','ﺭ'=>'ر','ﱜ'=>'رٰ','ﷶ'=>'رسول','﷼'=>'رىال','ﺰ'=>'ز','ﺯ'=>'ز','ﮍ'=>'ڑ','ﮌ'=>'ڑ','ﮋ'=>'ژ','ﮊ'=>'ژ','ﺳ'=>'س','ﺴ'=>'س','ﺲ'=>'س','ﺱ'=>'س','ﲭ'=>'سج','ﴴ'=>'سج','ﰜ'=>'سج','ﵝ'=>'سجح','ﵞ'=>'سجى','ﲮ'=>'سح','ﴵ'=>'سح','ﰝ'=>'سح','ﵜ'=>'سحج','ﲯ'=>'سخ','ﴶ'=>'سخ','ﰞ'=>'سخ','ﶨ'=>'سخى','ﷆ'=>'سخى','ﴪ'=>'سر','ﴎ'=>'سر','ﲰ'=>'سم','ﳧ'=>'سم','ﰟ'=>'سم','ﵡ'=>'سمج','ﵠ'=>'سمح','ﵟ'=>'سمح','ﵣ'=>'سمم','ﵢ'=>'سمم','ﴱ'=>'سه','ﳨ'=>'سه','ﴗ'=>'سى','ﳻ'=>'سى','ﴘ'=>'سى','ﳼ'=>'سى','ﺷ'=>'ش','ﺸ'=>'ش','ﺶ'=>'ش','ﺵ'=>'ش','ﴭ'=>'شج','ﴷ'=>'شج','ﴥ'=>'شج','ﴉ'=>'شج','ﵩ'=>'شجى','ﴮ'=>'شح','ﴸ'=>'شح','ﴦ'=>'شح','ﴊ'=>'شح','ﵨ'=>'شحم','ﵧ'=>'شحم','ﶪ'=>'شحى','ﴯ'=>'شخ','ﴹ'=>'شخ','ﴧ'=>'شخ','ﴋ'=>'شخ','ﴩ'=>'شر','ﴍ'=>'شر','ﴰ'=>'شم','ﳩ'=>'شم','ﴨ'=>'شم','ﴌ'=>'شم','ﵫ'=>'شمخ','ﵪ'=>'شمخ','ﵭ'=>'شمم','ﵬ'=>'شمم','ﴲ'=>'شه','ﳪ'=>'شه','ﴙ'=>'شى','ﳽ'=>'شى','ﴚ'=>'شى','ﳾ'=>'شى','ﺻ'=>'ص','ﺼ'=>'ص','ﺺ'=>'ص','ﺹ'=>'ص','ﲱ'=>'صح','ﰠ'=>'صح','ﵥ'=>'صحح','ﵤ'=>'صحح','ﶩ'=>'صحى','ﲲ'=>'صخ','ﴫ'=>'صر','ﴏ'=>'صر','ﷵ'=>'صلعم','ﷹ'=>'صلى','ﷺ'=>'صلى الله علىه وسلم','ﷰ'=>'صلے','ﲳ'=>'صم','ﰡ'=>'صم','ﷅ'=>'صمم','ﵦ'=>'صمم','ﴡ'=>'صى','ﴅ'=>'صى','ﴢ'=>'صى','ﴆ'=>'صى','ﺿ'=>'ض','ﻀ'=>'ض','ﺾ'=>'ض','ﺽ'=>'ض','ﲴ'=>'ضج','ﰢ'=>'ضج','ﲵ'=>'ضح','ﰣ'=>'ضح','ﵮ'=>'ضحى','ﶫ'=>'ضحى','ﲶ'=>'ضخ','ﰤ'=>'ضخ','ﵰ'=>'ضخم','ﵯ'=>'ضخم','ﴬ'=>'ضر','ﴐ'=>'ضر','ﲷ'=>'ضم','ﰥ'=>'ضم','ﴣ'=>'ضى','ﴇ'=>'ضى','ﴤ'=>'ضى','ﴈ'=>'ضى','ﻃ'=>'ط','ﻄ'=>'ط','ﻂ'=>'ط','ﻁ'=>'ط','ﲸ'=>'طح','ﰦ'=>'طح','ﴳ'=>'طم','ﴺ'=>'طم','ﰧ'=>'طم','ﵲ'=>'طمح','ﵱ'=>'طمح','ﵳ'=>'طمم','ﵴ'=>'طمى','ﴑ'=>'طى','ﳵ'=>'طى','ﴒ'=>'طى','ﳶ'=>'طى','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻆ'=>'ظ','ﻅ'=>'ظ','ﲹ'=>'ظم','ﴻ'=>'ظم','ﰨ'=>'ظم','ﻋ'=>'ع','ﻌ'=>'ع','ﻊ'=>'ع','ﻉ'=>'ع','ﲺ'=>'عج','ﰩ'=>'عج','ﷄ'=>'عجم','ﵵ'=>'عجم','ﷷ'=>'علىه','ﲻ'=>'عم','ﰪ'=>'عم','ﵷ'=>'عمم','ﵶ'=>'عمم','ﵸ'=>'عمى','ﶶ'=>'عمى','ﴓ'=>'عى','ﳷ'=>'عى','ﴔ'=>'عى','ﳸ'=>'عى','ﻏ'=>'غ','ﻐ'=>'غ','ﻎ'=>'غ','ﻍ'=>'غ','ﲼ'=>'غج','ﰫ'=>'غج','ﲽ'=>'غم','ﰬ'=>'غم','ﵹ'=>'غمم','ﵻ'=>'غمى','ﵺ'=>'غمى','ﴕ'=>'غى','ﳹ'=>'غى','ﴖ'=>'غى','ﳺ'=>'غى','ﻓ'=>'ف','ﻔ'=>'ف','ﻒ'=>'ف','ﻑ'=>'ف','ﲾ'=>'فج','ﰭ'=>'فج','ﲿ'=>'فح','ﰮ'=>'فح','ﳀ'=>'فخ','ﰯ'=>'فخ','ﵽ'=>'فخم','ﵼ'=>'فخم','ﳁ'=>'فم','ﰰ'=>'فم','ﷁ'=>'فمى','ﱼ'=>'فى','ﰱ'=>'فى','ﱽ'=>'فى','ﰲ'=>'فى','ﭬ'=>'ڤ','ﭭ'=>'ڤ','ﭫ'=>'ڤ','ﭪ'=>'ڤ','ﭰ'=>'ڦ','ﭱ'=>'ڦ','ﭯ'=>'ڦ','ﭮ'=>'ڦ','ﻗ'=>'ق','ﻘ'=>'ق','ﻖ'=>'ق','ﻕ'=>'ق','ﳂ'=>'قح','ﰳ'=>'قح','ﷱ'=>'قلے','ﳃ'=>'قم','ﰴ'=>'قم','ﶴ'=>'قمح','ﵾ'=>'قمح','ﵿ'=>'قمم','ﶲ'=>'قمى','ﱾ'=>'قى','ﰵ'=>'قى','ﱿ'=>'قى','ﰶ'=>'قى','ﻛ'=>'ك','ﻜ'=>'ك','ﻚ'=>'ك','ﻙ'=>'ك','ک'=>'ك','ﮐ'=>'ك','ﮑ'=>'ك','ﮏ'=>'ك','ﮎ'=>'ك','ﲀ'=>'كا','ﰷ'=>'كا','ﳄ'=>'كج','ﰸ'=>'كج','ﳅ'=>'كح','ﰹ'=>'كح','ﳆ'=>'كخ','ﰺ'=>'كخ','ﳇ'=>'كل','ﳫ'=>'كل','ﲁ'=>'كل','ﰻ'=>'كل','ﳈ'=>'كم','ﳬ'=>'كم','ﲂ'=>'كم','ﰼ'=>'كم','ﷃ'=>'كمم','ﶻ'=>'كمم','ﶷ'=>'كمى','ﲃ'=>'كى','ﰽ'=>'كى','ﲄ'=>'كى','ﰾ'=>'كى','ﯕ'=>'ڭ','ﯖ'=>'ڭ','ﯔ'=>'ڭ','ﯓ'=>'ڭ','ﮔ'=>'گ','ﮕ'=>'گ','ﮓ'=>'گ','ﮒ'=>'گ','ﮜ'=>'ڱ','ﮝ'=>'ڱ','ﮛ'=>'ڱ','ﮚ'=>'ڱ','ﮘ'=>'ڳ','ﮙ'=>'ڳ','ﮗ'=>'ڳ','ﮖ'=>'ڳ','ﻟ'=>'ل','ﻠ'=>'ل','ﻞ'=>'ل','ﻝ'=>'ل','ﻶ'=>'لآ','ﻵ'=>'لآ','ﻸ'=>'لأ','ﻷ'=>'لأ','ﻺ'=>'لإ','ﻹ'=>'لإ','ﻼ'=>'لا','ﻻ'=>'لا','ﳉ'=>'لج','ﰿ'=>'لج','ﶃ'=>'لجج','ﶄ'=>'لجج','ﶺ'=>'لجم','ﶼ'=>'لجم','ﶬ'=>'لجى','ﳊ'=>'لح','ﱀ'=>'لح','ﶵ'=>'لحم','ﶀ'=>'لحم','ﶂ'=>'لحى','ﶁ'=>'لحى','ﳋ'=>'لخ','ﱁ'=>'لخ','ﶆ'=>'لخم','ﶅ'=>'لخم','ﳌ'=>'لم','ﳭ'=>'لم','ﲅ'=>'لم','ﱂ'=>'لم','ﶈ'=>'لمح','ﶇ'=>'لمح','ﶭ'=>'لمى','ﳍ'=>'له','ﲆ'=>'لى','ﱃ'=>'لى','ﲇ'=>'لى','ﱄ'=>'لى','ﻣ'=>'م','ﻤ'=>'م','ﻢ'=>'م','ﻡ'=>'م','ﲈ'=>'ما','ﳎ'=>'مج','ﱅ'=>'مج','ﶌ'=>'مجح','ﶒ'=>'مجخ','ﶍ'=>'مجم','ﷀ'=>'مجى','ﳏ'=>'مح','ﱆ'=>'مح','ﶉ'=>'محج','ﶊ'=>'محم','ﷴ'=>'محمد','ﶋ'=>'محى','ﳐ'=>'مخ','ﱇ'=>'مخ','ﶎ'=>'مخج','ﶏ'=>'مخم','ﶹ'=>'مخى','ﳑ'=>'مم','ﲉ'=>'مم','ﱈ'=>'مم','ﶱ'=>'ممى','ﱉ'=>'مى','ﱊ'=>'مى','ﻧ'=>'ن','ﻨ'=>'ن','ﻦ'=>'ن','ﻥ'=>'ن','ﳒ'=>'نج','ﱋ'=>'نج','ﶸ'=>'نجح','ﶽ'=>'نجح','ﶘ'=>'نجم','ﶗ'=>'نجم','ﶙ'=>'نجى','ﷇ'=>'نجى','ﳓ'=>'نح','ﱌ'=>'نح','ﶕ'=>'نحم','ﶖ'=>'نحى','ﶳ'=>'نحى','ﳔ'=>'نخ','ﱍ'=>'نخ','ﲊ'=>'نر','ﲋ'=>'نز','ﳕ'=>'نم','ﳮ'=>'نم','ﲌ'=>'نم','ﱎ'=>'نم','ﶛ'=>'نمى','ﶚ'=>'نمى','ﲍ'=>'نن','ﳖ'=>'نه','ﳯ'=>'نه','ﲎ'=>'نى','ﱏ'=>'نى','ﲏ'=>'نى','ﱐ'=>'نى','ﮟ'=>'ں','ﮞ'=>'ں','ﻫ'=>'ه','ﻬ'=>'ه','ﻪ'=>'ه','ﻩ'=>'ه','ھ'=>'ه','ﮬ'=>'ه','ﮭ'=>'ه','ﮫ'=>'ه','ﮪ'=>'ه','ہ'=>'ه','ﮨ'=>'ه','ﮩ'=>'ه','ﮧ'=>'ه','ﮦ'=>'ه','ە'=>'ه','ﳙ'=>'هٰ','ﳗ'=>'هج','ﱑ'=>'هج','ﳘ'=>'هم','ﱒ'=>'هم','ﶓ'=>'همج','ﶔ'=>'همم','ﱓ'=>'هى','ﱔ'=>'هى','ﮥ'=>'ۀ','ﮤ'=>'ۀ','ﻮ'=>'و','ﻭ'=>'و','ﷸ'=>'وسلم','ﯡ'=>'ۅ','ﯠ'=>'ۅ','ﯚ'=>'ۆ','ﯙ'=>'ۆ','ﯘ'=>'ۇ','ﯗ'=>'ۇ','ٷ'=>'ۇٔ','ﯝ'=>'ۇٔ','ﯜ'=>'ۈ','ﯛ'=>'ۈ','ﯣ'=>'ۉ','ﯢ'=>'ۉ','ﯟ'=>'ۋ','ﯞ'=>'ۋ','ﯨ'=>'ى','ﯩ'=>'ى','ﻰ'=>'ى','ﻯ'=>'ى','ي'=>'ى','ﻳ'=>'ى','ﻴ'=>'ى','ﻲ'=>'ى','ﻱ'=>'ى','ی'=>'ى','ﯾ'=>'ى','ﯿ'=>'ى','ﯽ'=>'ى','ﯼ'=>'ى','ٸ'=>'ىٔ','ﲐ'=>'ىٰ','ﱝ'=>'ىٰ','ﳚ'=>'ىج','ﱕ'=>'ىج','ﶯ'=>'ىجى','ﳛ'=>'ىح','ﱖ'=>'ىح','ﶮ'=>'ىحى','ﳜ'=>'ىخ','ﱗ'=>'ىخ','ﲑ'=>'ىر','ﲒ'=>'ىز','ﳝ'=>'ىم','ﳰ'=>'ىم','ﲓ'=>'ىم','ﱘ'=>'ىم','ﶝ'=>'ىمم','ﶜ'=>'ىمم','ﶰ'=>'ىمى','ﲔ'=>'ىن','ﳞ'=>'ىه','ﳱ'=>'ىه','ﲕ'=>'ىى','ﱙ'=>'ىى','ﲖ'=>'ىى','ﱚ'=>'ىى','ۧ'=>'ۦ','ﮯ'=>'ے','ﮮ'=>'ے','ﮱ'=>'ۓ','ﮰ'=>'ۓ','∃'=>'ⴺ','आ'=>'अा','ऒ'=>'अाॆ','ओ'=>'अाे','औ'=>'अाै','ऄ'=>'अॆ','ऑ'=>'अॉ','ऍ'=>'एॅ','ऎ'=>'एॆ','ऐ'=>'एे','ई'=>'र्इ','আ'=>'অা','ৠ'=>'ঋৃ','ৡ'=>'ঌৢ','ਉ'=>'ੳੁ','ਊ'=>'ੳੂ','ਆ'=>'ਅਾ','ਐ'=>'ਅੈ','ਔ'=>'ਅੌ','ਇ'=>'ੲਿ','ਈ'=>'ੲੀ','ਏ'=>'ੲੇ','આ'=>'અા','ઑ'=>'અાૅ','ઓ'=>'અાે','ઔ'=>'અાૈ','ઍ'=>'અૅ','એ'=>'અે','ઐ'=>'અૈ','ଆ'=>'ଅା','௮'=>'அ','ர'=>'ஈ','ா'=>'ஈ','௫'=>'ஈு','௨'=>'உ','ஊ'=>'உள','௭'=>'எ','௷'=>'எவ','ஜ'=>'ஐ','௧'=>'க','௪'=>'ச','௬'=>'சு','௲'=>'சூ','௺'=>'நீ','ை'=>'ன','௴'=>'மீ','௰'=>'ய','ௗ'=>'ள','௸'=>'ஷ','ொ'=>'ெஈ','ௌ'=>'ெள','ோ'=>'ேஈ','ౠ'=>'ఋా','ౡ'=>'ఌా','ఔ'=>'ఒౌ','ఓ'=>'ఒౕ','ఢ'=>'డ̣','భ'=>'బ̣','ష'=>'వ̣','హ'=>'వా','మ'=>'వు','ూ'=>'ుా','ౄ'=>'ృా','ೡ'=>'ಌಾ','ಔ'=>'ఒౌ','ഈ'=>'ഇൗ','ഊ'=>'உൗ','ഐ'=>'എെ','ഓ'=>'ഒാ','ഔ'=>'ഒൗ','ൡ'=>'ഞ','൫'=>'ദ്ര','ഌ'=>'നூ','ങ'=>'നூ','൯'=>'ന്','റ'=>'ര','൪'=>'ര്','൮'=>'വ്','ീ'=>'ி','ൂ'=>'ூ','ൃ'=>'ூ','ൈ'=>'െെ','ฃ'=>'ข','ด'=>'ค','ต'=>'ค','ม'=>'ฆ','ซ'=>'ช','ฏ'=>'ฎ','ท'=>'ฑ','ๅ'=>'า','ำ'=>'̊า','แ'=>'เเ','ໜ'=>'ຫນ','ໝ'=>'ຫມ','ຳ'=>'̊າ','ཷ'=>'ྲཱྀ','ཹ'=>'ླཱྀ','၀'=>'o','ឣ'=>'អ','᧐'=>'ᦞ','᭒'=>'ᬍ','᭓'=>'ᬑ','᭘'=>'ᬨ','ᢖ'=>'ᡜ','ᡕ'=>'ᠵ','Ꮢ'=>'Ꭱ','Ꮍ'=>'y','𝐀'=>'A','𝐴'=>'A','𝑨'=>'A','𝒜'=>'A','𝓐'=>'A','𝔄'=>'A','𝔸'=>'A','𝕬'=>'A','𝖠'=>'A','𝗔'=>'A','𝘈'=>'A','𝘼'=>'A','𝙰'=>'A','𝚨'=>'A','𝛢'=>'A','𝜜'=>'A','𝝖'=>'A','𝞐'=>'A','𝐉'=>'J','𝐽'=>'J','𝑱'=>'J','𝒥'=>'J','𝓙'=>'J','𝔍'=>'J','𝕁'=>'J','𝕵'=>'J','𝖩'=>'J','𝗝'=>'J','𝘑'=>'J','𝙅'=>'J','𝙹'=>'J','Ꮷ'=>'J','⋿'=>'E','ℰ'=>'E','𝐄'=>'E','𝐸'=>'E','𝑬'=>'E','𝓔'=>'E','𝔈'=>'E','𝔼'=>'E','𝕰'=>'E','𝖤'=>'E','𝗘'=>'E','𝘌'=>'E','𝙀'=>'E','𝙴'=>'E','𝚬'=>'E','𝛦'=>'E','𝜠'=>'E','𝝚'=>'E','𝞔'=>'E','ℾ'=>'Ꮁ','𝚪'=>'Ꮁ','𝛤'=>'Ꮁ','𝜞'=>'Ꮁ','𝝘'=>'Ꮁ','𝞒'=>'Ꮁ','Ꮤ'=>'w','ℳ'=>'M','𝐌'=>'M','𝑀'=>'M','𝑴'=>'M','𝓜'=>'M','𝔐'=>'M','𝕄'=>'M','𝕸'=>'M','𝖬'=>'M','𝗠'=>'M','𝘔'=>'M','𝙈'=>'M','𝙼'=>'M','𝚳'=>'M','𝛭'=>'M','𝜧'=>'M','𝝡'=>'M','𝞛'=>'M','ℋ'=>'H','ℌ'=>'H','ℍ'=>'H','𝐇'=>'H','𝐻'=>'H','𝑯'=>'H','𝓗'=>'H','𝕳'=>'H','𝖧'=>'H','𝗛'=>'H','𝘏'=>'H','𝙃'=>'H','𝙷'=>'H','𝚮'=>'H','𝛨'=>'H','𝜢'=>'H','𝝜'=>'H','𝞖'=>'H','𝐆'=>'G','𝐺'=>'G','𝑮'=>'G','𝒢'=>'G','𝓖'=>'G','𝔊'=>'G','𝔾'=>'G','𝕲'=>'G','𝖦'=>'G','𝗚'=>'G','𝘎'=>'G','𝙂'=>'G','𝙶'=>'G','Ᏻ'=>'G','ℤ'=>'Z','ℨ'=>'Z','𝐙'=>'Z','𝑍'=>'Z','𝒁'=>'Z','𝒵'=>'Z','𝓩'=>'Z','𝖅'=>'Z','𝖹'=>'Z','𝗭'=>'Z','𝘡'=>'Z','𝙕'=>'Z','𝚉'=>'Z','𝚭'=>'Z','𝛧'=>'Z','𝜡'=>'Z','𝝛'=>'Z','𝞕'=>'Z','𝐒'=>'S','𝑆'=>'S','𝑺'=>'S','𝒮'=>'S','𝓢'=>'S','𝔖'=>'S','𝕊'=>'S','𝕾'=>'S','𝖲'=>'S','𝗦'=>'S','𝘚'=>'S','𝙎'=>'S','𝚂'=>'S','Ꮪ'=>'S','𝐕'=>'V','𝑉'=>'V','𝑽'=>'V','𝒱'=>'V','𝓥'=>'V','𝔙'=>'V','𝕍'=>'V','𝖁'=>'V','𝖵'=>'V','𝗩'=>'V','𝘝'=>'V','𝙑'=>'V','𝚅'=>'V','ℒ'=>'L','𝐋'=>'L','𝐿'=>'L','𝑳'=>'L','𝓛'=>'L','𝔏'=>'L','𝕃'=>'L','𝕷'=>'L','𝖫'=>'L','𝗟'=>'L','𝘓'=>'L','𝙇'=>'L','𝙻'=>'L','∑'=>'C','⅀'=>'C','ℂ'=>'C','ℭ'=>'C','𝐂'=>'C','𝐶'=>'C','𝑪'=>'C','𝒞'=>'C','𝓒'=>'C','𝕮'=>'C','𝖢'=>'C','𝗖'=>'C','𝘊'=>'C','𝘾'=>'C','𝙲'=>'C','𝚺'=>'C','𝛴'=>'C','𝜮'=>'C','𝝨'=>'C','𝞢'=>'C','ℙ'=>'P','𝐏'=>'P','𝑃'=>'P','𝑷'=>'P','𝒫'=>'P','𝓟'=>'P','𝔓'=>'P','𝕻'=>'P','𝖯'=>'P','𝗣'=>'P','𝘗'=>'P','𝙋'=>'P','𝙿'=>'P','𝚸'=>'P','𝛲'=>'P','𝜬'=>'P','𝝦'=>'P','𝞠'=>'P','𝐊'=>'K','𝐾'=>'K','𝑲'=>'K','𝒦'=>'K','𝓚'=>'K','𝔎'=>'K','𝕂'=>'K','𝕶'=>'K','𝖪'=>'K','𝗞'=>'K','𝘒'=>'K','𝙆'=>'K','𝙺'=>'K','𝚱'=>'K','𝛫'=>'K','𝜥'=>'K','𝝟'=>'K','𝞙'=>'K','ℬ'=>'B','𝐁'=>'B','𝐵'=>'B','𝑩'=>'B','𝓑'=>'B','𝔅'=>'B','𝔹'=>'B','𝕭'=>'B','𝖡'=>'B','𝗕'=>'B','𝘉'=>'B','𝘽'=>'B','𝙱'=>'B','𝚩'=>'B','𝛣'=>'B','𝜝'=>'B','𝝗'=>'B','𝞑'=>'B','ᐍ'=>'ᐁ·','∆'=>'ᐃ','𝚫'=>'ᐃ','𝛥'=>'ᐃ','𝜟'=>'ᐃ','𝝙'=>'ᐃ','𝞓'=>'ᐃ','ᐏ'=>'ᐃ·','ᐑ'=>'ᐄ·','ᐓ'=>'ᐅ·','ᐕ'=>'ᐆ·','ᐘ'=>'ᐊ·','ᐚ'=>'ᐋ·','ᓑ'=>'ᐡ','ᑶ'=>'·P','ᑺ'=>'·d','ᒘ'=>'·J','ᑁ'=>'ᐳ·','ᑃ'=>'ᐴ·','ᑅ'=>'ᐸ·','ᑇ'=>'ᐹ·','ˈ'=>'ᑊ','ᑘ'=>'ᑌ·','ᑧ'=>'ᑌᑊ','ᑚ'=>'ᑎ·','ᑨ'=>'ᑎᑊ','ᑜ'=>'ᑏ·','ᑞ'=>'ᑐ·','ᑩ'=>'ᑐᑊ','ᑠ'=>'ᑑ·','ᑢ'=>'ᑕ·','ᑪ'=>'ᑕᑊ','ᑤ'=>'ᑖ·','ᑵ'=>'ᑫ·','ᒅ'=>'ᑫᑊ','ᑷ'=>'P·','ᒆ'=>'Pᑊ','ᑹ'=>'ᑮ·','ᑻ'=>'d·','ᒇ'=>'dᑊ','ᑽ'=>'ᑰ·','ᑿ'=>'ᑲ·','ᒈ'=>'ᑲᑊ','ᒁ'=>'ᑳ·','ᘃ'=>'ᒉ','ᒓ'=>'ᒉ·','ᒕ'=>'ᒋ·','ᒗ'=>'ᒌ·','ᒙ'=>'J·','ᒛ'=>'ᒎ·','ᘂ'=>'ᒐ','ᒝ'=>'ᒐ·','ᒟ'=>'ᒑ·','ᒭ'=>'ᒣ·','ᒯ'=>'ᒥ·','ᒱ'=>'ᒦ·','ᒳ'=>'ᒧ·','ᒵ'=>'ᒨ·','ᒹ'=>'ᒫ·','ᓊ'=>'ᓀ·','ᓌ'=>'ᓇ·','ᓎ'=>'ᓈᒫ','ᘄ'=>'ᓓ','ᓝ'=>'ᓓ·','ᓟ'=>'ᓕ·','ᓡ'=>'ᓖ·','ᓣ'=>'ᓗ·','ᓥ'=>'ᓘ·','ᘇ'=>'ᓚ','ᓧ'=>'ᓚ·','ᓩ'=>'ᓛ·','ᓷ'=>'ᓭ·','ᓹ'=>'ᓯ·','ᓻ'=>'ᓰ·','ᓽ'=>'ᓱ·','ᓿ'=>'ᓲ·','ᔁ'=>'ᓴ·','ᔃ'=>'ᓵ·','ᔌ'=>'ᔋᐸ','ᔍ'=>'ᔋᑕ','ᔎ'=>'ᔋᑲ','ᔏ'=>'ᔋᒐ','ᔘ'=>'ᔐ·','ᔚ'=>'ᔑ·','ᔜ'=>'ᔒ·','ᔞ'=>'ᔓ·','ᔠ'=>'ᔔ·','ᔢ'=>'ᔕ·','ᔤ'=>'ᔖ·','ᔲ'=>'ᔨ·','ᔴ'=>'ᔩ·','ᔶ'=>'ᔪ·','ᔸ'=>'ᔫ·','ᔺ'=>'ᔭ·','ᔼ'=>'ᔮ·','᙮'=>'x','ᕽ'=>'x','ᘢ'=>'ᕃ','ᘣ'=>'ᕆ','ᘤ'=>'ᕊ','ᕏ'=>'ᕌ·','ᙯ'=>'ᕐᑫ','ᕾ'=>'ᕐᑬ','ᕿ'=>'ᕐP','ᖀ'=>'ᕐᑮ','ᖁ'=>'ᕐd','ᖂ'=>'ᕐᑰ','ᖃ'=>'ᕐᑲ','ᖄ'=>'ᕐᑳ','ᖅ'=>'ᕐᒃ','ᕜ'=>'ᕚ·','ᕩ'=>'ᕧ·','ℛ'=>'R','ℜ'=>'R','ℝ'=>'R','𝐑'=>'R','𝑅'=>'R','𝑹'=>'R','𝓡'=>'R','𝕽'=>'R','𝖱'=>'R','𝗥'=>'R','𝘙'=>'R','𝙍'=>'R','𝚁'=>'R','ᙰ'=>'ᖕᒉ','ᖎ'=>'ᖕᒊ','ᖏ'=>'ᖕᒋ','ᖐ'=>'ᖕᒌ','ᖑ'=>'ᖕJ','ᖒ'=>'ᖕᒎ','ᖓ'=>'ᖕᒐ','ᖔ'=>'ᖕᒑ','ᙱ'=>'ᖖᒋ','ᙲ'=>'ᖖᒌ','ᙳ'=>'ᖖJ','ᙴ'=>'ᖖᒎ','ᙵ'=>'ᖖᒐ','ᙶ'=>'ᖖᒑ','ℱ'=>'F','𝐅'=>'F','𝐹'=>'F','𝑭'=>'F','𝓕'=>'F','𝔉'=>'F','𝔽'=>'F','𝕱'=>'F','𝖥'=>'F','𝗙'=>'F','𝘍'=>'F','𝙁'=>'F','𝙵'=>'F','𝟊'=>'F','ⅅ'=>'D','𝐃'=>'D','𝐷'=>'D','𝑫'=>'D','𝒟'=>'D','𝓓'=>'D','𝔇'=>'D','𝔻'=>'D','𝕯'=>'D','𝖣'=>'D','𝗗'=>'D','𝘋'=>'D','𝘿'=>'D','𝙳'=>'D','ᗪ'=>'D','℧'=>'ᘮ','ᘴ'=>'ᘮ','𝛀'=>'ᘯ','𝛺'=>'ᘯ','𝜴'=>'ᘯ','𝝮'=>'ᘯ','𝞨'=>'ᘯ','ᘵ'=>'ᘯ','ㄱ'=>'ᄀ','ᄀ'=>'ᄀ','ᆨ'=>'ᄀ','ㄲ'=>'ᄁ','ᄁ'=>'ᄁ','ᆩ'=>'ᄁ','ㄴ'=>'ᄂ','ᄂ'=>'ᄂ','ᆫ'=>'ᄂ','ㄷ'=>'ᄃ','ᄃ'=>'ᄃ','ᆮ'=>'ᄃ','ㄸ'=>'ᄄ','ᄄ'=>'ᄄ','ㄹ'=>'ᄅ','ᄅ'=>'ᄅ','ᆯ'=>'ᄅ','ㅁ'=>'ᄆ','ᄆ'=>'ᄆ','ᆷ'=>'ᄆ','ㅂ'=>'ᄇ','ᄇ'=>'ᄇ','ᆸ'=>'ᄇ','ㅃ'=>'ᄈ','ᄈ'=>'ᄈ','ㅅ'=>'ᄉ','ᄉ'=>'ᄉ','ᆺ'=>'ᄉ','ㅆ'=>'ᄊ','ᄊ'=>'ᄊ','ᆻ'=>'ᄊ','ㅇ'=>'ᄋ','ᄋ'=>'ᄋ','ᆼ'=>'ᄋ','ㅈ'=>'ᄌ','ᄌ'=>'ᄌ','ᆽ'=>'ᄌ','ㅉ'=>'ᄍ','ᄍ'=>'ᄍ','ㅊ'=>'ᄎ','ᄎ'=>'ᄎ','ᆾ'=>'ᄎ','ㅋ'=>'ᄏ','ᄏ'=>'ᄏ','ᆿ'=>'ᄏ','ㅌ'=>'ᄐ','ᄐ'=>'ᄐ','ᇀ'=>'ᄐ','ㅍ'=>'ᄑ','ᄑ'=>'ᄑ','ᇁ'=>'ᄑ','ㅎ'=>'ᄒ','ᄒ'=>'ᄒ','ᇂ'=>'ᄒ','ᇅ'=>'ᄓ','ㅥ'=>'ᄔ','ㅦ'=>'ᄕ','ᇆ'=>'ᄕ','ᇊ'=>'ᄗ','ᇍ'=>'ᄘ','ᇐ'=>'ᄙ','ㅀ'=>'ᄚ','ᄚ'=>'ᄚ','ᄻ'=>'ᄚ','ᆶ'=>'ᄚ','ㅮ'=>'ᄜ','ᇜ'=>'ᄜ','ㅱ'=>'ᄝ','ᇢ'=>'ᄝ','ㅲ'=>'ᄞ','ㅳ'=>'ᄠ','ㅄ'=>'ᄡ','ᄡ'=>'ᄡ','ᆹ'=>'ᄡ','ㅴ'=>'ᄢ','ㅵ'=>'ᄣ','ㅶ'=>'ᄧ','ㅷ'=>'ᄩ','ㅸ'=>'ᄫ','ᇦ'=>'ᄫ','ㅹ'=>'ᄬ','ㅺ'=>'ᄭ','ᇧ'=>'ᄭ','ㅻ'=>'ᄮ','ㅼ'=>'ᄯ','ᇨ'=>'ᄯ','ᇩ'=>'ᄰ','ㅽ'=>'ᄲ','ᇪ'=>'ᄲ','ㅾ'=>'ᄶ','ㅿ'=>'ᅀ','ᇫ'=>'ᅀ','ᇬ'=>'ᅁ','ᇱ'=>'ᅅ','ㆂ'=>'ᅅ','ᇲ'=>'ᅆ','ㆃ'=>'ᅆ','ㆀ'=>'ᅇ','ᇮ'=>'ᅇ','ㆁ'=>'ᅌ','ᇰ'=>'ᅌ','ᇳ'=>'ᅖ','ㆄ'=>'ᅗ','ᇴ'=>'ᅗ','ㆅ'=>'ᅘ','ㆆ'=>'ᅙ','ᇹ'=>'ᅙ','ㅤ'=>'ᅠ','ᅠ'=>'ᅠ','ㅏ'=>'ᅡ','ᅡ'=>'ᅡ','ㅐ'=>'ᅢ','ᅢ'=>'ᅢ','ㅑ'=>'ᅣ','ᅣ'=>'ᅣ','ㅒ'=>'ᅤ','ᅤ'=>'ᅤ','ㅓ'=>'ᅥ','ᅥ'=>'ᅥ','ㅔ'=>'ᅦ','ᅦ'=>'ᅦ','ㅕ'=>'ᅧ','ᅧ'=>'ᅧ','ㅖ'=>'ᅨ','ᅨ'=>'ᅨ','ㅗ'=>'ᅩ','ᅩ'=>'ᅩ','ㅘ'=>'ᅪ','ᅪ'=>'ᅪ','ㅙ'=>'ᅫ','ᅫ'=>'ᅫ','ㅚ'=>'ᅬ','ᅬ'=>'ᅬ','ㅛ'=>'ᅭ','ᅭ'=>'ᅭ','ㅜ'=>'ᅮ','ᅮ'=>'ᅮ','ㅝ'=>'ᅯ','ᅯ'=>'ᅯ','ㅞ'=>'ᅰ','ᅰ'=>'ᅰ','ㅟ'=>'ᅱ','ᅱ'=>'ᅱ','ㅠ'=>'ᅲ','ᅲ'=>'ᅲ','ㅡ'=>'一','ᅳ'=>'一','ㅢ'=>'ᅴ','ᅴ'=>'ᅴ','ㅣ'=>'丨','ᅵ'=>'丨','ㆇ'=>'ᆄ','ᆆ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ㆍ'=>'ᆞ','ㆎ'=>'ᆡ','ㄳ'=>'ᆪ','ᆪ'=>'ᆪ','ㄵ'=>'ᆬ','ᆬ'=>'ᆬ','ㄶ'=>'ᆭ','ᆭ'=>'ᆭ','ㄺ'=>'ᆰ','ᆰ'=>'ᆰ','ㄻ'=>'ᆱ','ᆱ'=>'ᆱ','ㄼ'=>'ᆲ','ᆲ'=>'ᆲ','ㄽ'=>'ᆳ','ᆳ'=>'ᆳ','ㄾ'=>'ᆴ','ᆴ'=>'ᆴ','ㄿ'=>'ᆵ','ᆵ'=>'ᆵ','ㅧ'=>'ᇇ','ㅨ'=>'ᇈ','ㅩ'=>'ᇌ','ㅪ'=>'ᇎ','ㅫ'=>'ᇓ','ㅬ'=>'ᇗ','ㅭ'=>'ᇙ','ㅯ'=>'ᇝ','ㅰ'=>'ᇟ','ァ'=>'ァ','ア'=>'ア','ィ'=>'ィ','イ'=>'イ','ゥ'=>'ゥ','ウ'=>'ウ','ェ'=>'ェ','エ'=>'エ','ォ'=>'ォ','オ'=>'オ','カ'=>'カ','キ'=>'キ','ク'=>'ク','ケ'=>'ケ','コ'=>'コ','サ'=>'サ','シ'=>'シ','ス'=>'ス','セ'=>'セ','ソ'=>'ソ','タ'=>'タ','チ'=>'チ','ッ'=>'ッ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ナ'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ネ','ノ'=>'ノ','ハ'=>'ハ','ヒ'=>'ヒ','フ'=>'フ','ヘ'=>'へ','ホ'=>'ホ','マ'=>'マ','⧄'=>'〼','ミ'=>'ミ','ム'=>'ム','メ'=>'メ','モ'=>'モ','ャ'=>'ャ','ヤ'=>'ヤ','ュ'=>'ュ','ユ'=>'ユ','ョ'=>'ョ','ヨ'=>'ヨ','ラ'=>'ラ','リ'=>'リ','ル'=>'ル','レ'=>'レ','ロ'=>'ロ','ワ'=>'ワ','ヲ'=>'ヲ','ン'=>'ン','꒞'=>'ꁊ','꒬'=>'ꁐ','꒜'=>'ꃀ','꒿'=>'ꉙ','꒾'=>'ꊱ','꓀'=>'ꎫ','꓂'=>'ꎵ','꒺'=>'ꎿ','꒰'=>'ꏂ','𐒠'=>'𐒆','—'=>'一','―'=>'一','−'=>'一','─'=>'一','⼀'=>'一','不'=>'不','並'=>'並','|'=>'丨','|'=>'丨','∣'=>'丨','⼁'=>'丨','‖'=>'丨丨','∥'=>'丨丨','串'=>'串','⼂'=>'丶','丸'=>'丸','丹'=>'丹','丽'=>'丽','⼃'=>'丿','乁'=>'乁','⼄'=>'乙','亂'=>'亂','⼅'=>'亅','了'=>'了','⼆'=>'二','⼇'=>'亠','亮'=>'亮','⼈'=>'人','什'=>'什','仌'=>'仌','令'=>'令','你'=>'你','倂'=>'併','倂'=>'併','侀'=>'侀','來'=>'來','例'=>'例','侮'=>'侮','侮'=>'侮','侻'=>'侻','便'=>'便','值'=>'値','倫'=>'倫','偺'=>'偺','備'=>'備','像'=>'像','僚'=>'僚','僧'=>'僧','僧'=>'僧','⼉'=>'儿','兀'=>'兀','充'=>'充','免'=>'免','免'=>'免','兔'=>'兔','兤'=>'兤','⼊'=>'入','內'=>'內','全'=>'全','兩'=>'兩','⼋'=>'八','六'=>'六','具'=>'具','冀'=>'冀','⼌'=>'冂','再'=>'再','冒'=>'冒','冕'=>'冕','⼍'=>'冖','冗'=>'冗','冤'=>'冤','⼎'=>'冫','冬'=>'冬','况'=>'况','况'=>'况','冷'=>'冷','凉'=>'凉','凌'=>'凌','凜'=>'凜','凞'=>'凞','⼏'=>'几','凵'=>'凵','⼐'=>'凵','⼑'=>'刀','刃'=>'刃','切'=>'切','切'=>'切','列'=>'列','利'=>'利','刺'=>'刺','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','劉'=>'劉','力'=>'力','⼒'=>'力','劣'=>'劣','劳'=>'劳','勇'=>'勇','勇'=>'勇','勉'=>'勉','勉'=>'勉','勒'=>'勒','勞'=>'勞','勤'=>'勤','勤'=>'勤','勵'=>'勵','⼓'=>'勹','勺'=>'勺','勺'=>'勺','包'=>'包','匆'=>'匆','⼔'=>'匕','北'=>'北','北'=>'北','⼕'=>'匚','⼖'=>'匸','匿'=>'匿','⼗'=>'十','〸'=>'十','〹'=>'卄','〺'=>'卅','卉'=>'卉','卑'=>'卑','卑'=>'卑','博'=>'博','⼘'=>'卜','⼙'=>'卩','即'=>'即','卵'=>'卵','卽'=>'卽','卿'=>'卿','卿'=>'卿','卿'=>'卿','⼚'=>'厂','⼛'=>'厶','參'=>'參','⼜'=>'又','及'=>'及','叟'=>'叟','⼝'=>'口','句'=>'句','叫'=>'叫','叱'=>'叱','吆'=>'吆','吏'=>'吏','吝'=>'吝','吸'=>'吸','呂'=>'呂','呈'=>'呈','周'=>'周','咞'=>'咞','咢'=>'咢','咽'=>'咽','哶'=>'哶','唐'=>'唐','啓'=>'啓','啟'=>'啓','啕'=>'啕','啣'=>'啣','善'=>'善','善'=>'善','喇'=>'喇','喙'=>'喙','喙'=>'喙','喝'=>'喝','喝'=>'喝','喫'=>'喫','喳'=>'喳','嗀'=>'嗀','嗂'=>'嗂','嗢'=>'嗢','嘆'=>'嘆','嘆'=>'嘆','噑'=>'噑','器'=>'器','噴'=>'噴','⼞'=>'囗','囹'=>'囹','圖'=>'圖','圗'=>'圗','⼟'=>'土','型'=>'型','城'=>'城','埴'=>'埴','堍'=>'堍','報'=>'報','堲'=>'堲','塀'=>'塀','塚'=>'塚','塚'=>'塚','塞'=>'塞','填'=>'塡','墨'=>'墨','壿'=>'墫','墬'=>'墬','墳'=>'墳','壘'=>'壘','壟'=>'壟','⼠'=>'士','壮'=>'壮','売'=>'売','壷'=>'壷','⼡'=>'夂','夆'=>'夆','⼢'=>'夊','⼣'=>'夕','多'=>'多','夢'=>'夢','⼤'=>'大','奄'=>'奄','奈'=>'奈','契'=>'契','奔'=>'奔','奢'=>'奢','女'=>'女','⼥'=>'女','姘'=>'姘','姬'=>'姬','娛'=>'娛','娧'=>'娧','婢'=>'婢','婦'=>'婦','嬀'=>'媯','媵'=>'媵','嬈'=>'嬈','嬨'=>'嬨','嬾'=>'嬾','嬾'=>'嬾','⼦'=>'子','⼧'=>'宀','宅'=>'宅','寃'=>'寃','寘'=>'寘','寧'=>'寧','寧'=>'寧','寧'=>'寧','寮'=>'寮','寳'=>'寳','⼨'=>'寸','寿'=>'寿','将'=>'将','⼩'=>'小','尢'=>'尢','⼪'=>'尢','⼫'=>'尸','尿'=>'尿','屠'=>'屠','屢'=>'屢','層'=>'層','履'=>'履','屮'=>'屮','屮'=>'屮','⼬'=>'屮','⼭'=>'山','岍'=>'岍','峀'=>'峀','崙'=>'崙','嵃'=>'嵃','嵐'=>'嵐','嵫'=>'嵫','嵮'=>'嵮','嵼'=>'嵼','嶲'=>'嶲','嶺'=>'嶺','⼮'=>'巛','巡'=>'巡','巢'=>'巢','⼯'=>'工','⼰'=>'己','巽'=>'巽','⼱'=>'巾','帲'=>'帡','帨'=>'帨','帽'=>'帽','幩'=>'幩','⼲'=>'干','年'=>'年','⼳'=>'幺','⼴'=>'广','度'=>'度','庰'=>'庰','庳'=>'庳','庶'=>'庶','廉'=>'廉','廊'=>'廊','廊'=>'廊','廒'=>'廒','廓'=>'廓','廙'=>'廙','廬'=>'廬','⼵'=>'廴','廾'=>'廾','⼶'=>'廾','弄'=>'弄','⼷'=>'弋','⼸'=>'弓','弢'=>'弢','弢'=>'弢','⼹'=>'彐','当'=>'当','⼺'=>'彡','形'=>'形','彩'=>'彩','彫'=>'彫','⼻'=>'彳','律'=>'律','徚'=>'徚','復'=>'復','徭'=>'徭','⼼'=>'心','忍'=>'忍','志'=>'志','念'=>'念','忹'=>'忹','怒'=>'怒','怜'=>'怜','悁'=>'悁','悔'=>'悔','悔'=>'悔','惇'=>'惇','惘'=>'惘','惡'=>'惡','愈'=>'愈','慄'=>'慄','慈'=>'慈','慌'=>'慌','慌'=>'慌','慎'=>'慎','慎'=>'慎','慠'=>'慠','慨'=>'慨','慺'=>'慺','憎'=>'憎','憎'=>'憎','憎'=>'憎','憐'=>'憐','憤'=>'憤','憯'=>'憯','憲'=>'憲','懞'=>'懞','懲'=>'懲','懲'=>'懲','懲'=>'懲','懶'=>'懶','懶'=>'懶','戀'=>'戀','⼽'=>'戈','成'=>'成','戛'=>'戛','戮'=>'戮','戴'=>'戴','⼾'=>'戶','⼿'=>'手','扝'=>'扝','抱'=>'抱','拉'=>'拉','拏'=>'拏','拓'=>'拓','拔'=>'拔','拼'=>'拼','拾'=>'拾','挽'=>'挽','捐'=>'捐','捨'=>'捨','捻'=>'捻','掃'=>'掃','掠'=>'掠','掩'=>'掩','揄'=>'揄','揅'=>'揅','揤'=>'揤','㩁'=>'搉','搜'=>'搜','搢'=>'搢','摒'=>'摒','摩'=>'摩','摷'=>'摷','摾'=>'摾','撚'=>'撚','撝'=>'撝','擄'=>'擄','⽀'=>'支','⽁'=>'攴','敏'=>'敏','敏'=>'敏','敖'=>'敖','敬'=>'敬','數'=>'數','⽂'=>'文','⽃'=>'斗','料'=>'料','⽄'=>'斤','⽅'=>'方','旅'=>'旅','⽆'=>'无','既'=>'既','旣'=>'旣','⽇'=>'日','易'=>'易','晉'=>'晉','晩'=>'晚','䀿'=>'晣','晴'=>'晴','晴'=>'晴','暈'=>'暈','暑'=>'暑','暑'=>'暑','暜'=>'暜','暴'=>'暴','曆'=>'曆','⽈'=>'曰','更'=>'更','㫚'=>'曶','書'=>'書','最'=>'最','⽉'=>'月','肦'=>'朌','胐'=>'朏','胊'=>'朐','脁'=>'朓','朗'=>'朗','朗'=>'朗','朗'=>'朗','脧'=>'朘','望'=>'望','望'=>'望','朡'=>'朡','膧'=>'朣','⽊'=>'木','李'=>'李','杓'=>'杓','杖'=>'杖','杞'=>'杞','柿'=>'杮','杻'=>'杻','枅'=>'枅','林'=>'林','柳'=>'柳','柺'=>'柺','栗'=>'栗','栟'=>'栟','桒'=>'桒','梁'=>'梁','梅'=>'梅','梅'=>'梅','梎'=>'梎','梨'=>'梨','椔'=>'椔','楂'=>'楂','樧'=>'榝','榣'=>'榣','槪'=>'槪','樂'=>'樂','樂'=>'樂','樂'=>'樂','樓'=>'樓','檨'=>'檨','櫓'=>'櫓','櫛'=>'櫛','欄'=>'欄','⽋'=>'欠','次'=>'次','歔'=>'歔','⽌'=>'止','歲'=>'歲','歷'=>'歷','歹'=>'歹','⽍'=>'歹','殟'=>'殟','殮'=>'殮','⽎'=>'殳','殺'=>'殺','殺'=>'殺','殺'=>'殺','殻'=>'殻','⽏'=>'毋','⺟'=>'母','⽐'=>'比','⽑'=>'毛','⽒'=>'氏','⽓'=>'气','⽔'=>'水','汎'=>'汎','汧'=>'汧','沈'=>'沈','沿'=>'沿','泌'=>'泌','泍'=>'泍','泥'=>'泥','洖'=>'洖','洛'=>'洛','洞'=>'洞','洴'=>'洴','派'=>'派','流'=>'流','流'=>'流','流'=>'流','浩'=>'浩','浪'=>'浪','海'=>'海','海'=>'海','浸'=>'浸','涅'=>'涅','淋'=>'淋','淚'=>'淚','淪'=>'淪','淹'=>'淹','渚'=>'渚','港'=>'港','湮'=>'湮','潙'=>'溈','溜'=>'溜','溺'=>'溺','滇'=>'滇','滋'=>'滋','滋'=>'滋','滑'=>'滑','滛'=>'滛','漏'=>'漏','漢'=>'漢','漢'=>'漢','漣'=>'漣','潮'=>'潮','濆'=>'濆','濫'=>'濫','濾'=>'濾','瀛'=>'瀛','瀞'=>'瀞','瀞'=>'瀞','瀹'=>'瀹','灊'=>'灊','⽕'=>'火','灰'=>'灰','灷'=>'灷','災'=>'災','炙'=>'炙','炭'=>'炭','烈'=>'烈','烙'=>'烙','煅'=>'煅','煉'=>'煉','煮'=>'煮','煮'=>'煮','熜'=>'熜','燎'=>'燎','燐'=>'燐','爐'=>'爐','爛'=>'爛','爨'=>'爨','⽖'=>'爪','爫'=>'爫','⺤'=>'爫','爵'=>'爵','爵'=>'爵','⽗'=>'父','⽘'=>'爻','⽙'=>'爿','⽚'=>'片','牐'=>'牐','⽛'=>'牙','⽜'=>'牛','牢'=>'牢','犀'=>'犀','犕'=>'犕','⽝'=>'犬','犯'=>'犯','狀'=>'狀','狼'=>'狼','猪'=>'猪','猪'=>'猪','獵'=>'獵','獺'=>'獺','⽞'=>'玄','率'=>'率','率'=>'率','⽟'=>'玉','王'=>'王','玥'=>'玥','玲'=>'玲','珞'=>'珞','理'=>'理','琉'=>'琉','琢'=>'琢','瑇'=>'瑇','瑜'=>'瑜','瑩'=>'瑩','瑱'=>'瑱','瑱'=>'瑱','璅'=>'璅','璉'=>'璉','璘'=>'璘','瓊'=>'瓊','⽠'=>'瓜','⽡'=>'瓦','甆'=>'甆','⽢'=>'甘','⽣'=>'生','甤'=>'甤','⽤'=>'用','⽥'=>'田','画'=>'画','甾'=>'甾','留'=>'留','略'=>'略','異'=>'異','異'=>'異','⽦'=>'疋','⽧'=>'疒','痢'=>'痢','瘐'=>'瘐','瘝'=>'瘝','瘟'=>'瘟','療'=>'療','癩'=>'癩','⽨'=>'癶','⽩'=>'白','⽪'=>'皮','⽫'=>'皿','益'=>'益','益'=>'益','盛'=>'盛','盧'=>'盧','⽬'=>'目','直'=>'直','直'=>'直','省'=>'省','眞'=>'眞','真'=>'真','真'=>'真','着'=>'着','睊'=>'睊','睊'=>'睊','瞋'=>'瞋','瞧'=>'瞧','⽭'=>'矛','⽮'=>'矢','⽯'=>'石','硏'=>'研','硎'=>'硎','硫'=>'硫','碌'=>'碌','碌'=>'碌','碑'=>'碑','磊'=>'磊','磌'=>'磌','磌'=>'磌','磻'=>'磻','礪'=>'礪','⽰'=>'示','礼'=>'礼','社'=>'社','祈'=>'祈','祉'=>'祉','祐'=>'祐','祖'=>'祖','祖'=>'祖','祝'=>'祝','神'=>'神','祥'=>'祥','祿'=>'祿','禍'=>'禍','禎'=>'禎','福'=>'福','福'=>'福','禮'=>'禮','⽱'=>'禸','⽲'=>'禾','秊'=>'秊','秫'=>'秫','稜'=>'稜','穀'=>'穀','穀'=>'穀','穊'=>'穊','穏'=>'穏','⽳'=>'穴','突'=>'突','窱'=>'窱','立'=>'立','⽴'=>'立','竮'=>'竮','⽵'=>'竹','笠'=>'笠','節'=>'節','節'=>'節','篆'=>'篆','築'=>'築','簾'=>'簾','籠'=>'籠','⽶'=>'米','类'=>'类','粒'=>'粒','精'=>'精','糒'=>'糒','糖'=>'糖','糣'=>'糣','糧'=>'糧','糨'=>'糨','⽷'=>'糸','紀'=>'紀','紐'=>'紐','索'=>'索','累'=>'累','絶'=>'絕','絛'=>'絛','絣'=>'絣','綠'=>'綠','綾'=>'綾','緇'=>'緇','練'=>'練','練'=>'練','練'=>'練','縂'=>'縂','縉'=>'縉','縷'=>'縷','繁'=>'繁','繅'=>'繅','⽸'=>'缶','缾'=>'缾','⽹'=>'网','⺫'=>'罒','署'=>'署','罹'=>'罹','罺'=>'罺','羅'=>'羅','⽺'=>'羊','羕'=>'羕','羚'=>'羚','羽'=>'羽','⽻'=>'羽','翺'=>'翺','老'=>'老','⽼'=>'老','者'=>'者','者'=>'者','者'=>'者','⽽'=>'而','⽾'=>'耒','⽿'=>'耳','聆'=>'聆','聠'=>'聠','聯'=>'聯','聰'=>'聰','聾'=>'聾','⾀'=>'聿','⾁'=>'肉','肋'=>'肋','肭'=>'肭','育'=>'育','㬵'=>'胶','腁'=>'胼','脃'=>'脃','脾'=>'脾','臘'=>'臘','⾂'=>'臣','臨'=>'臨','⾃'=>'自','臭'=>'臭','⾄'=>'至','⾅'=>'臼','舁'=>'舁','舁'=>'舁','舄'=>'舄','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','良'=>'良','⾊'=>'色','⾋'=>'艸','艹'=>'艹','艹'=>'艹','芋'=>'芋','芑'=>'芑','芝'=>'芝','花'=>'花','芳'=>'芳','芽'=>'芽','若'=>'若','若'=>'若','苦'=>'苦','茝'=>'茝','茣'=>'茣','茶'=>'茶','荒'=>'荒','荓'=>'荓','荣'=>'荣','莭'=>'莭','莽'=>'莽','菉'=>'菉','菊'=>'菊','菌'=>'菌','菜'=>'菜','菧'=>'菧','華'=>'華','菱'=>'菱','落'=>'落','葉'=>'葉','著'=>'著','著'=>'著','蔿'=>'蒍','蓮'=>'蓮','蓱'=>'蓱','蓳'=>'蓳','蓼'=>'蓼','蔖'=>'蔖','蕤'=>'蕤','藍'=>'藍','藺'=>'藺','蘆'=>'蘆','蘒'=>'蘒','蘭'=>'蘭','虁'=>'蘷','蘿'=>'蘿','⾌'=>'虍','虐'=>'虐','虜'=>'虜','虜'=>'虜','虧'=>'虧','虩'=>'虩','⾍'=>'虫','蚈'=>'蚈','蚩'=>'蚩','蛢'=>'蛢','蜎'=>'蜎','蜨'=>'蜨','蝫'=>'蝫','蝹'=>'蝹','蝹'=>'蝹','螆'=>'螆','螺'=>'螺','蟡'=>'蟡','蠁'=>'蠁','蠟'=>'蠟','⾎'=>'血','行'=>'行','⾏'=>'行','衠'=>'衠','衣'=>'衣','⾐'=>'衣','裂'=>'裂','裏'=>'裏','裗'=>'裗','裞'=>'裞','裡'=>'裡','裸'=>'裸','裺'=>'裺','褐'=>'褐','襁'=>'襁','襤'=>'襤','⾑'=>'襾','覆'=>'覆','見'=>'見','⾒'=>'見','視'=>'視','視'=>'視','⾓'=>'角','⾔'=>'言','䚶'=>'訞','詽'=>'訮','誠'=>'誠','說'=>'說','說'=>'說','調'=>'調','請'=>'請','諒'=>'諒','論'=>'論','諭'=>'諭','諭'=>'諭','諸'=>'諸','諸'=>'諸','諾'=>'諾','諾'=>'諾','謁'=>'謁','謁'=>'謁','謹'=>'謹','謹'=>'謹','識'=>'識','讀'=>'讀','讏'=>'讆','變'=>'變','變'=>'變','⾕'=>'谷','⾖'=>'豆','豈'=>'豈','豕'=>'豕','⾗'=>'豕','⾘'=>'豸','⾙'=>'貝','貫'=>'貫','賁'=>'賁','賂'=>'賂','賈'=>'賈','賓'=>'賓','贈'=>'贈','贈'=>'贈','贛'=>'贛','⾚'=>'赤','⾛'=>'走','起'=>'起','趆'=>'赿','⾜'=>'足','趼'=>'趼','跋'=>'跋','跺'=>'跥','路'=>'路','跰'=>'跰','躛'=>'躗','⾝'=>'身','車'=>'車','⾞'=>'車','軔'=>'軔','輧'=>'軿','輦'=>'輦','輪'=>'輪','輸'=>'輸','輸'=>'輸','輻'=>'輻','轢'=>'轢','⾟'=>'辛','辞'=>'辞','辰'=>'辰','⾠'=>'辰','⾡'=>'辵','辶'=>'辶','⻌'=>'辶','連'=>'連','逸'=>'逸','逸'=>'逸','遲'=>'遲','遼'=>'遼','邏'=>'邏','⾢'=>'邑','邔'=>'邔','郎'=>'郎','郱'=>'郱','都'=>'都','鄑'=>'鄑','鄛'=>'鄛','⾣'=>'酉','酪'=>'酪','醙'=>'醙','醴'=>'醴','⾤'=>'釆','里'=>'里','⾥'=>'里','量'=>'量','金'=>'金','⾦'=>'金','鈴'=>'鈴','鈸'=>'鈸','鉶'=>'鉶','鉼'=>'鉼','鋗'=>'鋗','鋘'=>'鋘','錄'=>'錄','鍊'=>'鍊','鎮'=>'鎭','鏹'=>'鏹','鐕'=>'鐕','⾧'=>'長','⾨'=>'門','開'=>'開','閭'=>'閭','閷'=>'閷','⾩'=>'阜','阮'=>'阮','陋'=>'陋','降'=>'降','陵'=>'陵','陸'=>'陸','陼'=>'陼','隆'=>'隆','隣'=>'隣','⾪'=>'隶','隸'=>'隸','⾫'=>'隹','雃'=>'雃','離'=>'離','難'=>'難','難'=>'難','⾬'=>'雨','零'=>'零','雷'=>'雷','霣'=>'霣','露'=>'露','靈'=>'靈','⾭'=>'靑','靖'=>'靖','靖'=>'靖','⾮'=>'非','⾯'=>'面','⾰'=>'革','⾱'=>'韋','韛'=>'韛','韠'=>'韠','⾲'=>'韭','⾳'=>'音','響'=>'響','響'=>'響','⾴'=>'頁','頋'=>'頋','頋'=>'頋','頋'=>'頋','領'=>'領','頩'=>'頩','頻'=>'頻','頻'=>'頻','類'=>'類','⾵'=>'風','⾶'=>'飛','⻝'=>'食','⾷'=>'食','飢'=>'飢','飯'=>'飯','飼'=>'飼','館'=>'館','餩'=>'餩','⾸'=>'首','⾹'=>'香','馧'=>'馧','⾺'=>'馬','駂'=>'駂','駱'=>'駱','駾'=>'駾','驪'=>'驪','⾻'=>'骨','⾼'=>'高','⾽'=>'髟','鬒'=>'鬒','鬒'=>'鬒','⾾'=>'鬥','⾿'=>'鬯','⿀'=>'鬲','⿁'=>'鬼','⿂'=>'魚','魯'=>'魯','鱀'=>'鱀','鱗'=>'鱗','⿃'=>'鳥','鳽'=>'鳽','鵧'=>'鵧','鶴'=>'鶴','鷺'=>'鷺','鸞'=>'鸞','鹃'=>'鹂','⿄'=>'鹵','鹿'=>'鹿','⿅'=>'鹿','麗'=>'麗','麟'=>'麟','⿆'=>'麥','麻'=>'麻','⿇'=>'麻','⿈'=>'黃','⿉'=>'黍','黎'=>'黎','⿊'=>'黑','黹'=>'黹','⿋'=>'黹','⿌'=>'黽','黾'=>'黾','鼅'=>'鼅','⿍'=>'鼎','鼏'=>'鼏','⿎'=>'鼓','鼖'=>'鼖','⿏'=>'鼠','鼻'=>'鼻','⿐'=>'鼻','齃'=>'齃','⿑'=>'齊','⿒'=>'齒','龍'=>'龍','⿓'=>'龍','龎'=>'龎','龜'=>'龜','龜'=>'龜','龜'=>'龜','⿔'=>'龜','⻳'=>'龟','⿕'=>'龠','㒞'=>'㒞','㒹'=>'㒹','㒻'=>'㒻','㓟'=>'㓟','㔕'=>'㔕','䎛'=>'㖈','㛮'=>'㛮','㛼'=>'㛼','㞁'=>'㞁','㠯'=>'㠯','㡢'=>'㡢','㡼'=>'㡼','㣇'=>'㣇','㣣'=>'㣣','㤜'=>'㤜','㤺'=>'㤺','㨮'=>'㨮','㩬'=>'㩬','㫤'=>'㫤','㬈'=>'㬈','㬙'=>'㬙','䐠'=>'㬻','㭉'=>'㭉','㮝'=>'㮝','㮝'=>'㮝','㰘'=>'㰘','㱎'=>'㱎','㴳'=>'㴳','㶖'=>'㶖','㺬'=>'㺬','㺸'=>'㺸','㺸'=>'㺸','㼛'=>'㼛','㿼'=>'㿼','䀈'=>'䀈','䀘'=>'䀘','䀹'=>'䀹','䀹'=>'䀹','䁆'=>'䁆','䂖'=>'䂖','䃣'=>'䃣','䄯'=>'䄯','䈂'=>'䈂','䈧'=>'䈧','䊠'=>'䊠','䌁'=>'䌁','䌴'=>'䌴','䍙'=>'䍙','䏕'=>'䏕','䏙'=>'䏙','䐋'=>'䐋','䑫'=>'䑫','䔫'=>'䔫','䕝'=>'䕝','䕡'=>'䕡','䕫'=>'䕫','䗗'=>'䗗','䗹'=>'䗹','䘵'=>'䘵','䚾'=>'䚾','䛇'=>'䛇','䦕'=>'䦕','䧦'=>'䧦','䩮'=>'䩮','䩶'=>'䩶','䪲'=>'䪲','䬳'=>'䬳','䯎'=>'䯎','䳎'=>'䳎','䳭'=>'䳭','䳸'=>'䳸','䵖'=>'䵖','𠄢'=>'𠄢','𠔜'=>'𠔜','𠔥'=>'𠔥','𠕋'=>'𠕋','𠘺'=>'𠘺','𠠄'=>'𠠄','𠣞'=>'𠣞','𠨬'=>'𠨬','𠭣'=>'𠭣','𡓤'=>'𡓤','𡚨'=>'𡚨','𡛪'=>'𡛪','𡧈'=>'𡧈','𡬘'=>'𡬘','𡴋'=>'𡴋','𡷤'=>'𡷤','𡷦'=>'𡷦','𢆃'=>'𢆃','𢆟'=>'𢆟','𢌱'=>'𢌱','𢌱'=>'𢌱','𢛔'=>'𢛔','𢡄'=>'𢡄','𢡊'=>'𢡊','𢬌'=>'𢬌','𢯱'=>'𢯱','𣀊'=>'𣀊','𣊸'=>'𣊸','𣍟'=>'𣍟','𣎓'=>'𣎓','𣎜'=>'𣎜','𣏃'=>'𣏃','𣏕'=>'𣏕','𣑭'=>'𣑭','𣚣'=>'𣚣','𣢧'=>'𣢧','𣪍'=>'𣪍','𣫺'=>'𣫺','𣲼'=>'𣲼','𣴞'=>'𣴞','𣻑'=>'𣻑','𣽞'=>'𣽞','𣾎'=>'𣾎','𤉣'=>'𤉣','𤎫'=>'𤎫','𤘈'=>'𤘈','𤜵'=>'𤜵','𤠔'=>'𤠔','𤰶'=>'𤰶','𤲒'=>'𤲒','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'𥁄','𥃲'=>'𥃲','𥃳'=>'𥃳','𥄙'=>'𥄙','𥄳'=>'𥄳','𥉉'=>'𥉉','𥐝'=>'𥐝','𥘦'=>'𥘦','𥚚'=>'𥚚','𥛅'=>'𥛅','𥥼'=>'𥥼','𥪧'=>'𥪧','𥪧'=>'𥪧','𥮫'=>'𥮫','𥲀'=>'𥲀','𥳐'=>'𥳐','𥾆'=>'𥾆','𦇚'=>'𦇚','𦈨'=>'𦈨','𦉇'=>'𦉇','𦋙'=>'𦋙','𦌾'=>'𦌾','𦓚'=>'𦓚','𦔣'=>'𦔣','𦖨'=>'𦖨','𦞧'=>'𦞧','𦞵'=>'𦞵','𦬼'=>'𦬼','𦰶'=>'𦰶','𦳕'=>'𦳕','𦵫'=>'𦵫','𦼬'=>'𦼬','𦾱'=>'𦾱','𧃒'=>'𧃒','𧏊'=>'𧏊','𧙧'=>'𧙧','𧢮'=>'𧢮','𧥦'=>'𧥦','𧲨'=>'𧲨','𧻓'=>'𧻓','𧼯'=>'𧼯','𨗒'=>'𨗒','𨗭'=>'𨗭','𨜮'=>'𨜮','𨯺'=>'𨯺','𨵷'=>'𨵷','𩅅'=>'𩅅','𩇟'=>'𩇟','𩈚'=>'𩈚','𩐊'=>'𩐊','𩒖'=>'𩒖','𩖶'=>'𩖶','𩬰'=>'𩬰','𪃎'=>'𪃎','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','𪎒'=>'𪎒','𪘀'=>'𪘀','℃'=>'°C','℉'=>'°F','ℇ'=>'Ɛ','℻'=>'FAX','ℕ'=>'N','№'=>'No','ℚ'=>'Q','₨'=>'Rs','𝐓'=>'T','℡'=>'TEL','𝐔'=>'U','𝐖'=>'W','₩'=>'W̵','𝐗'=>'X','¥'=>'Y̵','𝚲'=>'Λ','𝚵'=>'Ξ','ℿ'=>'Π','ϲ'=>'c','ϒ'=>'Y','𝚽'=>'Φ','𝚿'=>'Ψ','ѣ'=>'Ь̵','ਃ'=>'ঃ','ಃ'=>'ః','່'=>'่','់'=>'่','້'=>'้','໊'=>'๊','໋'=>'๋','៕'=>'๚','៚'=>'๛','ъ'=>'ˉb','៙'=>'๏','೧'=>'౧','૨'=>'२','೨'=>'౨','૩'=>'३','૪'=>'४','૮'=>'८','೯'=>'౯','а'=>'a','Ꮟ'=>'b','ᖯ'=>'b','с'=>'c','ԁ'=>'d','ᑯ'=>'d','е'=>'e','ә'=>'ǝ','ε'=>'ɛ','є'=>'ɛ','ք'=>'f','ց'=>'g','һ'=>'h','հ'=>'h','Ꮒ'=>'h','Ᏺ'=>'h̔','ι'=>'i','і'=>'i','Ꭵ'=>'i','ј'=>'j','յ'=>'j','ᗰ'=>'m','ո'=>'n','η'=>'n̩','ం'=>'o','ಂ'=>'o','ം'=>'o','०'=>'o','੦'=>'o','૦'=>'o','๐'=>'o','໐'=>'o','ο'=>'o','о'=>'o','օ'=>'o','ဝ'=>'o','ρ'=>'p','р'=>'p','ᴩ'=>'ᴘ','գ'=>'q','κ'=>'ĸ','к'=>'ĸ','ᴦ'=>'r','г'=>'r','ѕ'=>'s','υ'=>'u','ս'=>'u','ν'=>'v','ѵ'=>'v','Ꮃ'=>'w','ᗯ'=>'w','х'=>'x','ᕁ'=>'x','у'=>'y','Ꭹ'=>'y','ӡ'=>'ʒ','ჳ'=>'ʒ','ϩ'=>'ƨ','ь'=>'ƅ','ы'=>'ƅi','ɑ'=>'α','ծ'=>'δ','ᕷ'=>'δ','п'=>'π','ɸ'=>'φ','ф'=>'φ','ʙ'=>'в','ɜ'=>'з','ᴍ'=>'м','ʜ'=>'н','ɢ'=>'ԍ','ᴛ'=>'т','ᴙ'=>'я','ઽ'=>'ऽ','ુ'=>'ु','ૂ'=>'ू','ੋ'=>'ॆ','੍'=>'्','્'=>'्','ഉ'=>'உ','ജ'=>'ஐ','ണ'=>'ண','ഴ'=>'ழ','ി'=>'ி','ു'=>'ூ','ಅ'=>'అ','ಆ'=>'ఆ','ಇ'=>'ఇ','ಒ'=>'ఒ','ಓ'=>'ఒౕ','ಜ'=>'జ','ಞ'=>'ఞ','ಣ'=>'ణ','థ'=>'ధּ','ಯ'=>'య','ఠ'=>'రּ','ಱ'=>'ఱ','ಲ'=>'ల','ඌ'=>'ന്ന','ஶ'=>'ശ','ຈ'=>'จ','ບ'=>'บ','ປ'=>'ป','ຝ'=>'ฝ','ພ'=>'พ','ຟ'=>'ฟ','ຍ'=>'ย','។'=>'ฯ','ិ'=>'ิ','ី'=>'ี','ឹ'=>'ึ','ឺ'=>'ื','ຸ'=>'ุ','ູ'=>'ู','ᗅ'=>'A','ᒍ'=>'J','ᕼ'=>'H','ᐯ'=>'V','ᑭ'=>'P','ᗷ'=>'B','ヘ'=>'へ','𐏑'=>'𐎂','𐏓'=>'𐎓','𒀸'=>'𐎚','ᅳ'=>'一','ǀ'=>'丨','ᅵ'=>'丨','Ꭺ'=>'A','Ᏼ'=>'B','Ꮯ'=>'C','ᗞ'=>'D','Ꭼ'=>'E','ᖴ'=>'F','Ꮐ'=>'G','Ꮋ'=>'H','Ꭻ'=>'J','Ꮶ'=>'K','Ꮮ'=>'L','Ꮇ'=>'M','Ꮲ'=>'P','ᖇ'=>'R','Ꮥ'=>'S','Ꮩ'=>'V','Ꮓ'=>'Z');
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
new file mode 100644
index 0000000000..7ba11c37c4
--- /dev/null
+++ b/phpBB/install/database_update.php
@@ -0,0 +1,267 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+$update_start_time = time();
+
+/**
+* @ignore
+*/
+define('IN_PHPBB', true);
+define('IN_INSTALL', true);
+$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
+$phpEx = substr(strrchr(__FILE__, '.'), 1);
+
+function phpbb_end_update($cache, $config)
+{
+ $cache->purge();
+
+ $config->increment('assets_version', 1);
+
+?>
+ </p>
+ </div>
+ </div>
+ <span class="corners-bottom"><span></span></span>
+ </div>
+ </div>
+ </div>
+
+ <div id="page-footer">
+ <div class="copyright">
+ Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
+ </div>
+ </div>
+ </div>
+</body>
+</html>
+
+<?php
+
+ garbage_collection();
+ exit_handler();
+}
+
+require($phpbb_root_path . 'includes/startup.' . $phpEx);
+require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
+
+$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
+$phpbb_class_loader->register();
+
+$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
+extract($phpbb_config_php_file->get_all());
+
+if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
+{
+ die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
+}
+
+// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
+$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
+$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
+
+// Include files
+require($phpbb_root_path . 'includes/functions.' . $phpEx);
+require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
+
+require($phpbb_root_path . 'includes/constants.' . $phpEx);
+require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
+
+// Set PHP error handler to ours
+set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
+
+// Set up container (must be done here because extensions table may not exist)
+$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+$phpbb_container = $phpbb_container_builder
+ ->with_config($phpbb_config_php_file)
+ ->without_extensions()
+ ->without_cache()
+ ->get_container()
+;
+
+// set up caching
+/* @var $cache \phpbb\cache\service */
+$cache = $phpbb_container->get('cache');
+
+// Instantiate some basic classes
+/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
+$phpbb_dispatcher = $phpbb_container->get('dispatcher');
+
+/* @var $request \phpbb\request\request_interface */
+$request = $phpbb_container->get('request');
+
+/* @var $user \phpbb\user */
+$user = $phpbb_container->get('user');
+
+/* @var $auth \phpbb\auth\auth */
+$auth = $phpbb_container->get('auth');
+
+/* @var $db \phpbb\db\driver\driver_interface */
+$db = $phpbb_container->get('dbal.conn');
+
+/* @var $phpbb_log \phpbb\log\log_interface */
+$phpbb_log = $phpbb_container->get('log');
+
+// Grab global variables, re-cache if necessary
+/* @var $config \phpbb\config\config */
+$config = $phpbb_container->get('config');
+
+if (!isset($config['version_update_from']))
+{
+ $config->set('version_update_from', $config['version']);
+}
+
+$orig_version = $config['version_update_from'];
+
+$user->add_lang(array('common', 'acp/common', 'old_install', 'migrator'));
+
+// Add own hook handler, if present. :o
+if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
+{
+ require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
+ $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
+
+ /* @var $phpbb_hook_finder \phpbb\hook\finder */
+ $phpbb_hook_finder = $phpbb_container->get('hook_finder');
+ foreach ($phpbb_hook_finder->find() as $hook)
+ {
+ @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
+ }
+}
+else
+{
+ $phpbb_hook = false;
+}
+
+header('Content-type: text/html; charset=UTF-8');
+?>
+<!DOCTYPE html>
+<html dir="<?php echo $user->lang['DIRECTION']; ?>" lang="<?php echo $user->lang['USER_LANG']; ?>">
+<head>
+<meta charset="utf-8">
+
+<title><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></title>
+
+<link href="<?php echo htmlspecialchars($phpbb_admin_path); ?>style/admin.css" rel="stylesheet" type="text/css" media="screen" />
+
+</head>
+
+<body>
+ <div id="wrap">
+ <div id="page-header">&nbsp;</div>
+
+ <div id="page-body">
+ <div id="acp">
+ <div class="panel">
+ <span class="corners-top"><span></span></span>
+ <div id="content">
+ <div id="main" class="install-body">
+
+ <h1><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
+
+ <br />
+
+ <p><?php echo $user->lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->get_sql_layer(); ?></strong><br />
+ <?php echo $user->lang['PREVIOUS_VERSION']; ?> :: <strong><?php echo $config['version']; ?></strong><br />
+
+<?php
+
+define('IN_DB_UPDATE', true);
+
+/**
+* @todo mysql update?
+*/
+
+// End startup code
+
+/* @var $migrator \phpbb\db\migrator */
+$migrator = $phpbb_container->get('migrator');
+
+/** @var \phpbb\filesystem\filesystem_interface $phpbb_filesystem */
+$phpbb_filesystem = $phpbb_container->get('filesystem');
+$migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($user, new \phpbb\db\html_migrator_output_handler($user), $phpbb_root_path . 'store/migrations_' . time() . '.log', $phpbb_filesystem));
+
+$migrator->create_migrations_table();
+
+/* @var $phpbb_extension_manager \phpbb\extension\manager */
+$phpbb_extension_manager = $phpbb_container->get('ext.manager');
+
+$migrations = $phpbb_extension_manager
+ ->get_finder()
+ ->core_path('phpbb/db/migration/data/')
+ ->extension_directory('/migrations')
+ ->get_classes();
+
+$migrator->set_migrations($migrations);
+
+// What is a safe limit of execution time? Half the max execution time should be safe.
+// No more than 15 seconds so the user isn't sitting and waiting for a very long time
+$phpbb_ini = new \phpbb\php\ini();
+$safe_time_limit = min(15, ($phpbb_ini->get_int('max_execution_time') / 2));
+
+// While we're going to try limit this to half the max execution time,
+// we want to try and take additional measures to prevent hitting the
+// max execution time (if, say, one migration step takes much longer
+// than the max execution time)
+@set_time_limit(0);
+
+while (!$migrator->finished())
+{
+ try
+ {
+ $migrator->update();
+ }
+ catch (\phpbb\db\migration\exception $e)
+ {
+ echo $e->getLocalisedMessage($user);
+
+ phpbb_end_update($cache, $config);
+ }
+
+ $state = array_merge(array(
+ 'migration_schema_done' => false,
+ 'migration_data_done' => false,
+ ),
+ $migrator->last_run_migration['state']
+ );
+
+ // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
+ if ((time() - $update_start_time) >= $safe_time_limit)
+ {
+ echo '<br />' . $user->lang['DATABASE_UPDATE_NOT_COMPLETED'] . '<br /><br />';
+ echo '<a href="' . append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=' . $request->variable('type', 0) . '&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['DATABASE_UPDATE_CONTINUE'] . '</a>';
+
+ phpbb_end_update($cache, $config);
+ }
+}
+
+if ($orig_version != $config['version'])
+{
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_DATABASE', false, array($orig_version, $config['version']));
+}
+
+echo $user->lang['DATABASE_UPDATE_COMPLETE'] . '<br />';
+
+if ($request->variable('type', 0))
+{
+ echo $user->lang['INLINE_UPDATE_SUCCESSFUL'] . '<br /><br />';
+ echo '<a href="' . append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update&amp;sub=update_db&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['CONTINUE_UPDATE_NOW'] . '</a>';
+}
+else
+{
+ echo '<div class="errorbox">' . $user->lang['UPDATE_FILES_NOTICE'] . '</div>';
+ echo $user->lang['COMPLETE_LOGIN_TO_BOARD'];
+}
+
+$config->delete('version_update_from');
+
+phpbb_end_update($cache, $config);
diff --git a/phpBB/install/index.php b/phpBB/install/index.php
new file mode 100644
index 0000000000..a1a8fc02b6
--- /dev/null
+++ b/phpBB/install/index.php
@@ -0,0 +1,867 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**#@+
+* @ignore
+*/
+define('IN_PHPBB', true);
+define('IN_INSTALL', true);
+define('PHPBB_ENVIRONMENT', 'production');
+/**#@-*/
+
+$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
+$phpEx = substr(strrchr(__FILE__, '.'), 1);
+
+if (version_compare(PHP_VERSION, '5.3.9') < 0)
+{
+ die('You are running an unsupported PHP version. Please upgrade to PHP 5.3.9 or higher before trying to install phpBB 3.1');
+}
+
+function phpbb_require_updated($path, $optional = false)
+{
+ global $phpbb_root_path, $table_prefix;
+
+ $new_path = $phpbb_root_path . 'install/update/new/' . $path;
+ $old_path = $phpbb_root_path . $path;
+
+ if (file_exists($new_path))
+ {
+ require($new_path);
+ }
+ else if (!$optional || file_exists($old_path))
+ {
+ require($old_path);
+ }
+}
+
+function phpbb_include_updated($path, $optional = false)
+{
+ global $phpbb_root_path;
+
+ $new_path = $phpbb_root_path . 'install/update/new/' . $path;
+ $old_path = $phpbb_root_path . $path;
+
+ if (file_exists($new_path))
+ {
+ include($new_path);
+ }
+ else if (!$optional || file_exists($old_path))
+ {
+ include($old_path);
+ }
+}
+
+phpbb_require_updated('includes/startup.' . $phpEx);
+
+// Try to override some limits - maybe it helps some...
+@set_time_limit(0);
+$mem_limit = @ini_get('memory_limit');
+if (!empty($mem_limit))
+{
+ $unit = strtolower(substr($mem_limit, -1, 1));
+ $mem_limit = (int) $mem_limit;
+
+ if ($unit == 'k')
+ {
+ $mem_limit = floor($mem_limit / 1024);
+ }
+ else if ($unit == 'g')
+ {
+ $mem_limit *= 1024;
+ }
+ else if (is_numeric($unit))
+ {
+ $mem_limit = floor((int) ($mem_limit . $unit) / 1048576);
+ }
+ $mem_limit = max(128, $mem_limit) . 'M';
+}
+else
+{
+ $mem_limit = '128M';
+}
+@ini_set('memory_limit', $mem_limit);
+
+// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
+$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
+$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
+
+// Include essential scripts
+phpbb_require_updated('phpbb/class_loader.' . $phpEx);
+
+phpbb_require_updated('includes/functions.' . $phpEx);
+
+phpbb_require_updated('includes/functions_content.' . $phpEx, true);
+
+phpbb_include_updated('includes/functions_admin.' . $phpEx);
+phpbb_include_updated('includes/utf/utf_tools.' . $phpEx);
+phpbb_require_updated('includes/functions_install.' . $phpEx);
+
+// Setup class loader first
+$phpbb_class_loader_new = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}install/update/new/phpbb/", $phpEx);
+$phpbb_class_loader_new->register();
+$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
+$phpbb_class_loader->register();
+$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
+$phpbb_class_loader_ext->register();
+
+// Set up container
+$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
+$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+$phpbb_container_builder
+ ->without_extensions()
+ ->without_cache()
+ ->without_compiled_container()
+;
+
+$other_config_path = $phpbb_root_path . 'install/update/new/config/';
+$config_path = file_exists($other_config_path . 'services.yml') ? $other_config_path : $phpbb_root_path . 'config/';
+$phpbb_container_builder->with_config_path($config_path);
+
+$phpbb_container_builder->with_custom_parameters(array(
+ 'core.root_path' => $phpbb_root_path,
+ 'core.adm_relative_path' => $phpbb_adm_relative_path,
+ 'core.php_ext' => $phpEx,
+ 'core.table_prefix' => '',
+ 'cache.driver.class' => 'phpbb\cache\driver\file',
+));
+
+$phpbb_container = $phpbb_container_builder->get_container();
+$phpbb_container->register('dbal.conn.driver')->setSynthetic(true);
+$phpbb_container->register('template.twig.environment')->setSynthetic(true);
+$phpbb_container->register('language.loader')->setSynthetic(true);
+$phpbb_container->compile();
+
+$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
+$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
+
+/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
+$phpbb_dispatcher = $phpbb_container->get('dispatcher');
+
+/* @var $request \phpbb\request\request_interface */
+$request = $phpbb_container->get('request');
+
+// Try and load an appropriate language if required
+$language = basename($request->variable('language', ''));
+
+if ($request->header('Accept-Language') && !$language)
+{
+ $accept_lang_ary = explode(',', strtolower($request->header('Accept-Language')));
+ foreach ($accept_lang_ary as $accept_lang)
+ {
+ // Set correct format ... guess full xx_yy form
+ $accept_lang = substr($accept_lang, 0, 2) . '_' . substr($accept_lang, 3, 2);
+
+ if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
+ {
+ $language = $accept_lang;
+ break;
+ }
+ else
+ {
+ // No match on xx_yy so try xx
+ $accept_lang = substr($accept_lang, 0, 2);
+ if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
+ {
+ $language = $accept_lang;
+ break;
+ }
+ }
+ }
+}
+
+// No appropriate language found ... so let's use the first one in the language
+// dir, this may or may not be English
+if (!$language)
+{
+ $dir = @opendir($phpbb_root_path . 'language');
+
+ if (!$dir)
+ {
+ die('Unable to access the language directory');
+ exit;
+ }
+
+ while (($file = readdir($dir)) !== false)
+ {
+ $path = $phpbb_root_path . 'language/' . $file;
+
+ if (!is_file($path) && !is_link($path) && file_exists($path . '/iso.txt'))
+ {
+ $language = $file;
+ break;
+ }
+ }
+ closedir($dir);
+}
+
+if (!file_exists($phpbb_root_path . 'language/' . $language) || !is_dir($phpbb_root_path . 'language/' . $language))
+{
+ die('No language found!');
+}
+
+// And finally, load the relevant language files
+$load_lang_files = array('common', 'acp/common', 'acp/board', 'old_install', 'posting');
+$new_path = $phpbb_root_path . 'install/update/new/language/' . $language . '/';
+$old_path = $phpbb_root_path . 'language/' . $language . '/';
+
+// NOTE: we can not use "phpbb_include_updated" as the files uses vars which would be required
+// to be global while loading.
+foreach ($load_lang_files as $lang_file)
+{
+ if (file_exists($new_path . $lang_file . '.' . $phpEx))
+ {
+ include($new_path . $lang_file . '.' . $phpEx);
+ }
+ else
+ {
+ include($old_path . $lang_file . '.' . $phpEx);
+ }
+}
+
+// usually we would need every single constant here - and it would be consistent. For 3.0.x, use a dirty hack... :(
+
+// Define needed constants
+define('CHMOD_ALL', 7);
+define('CHMOD_READ', 4);
+define('CHMOD_WRITE', 2);
+define('CHMOD_EXECUTE', 1);
+
+$mode = $request->variable('mode', 'overview');
+$sub = $request->variable('sub', '');
+
+// Set PHP error handler to ours
+set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
+
+$lang_service = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+$user = new \phpbb\user($lang_service, '\phpbb\datetime');
+$auth = new \phpbb\auth\auth();
+
+// Add own hook handler, if present. :o
+if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
+{
+ require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
+ $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
+
+ /* @var $phpbb_hook_finder \phpbb\hook\finder */
+ $phpbb_hook_finder = $phpbb_container->get('hook_finder');
+ foreach ($phpbb_hook_finder->find() as $hook)
+ {
+ @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
+ }
+}
+else
+{
+ $phpbb_hook = false;
+}
+
+// Set some standard variables we want to force
+$config = new \phpbb\config\config(array(
+ 'load_tplcompile' => '1'
+));
+
+/* @var $symfony_request \phpbb\symfony_request */
+$symfony_request = $phpbb_container->get('symfony_request');
+
+/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */
+$phpbb_filesystem = $phpbb_container->get('filesystem');
+
+/* @var $phpbb_path_helper \phpbb\path_helper */
+$phpbb_path_helper = $phpbb_container->get('path_helper');
+$cache_path = $phpbb_root_path . 'cache/';
+
+$twig_environment = new \phpbb\template\twig\environment(
+ $config,
+ $phpbb_filesystem,
+ $phpbb_path_helper,
+ $phpbb_container,
+ $cache_path,
+ null,
+ $phpbb_container->get('template.twig.loader')
+);
+
+$language_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
+$phpbb_container->set('template.twig.environment', $twig_environment);
+$phpbb_container->set('language.loader', $language_loader);
+$twig_context = new \phpbb\template\context();
+$template = new \phpbb\template\twig\twig(
+ $phpbb_path_helper,
+ $config,
+ $twig_context,
+ $twig_environment,
+ $cache_path,
+ $user,
+ array($phpbb_container->get('template.twig.extensions.phpbb'))
+);
+
+$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
+$paths = array_filter($paths, 'is_dir');
+$template->set_custom_style(array(
+ array(
+ 'name' => 'adm',
+ 'ext_path' => 'adm/style/',
+ ),
+), $paths);
+
+$path = array_shift($paths);
+
+$template->assign_var('T_ASSETS_PATH', $path . '/../../assets');
+$template->assign_var('T_TEMPLATE_PATH', $path);
+
+$install = new module();
+
+$install->create('install', "index.$phpEx", $mode, $sub);
+$install->load();
+
+// Generate the page
+$install->page_header();
+$install->generate_navigation();
+
+$template->set_filenames(array(
+ 'body' => $install->get_tpl_name())
+);
+
+$install->page_footer();
+
+class module
+{
+ var $id = 0;
+ var $type = 'install';
+ var $module_ary = array();
+ var $filename;
+ var $module_url = '';
+ var $tpl_name = '';
+ var $mode;
+ var $sub;
+
+ /**
+ * Private methods, should not be overwritten
+ */
+ function create($module_type, $module_url, $selected_mod = false, $selected_submod = false)
+ {
+ global $db, $config, $phpEx, $phpbb_root_path;
+
+ $module = array();
+
+ // Grab module information using Bart's "neat-o-module" system (tm)
+ $dir = @opendir('.');
+
+ if (!$dir)
+ {
+ $this->error('Unable to access the installation directory', __LINE__, __FILE__);
+ }
+
+ $setmodules = 1;
+ while (($file = readdir($dir)) !== false)
+ {
+ if (preg_match('#^install_(.*?)\.' . $phpEx . '$#', $file))
+ {
+ include($file);
+ }
+ }
+ closedir($dir);
+
+ unset($setmodules);
+
+ if (!sizeof($module))
+ {
+ $this->error('No installation modules found', __LINE__, __FILE__);
+ }
+
+ // Order to use and count further if modules get assigned to the same position or not having an order
+ $max_module_order = 1000;
+
+ foreach ($module as $row)
+ {
+ // Module order not specified or module already assigned at this position?
+ if (!isset($row['module_order']) || isset($this->module_ary[$row['module_order']]))
+ {
+ $row['module_order'] = $max_module_order;
+ $max_module_order++;
+ }
+
+ $this->module_ary[$row['module_order']]['name'] = $row['module_title'];
+ $this->module_ary[$row['module_order']]['filename'] = $row['module_filename'];
+ $this->module_ary[$row['module_order']]['subs'] = $row['module_subs'];
+ $this->module_ary[$row['module_order']]['stages'] = $row['module_stages'];
+
+ if (strtolower($selected_mod) == strtolower($row['module_title']))
+ {
+ $this->id = (int) $row['module_order'];
+ $this->filename = (string) $row['module_filename'];
+ $this->module_url = (string) $module_url;
+ $this->mode = (string) $selected_mod;
+ // Check that the sub-mode specified is valid or set a default if not
+ if (is_array($row['module_subs']))
+ {
+ $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_subs'])) ? $selected_submod : $row['module_subs'][0]);
+ }
+ else if (is_array($row['module_stages']))
+ {
+ $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_stages'])) ? $selected_submod : $row['module_stages'][0]);
+ }
+ else
+ {
+ $this->sub = '';
+ }
+ }
+ } // END foreach
+ } // END create
+
+ /**
+ * Load and run the relevant module if applicable
+ */
+ function load($mode = false, $run = true)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if ($run)
+ {
+ if (!empty($mode))
+ {
+ $this->mode = $mode;
+ }
+
+ $module = $this->filename;
+ if (!class_exists($module))
+ {
+ $this->error('Module "' . htmlspecialchars($module) . '" not accessible.', __LINE__, __FILE__);
+ }
+ $this->module = new $module($this);
+
+ if (method_exists($this->module, 'main'))
+ {
+ $this->module->main($this->mode, $this->sub);
+ }
+ }
+ }
+
+ /**
+ * Output the standard page header
+ */
+ function page_header()
+ {
+ if (defined('HEADER_INC'))
+ {
+ return;
+ }
+
+ define('HEADER_INC', true);
+ global $template, $lang, $stage, $phpbb_admin_path, $path;
+
+ $template->assign_vars(array(
+ 'L_CHANGE' => $lang['CHANGE'],
+ 'L_COLON' => $lang['COLON'],
+ 'L_INSTALL_PANEL' => $lang['INSTALL_PANEL'],
+ 'L_SELECT_LANG' => $lang['SELECT_LANG'],
+ 'L_SKIP' => $lang['SKIP'],
+ 'PAGE_TITLE' => $this->get_page_title(),
+ 'T_IMAGE_PATH' => htmlspecialchars($phpbb_admin_path) . 'images/',
+ 'T_JQUERY_LINK' => $path . '/../../assets/javascript/jquery.min.js',
+
+ 'S_CONTENT_DIRECTION' => $lang['DIRECTION'],
+ 'S_CONTENT_FLOW_BEGIN' => ($lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
+ 'S_CONTENT_FLOW_END' => ($lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
+ 'S_CONTENT_ENCODING' => 'UTF-8',
+
+ 'S_USER_LANG' => $lang['USER_LANG'],
+ )
+ );
+
+ header('Content-type: text/html; charset=UTF-8');
+ header('Cache-Control: private, no-cache="set-cookie"');
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
+
+ return;
+ }
+
+ /**
+ * Output the standard page footer
+ */
+ function page_footer()
+ {
+ global $db, $template;
+
+ $template->display('body');
+
+ // Close our DB connection.
+ if (!empty($db) && is_object($db))
+ {
+ $db->sql_close();
+ }
+
+ if (function_exists('exit_handler'))
+ {
+ exit_handler();
+ }
+ }
+
+ /**
+ * Returns desired template name
+ */
+ function get_tpl_name()
+ {
+ return $this->module->tpl_name . '.html';
+ }
+
+ /**
+ * Returns the desired page title
+ */
+ function get_page_title()
+ {
+ global $lang;
+
+ if (!isset($this->module->page_title))
+ {
+ return '';
+ }
+
+ return (isset($lang[$this->module->page_title])) ? $lang[$this->module->page_title] : $this->module->page_title;
+ }
+
+ /**
+ * Generate an HTTP/1.1 header to redirect the user to another page
+ * This is used during the installation when we do not have a database available to call the normal redirect function
+ * @param string $page The page to redirect to relative to the installer root path
+ */
+ function redirect($page)
+ {
+ global $request;
+
+ // HTTP_HOST is having the correct browser url in most cases...
+ $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
+ $server_port = $request->server('SERVER_PORT', 0);
+ $secure = $request->is_secure() ? 1 : 0;
+
+ $script_name = htmlspecialchars_decode($request->server('PHP_SELF'));
+ if (!$script_name)
+ {
+ $script_name = htmlspecialchars_decode($request->server('REQUEST_URI'));
+ }
+
+ // Replace backslashes and doubled slashes (could happen on some proxy setups)
+ $script_name = str_replace(array('\\', '//'), '/', $script_name);
+ $script_path = trim(dirname($script_name));
+
+ $url = (($secure) ? 'https://' : 'http://') . $server_name;
+
+ if ($server_port && (($secure && $server_port <> 443) || (!$secure && $server_port <> 80)))
+ {
+ // HTTP HOST can carry a port number...
+ if (strpos($server_name, ':') === false)
+ {
+ $url .= ':' . $server_port;
+ }
+ }
+
+ $url .= $script_path . '/' . $page;
+ header('Location: ' . $url);
+ exit;
+ }
+
+ /**
+ * Generate the navigation tabs
+ */
+ function generate_navigation()
+ {
+ global $lang, $template, $phpEx, $language;
+
+ if (is_array($this->module_ary))
+ {
+ @ksort($this->module_ary);
+ foreach ($this->module_ary as $cat_ary)
+ {
+ $cat = $cat_ary['name'];
+ $l_cat = (!empty($lang['CAT_' . $cat])) ? $lang['CAT_' . $cat] : preg_replace('#_#', ' ', $cat);
+ $cat = strtolower($cat);
+ $url = $this->module_url . "?mode=$cat&amp;language=$language";
+
+ if ($this->mode == $cat)
+ {
+ $template->assign_block_vars('t_block1', array(
+ 'L_TITLE' => $l_cat,
+ 'S_SELECTED' => true,
+ 'U_TITLE' => $url,
+ ));
+
+ if (is_array($this->module_ary[$this->id]['subs']))
+ {
+ $subs = $this->module_ary[$this->id]['subs'];
+ foreach ($subs as $option)
+ {
+ $l_option = (!empty($lang['SUB_' . $option])) ? $lang['SUB_' . $option] : preg_replace('#_#', ' ', $option);
+ $option = strtolower($option);
+ $url = $this->module_url . '?mode=' . $this->mode . "&amp;sub=$option&amp;language=$language";
+
+ $template->assign_block_vars('l_block1', array(
+ 'L_TITLE' => $l_option,
+ 'S_SELECTED' => ($this->sub == $option),
+ 'U_TITLE' => $url,
+ ));
+ }
+ }
+
+ if (is_array($this->module_ary[$this->id]['stages']))
+ {
+ $subs = $this->module_ary[$this->id]['stages'];
+ $matched = false;
+ foreach ($subs as $option)
+ {
+ $l_option = (!empty($lang['STAGE_' . $option])) ? $lang['STAGE_' . $option] : preg_replace('#_#', ' ', $option);
+ $option = strtolower($option);
+ $matched = ($this->sub == $option) ? true : $matched;
+
+ $template->assign_block_vars('l_block2', array(
+ 'L_TITLE' => $l_option,
+ 'S_SELECTED' => ($this->sub == $option),
+ 'S_COMPLETE' => !$matched,
+ ));
+ }
+ }
+ }
+ else
+ {
+ $template->assign_block_vars('t_block1', array(
+ 'L_TITLE' => $l_cat,
+ 'S_SELECTED' => false,
+ 'U_TITLE' => $url,
+ ));
+ }
+ }
+ }
+ }
+
+ /**
+ * Output an error message
+ * If skip is true, return and continue execution, else exit
+ */
+ function error($error, $line, $file, $skip = false)
+ {
+ global $lang, $db, $template, $phpbb_admin_path;
+
+ if ($skip)
+ {
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['INST_ERR'],
+ ));
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
+ 'RESULT' => '<b style="color:red">' . $error . '</b>',
+ ));
+
+ return;
+ }
+
+ echo '<!DOCTYPE html>';
+ echo '<html dir="ltr">';
+ echo '<head>';
+ echo '<meta charset="utf-8">';
+ echo '<title>' . $lang['INST_ERR_FATAL'] . '</title>';
+ echo '<link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />';
+ echo '</head>';
+ echo '<body id="errorpage">';
+ echo '<div id="wrap">';
+ echo ' <div id="page-header">';
+ echo ' </div>';
+ echo ' <div id="page-body">';
+ echo ' <div id="acp">';
+ echo ' <div class="panel">';
+ echo ' <span class="corners-top"><span></span></span>';
+ echo ' <div id="content">';
+ echo ' <h1>' . $lang['INST_ERR_FATAL'] . '</h1>';
+ echo ' <p>' . $lang['INST_ERR_FATAL'] . "</p>\n";
+ echo ' <p>' . basename($file) . ' [ ' . $line . " ]</p>\n";
+ echo ' <p><b>' . $error . "</b></p>\n";
+ echo ' </div>';
+ echo ' <span class="corners-bottom"><span></span></span>';
+ echo ' </div>';
+ echo ' </div>';
+ echo ' </div>';
+ echo ' <div id="page-footer">';
+ echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited';
+ echo ' </div>';
+ echo '</div>';
+ echo '</body>';
+ echo '</html>';
+
+ if (!empty($db) && is_object($db))
+ {
+ $db->sql_close();
+ }
+
+ exit_handler();
+ }
+
+ /**
+ * Output an error message for a database related problem
+ * If skip is true, return and continue execution, else exit
+ */
+ function db_error($error, $sql, $line, $file, $skip = false)
+ {
+ global $lang, $db, $template;
+
+ if ($skip)
+ {
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['INST_ERR_FATAL'],
+ ));
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
+ 'RESULT' => '<b style="color:red">' . $error . '</b><br />&#187; SQL:' . $sql,
+ ));
+
+ return;
+ }
+
+ $template->set_filenames(array(
+ 'body' => 'install_error.html')
+ );
+ $this->page_header();
+ $this->generate_navigation();
+
+ $template->assign_vars(array(
+ 'MESSAGE_TITLE' => $lang['INST_ERR_FATAL_DB'],
+ 'MESSAGE_TEXT' => '<p>' . basename($file) . ' [ ' . $line . ' ]</p><p>SQL : ' . $sql . '</p><p><b>' . $error . '</b></p>',
+ ));
+
+ // Rollback if in transaction
+ if ($db->get_transaction())
+ {
+ $db->sql_transaction('rollback');
+ }
+
+ $this->page_footer();
+ }
+
+ /**
+ * Generate the relevant HTML for an input field and the associated label and explanatory text
+ */
+ function input_field($name, $type, $value = '', $options = '')
+ {
+ global $lang;
+ $tpl_type = explode(':', $type);
+ $tpl = '';
+
+ switch ($tpl_type[0])
+ {
+ case 'text':
+ case 'password':
+ // HTML5 text-like input types
+ case 'color':
+ case 'date':
+ case 'time':
+ case 'datetime':
+ case 'datetime-local':
+ case 'email':
+ case 'month':
+ case 'number':
+ case 'range':
+ case 'search':
+ case 'tel':
+ case 'url':
+ case 'week':
+
+ $size = (int) $tpl_type[1];
+ $maxlength = (int) $tpl_type[2];
+ $autocomplete = (isset($options['autocomplete']) && $options['autocomplete'] == 'off') ? ' autocomplete="off"' : '';
+
+ $tpl = '<input id="' . $name . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '"' . $autocomplete . ' value="' . $value . '" />';
+ break;
+
+ case 'textarea':
+ $rows = (int) $tpl_type[1];
+ $cols = (int) $tpl_type[2];
+
+ $tpl = '<textarea id="' . $name . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $value . '</textarea>';
+ break;
+
+ case 'radio':
+ $key_yes = ($value) ? ' checked="checked" id="' . $name . '"' : '';
+ $key_no = (!$value) ? ' checked="checked" id="' . $name . '"' : '';
+
+ $tpl_type_cond = explode('_', $tpl_type[1]);
+ $type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
+
+ $tpl_no = '<label><input type="radio" name="' . $name . '" value="0"' . $key_no . ' class="radio" /> ' . (($type_no) ? $lang['NO'] : $lang['DISABLED']) . '</label>';
+ $tpl_yes = '<label><input type="radio" name="' . $name . '" value="1"' . $key_yes . ' class="radio" /> ' . (($type_no) ? $lang['YES'] : $lang['ENABLED']) . '</label>';
+
+ $tpl = ($tpl_type_cond[0] == 'yes' || $tpl_type_cond[0] == 'enabled') ? $tpl_yes . '&nbsp;&nbsp;' . $tpl_no : $tpl_no . '&nbsp;&nbsp;' . $tpl_yes;
+ break;
+
+ case 'select':
+ // @codingStandardsIgnoreStart
+ eval('$s_options = ' . str_replace('{VALUE}', $value, $options) . ';');
+ // @codingStandardsIgnoreEnd
+ $tpl = '<select id="' . $name . '" name="' . $name . '">' . $s_options . '</select>';
+ break;
+
+ case 'custom':
+ // @codingStandardsIgnoreStart
+ eval('$tpl = ' . str_replace('{VALUE}', $value, $options) . ';');
+ // @codingStandardsIgnoreEnd
+ break;
+
+ default:
+ break;
+ }
+
+ return $tpl;
+ }
+
+ /**
+ * Generate the drop down of available language packs
+ */
+ function inst_language_select($default = '')
+ {
+ global $phpbb_root_path, $phpEx;
+
+ $dir = @opendir($phpbb_root_path . 'language');
+
+ if (!$dir)
+ {
+ $this->error('Unable to access the language directory', __LINE__, __FILE__);
+ }
+
+ while ($file = readdir($dir))
+ {
+ $path = $phpbb_root_path . 'language/' . $file;
+
+ if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
+ {
+ continue;
+ }
+
+ if (file_exists($path . '/iso.txt'))
+ {
+ list($displayname, $localname) = @file($path . '/iso.txt');
+ $lang[$localname] = $file;
+ }
+ }
+ closedir($dir);
+
+ @asort($lang);
+ @reset($lang);
+
+ $user_select = '';
+ foreach ($lang as $displayname => $filename)
+ {
+ $selected = (strtolower($default) == strtolower($filename)) ? ' selected="selected"' : '';
+ $user_select .= '<option value="' . $filename . '"' . $selected . '>' . ucwords($displayname) . '</option>';
+ }
+
+ return $user_select;
+ }
+}
diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php
new file mode 100644
index 0000000000..d72ee1a633
--- /dev/null
+++ b/phpBB/install/install_convert.php
@@ -0,0 +1,2153 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+*/
+
+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.
+*/
+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
+*/
+class install_convert extends module
+{
+ /** @var array */
+ protected $lang;
+
+ /** @var string */
+ protected $language;
+
+ /** @var \phpbb\template\template */
+ protected $template;
+
+ /** @var string */
+ protected $phpbb_root_path;
+
+ /** @var string */
+ protected $php_ext;
+
+ /** @var \phpbb\filesystem\filesystem_interface */
+ protected $filesystem;
+
+ /**
+ * 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, $request, $phpbb_container, $phpbb_config_php_file;
+
+ $this->tpl_name = 'install_convert';
+ $this->mode = $mode;
+ $this->lang = $lang;
+ $this->language = $language;
+ $this->template = $template;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $phpEx;
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+
+ if (!$this->check_phpbb_installed())
+ {
+ return;
+ }
+
+ $convert = new convert($this->p_master);
+
+ // Enable super globals to prevent issues with the new \phpbb\request\request object
+ $request->enable_super_globals();
+ // Create a normal container now
+ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
+
+ // Create cache
+ /* @var $cache \phpbb\cache\service */
+ $cache = $phpbb_container->get('cache');
+
+ switch ($sub)
+ {
+ case 'intro':
+ extract($phpbb_config_php_file->get_all());
+
+ require($phpbb_root_path . 'includes/constants.' . $phpEx);
+ require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ $db = new $dbms();
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
+ unset($dbpasswd);
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ // 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->variable('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($options, unserialize($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();
+
+ extract($phpbb_config_php_file->get_all());
+
+ require($phpbb_root_path . 'includes/constants.' . $phpEx);
+ require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ $db = new $dbms();
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
+ 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->get_sql_layer())
+ {
+ case 'sqlite':
+ case 'sqlite3':
+ $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;
+ }
+ }
+
+ /**
+ * Check whether phpBB is installed.
+ * Assigns error template vars if not installed.
+ *
+ * @return bool Returns true if phpBB is installed.
+ */
+ public function check_phpbb_installed()
+ {
+ if (phpbb_check_installation_exists($this->phpbb_root_path, $this->php_ext))
+ {
+ return true;
+ }
+
+ $this->page_title = 'BOARD_NOT_INSTALLED';
+ $install_url = append_sid($this->phpbb_root_path . 'install/index.' . $this->php_ext, 'mode=install&amp;language=' . $this->language);
+
+ $this->template->assign_vars(array(
+ 'S_NOT_INSTALLED' => true,
+ 'BODY' => sprintf($this->lang['BOARD_NOT_INSTALLED_EXPLAIN'], $install_url),
+ ));
+
+ return false;
+ }
+
+ /**
+ * 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, $phpbb_config_php_file;
+
+ extract($phpbb_config_php_file->get_all());
+
+ require($phpbb_root_path . 'includes/constants.' . $phpEx);
+ require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ $db = new $dbms();
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
+ unset($dbpasswd);
+
+ $this->page_title = $lang['STAGE_SETTINGS'];
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ $convertor_tag = $request->variable('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->variable('src_dbms', $convertor_data['dbms']);
+ $src_dbhost = $request->variable('src_dbhost', $convertor_data['dbhost']);
+ $src_dbport = $request->variable('src_dbport', $convertor_data['dbport']);
+ $src_dbuser = $request->variable('src_dbuser', $convertor_data['dbuser']);
+ $src_dbpasswd = $request->variable('src_dbpasswd', $convertor_data['dbpasswd']);
+ $src_dbname = $request->variable('src_dbname', $convertor_data['dbname']);
+ $src_table_prefix = $request->variable('src_table_prefix', $convertor_data['table_prefix']);
+ $forum_path = $request->variable('forum_path', $convertor_data['forum_path']);
+ $refresh = $request->variable('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->variable('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_path, 0, -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(false, true, true);
+
+ 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_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, true, ($src_dbms == $dbms) ? false : true, false);
+ }
+
+ // 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);
+ }
+
+ $src_dbms = $phpbb_config_php_file->convert_30_dbms_to_31($src_dbms);
+
+ // 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)
+ {
+ $src_db = new $src_dbms();
+ $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true);
+ $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();
+
+ $db_tools_factory = new \phpbb\db\tools\factory();
+ $db_tools = $db_tools_factory->get($src_db);
+ $tables_existing = $db_tools->sql_list_tables();
+ $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
+ $config->set('convert_progress', serialize(array(
+ 'step' => '',
+ 'table_prefix' => $src_table_prefix,
+ 'tag' => $convertor_tag,
+ )), false);
+ $config->set('convert_db_server', serialize(array(
+ 'dbms' => $src_dbms,
+ 'dbhost' => $src_dbhost,
+ 'dbport' => $src_dbport,
+ 'dbname' => $src_dbname,
+ )), false);
+ $config->set('convert_db_user', serialize(array(
+ 'dbuser' => $src_dbuser,
+ 'dbpasswd' => $src_dbpasswd,
+ )), false);
+
+ // Save options
+ $config->set('convert_options', serialize(array(
+ 'forum_path' => './../' . $forum_path,
+ 'refresh' => $refresh
+ )), false);
+
+ $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, $auth;
+ global $convert, $convert_row, $message_parser, $skip_rows, $language;
+ global $request, $phpbb_config_php_file, $phpbb_dispatcher;
+
+ extract($phpbb_config_php_file->get_all());
+
+ require($phpbb_root_path . 'includes/constants.' . $phpEx);
+ require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ $db = new $dbms();
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
+ unset($dbpasswd);
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ // 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->options, unserialize($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)
+ {
+ $dbms = $convert->src_dbms;
+ $src_db = new $dbms();
+ $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
+ $same_db = false;
+ }
+ else
+ {
+ $src_db = $db;
+ $same_db = true;
+ }
+
+ $convert->mysql_convert = false;
+ switch ($src_db->sql_layer)
+ {
+ case 'sqlite':
+ case 'sqlite3':
+ $convert->src_truncate_statement = 'DELETE FROM ';
+ break;
+
+ // Thanks MySQL, for silently converting...
+ case 'mysql':
+ case 'mysql4':
+ if (version_compare($src_db->sql_server_info(true, false), '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->get_sql_layer())
+ {
+ case 'sqlite':
+ case 'sqlite3':
+ $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 = $config['search_type'];
+
+ // For conversions we are a bit less strict and set to a search backend we know exist...
+ if (!class_exists($search_type))
+ {
+ $search_type = '\phpbb\search\fulltext_native';
+ $config->set('search_type', $search_type);
+ }
+
+ if (!class_exists($search_type))
+ {
+ trigger_error('NO_SUCH_SEARCH_MODULE');
+ }
+
+ $error = false;
+ $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
+
+ if ($error)
+ {
+ trigger_error($error);
+ }
+
+ include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ $message_parser = new parse_message();
+
+ $jump = $request->variable('jump', 0);
+ $final_jump = $request->variable('final_jump', 0);
+ $sync_batch = $request->variable('sync_batch', -1);
+ $last_statement = $request->variable('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->variable('current_table', 0);
+ $old_current_table = min(-1, $current_table - 1);
+ $skip_rows = $request->variable('skip_rows', 0);
+
+ if (!$current_table && !$skip_rows)
+ {
+ if (!$request->variable('confirm', false))
+ {
+ // 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 || !$this->filesystem->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($msg, implode('<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($sql, 1);
+
+ 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($user->lang['COMMA_SEPARATOR'], $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 (!$request->variable('confirm', false)))
+
+ $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']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_first']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ 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']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($schema['execute_first']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ 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->get_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']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($schema['execute_always']);
+ // @codingStandardsIgnoreEnd
+ }
+
+ //
+ // 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($select, 0, $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 === -1 || ($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') && 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->get_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 === 0 || 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->get_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->get_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')*/)
+ {
+ $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_table, sizeof($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', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true);
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''),
+ '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 $config, $convert, $language;
+
+ // Save convertor Status
+ $config->set('convert_progress', serialize(array(
+ 'step' => $step,
+ 'table_prefix' => $convert->src_table_prefix,
+ 'tag' => $convert->convertor_tag,
+ )), false);
+
+ $config->set('convert_db_server', serialize(array(
+ 'dbms' => $convert->src_dbms,
+ 'dbhost' => $convert->src_dbhost,
+ 'dbport' => $convert->src_dbport,
+ 'dbname' => $convert->src_dbname,
+ )), false);
+
+ $config->set('convert_db_user', serialize(array(
+ 'dbuser' => $convert->src_dbuser,
+ 'dbpasswd' => $convert->src_dbpasswd,
+ )), false);
+
+ 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;
+ global $cache, $auth, $phpbb_container, $phpbb_log;
+
+ $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);
+ phpbb_cache_moderators($db, $cache, $auth);
+
+ // And finally, add a note to the log
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_CONVERTED', false, array($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->get_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']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_last']);
+ // @codingStandardsIgnoreEnd
+ }
+ else
+ {
+ while ($last_statement < sizeof($convert->convertor['execute_last']))
+ {
+ // @codingStandardsIgnoreStart
+ eval($convert->convertor['execute_last'][$last_statement]);
+ // @codingStandardsIgnoreEnd
+
+ $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) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement));
+ $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($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))
+ {
+ $config->set('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', '', '', false, true);
+ $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->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? '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_query, 0, -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]) && !is_callable($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);
+ // @codingStandardsIgnoreStart
+ eval($execution);
+ // @codingStandardsIgnoreEnd
+ }
+ }
+ }
+ 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);
+ // @codingStandardsIgnoreStart
+ eval($execution);
+ // @codingStandardsIgnoreEnd
+ }
+ }
+ }
+ 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),
+ );
+}
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
new file mode 100644
index 0000000000..0e223866b1
--- /dev/null
+++ b/phpBB/install/install_install.php
@@ -0,0 +1,2368 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+*/
+if (!defined('IN_INSTALL'))
+{
+ // Someone has tried to access the file direct. This is not a good idea, so exit
+ exit;
+}
+
+if (!empty($setmodules))
+{
+ // If phpBB is already installed we do not include this module
+ if (phpbb_check_installation_exists($phpbb_root_path, $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock'))
+ {
+ return;
+ }
+
+ $module[] = array(
+ 'module_type' => 'install',
+ 'module_title' => 'INSTALL',
+ 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
+ 'module_order' => 10,
+ 'module_subs' => '',
+ 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'),
+ 'module_reqs' => ''
+ );
+}
+
+/**
+* Installation
+*/
+class install_install extends module
+{
+ /**
+ * @var \phpbb\filesystem\filesystem_interface
+ */
+ protected $filesystem;
+
+ function install_install(&$p_master)
+ {
+ $this->p_master = &$p_master;
+ $this->filesystem = new \phpbb\filesystem\filesystem();
+ }
+
+ function main($mode, $sub)
+ {
+ global $lang, $template, $language, $phpbb_root_path, $phpEx;
+ global $phpbb_container, $cache, $phpbb_log, $request, $phpbb_config_php_file;
+
+ switch ($sub)
+ {
+ case 'intro':
+ $phpbb_container->get('cache.driver')->purge();
+
+ $this->page_title = $lang['SUB_INTRO'];
+
+ $template->assign_vars(array(
+ 'TITLE' => $lang['INSTALL_INTRO'],
+ 'BODY' => $lang['INSTALL_INTRO_BODY'],
+ 'L_SUBMIT' => $lang['NEXT_STEP'],
+ 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
+ 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language",
+ ));
+
+ break;
+
+ case 'requirements':
+ $this->check_server_requirements($mode, $sub);
+
+ break;
+
+ case 'database':
+ $this->obtain_database_settings($mode, $sub);
+
+ break;
+
+ case 'administrator':
+ $this->obtain_admin_settings($mode, $sub);
+
+ break;
+
+ case 'config_file':
+ $this->create_config_file($mode, $sub);
+
+ break;
+
+ case 'advanced':
+ $this->obtain_advanced_settings($mode, $sub);
+
+ break;
+
+ case 'create_table':
+ $this->load_schema($mode, $sub);
+ break;
+
+ case 'final':
+ // Enable super globals to prevent issues with the new \phpbb\request\request object
+ $request->enable_super_globals();
+
+ // Create a normal container now
+ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
+
+ // Sets the global variables
+ /* @var $cache \phpbb\cache\service */
+ $cache = $phpbb_container->get('cache');
+
+ /* @var $phpbb_log \phpbb\log\log_interface */
+ $phpbb_log = $phpbb_container->get('log');
+
+ $this->build_search_index($mode, $sub);
+ $this->add_modules($mode, $sub);
+ $this->add_language($mode, $sub);
+ $this->add_bots($mode, $sub);
+ $this->email_admin($mode, $sub);
+ $this->disable_avatars_if_unwritable();
+ $this->populate_migrations($phpbb_container->get('ext.manager'), $phpbb_container->get('migrator'));
+
+ // Remove the lock file
+ @unlink($phpbb_root_path . 'cache/install_lock');
+
+ break;
+ }
+
+ $this->tpl_name = 'install_install';
+ }
+
+ /**
+ * Checks that the server we are installing on meets the requirements for running phpBB
+ */
+ function check_server_requirements($mode, $sub)
+ {
+ global $lang, $template, $phpbb_root_path, $phpEx, $language;
+
+ $this->page_title = $lang['STAGE_REQUIREMENTS'];
+
+ $template->assign_vars(array(
+ 'TITLE' => $lang['REQUIREMENTS_TITLE'],
+ 'BODY' => $lang['REQUIREMENTS_EXPLAIN'],
+ ));
+
+ $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false, 'imagesize' => false, 'json' => false,);
+
+ // Test for basic PHP settings
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['PHP_SETTINGS'],
+ 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'],
+ ));
+
+ // Test the minimum PHP version
+ $php_version = PHP_VERSION;
+
+ if (version_compare($php_version, '5.3.9') < 0)
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+ else
+ {
+ $passed['php'] = true;
+
+ // We also give feedback on whether we're running in safe mode
+ $result = '<strong style="color:green">' . $lang['YES'];
+ if (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) == 'on')
+ {
+ $result .= ', ' . $lang['PHP_SAFE_MODE'];
+ }
+ $result .= '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PHP_VERSION_REQD'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+
+ // Don't check for register_globals on 5.4+
+ if (version_compare($php_version, '5.4.0-dev') < 0)
+ {
+ // Check for register_globals being enabled
+ if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on')
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+ else
+ {
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PHP_REGISTER_GLOBALS'],
+ 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+ }
+
+ // Check for url_fopen
+ if (@ini_get('allow_url_fopen') == '1' || strtolower(@ini_get('allow_url_fopen')) == 'on')
+ {
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ else
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PHP_URL_FOPEN_SUPPORT'],
+ 'TITLE_EXPLAIN' => $lang['PHP_URL_FOPEN_SUPPORT_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+
+ // Check for getimagesize
+ if (@function_exists('getimagesize'))
+ {
+ $passed['imagesize'] = true;
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ else
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PHP_GETIMAGESIZE_SUPPORT'],
+ 'TITLE_EXPLAIN' => $lang['PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+
+ // Check for PCRE UTF-8 support
+ if (@preg_match('//u', ''))
+ {
+ $passed['pcre'] = true;
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ else
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PCRE_UTF_SUPPORT'],
+ 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+
+ // Check for php json support
+ if (@extension_loaded('json'))
+ {
+ $passed['json'] = true;
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ else
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['PHP_JSON_SUPPORT'],
+ 'TITLE_EXPLAIN' => $lang['PHP_JSON_SUPPORT_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+
+ $passed['mbstring'] = true;
+ if (@extension_loaded('mbstring'))
+ {
+ // Test for available database modules
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['MBSTRING_CHECK'],
+ 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'],
+ ));
+
+ $checks = array(
+ array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING),
+ array('encoding_translation', '!=', 0),
+ array('http_input', '!=', array('pass', '')),
+ array('http_output', '!=', array('pass', ''))
+ );
+
+ foreach ($checks as $mb_checks)
+ {
+ $ini_val = @ini_get('mbstring.' . $mb_checks[0]);
+ switch ($mb_checks[1])
+ {
+ case '&':
+ if (intval($ini_val) & $mb_checks[2])
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ $passed['mbstring'] = false;
+ }
+ else
+ {
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ break;
+
+ case '!=':
+ if (!is_array($mb_checks[2]) && $ini_val != $mb_checks[2] ||
+ is_array($mb_checks[2]) && !in_array($ini_val, $mb_checks[2]))
+ {
+ $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
+ $passed['mbstring'] = false;
+ }
+ else
+ {
+ $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
+ }
+ break;
+ }
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])],
+ 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'],
+ 'RESULT' => $result,
+
+ 'S_EXPLAIN' => true,
+ 'S_LEGEND' => false,
+ ));
+ }
+ }
+
+ // Test for available database modules
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['PHP_SUPPORTED_DB'],
+ 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'],
+ ));
+
+ $available_dbms = get_available_dbms(false, true);
+ $passed['db'] = $available_dbms['ANY_DB_SUPPORT'];
+ unset($available_dbms['ANY_DB_SUPPORT']);
+
+ foreach ($available_dbms as $db_name => $db_ary)
+ {
+ if (!$db_ary['AVAILABLE'])
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
+ 'RESULT' => '<span style="color:red">' . $lang['UNAVAILABLE'] . '</span>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ else
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
+ 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ }
+
+ // Test for other modules
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'],
+ 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'],
+ ));
+
+ foreach ($this->php_dlls_other as $dll)
+ {
+ if (!@extension_loaded($dll))
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DLL_' . strtoupper($dll)],
+ 'RESULT' => '<strong style="color:red">' . $lang['UNAVAILABLE'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ continue;
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DLL_' . strtoupper($dll)],
+ 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+
+ // Can we find Imagemagick anywhere on the system?
+ $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : '';
+
+ $magic_home = getenv('MAGICK_HOME');
+ $img_imagick = '';
+ if (empty($magic_home))
+ {
+ $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/');
+ $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH'))));
+
+ $locations = array_merge($path_locations, $locations);
+ foreach ($locations as $location)
+ {
+ // The path might not end properly, fudge it
+ if (substr($location, -1, 1) !== '/')
+ {
+ $location .= '/';
+ }
+
+ if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000)
+ {
+ $img_imagick = str_replace('\\', '/', $location);
+ continue;
+ }
+ }
+ }
+ else
+ {
+ $img_imagick = str_replace('\\', '/', $magic_home);
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['APP_MAGICK'],
+ 'RESULT' => ($img_imagick) ? '<strong style="color:green">' . $lang['AVAILABLE'] . ', ' . $img_imagick . '</strong>' : '<strong style="color:blue">' . $lang['NO_LOCATION'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+
+ // Check permissions on files/directories we need access to
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['FILES_REQUIRED'],
+ 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'],
+ ));
+
+ $directories = array('cache/', 'files/', 'store/');
+
+ umask(0);
+
+ $passed['files'] = true;
+ foreach ($directories as $dir)
+ {
+ $exists = $write = false;
+
+ // Try to create the directory if it does not exist
+ if (!file_exists($phpbb_root_path . $dir))
+ {
+ @mkdir($phpbb_root_path . $dir, 0777);
+
+ try
+ {
+ $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+
+ // Now really check
+ if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir))
+ {
+ try
+ {
+ $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+
+ $exists = true;
+ }
+
+ // Now check if it is writable by storing a simple file
+ $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb');
+ if ($fp !== false)
+ {
+ $write = true;
+ }
+ @fclose($fp);
+
+ @unlink($phpbb_root_path . $dir . 'test_lock');
+
+ $passed['files'] = ($exists && $write && $passed['files']) ? true : false;
+
+ $exists = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
+ $write = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $dir,
+ 'RESULT' => $exists . $write,
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+
+ // Check permissions on files/directories it would be useful access to
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['FILES_OPTIONAL'],
+ 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'],
+ ));
+
+ $directories = array('config.' . $phpEx, 'images/avatars/upload/');
+
+ foreach ($directories as $dir)
+ {
+ $write = $exists = true;
+ if (file_exists($phpbb_root_path . $dir))
+ {
+ if (!$this->filesystem->is_writable($phpbb_root_path . $dir))
+ {
+ $write = false;
+ }
+ }
+ else
+ {
+ $write = $exists = false;
+ }
+
+ $exists_str = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
+ $write_str = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
+
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $dir,
+ 'RESULT' => $exists_str . $write_str,
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+
+ // And finally where do we want to go next (well today is taken isn't it :P)
+ $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
+
+ $url = (!in_array(false, $passed)) ? $this->p_master->module_url . "?mode=$mode&amp;sub=database&amp;language=$language" : $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language ";
+ $submit = (!in_array(false, $passed)) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST'];
+
+ $template->assign_vars(array(
+ 'L_SUBMIT' => $submit,
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'U_ACTION' => $url,
+ ));
+ }
+
+ /**
+ * Obtain the information required to connect to the database
+ */
+ function obtain_database_settings($mode, $sub)
+ {
+ global $lang, $template, $phpEx;
+
+ $this->page_title = $lang['STAGE_DATABASE'];
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ $connect_test = false;
+ $error = array();
+ $available_dbms = get_available_dbms(false, true);
+
+ // Has the user opted to test the connection?
+ if (isset($_POST['testdb']))
+ {
+ if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE'])
+ {
+ $error[] = $lang['INST_ERR_NO_DB'];
+ $connect_test = false;
+ }
+ else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix']))
+ {
+ $error[] = $lang['INST_ERR_DB_INVALID_PREFIX'];
+ $connect_test = false;
+ }
+ else
+ {
+ $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']);
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['DB_CONNECTION'],
+ 'LEGEND_EXPLAIN' => false,
+ ));
+
+ if ($connect_test)
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DB_TEST'],
+ 'RESULT' => '<strong style="color:green">' . $lang['SUCCESSFUL_CONNECT'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ else
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['DB_TEST'],
+ 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ }
+
+ if (!$connect_test)
+ {
+ // Update the list of available DBMS modules to only contain those which can be used
+ $available_dbms_temp = array();
+ foreach ($available_dbms as $type => $dbms_ary)
+ {
+ if (!$dbms_ary['AVAILABLE'])
+ {
+ continue;
+ }
+
+ $available_dbms_temp[$type] = $dbms_ary;
+ }
+
+ $available_dbms = &$available_dbms_temp;
+
+ // And now for the main part of this page
+ $data['table_prefix'] = (!empty($data['table_prefix']) ? $data['table_prefix'] : 'phpbb_');
+
+ foreach ($this->db_config_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'], $data[$config_key], $options),
+ )
+ );
+ }
+ }
+
+ // And finally where do we want to go next (well today is taken isn't it :P)
+ $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
+ $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
+ if ($connect_test)
+ {
+ foreach ($this->db_config_options as $config_key => $vars)
+ {
+ if (!is_array($vars))
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
+ }
+ }
+
+ $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&amp;sub=administrator" : $this->p_master->module_url . "?mode=$mode&amp;sub=database";
+ $s_hidden_fields .= ($connect_test) ? '' : '<input type="hidden" name="testdb" value="true" />';
+
+ $submit = $lang['NEXT_STEP'];
+
+ $template->assign_vars(array(
+ 'L_SUBMIT' => $submit,
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'U_ACTION' => $url,
+ ));
+ }
+
+ /**
+ * Obtain the administrator's name, password and email address
+ */
+ function obtain_admin_settings($mode, $sub)
+ {
+ global $lang, $template, $phpEx;
+
+ $this->page_title = $lang['STAGE_ADMINISTRATOR'];
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ if ($data['dbms'] == '')
+ {
+ // Someone's been silly and tried calling this page direct
+ // So we send them back to the start to do it again properly
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
+ $passed = false;
+
+ $data['default_lang'] = ($data['default_lang'] !== '') ? $data['default_lang'] : $data['language'];
+
+ if (isset($_POST['check']))
+ {
+ $error = array();
+
+ // Check the entered email address and password
+ if ($data['admin_name'] == '' || $data['admin_pass1'] == '' || $data['admin_pass2'] == '' || $data['board_email'] == '')
+ {
+ $error[] = $lang['INST_ERR_MISSING_DATA'];
+ }
+
+ if ($data['admin_pass1'] != $data['admin_pass2'] && $data['admin_pass1'] != '')
+ {
+ $error[] = $lang['INST_ERR_PASSWORD_MISMATCH'];
+ }
+
+ // Test against the default username rules
+ if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) < 3)
+ {
+ $error[] = $lang['INST_ERR_USER_TOO_SHORT'];
+ }
+
+ if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) > 20)
+ {
+ $error[] = $lang['INST_ERR_USER_TOO_LONG'];
+ }
+
+ // Test against the default password rules
+ if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) < 6)
+ {
+ $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT'];
+ }
+
+ if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) > 30)
+ {
+ $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG'];
+ }
+
+ if ($data['board_email'] != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $data['board_email']))
+ {
+ $error[] = $lang['INST_ERR_EMAIL_INVALID'];
+ }
+
+ $template->assign_block_vars('checks', array(
+ 'S_LEGEND' => true,
+ 'LEGEND' => $lang['STAGE_ADMINISTRATOR'],
+ 'LEGEND_EXPLAIN' => false,
+ ));
+
+ if (!sizeof($error))
+ {
+ $passed = true;
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['ADMIN_TEST'],
+ 'RESULT' => '<strong style="color:green">' . $lang['TESTS_PASSED'] . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ else
+ {
+ $template->assign_block_vars('checks', array(
+ 'TITLE' => $lang['ADMIN_TEST'],
+ 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
+
+ 'S_EXPLAIN' => false,
+ 'S_LEGEND' => false,
+ ));
+ }
+ }
+
+ if (!$passed)
+ {
+ foreach ($this->admin_config_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'], $data[$config_key], $options),
+ )
+ );
+ }
+ }
+ else
+ {
+ foreach ($this->admin_config_options as $config_key => $vars)
+ {
+ if (!is_array($vars))
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
+ }
+ }
+
+ $s_hidden_fields .= ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
+ $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
+
+ foreach ($this->db_config_options as $config_key => $vars)
+ {
+ if (!is_array($vars))
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
+ }
+
+ $submit = $lang['NEXT_STEP'];
+
+ $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&amp;sub=config_file" : $this->p_master->module_url . "?mode=$mode&amp;sub=administrator";
+ $s_hidden_fields .= ($passed) ? '' : '<input type="hidden" name="check" value="true" />';
+
+ $template->assign_vars(array(
+ 'L_SUBMIT' => $submit,
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'U_ACTION' => $url,
+ ));
+ }
+
+ /**
+ * Writes the config file to disk, or if unable to do so offers alternative methods
+ */
+ function create_config_file($mode, $sub)
+ {
+ global $lang, $template, $phpbb_root_path, $phpEx;
+
+ $this->page_title = $lang['STAGE_CONFIG_FILE'];
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ if ($data['dbms'] == '')
+ {
+ // Someone's been silly and tried calling this page direct
+ // So we send them back to the start to do it again properly
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
+ $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
+ $written = false;
+
+ // Create a list of any PHP modules we wish to have loaded
+ $available_dbms = get_available_dbms($data['dbms']);
+
+ // Create a lock file to indicate that there is an install in progress
+ $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb');
+ if ($fp === false)
+ {
+ // We were unable to create the lock file - abort
+ $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__);
+ }
+ @fclose($fp);
+
+ @chmod($phpbb_root_path . 'cache/install_lock', 0777);
+
+ // Time to convert the data provided into a config file
+ $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']);
+
+ // Attempt to write out the config file directly. If it works, this is the easiest way to do it ...
+ if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && $this->filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) || $this->filesystem->is_writable($phpbb_root_path))
+ {
+ // Assume it will work ... if nothing goes wrong below
+ $written = true;
+
+ if (!($fp = @fopen($phpbb_root_path . 'config.' . $phpEx, 'w')))
+ {
+ // Something went wrong ... so let's try another method
+ $written = false;
+ }
+
+ if (!(@fwrite($fp, $config_data)))
+ {
+ // Something went wrong ... so let's try another method
+ $written = false;
+ }
+
+ @fclose($fp);
+
+ if ($written)
+ {
+ // We may revert back to chmod() if we see problems with users not able to change their config.php file directly
+ try
+ {
+ $this->filesystem->phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ);
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $e)
+ {
+ // Do nothing
+ }
+ }
+ }
+
+ if (isset($_POST['dldone']))
+ {
+ // Do a basic check to make sure that the file has been uploaded
+ // Note that all we check is that the file has _something_ in it
+ // We don't compare the contents exactly - if they can't upload
+ // a single file correctly, it's likely they will have other problems....
+ if (filesize($phpbb_root_path . 'config.' . $phpEx) > 10)
+ {
+ $written = true;
+ }
+ }
+
+ $config_options = array_merge($this->db_config_options, $this->admin_config_options);
+
+ foreach ($config_options as $config_key => $vars)
+ {
+ if (!is_array($vars))
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
+ }
+
+ if (!$written)
+ {
+ // OK, so it didn't work let's try the alternatives
+
+ if (isset($_POST['dlconfig']))
+ {
+ // They want a copy of the file to download, so send the relevant headers and dump out the data
+ header("Content-Type: text/x-delimtext; name=\"config.$phpEx\"");
+ header("Content-disposition: attachment; filename=config.$phpEx");
+ echo $config_data;
+ exit;
+ }
+
+ // The option to download the config file is always available, so output it here
+ $template->assign_vars(array(
+ 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'],
+ 'L_DL_CONFIG' => $lang['DL_CONFIG'],
+ 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'],
+ 'L_DL_DONE' => $lang['DONE'],
+ 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'],
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'S_SHOW_DOWNLOAD' => true,
+ 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=config_file",
+ ));
+ return;
+ }
+ else
+ {
+ $template->assign_vars(array(
+ 'BODY' => $lang['CONFIG_FILE_WRITTEN'],
+ 'L_SUBMIT' => $lang['NEXT_STEP'],
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=advanced",
+ ));
+ return;
+ }
+ }
+
+ /**
+ * Provide an opportunity to customise some advanced settings during the install
+ * in case it is necessary for them to be set to access later
+ */
+ function obtain_advanced_settings($mode, $sub)
+ {
+ global $lang, $template, $phpEx, $request;
+
+ $this->page_title = $lang['STAGE_ADVANCED'];
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ if ($data['dbms'] == '')
+ {
+ // Someone's been silly and tried calling this page direct
+ // So we send them back to the start to do it again properly
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
+ $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
+
+ // HTTP_HOST is having the correct browser url in most cases...
+ $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
+
+ // HTTP HOST can carry a port number...
+ if (strpos($server_name, ':') !== false)
+ {
+ $server_name = substr($server_name, 0, strpos($server_name, ':'));
+ }
+
+ $data['email_enable'] = ($data['email_enable'] !== '') ? $data['email_enable'] : true;
+ $data['server_name'] = ($data['server_name'] !== '') ? $data['server_name'] : $server_name;
+ $data['server_port'] = ($data['server_port'] !== '') ? $data['server_port'] : $request->server('SERVER_PORT', 0);
+ $data['server_protocol'] = ($data['server_protocol'] !== '') ? $data['server_protocol'] : ($request->is_secure() ? 'https://' : 'http://');
+ $data['cookie_secure'] = ($data['cookie_secure'] !== '') ? $data['cookie_secure'] : $request->is_secure();
+
+ if ($data['script_path'] === '')
+ {
+ $name = htmlspecialchars_decode($request->server('PHP_SELF'));
+ if (!$name)
+ {
+ $name = htmlspecialchars_decode($request->server('REQUEST_URI'));
+ }
+
+ // Replace backslashes and doubled slashes (could happen on some proxy setups)
+ $name = str_replace(array('\\', '//'), '/', $name);
+ $data['script_path'] = trim(dirname(dirname($name)));
+ }
+
+ foreach ($this->advanced_config_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'], $data[$config_key], $options),
+ )
+ );
+ }
+
+ $config_options = array_merge($this->db_config_options, $this->admin_config_options);
+ foreach ($config_options as $config_key => $vars)
+ {
+ if (!is_array($vars))
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
+ }
+
+ $submit = $lang['NEXT_STEP'];
+
+ $url = $this->p_master->module_url . "?mode=$mode&amp;sub=create_table";
+
+ $template->assign_vars(array(
+ 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'],
+ 'L_SUBMIT' => $submit,
+ 'S_HIDDEN' => $s_hidden_fields,
+ 'U_ACTION' => $url,
+ ));
+ }
+
+ /**
+ * Load the contents of the schema into the database and then alter it based on what has been input during the installation
+ */
+ function load_schema($mode, $sub)
+ {
+ global $db, $lang, $template, $phpbb_root_path, $phpEx, $request;
+
+ $this->page_title = $lang['STAGE_CREATE_TABLE'];
+ $s_hidden_fields = '';
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ if ($data['dbms'] == '')
+ {
+ // Someone's been silly and tried calling this page direct
+ // So we send them back to the start to do it again properly
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ // HTTP_HOST is having the correct browser url in most cases...
+ $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
+ $referer = strtolower($request->header('Referer'));
+
+ // HTTP HOST can carry a port number...
+ if (strpos($server_name, ':') !== false)
+ {
+ $server_name = substr($server_name, 0, strpos($server_name, ':'));
+ }
+
+ $cookie_domain = ($data['server_name'] != '') ? $data['server_name'] : $server_name;
+
+ // Try to come up with the best solution for cookie domain...
+ if (strpos($cookie_domain, 'www.') === 0)
+ {
+ $cookie_domain = str_replace('www.', '.', $cookie_domain);
+ }
+
+ // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
+ $available_dbms = get_available_dbms($data['dbms']);
+
+ if (!isset($available_dbms[$data['dbms']]))
+ {
+ // Someone's been silly and tried providing a non-existant dbms
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ $dbms = $available_dbms[$data['dbms']]['DRIVER'];
+
+ // Instantiate the database
+ $db = new $dbms();
+ $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
+
+ // NOTE: trigger_error does not work here.
+ $db->sql_return_on_error(true);
+
+ // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;)
+ if ($data['dbms'] == 'mysql')
+ {
+ if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
+ {
+ $available_dbms[$data['dbms']]['SCHEMA'] .= '_41';
+ }
+ else
+ {
+ $available_dbms[$data['dbms']]['SCHEMA'] .= '_40';
+ }
+ }
+
+ // Ok we have the db info go ahead and read in the relevant schema
+ // and work on building the table
+ $dbms_schema = 'schemas/' . $available_dbms[$data['dbms']]['SCHEMA'] . '_schema.sql';
+
+ // How should we treat this schema?
+ $delimiter = $available_dbms[$data['dbms']]['DELIM'];
+
+ if (file_exists($dbms_schema))
+ {
+ $sql_query = @file_get_contents($dbms_schema);
+ $sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query);
+ $sql_query = phpbb_remove_comments($sql_query);
+ $sql_query = split_sql_file($sql_query, $delimiter);
+
+ foreach ($sql_query as $sql)
+ {
+ // Ignore errors when the functions or types already exist
+ // to allow installing phpBB twice in the same database with
+ // a different prefix
+ $db->sql_query($sql);
+ }
+ unset($sql_query);
+ }
+
+ // Ok we have the db info go ahead and work on building the table
+ if (file_exists('schemas/schema.json'))
+ {
+ $db_table_schema = @file_get_contents('schemas/schema.json');
+ $db_table_schema = json_decode($db_table_schema, true);
+ }
+ else
+ {
+ global $phpbb_root_path, $phpEx, $table_prefix;
+ $table_prefix = 'phpbb_';
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // We need to include the constants file for the table constants
+ // when we generate the schema from the migration files.
+ include($phpbb_root_path . 'includes/constants.' . $phpEx);
+ }
+
+ $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);
+ $classes = $finder->core_path('phpbb/db/migration/data/')
+ ->get_classes();
+
+ $sqlite_db = new \phpbb\db\driver\sqlite();
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($sqlite_db, true);
+ $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
+ $db_table_schema = $schema_generator->get_schema();
+ }
+
+ if (!defined('CONFIG_TABLE'))
+ {
+ // CONFIG_TABLE is required by sql_create_index() to check the
+ // length of index names. However table_prefix is not defined
+ // here yet, so we need to create the constant ourselves.
+ define('CONFIG_TABLE', $data['table_prefix'] . 'config');
+ }
+
+ $factory = new \phpbb\db\tools\factory();
+ $db_tools = $factory->get($db);
+ foreach ($db_table_schema as $table_name => $table_data)
+ {
+ $db_tools->sql_create_table(
+ $data['table_prefix'] . substr($table_name, 6),
+ $table_data
+ );
+ }
+
+ // Ok tables have been built, let's fill in the basic information
+ $sql_query = file_get_contents('schemas/schema_data.sql');
+
+ // Deal with any special comments and characters
+ switch ($data['dbms'])
+ {
+ case 'mssql':
+ case 'mssql_odbc':
+ case 'mssqlnative':
+ $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query);
+ break;
+
+ case 'postgres':
+ $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query);
+ break;
+
+ case 'mysql':
+ case 'mysqli':
+ $sql_query = str_replace('\\', '\\\\', $sql_query);
+ break;
+ }
+
+ // Change prefix
+ $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $data['table_prefix'] . '\1 ', $sql_query);
+
+ // Change language strings...
+ $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query);
+
+ $sql_query = phpbb_remove_comments($sql_query);
+ $sql_query = split_sql_file($sql_query, ';');
+
+ foreach ($sql_query as $sql)
+ {
+ //$sql = trim(str_replace('|', ';', $sql));
+ if (!$db->sql_query($sql))
+ {
+ $error = $db->sql_error();
+ $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
+ }
+ }
+ unset($sql_query);
+
+ $current_time = time();
+
+ $user_ip = $request->server('REMOTE_ADDR') ? phpbb_ip_normalise($request->server('REMOTE_ADDR')) : '';
+
+ if ($data['script_path'] !== '/')
+ {
+ // Adjust destination path (no trailing slash)
+ if (substr($data['script_path'], -1) == '/')
+ {
+ $data['script_path'] = substr($data['script_path'], 0, -1);
+ }
+
+ $data['script_path'] = str_replace(array('../', './'), '', $data['script_path']);
+
+ if ($data['script_path'][0] != '/')
+ {
+ $data['script_path'] = '/' . $data['script_path'];
+ }
+ }
+
+ // Set default config and post data, this applies to all DB's
+ $sql_ary = array(
+ 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
+ VALUES ('board_startdate', '$current_time')",
+
+ 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
+ VALUES ('default_lang', '" . $db->sql_escape($data['default_lang']) . "')",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['img_imagick']) . "'
+ WHERE config_name = 'img_imagick'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['server_name']) . "'
+ WHERE config_name = 'server_name'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['server_port']) . "'
+ WHERE config_name = 'server_port'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['board_email']) . "'
+ WHERE config_name = 'board_email'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['board_email']) . "'
+ WHERE config_name = 'board_contact'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($cookie_domain) . "'
+ WHERE config_name = 'cookie_domain'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "'
+ WHERE config_name = 'default_dateformat'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['email_enable']) . "'
+ WHERE config_name = 'email_enable'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['smtp_delivery']) . "'
+ WHERE config_name = 'smtp_delivery'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['smtp_host']) . "'
+ WHERE config_name = 'smtp_host'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['smtp_auth']) . "'
+ WHERE config_name = 'smtp_auth_method'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['smtp_user']) . "'
+ WHERE config_name = 'smtp_username'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['smtp_pass']) . "'
+ WHERE config_name = 'smtp_password'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['cookie_secure']) . "'
+ WHERE config_name = 'cookie_secure'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['force_server_vars']) . "'
+ WHERE config_name = 'force_server_vars'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['script_path']) . "'
+ WHERE config_name = 'script_path'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['server_protocol']) . "'
+ WHERE config_name = 'server_protocol'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($data['admin_name']) . "'
+ WHERE config_name = 'newest_username'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . md5(mt_rand()) . "'
+ WHERE config_name = 'avatar_salt'",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . md5(mt_rand()) . "'
+ WHERE config_name = 'plupload_salt'",
+
+ 'UPDATE ' . $data['table_prefix'] . "users
+ SET username = '" . $db->sql_escape($data['admin_name']) . "', user_password='" . $db->sql_escape(md5($data['admin_pass1'])) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($data['default_lang']) . "', user_email='" . $db->sql_escape($data['board_email']) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . $db->sql_escape(phpbb_email_hash($data['board_email'])) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($data['admin_name'])) . "'
+ WHERE username = 'Admin'",
+
+ 'UPDATE ' . $data['table_prefix'] . "moderator_cache
+ SET username = '" . $db->sql_escape($data['admin_name']) . "'
+ WHERE username = 'Admin'",
+
+ 'UPDATE ' . $data['table_prefix'] . "forums
+ SET forum_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
+ WHERE forum_last_poster_name = 'Admin'",
+
+ 'UPDATE ' . $data['table_prefix'] . "topics
+ SET topic_first_poster_name = '" . $db->sql_escape($data['admin_name']) . "', topic_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
+ WHERE topic_first_poster_name = 'Admin'
+ OR topic_last_poster_name = 'Admin'",
+
+ 'UPDATE ' . $data['table_prefix'] . "users
+ SET user_regdate = $current_time",
+
+ 'UPDATE ' . $data['table_prefix'] . "posts
+ SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'",
+
+ 'UPDATE ' . $data['table_prefix'] . "topics
+ SET topic_time = $current_time, topic_last_post_time = $current_time",
+
+ 'UPDATE ' . $data['table_prefix'] . "forums
+ SET forum_last_post_time = $current_time",
+
+ 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($db->sql_server_info(true)) . "'
+ WHERE config_name = 'dbms_version'",
+ );
+
+ if (@extension_loaded('gd'))
+ {
+ $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = 'core.captcha.plugins.gd'
+ WHERE config_name = 'captcha_plugin'";
+
+ $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '1'
+ WHERE config_name = 'captcha_gd'";
+ }
+
+ $ref = substr($referer, strpos($referer, '://') + 3);
+
+ if (!(stripos($ref, $server_name) === 0))
+ {
+ $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '0'
+ WHERE config_name = 'referer_validation'";
+ }
+
+ // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.
+ $cookie_name = 'phpbb3_';
+ $rand_str = md5(mt_rand());
+ $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35));
+ $rand_str = substr($rand_str, 0, 5);
+ $cookie_name .= strtolower($rand_str);
+
+ $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
+ SET config_value = '" . $db->sql_escape($cookie_name) . "'
+ WHERE config_name = 'cookie_name'";
+
+ foreach ($sql_ary as $sql)
+ {
+ //$sql = trim(str_replace('|', ';', $sql));
+
+ if (!$db->sql_query($sql))
+ {
+ $error = $db->sql_error();
+ $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
+ }
+ }
+
+ $submit = $lang['NEXT_STEP'];
+
+ $url = $this->p_master->module_url . "?mode=$mode&amp;sub=final";
+
+ $template->assign_vars(array(
+ 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'],
+ 'L_SUBMIT' => $submit,
+ 'S_HIDDEN' => build_hidden_fields($data),
+ 'U_ACTION' => $url,
+ ));
+ }
+
+ /**
+ * Build the search index...
+ */
+ function build_search_index($mode, $sub)
+ {
+ global $db, $lang, $phpbb_root_path, $phpbb_dispatcher, $phpEx, $config, $auth, $user;
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+ $table_prefix = $data['table_prefix'];
+
+ // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
+ $available_dbms = get_available_dbms($data['dbms']);
+
+ if (!isset($available_dbms[$data['dbms']]))
+ {
+ // Someone's been silly and tried providing a non-existant dbms
+ $this->p_master->redirect("index.$phpEx?mode=install");
+ }
+
+ $dbms = $available_dbms[$data['dbms']]['DRIVER'];
+
+ // Instantiate the database
+ $db = new $dbms();
+ $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
+
+ // NOTE: trigger_error does not work here.
+ $db->sql_return_on_error(true);
+
+ include_once($phpbb_root_path . 'includes/constants.' . $phpEx);
+ include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx);
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ $error = false;
+ $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
+
+ $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
+ FROM ' . POSTS_TABLE;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);
+ }
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * Populate the module tables
+ */
+ function add_modules($mode, $sub)
+ {
+ global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config, $phpbb_container;
+
+ // modules require an extension manager
+ if (empty($phpbb_extension_manager))
+ {
+ /* @var $phpbb_extension_manager \phpbb\extension\manager */
+ $phpbb_extension_manager = $phpbb_container->get('ext.manager');
+ }
+
+ $_module = new \phpbb\module\module_manager(
+ new \phpbb\cache\driver\dummy(),
+ $db,
+ $phpbb_extension_manager,
+ MODULES_TABLE,
+ $phpbb_root_path,
+ $phpEx
+ );
+ $module_classes = array('acp', 'mcp', 'ucp');
+
+ // Add categories
+ foreach ($module_classes as $module_class)
+ {
+ $categories = array();
+
+ // Set the module class
+ $_module->module_class = $module_class;
+
+ foreach ($this->module_categories[$module_class] as $cat_name => $subs)
+ {
+ $basename = '';
+ // Check if this sub-category has a basename. If it has, use it.
+ if (isset($this->module_categories_basenames[$cat_name]))
+ {
+ $basename = $this->module_categories_basenames[$cat_name];
+ }
+ $module_data = array(
+ 'module_basename' => $basename,
+ 'module_enabled' => 1,
+ 'module_display' => 1,
+ 'parent_id' => 0,
+ 'module_class' => $module_class,
+ 'module_langname' => $cat_name,
+ 'module_mode' => '',
+ 'module_auth' => '',
+ );
+
+ // Add category
+ $_module->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($db->get_sql_error_triggered())
+ {
+ $error = $db->sql_error($db->get_sql_error_sql());
+ $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
+ }
+
+ $categories[$cat_name]['id'] = (int) $module_data['module_id'];
+ $categories[$cat_name]['parent_id'] = 0;
+
+ // Create sub-categories...
+ if (is_array($subs))
+ {
+ foreach ($subs as $level2_name)
+ {
+ $basename = '';
+ // Check if this sub-category has a basename. If it has, use it.
+ if (isset($this->module_categories_basenames[$level2_name]))
+ {
+ $basename = $this->module_categories_basenames[$level2_name];
+ }
+ $module_data = array(
+ 'module_basename' => $basename,
+ 'module_enabled' => 1,
+ 'module_display' => 1,
+ 'parent_id' => (int) $categories[$cat_name]['id'],
+ 'module_class' => $module_class,
+ 'module_langname' => $level2_name,
+ 'module_mode' => '',
+ 'module_auth' => '',
+ );
+
+ $_module->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($db->get_sql_error_triggered())
+ {
+ $error = $db->sql_error($db->get_sql_error_sql());
+ $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
+ }
+
+ $categories[$level2_name]['id'] = (int) $module_data['module_id'];
+ $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id'];
+ }
+ }
+ }
+
+ // Get the modules we want to add... returned sorted by name
+ $module_info = $_module->get_module_infos($module_class);
+
+ foreach ($module_info as $module_basename => $fileinfo)
+ {
+ foreach ($fileinfo['modes'] as $module_mode => $row)
+ {
+ foreach ($row['cat'] as $cat_name)
+ {
+ if (!isset($categories[$cat_name]))
+ {
+ continue;
+ }
+
+ $module_data = array(
+ 'module_basename' => $module_basename,
+ 'module_enabled' => 1,
+ 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1,
+ 'parent_id' => (int) $categories[$cat_name]['id'],
+ 'module_class' => $module_class,
+ 'module_langname' => $row['title'],
+ 'module_mode' => $module_mode,
+ 'module_auth' => $row['auth'],
+ );
+
+ $_module->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($db->get_sql_error_triggered())
+ {
+ $error = $db->sql_error($db->get_sql_error_sql());
+ $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
+ }
+ }
+ }
+ }
+
+ // Move some of the modules around since the code above will put them in the wrong place
+ if ($module_class == 'acp')
+ {
+ // Move main module 4 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_main'
+ AND module_class = 'acp'
+ AND module_mode = 'main'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'acp', 'move_up', 4);
+
+ // Move permissions intro screen module 4 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_permissions'
+ AND module_class = 'acp'
+ AND module_mode = 'intro'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'acp', 'move_up', 4);
+
+ // Move manage users screen module 5 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'acp_users'
+ AND module_class = 'acp'
+ AND module_mode = 'overview'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'acp', 'move_up', 5);
+
+ // Move extension management module 1 up...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT'
+ AND module_class = 'acp'
+ AND module_mode = ''
+ AND module_basename = ''";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'acp', 'move_up', 1);
+ }
+
+ if ($module_class == 'mcp')
+ {
+ // Move pm report details module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_report_details'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'mcp', 'move_down', 3);
+
+ // Move closed pm reports module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_reports_closed'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'mcp', 'move_down', 3);
+
+ // Move open pm reports module 3 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'mcp_pm_reports'
+ AND module_class = 'mcp'
+ AND module_mode = 'pm_reports'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'mcp', 'move_down', 3);
+ }
+
+ if ($module_class == 'ucp')
+ {
+ // Move attachment module 4 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_attachments'
+ AND module_class = 'ucp'
+ AND module_mode = 'attachments'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'ucp', 'move_down', 4);
+
+ // Move notification options module 4 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_notifications'
+ AND module_class = 'ucp'
+ AND module_mode = 'notification_options'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'ucp', 'move_down', 4);
+
+ // Move OAuth module 5 down...
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_basename = 'ucp_auth_link'
+ AND module_class = 'ucp'
+ AND module_mode = 'auth_link'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $_module->move_module_by($row, 'ucp', 'move_down', 5);
+ }
+
+ // And now for the special ones
+ // (these are modules which appear in multiple categories and thus get added manually to some for more control)
+ if (isset($this->module_extras[$module_class]))
+ {
+ foreach ($this->module_extras[$module_class] as $cat_name => $mods)
+ {
+ $sql = 'SELECT module_id, left_id, right_id
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = '" . $db->sql_escape($cat_name) . "'
+ AND module_class = '" . $db->sql_escape($module_class) . "'";
+ $result = $db->sql_query_limit($sql, 1);
+ $row2 = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ foreach ($mods as $mod_name)
+ {
+ $sql = 'SELECT *
+ FROM ' . MODULES_TABLE . "
+ WHERE module_langname = '" . $db->sql_escape($mod_name) . "'
+ AND module_class = '" . $db->sql_escape($module_class) . "'
+ AND module_basename <> ''";
+ $result = $db->sql_query_limit($sql, 1);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $module_data = array(
+ 'module_basename' => $row['module_basename'],
+ 'module_enabled' => (int) $row['module_enabled'],
+ 'module_display' => (int) $row['module_display'],
+ 'parent_id' => (int) $row2['module_id'],
+ 'module_class' => $row['module_class'],
+ 'module_langname' => $row['module_langname'],
+ 'module_mode' => $row['module_mode'],
+ 'module_auth' => $row['module_auth'],
+ );
+
+ $_module->update_module_data($module_data);
+
+ // Check for last sql error happened
+ if ($db->get_sql_error_triggered())
+ {
+ $error = $db->sql_error($db->get_sql_error_sql());
+ $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
+ }
+ }
+ }
+ }
+
+ $_module->remove_cache_file($module_class);
+ }
+ }
+
+ /**
+ * Populate the language tables
+ */
+ function add_language($mode, $sub)
+ {
+ global $db, $lang, $phpbb_root_path, $phpEx;
+
+ $dir = @opendir($phpbb_root_path . 'language');
+
+ if (!$dir)
+ {
+ $this->error('Unable to access the language directory', __LINE__, __FILE__);
+ }
+
+ $installed_languages = array();
+ while (($file = readdir($dir)) !== false)
+ {
+ $path = $phpbb_root_path . 'language/' . $file;
+
+ if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
+ {
+ continue;
+ }
+
+ if (is_dir($path) && file_exists($path . '/iso.txt'))
+ {
+ $lang_file = file("$path/iso.txt");
+
+ $lang_pack = array(
+ 'lang_iso' => basename($path),
+ 'lang_dir' => basename($path),
+ 'lang_english_name' => trim(htmlspecialchars($lang_file[0])),
+ 'lang_local_name' => trim(htmlspecialchars($lang_file[1], ENT_COMPAT, 'UTF-8')),
+ 'lang_author' => trim(htmlspecialchars($lang_file[2], ENT_COMPAT, 'UTF-8')),
+ );
+
+ $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $lang_pack));
+
+ $installed_languages[] = (int) $db->sql_nextid();
+ if ($db->get_sql_error_triggered())
+ {
+ $error = $db->sql_error($db->get_sql_error_sql());
+ $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
+ }
+ }
+ }
+ closedir($dir);
+
+ $sql = 'SELECT *
+ FROM ' . PROFILE_FIELDS_TABLE;
+ $result = $db->sql_query($sql);
+
+ $profile_fields = array();
+ $insert_buffer = new \phpbb\db\sql_insert_buffer($db, PROFILE_LANG_TABLE);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ foreach ($installed_languages as $lang_id)
+ {
+ $insert_buffer->insert(array(
+ 'field_id' => $row['field_id'],
+ 'lang_id' => $lang_id,
+ 'lang_name' => strtoupper(substr($row['field_name'], 6)),// Remove phpbb_ from field name
+ 'lang_explain' => '',
+ 'lang_default_value' => '',
+ ));
+ }
+ }
+ $db->sql_freeresult($result);
+
+ $insert_buffer->flush();
+ }
+
+ /**
+ * Add search robots to the database
+ */
+ function add_bots($mode, $sub)
+ {
+ global $db, $lang, $phpbb_root_path, $phpEx, $config;
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = 'BOTS'";
+ $result = $db->sql_query($sql);
+ $group_id = (int) $db->sql_fetchfield('group_id');
+ $db->sql_freeresult($result);
+
+ if (!$group_id)
+ {
+ // If we reach this point then something has gone very wrong
+ $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__);
+ }
+
+ if (!function_exists('user_add'))
+ {
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ }
+
+ foreach ($this->bot_list as $bot_name => $bot_ary)
+ {
+ $user_row = array(
+ 'user_type' => USER_IGNORE,
+ 'group_id' => $group_id,
+ 'username' => $bot_name,
+ 'user_regdate' => time(),
+ 'user_password' => '',
+ 'user_colour' => '9E8DA7',
+ 'user_email' => '',
+ 'user_lang' => $data['default_lang'],
+ 'user_style' => 1,
+ 'user_timezone' => 'UTC',
+ 'user_dateformat' => $lang['default_dateformat'],
+ 'user_allow_massemail' => 0,
+ 'user_allow_pm' => 0,
+ );
+
+ $user_id = user_add($user_row);
+
+ if (!$user_id)
+ {
+ // If we can't insert this user then continue to the next one to avoid inconsistent data
+ $this->p_master->db_error('Unable to insert bot into users table', $db->get_sql_error_sql(), __LINE__, __FILE__, true);
+ continue;
+ }
+
+ $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
+ 'bot_active' => 1,
+ 'bot_name' => (string) $bot_name,
+ 'user_id' => (int) $user_id,
+ 'bot_agent' => (string) $bot_ary[0],
+ 'bot_ip' => (string) $bot_ary[1],
+ ));
+
+ $db->sql_query($sql);
+ }
+ }
+
+ /**
+ * Sends an email to the board administrator with their password and some useful links
+ */
+ function email_admin($mode, $sub)
+ {
+ global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log;
+
+ $this->page_title = $lang['STAGE_FINAL'];
+
+ // Obtain any submitted data
+ $data = $this->get_submitted_data();
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ $user->session_begin();
+ $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true);
+
+ // OK, Now that we've reached this point we can be confident that everything
+ // is installed and working......I hope :)
+ // So it's time to send an email to the administrator confirming the details
+ // they entered
+
+ if ($config['email_enable'])
+ {
+ include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
+
+ $messenger = new messenger(false);
+
+ $messenger->template('installed', $data['language']);
+
+ $messenger->to($data['board_email'], $data['admin_name']);
+
+ $messenger->anti_abuse_headers($config, $user);
+
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($data['admin_name']),
+ 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1']))
+ );
+
+ $messenger->send(NOTIFY_EMAIL);
+ }
+
+ // And finally, add a note to the log
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_INSTALLED', false, array($config['version']));
+
+ $template->assign_vars(array(
+ 'TITLE' => $lang['INSTALL_CONGRATS'],
+ 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&amp;language=' . $data['language']), '../docs/README.html'),
+ 'L_SUBMIT' => $lang['INSTALL_LOGIN'],
+ 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&amp;mode=send_statistics'),
+ ));
+ }
+
+ /**
+ * Check if the avatar directory is writable and disable avatars
+ * if it isn't writable.
+ */
+ function disable_avatars_if_unwritable()
+ {
+ global $config, $phpbb_root_path;
+
+ if (!$this->filesystem->is_writable($phpbb_root_path . 'images/avatars/upload/'))
+ {
+ $config->set('allow_avatar', 0);
+ $config->set('allow_avatar_upload', 0);
+ }
+ }
+
+ /**
+ * Populate migrations for the installation
+ *
+ * This "installs" all migrations from (root path)/phpbb/db/migrations/data.
+ * "installs" means it adds all migrations to the migrations table, but does not
+ * perform any of the actions in the migrations.
+ *
+ * @param \phpbb\extension\manager $extension_manager
+ * @param \phpbb\db\migrator $migrator
+ */
+ function populate_migrations($extension_manager, $migrator)
+ {
+ $finder = $extension_manager->get_finder();
+
+ $migrations = $finder
+ ->core_path('phpbb/db/migration/data/')
+ ->get_classes();
+ $migrator->populate_migrations($migrations);
+ }
+
+ /**
+ * Generate a list of available mail server authentication methods
+ */
+ function mail_auth_select($selected_method)
+ {
+ global $lang;
+
+ $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP');
+ $s_smtp_auth_options = '';
+
+ foreach ($auth_methods as $method)
+ {
+ $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $lang['SMTP_' . str_replace('-', '_', $method)] . '</option>';
+ }
+
+ return $s_smtp_auth_options;
+ }
+
+ /**
+ * Get submitted data
+ */
+ function get_submitted_data()
+ {
+ global $request;
+
+ return array(
+ 'language' => basename($request->variable('language', '')),
+ 'dbms' => $request->variable('dbms', ''),
+ 'dbhost' => $request->variable('dbhost', ''),
+ 'dbport' => $request->variable('dbport', ''),
+ 'dbuser' => $request->variable('dbuser', ''),
+ 'dbpasswd' => $request->variable('dbpasswd', '', true),
+ 'dbname' => $request->variable('dbname', ''),
+ 'table_prefix' => $request->variable('table_prefix', ''),
+ 'default_lang' => basename($request->variable('default_lang', '')),
+ 'admin_name' => $request->variable('admin_name', '', true),
+ 'admin_pass1' => $request->variable('admin_pass1', '', true),
+ 'admin_pass2' => $request->variable('admin_pass2', '', true),
+ 'board_email' => strtolower($request->variable('board_email', '')),
+ 'img_imagick' => $request->variable('img_imagick', ''),
+ 'ftp_path' => $request->variable('ftp_path', ''),
+ 'ftp_user' => $request->variable('ftp_user', ''),
+ 'ftp_pass' => $request->variable('ftp_pass', ''),
+ 'email_enable' => $request->variable('email_enable', ''),
+ 'smtp_delivery' => $request->variable('smtp_delivery', ''),
+ 'smtp_host' => $request->variable('smtp_host', ''),
+ 'smtp_auth' => $request->variable('smtp_auth', ''),
+ 'smtp_user' => $request->variable('smtp_user', ''),
+ 'smtp_pass' => $request->variable('smtp_pass', ''),
+ 'cookie_secure' => $request->variable('cookie_secure', ''),
+ 'force_server_vars' => $request->variable('force_server_vars', ''),
+ 'server_protocol' => $request->variable('server_protocol', ''),
+ 'server_name' => $request->variable('server_name', ''),
+ 'server_port' => $request->variable('server_port', ''),
+ 'script_path' => $request->variable('script_path', ''),
+ );
+ }
+
+ /**
+ * The information below will be used to build the input fields presented to the user
+ */
+ var $db_config_options = array(
+ 'legend1' => 'DB_CONFIG',
+ 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false),
+ 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
+ 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
+ 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
+ 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
+ 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
+ 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true),
+ );
+ var $admin_config_options = array(
+ 'legend1' => 'ADMIN_CONFIG',
+ 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false),
+ 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true),
+ 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true),
+ 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false),
+ 'board_email' => array('lang' => 'CONTACT_EMAIL', 'type' => 'email:25:100', 'explain' => false),
+ );
+ var $advanced_config_options = array(
+ 'legend1' => 'ACP_EMAIL_SETTINGS',
+ 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true),
+ 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true),
+ 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false),
+ 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true),
+ 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
+ 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
+
+ 'legend2' => 'SERVER_URL_SETTINGS',
+ 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true),
+ 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true),
+ 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true),
+ 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true),
+ 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true),
+ 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true),
+ );
+
+ /**
+ * Specific PHP modules we may require for certain optional or extended features
+ */
+ var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml');
+
+ /**
+ * A list of the web-crawlers/bots we recognise by default
+ *
+ * Candidates but not included:
+ * 'Accoona [Bot]' 'Accoona-AI-Agent/'
+ * 'ASPseek [Crawler]' 'ASPseek/'
+ * 'Boitho [Crawler]' 'boitho.com-dc/'
+ * 'Bunnybot [Bot]' 'powered by www.buncat.de'
+ * 'Cosmix [Bot]' 'cfetch/'
+ * 'Crawler Search [Crawler]' '.Crawler-Search.de'
+ * 'Findexa [Crawler]' 'Findexa Crawler ('
+ * 'GBSpider [Spider]' 'GBSpider v'
+ * 'genie [Bot]' 'genieBot ('
+ * 'Hogsearch [Bot]' 'oegp v. 1.3.0'
+ * 'Insuranco [Bot]' 'InsurancoBot'
+ * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler'
+ * 'ISC Systems [Bot]' 'ISC Systems iRc Search'
+ * 'Jyxobot [Bot]' 'Jyxobot/'
+ * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/'
+ * 'LinkWalker' 'LinkWalker'
+ * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html'
+ * 'Naver [Bot]' 'nhnbot@naver.com)'
+ * 'NetResearchServer' 'NetResearchServer/'
+ * 'Nimble [Crawler]' 'NimbleCrawler'
+ * 'Ocelli [Bot]' 'Ocelli/'
+ * 'Onsearch [Bot]' 'onCHECK-Robot'
+ * 'Orange [Spider]' 'OrangeSpider'
+ * 'Sproose [Bot]' 'http://www.sproose.com/bot'
+ * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)'
+ * 'Tbot [Bot]' 'Tbot/'
+ * 'Thumbshots [Capture]' 'thumbshots-de-Bot'
+ * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/'
+ * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)'
+ * 'WissenOnline [Bot]' 'WissenOnline-Bot'
+ * 'WWWeasel [Bot]' 'WWWeasel Robot v'
+ * 'Xaldon [Spider]' 'Xaldon WebSpider'
+ */
+ var $bot_list = array(
+ 'AdsBot [Google]' => array('AdsBot-Google', ''),
+ 'Alexa [Bot]' => array('ia_archiver', ''),
+ 'Alta Vista [Bot]' => array('Scooter/', ''),
+ 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
+ 'Baidu [Spider]' => array('Baiduspider', ''),
+ 'Bing [Bot]' => array('bingbot/', ''),
+ 'Exabot [Bot]' => array('Exabot', ''),
+ 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
+ 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
+ 'Francis [Bot]' => array('http://www.neomo.de/', ''),
+ 'Gigabot [Bot]' => array('Gigabot/', ''),
+ 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
+ 'Google Desktop' => array('Google Desktop', ''),
+ 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
+ 'Google [Bot]' => array('Googlebot', ''),
+ 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
+ 'Heritrix [Crawler]' => array('heritrix/1.', ''),
+ 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
+ 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
+ 'ichiro [Crawler]' => array('ichiro/', ''),
+ 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
+ 'Metager [Bot]' => array('MetagerBot/', ''),
+ 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
+ 'MSN [Bot]' => array('msnbot/', ''),
+ 'MSNbot Media' => array('msnbot-media/', ''),
+ 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
+ 'Online link [Validator]' => array('online link validator', ''),
+ 'psbot [Picsearch]' => array('psbot/0', ''),
+ 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
+ 'SEO Crawler' => array('SEO search Crawler/', ''),
+ 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
+ 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
+ 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
+ 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
+ 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
+ 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
+ 'Voyager [Bot]' => array('voyager/', ''),
+ 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
+ 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
+ 'W3C [Validator]' => array('W3C_Validator', ''),
+ 'YaCy [Bot]' => array('yacybot', ''),
+ 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
+ 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
+ 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
+ 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
+ );
+
+ /**
+ * Define the module structure so that we can populate the database without
+ * needing to hard-code module_id values
+ */
+ var $module_categories = array(
+ 'acp' => array(
+ 'ACP_CAT_GENERAL' => array(
+ 'ACP_QUICK_ACCESS',
+ 'ACP_BOARD_CONFIGURATION',
+ 'ACP_CLIENT_COMMUNICATION',
+ 'ACP_SERVER_CONFIGURATION',
+ ),
+ 'ACP_CAT_FORUMS' => array(
+ 'ACP_MANAGE_FORUMS',
+ 'ACP_FORUM_BASED_PERMISSIONS',
+ ),
+ 'ACP_CAT_POSTING' => array(
+ 'ACP_MESSAGES',
+ 'ACP_ATTACHMENTS',
+ ),
+ 'ACP_CAT_USERGROUP' => array(
+ 'ACP_CAT_USERS',
+ 'ACP_GROUPS',
+ 'ACP_USER_SECURITY',
+ ),
+ 'ACP_CAT_PERMISSIONS' => array(
+ 'ACP_GLOBAL_PERMISSIONS',
+ 'ACP_FORUM_BASED_PERMISSIONS',
+ 'ACP_PERMISSION_ROLES',
+ 'ACP_PERMISSION_MASKS',
+ ),
+ 'ACP_CAT_CUSTOMISE' => array(
+ 'ACP_STYLE_MANAGEMENT',
+ 'ACP_EXTENSION_MANAGEMENT',
+ 'ACP_LANGUAGE',
+ ),
+ 'ACP_CAT_MAINTENANCE' => array(
+ 'ACP_FORUM_LOGS',
+ 'ACP_CAT_DATABASE',
+ ),
+ 'ACP_CAT_SYSTEM' => array(
+ 'ACP_AUTOMATION',
+ 'ACP_GENERAL_TASKS',
+ 'ACP_MODULE_MANAGEMENT',
+ ),
+ 'ACP_CAT_DOT_MODS' => null,
+ ),
+ 'mcp' => array(
+ 'MCP_MAIN' => null,
+ 'MCP_QUEUE' => null,
+ 'MCP_REPORTS' => null,
+ 'MCP_NOTES' => null,
+ 'MCP_WARN' => null,
+ 'MCP_LOGS' => null,
+ 'MCP_BAN' => null,
+ ),
+ 'ucp' => array(
+ 'UCP_MAIN' => null,
+ 'UCP_PROFILE' => null,
+ 'UCP_PREFS' => null,
+ 'UCP_PM' => null,
+ 'UCP_USERGROUPS' => null,
+ 'UCP_ZEBRA' => null,
+ ),
+ );
+ var $module_categories_basenames = array(
+ 'UCP_PM' => 'ucp_pm',
+ );
+
+ var $module_extras = array(
+ 'acp' => array(
+ 'ACP_QUICK_ACCESS' => array(
+ 'ACP_MANAGE_USERS',
+ 'ACP_GROUPS_MANAGE',
+ 'ACP_MANAGE_FORUMS',
+ 'ACP_MOD_LOGS',
+ 'ACP_BOTS',
+ 'ACP_PHP_INFO',
+ ),
+ 'ACP_FORUM_BASED_PERMISSIONS' => array(
+ 'ACP_FORUM_PERMISSIONS',
+ 'ACP_FORUM_PERMISSIONS_COPY',
+ 'ACP_FORUM_MODERATORS',
+ 'ACP_USERS_FORUM_PERMISSIONS',
+ 'ACP_GROUPS_FORUM_PERMISSIONS',
+ ),
+ ),
+ );
+}
diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php
new file mode 100644
index 0000000000..d5874dac83
--- /dev/null
+++ b/phpBB/install/install_main.php
@@ -0,0 +1,78 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+*/
+
+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' => 'OVERVIEW',
+ 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
+ 'module_order' => 0,
+ 'module_subs' => array('INTRO', 'LICENSE', 'SUPPORT'),
+ 'module_stages' => '',
+ 'module_reqs' => ''
+ );
+}
+
+/**
+* Main Tab - Installation
+*/
+class install_main extends module
+{
+ function install_main(&$p_master)
+ {
+ $this->p_master = &$p_master;
+ }
+
+ function main($mode, $sub)
+ {
+ global $lang, $template, $language;
+
+ switch ($sub)
+ {
+ case 'intro' :
+ $title = $lang['SUB_INTRO'];
+ $body = $lang['OVERVIEW_BODY'];
+ break;
+
+ case 'license' :
+ $title = $lang['GPL'];
+ $body = implode("<br/>\n", file(__DIR__ . '/../docs/LICENSE.txt'));
+ break;
+
+ case 'support' :
+ $title = $lang['SUB_SUPPORT'];
+ $body = $lang['SUPPORT_BODY'];
+ break;
+ }
+
+ $this->tpl_name = 'install_main';
+ $this->page_title = $title;
+
+ $template->assign_vars(array(
+ 'TITLE' => $title,
+ 'BODY' => $body,
+
+ 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
+ ));
+ }
+}
diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php
new file mode 100644
index 0000000000..d9ba2e7fe9
--- /dev/null
+++ b/phpBB/install/install_update.php
@@ -0,0 +1,1790 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+/**
+* @todo check for writable cache/store/files directory
+*/
+
+if (!defined('IN_INSTALL'))
+{
+ // Someone has tried to access the file directly. This is not a good idea, so exit
+ exit;
+}
+
+if (!empty($setmodules))
+{
+ // If phpBB is not installed we do not include this module
+ if (!phpbb_check_installation_exists($phpbb_root_path, $phpEx) || file_exists($phpbb_root_path . 'cache/install_lock'))
+ {
+ return;
+ }
+
+ $module[] = array(
+ 'module_type' => 'update',
+ 'module_title' => 'UPDATE',
+ 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
+ 'module_order' => 30,
+ 'module_subs' => '',
+ 'module_stages' => array('INTRO', 'VERSION_CHECK', 'FILE_CHECK', 'UPDATE_FILES', 'UPDATE_DB'),
+ 'module_reqs' => ''
+ );
+}
+
+/**
+* Update Installation
+*/
+class install_update extends module
+{
+ var $p_master;
+ var $update_info;
+
+ var $old_location;
+ var $new_location;
+ var $latest_version;
+ var $current_version;
+
+ var $update_to_version;
+
+ protected $filesystem;
+
+ // Set to false
+ var $test_update = false;
+
+ function install_update(&$p_master)
+ {
+ $this->p_master = &$p_master;
+ }
+
+ function main($mode, $sub)
+ {
+ global $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language;
+ global $request, $phpbb_admin_path, $phpbb_adm_relative_path, $phpbb_container, $phpbb_config_php_file;
+
+ // We must enable super globals, otherwise creating a new instance of the request class,
+ // using the new container with a dbal connection will fail with the following PHP Notice:
+ // Object of class phpbb_request_deactivated_super_global could not be converted to int
+ $request->enable_super_globals();
+
+ // Create a normal container now
+ $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $phpbb_container = $phpbb_container_builder
+ ->with_config($phpbb_config_php_file)
+ ->without_cache()
+ ->without_extensions()
+ ;
+
+ if (file_exists($phpbb_root_path . 'install/update/new/config'))
+ {
+ $phpbb_container_builder->with_config_path($phpbb_root_path . 'install/update/new/config');
+ }
+ $phpbb_container = $phpbb_container_builder->get_container();
+
+ // Writes into global $cache
+ /* @var $cache \phpbb\cache\service */
+ $cache = $phpbb_container->get('cache');
+
+ $this->filesystem = $phpbb_container->get('filesystem');
+
+ $this->tpl_name = 'install_update';
+ $this->page_title = 'UPDATE_INSTALLATION';
+
+ $this->old_location = $phpbb_root_path . 'install/update/old/';
+ $this->new_location = $phpbb_root_path . 'install/update/new/';
+
+ // Init DB
+ extract($phpbb_config_php_file->get_all());
+ require($phpbb_root_path . 'includes/constants.' . $phpEx);
+
+ // Special options for conflicts/modified files
+ define('MERGE_NO_MERGE_NEW', 1);
+ define('MERGE_NO_MERGE_MOD', 2);
+ define('MERGE_NEW_FILE', 3);
+ define('MERGE_MOD_FILE', 4);
+
+ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
+
+ $db = new $dbms();
+
+ // Connect to DB
+ $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
+
+ // We do not need this any longer, unset for safety purposes
+ unset($dbpasswd);
+
+ // We need to fill the config to let internal functions correctly work
+ $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
+
+ // Force template recompile
+ $config['load_tplcompile'] = 1;
+
+ // First of all, init the user session
+ $user->session_begin();
+ $auth->acl($user->data);
+
+ // Overwrite user's language with the selected one.
+ // Config needs to be changed to ensure that guests also get the selected language.
+ $config_default_lang = $config['default_lang'];
+ $config['default_lang'] = $language;
+ $user->data['user_lang'] = $language;
+
+ $user->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+ // Reset the default_lang
+ $config['default_lang'] = $config_default_lang;
+ unset($config_default_lang);
+
+ // If we are within the intro page we need to make sure we get up-to-date version info
+ if ($sub == 'intro')
+ {
+ $cache->destroy('_version_info');
+ }
+
+ // Set custom template again. ;)
+ $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
+ $paths = array_filter($paths, 'is_dir');
+ $template->set_custom_style(array(
+ array(
+ 'name' => 'adm',
+ 'ext_path' => 'adm/style/',
+ ),
+ ), $paths);
+
+ $template->assign_vars(array(
+ 'S_USER_LANG' => $user->lang['USER_LANG'],
+ 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
+ 'S_CONTENT_ENCODING' => 'UTF-8',
+ 'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
+ 'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
+ ));
+
+ // Get current and latest version
+ /* @var $version_helper \phpbb\version_helper */
+ $version_helper = $phpbb_container->get('version_helper');
+ try
+ {
+ $this->latest_version = $version_helper->get_latest_on_current_branch(true);
+ }
+ catch (\RuntimeException $e)
+ {
+ $this->latest_version = false;
+
+ $update_info = array();
+ include($phpbb_root_path . 'install/update/index.' . $phpEx);
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+
+ if ($info !== false)
+ {
+ $this->latest_version = (!empty($info['version']['to'])) ? trim($info['version']['to']) : false;
+ }
+ }
+
+ // For the current version we trick a bit. ;)
+ $this->current_version = (!empty($config['version_update_from'])) ? $config['version_update_from'] : $config['version'];
+
+ $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->latest_version)), '<')) ? false : true;
+
+ // Check for a valid update directory, else point the user to the phpbb.com website
+ if (!file_exists($phpbb_root_path . 'install/update') || !file_exists($phpbb_root_path . 'install/update/index.' . $phpEx) || !file_exists($this->old_location) || !file_exists($this->new_location))
+ {
+ $template->assign_vars(array(
+ 'S_ERROR' => true,
+ 'ERROR_MSG' => ($up_to_date) ? $user->lang['NO_UPDATE_FILES_UP_TO_DATE'] : sprintf($user->lang['NO_UPDATE_FILES_OUTDATED'], $config['version'], $this->current_version, $this->latest_version))
+ );
+
+ return;
+ }
+
+ $this->update_info = $this->get_file('update_info');
+
+ // Make sure the update directory holds the correct information
+ // Since admins are able to run the update/checks more than once we only check if the current version is lower or equal than the version to which we update to.
+ if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '>'))
+ {
+ $template->assign_vars(array(
+ 'S_ERROR' => true,
+ 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $config['version'], $this->update_info['version']['from'], $this->update_info['version']['to']))
+ );
+
+ return;
+ }
+
+ // Check if the update files are actually meant to update from the current version
+ if ($this->current_version != $this->update_info['version']['from'])
+ {
+ $template->assign_vars(array(
+ 'S_ERROR' => true,
+ 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $this->current_version, $this->update_info['version']['from'], $this->update_info['version']['to']),
+ ));
+ }
+
+ // Check if the update files stored are for the latest version...
+ if (version_compare(strtolower($this->latest_version), strtolower($this->update_info['version']['to']), '>'))
+ {
+ $template->assign_vars(array(
+ 'S_WARNING' => true,
+ 'WARNING_MSG' => sprintf($user->lang['OLD_UPDATE_FILES'], $this->update_info['version']['from'], $this->update_info['version']['to'], $this->latest_version))
+ );
+ }
+
+ // We store the "update to" version, because it is not always the latest. ;)
+ $this->update_to_version = $this->update_info['version']['to'];
+
+ // Fill DB version
+ if (empty($config['dbms_version']))
+ {
+ $config->set('dbms_version', $db->sql_server_info(true));
+ }
+
+ if ($this->test_update === false)
+ {
+ // What about the language file? Got it updated?
+ if (in_array('language/' . $language . '/install.' . $phpEx, $this->update_info['files']))
+ {
+ $lang = array();
+ include($this->new_location . 'language/' . $language . '/install.' . $phpEx);
+ // this is the user's language.. just merge it
+ $user->lang = array_merge($user->lang, $lang);
+ }
+ if ($language != 'en' && in_array('language/en/install.' . $phpEx, $this->update_info['files']))
+ {
+ $lang = array();
+ include($this->new_location . 'language/en/install.' . $phpEx);
+ // only add new keys to user's language in english
+ $new_keys = array_diff(array_keys($lang), array_keys($user->lang));
+ foreach ($new_keys as $i => $new_key)
+ {
+ $user->lang[$new_key] = $lang[$new_key];
+ }
+ }
+ }
+
+ // Include renderer and engine
+ $this->include_file('includes/diff/diff.' . $phpEx);
+ $this->include_file('includes/diff/engine.' . $phpEx);
+ $this->include_file('includes/diff/renderer.' . $phpEx);
+
+ // Make sure we stay at the file check if checking the files again
+ if ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST))
+ {
+ $sub = $this->p_master->sub = 'file_check';
+ }
+
+ switch ($sub)
+ {
+ case 'intro':
+ $this->page_title = 'UPDATE_INSTALLATION';
+
+ $template->assign_vars(array(
+ 'S_INTRO' => true,
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=version_check"),
+ ));
+
+ // Make sure the update list is destroyed.
+ $cache->destroy('_update_list');
+ $cache->destroy('_diff_files');
+ $cache->destroy('_expected_files');
+ break;
+
+ case 'version_check':
+ $this->page_title = 'STAGE_VERSION_CHECK';
+
+ $template->assign_vars(array(
+ 'S_VERSION_CHECK' => true,
+
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
+
+ 'S_UP_TO_DATE' => $up_to_date,
+ 'LATEST_VERSION' => $this->latest_version,
+ 'CURRENT_VERSION' => $this->current_version,
+ ));
+
+ // Print out version the update package updates to
+ if ($this->latest_version != $this->update_info['version']['to'])
+ {
+ $template->assign_var('PACKAGE_VERSION', $this->update_info['version']['to']);
+ }
+
+ // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
+ // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
+ // We now try to cope with this by triggering the update process
+ if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
+ {
+ $template->assign_vars(array(
+ 'S_UP_TO_DATE' => false,
+ ));
+ }
+
+ break;
+
+ case 'update_db':
+ // Redirect the user to the database update script with some explanations...
+ $template->assign_vars(array(
+ 'S_DB_UPDATE' => true,
+ 'S_DB_UPDATE_FINISHED' => ($config['version'] == $this->update_info['version']['to']) ? true : false,
+ 'U_DB_UPDATE' => append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=1&amp;language=' . $user->data['user_lang']),
+ 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
+ 'L_EVERYTHING_UP_TO_DATE' => $user->lang('EVERYTHING_UP_TO_DATE', append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login&amp;redirect=' . $phpbb_adm_relative_path . 'index.php%3Fi=send_statistics%26mode=send_statistics')),
+ ));
+
+ // Do not display incompatible package note after successful update
+ if ($config['version'] == $this->update_info['version']['to'])
+ {
+ $template->assign_var('S_ERROR', false);
+ }
+ break;
+
+ case 'file_check':
+
+ // retrieve info on what changes should have already been made to the files.
+ $expected_files = $cache->get('_expected_files');
+ if (!$expected_files)
+ {
+ $expected_files = array();
+ }
+
+ // Now make sure the previous file collection is no longer valid...
+ $cache->destroy('_diff_files');
+
+ $this->page_title = 'STAGE_FILE_CHECK';
+
+ // Now make sure our update list is correct if the admin refreshes
+ $action = $request->variable('action', '');
+
+ // We are directly within an update. To make sure our update list is correct we check its status.
+ $update_list = ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST)) ? false : $cache->get('_update_list');
+ $modified = ($update_list !== false) ? @filemtime($cache->get_driver()->cache_dir . 'data_update_list.' . $phpEx) : 0;
+
+ // Make sure the list is up-to-date
+ if ($update_list !== false)
+ {
+ $get_new_list = false;
+ foreach ($this->update_info['files'] as $file)
+ {
+ if (file_exists($phpbb_root_path . $file) && filemtime($phpbb_root_path . $file) > $modified)
+ {
+ $get_new_list = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ $get_new_list = true;
+ }
+
+ if (!$get_new_list && $update_list['status'] != -1)
+ {
+ $get_new_list = true;
+ }
+
+ if ($get_new_list)
+ {
+ $this->get_update_structure($update_list, $expected_files);
+ $cache->put('_update_list', $update_list);
+
+ // Refresh the page if we are still not finished...
+ if ($update_list['status'] != -1)
+ {
+ $refresh_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check");
+ meta_refresh(2, $refresh_url);
+
+ $template->assign_vars(array(
+ 'S_IN_PROGRESS' => true,
+ 'S_COLLECTED' => (int) $update_list['status'],
+ 'S_TO_COLLECT' => sizeof($this->update_info['files']),
+ 'L_IN_PROGRESS' => $user->lang['COLLECTING_FILE_DIFFS'],
+ 'L_IN_PROGRESS_EXPLAIN' => sprintf($user->lang['NUMBER_OF_FILES_COLLECTED'], (int) $update_list['status'], sizeof($this->update_info['files']) + sizeof($this->update_info['deleted'])),
+ ));
+
+ return;
+ }
+ }
+
+ if ($action == 'diff')
+ {
+ $this->show_diff($update_list);
+ return;
+ }
+
+ if (sizeof($update_list['no_update']))
+ {
+ $template->assign_vars(array(
+ 'S_NO_UPDATE_FILES' => true,
+ 'NO_UPDATE_FILES' => implode(', ', array_map('htmlspecialchars', $update_list['no_update'])))
+ );
+ }
+
+ $new_expected_files = array();
+
+ // Now assign the list to the template
+ foreach ($update_list as $status => $filelist)
+ {
+ if ($status == 'no_update' || !sizeof($filelist) || $status == 'status' || $status == 'status_deleted')
+ {
+ continue;
+ }
+
+/* $template->assign_block_vars('files', array(
+ 'S_STATUS' => true,
+ 'STATUS' => $status,
+ 'L_STATUS' => $user->lang['STATUS_' . strtoupper($status)],
+ 'TITLE' => $user->lang['FILES_' . strtoupper($status)],
+ 'EXPLAIN' => $user->lang['FILES_' . strtoupper($status) . '_EXPLAIN'],
+ )
+ );*/
+
+ foreach ($filelist as $file_struct)
+ {
+ $s_binary = (!empty($this->update_info['binary']) && in_array($file_struct['filename'], $this->update_info['binary'])) ? true : false;
+
+ $filename = htmlspecialchars($file_struct['filename']);
+ if (strrpos($filename, '/') !== false)
+ {
+ $dir_part = substr($filename, 0, strrpos($filename, '/') + 1);
+ $file_part = substr($filename, strrpos($filename, '/') + 1);
+ }
+ else
+ {
+ $dir_part = '';
+ $file_part = $filename;
+ }
+
+ $diff_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check&amp;action=diff&amp;status=$status&amp;file=" . urlencode($file_struct['filename']));
+
+ if (isset($file_struct['as_expected']) && $file_struct['as_expected'])
+ {
+ $new_expected_files[$file_struct['filename']] = $expected_files[$file_struct['filename']];
+ }
+ else
+ {
+ $template->assign_block_vars($status, array(
+ 'STATUS' => $status,
+
+ 'FILENAME' => $filename,
+ 'DIR_PART' => $dir_part,
+ 'FILE_PART' => $file_part,
+ 'NUM_CONFLICTS' => (isset($file_struct['conflicts'])) ? $file_struct['conflicts'] : 0,
+
+ 'S_CUSTOM' => ($file_struct['custom']) ? true : false,
+ 'S_BINARY' => $s_binary,
+ 'CUSTOM_ORIGINAL' => ($file_struct['custom']) ? $file_struct['original'] : '',
+
+ 'U_SHOW_DIFF' => $diff_url,
+ 'L_SHOW_DIFF' => ($status != 'up_to_date') ? $user->lang['SHOW_DIFF_' . strtoupper($status)] : '',
+
+ 'U_VIEW_MOD_FILE' => $diff_url . '&amp;op=' . MERGE_MOD_FILE,
+ 'U_VIEW_NEW_FILE' => $diff_url . '&amp;op=' . MERGE_NEW_FILE,
+ 'U_VIEW_NO_MERGE_MOD' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_MOD,
+ 'U_VIEW_NO_MERGE_NEW' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_NEW,
+ ));
+ }
+ }
+ }
+
+ $cache->put('_expected_files', $new_expected_files);
+
+ $all_up_to_date = true;
+ foreach ($update_list as $status => $filelist)
+ {
+ if ($status != 'up_to_date' && $status != 'custom' && $status != 'status' && $status != 'status_deleted' && sizeof($filelist))
+ {
+ $all_up_to_date = false;
+ break;
+ }
+ }
+
+ $template->assign_vars(array(
+ 'S_FILE_CHECK' => true,
+ 'S_ALL_UP_TO_DATE' => $all_up_to_date,
+ 'S_VERSION_UP_TO_DATE' => $up_to_date,
+ 'S_UP_TO_DATE' => $up_to_date,
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
+ 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
+ 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
+ ));
+
+ // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
+ // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
+ // We now try to cope with this by triggering the update process
+ if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
+ {
+ $template->assign_vars(array(
+ 'S_UP_TO_DATE' => false,
+ ));
+ }
+
+ if ($all_up_to_date)
+ {
+ global $phpbb_container;
+
+ /* @var $phpbb_log \phpbb\log\log_interface */
+ $phpbb_log = $phpbb_container->get('log');
+
+ // Add database update to log
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_PHPBB', time(), array($this->current_version, $this->update_to_version));
+
+ $db->sql_return_on_error(true);
+ $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
+ $db->sql_return_on_error(false);
+
+ $cache->purge();
+ }
+
+ break;
+
+ case 'update_files':
+
+ $this->page_title = 'STAGE_UPDATE_FILES';
+
+ $s_hidden_fields = '';
+ $params = array();
+ $conflicts = $request->variable('conflict', array('' => 0));
+ $modified = $request->variable('modified', array('' => 0));
+
+ foreach ($conflicts as $filename => $merge_option)
+ {
+ $s_hidden_fields .= '<input type="hidden" name="conflict[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
+ $params[] = 'conflict[' . urlencode($filename) . ']=' . urlencode($merge_option);
+ }
+
+ foreach ($modified as $filename => $merge_option)
+ {
+ if (!$merge_option)
+ {
+ continue;
+ }
+ $s_hidden_fields .= '<input type="hidden" name="modified[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
+ $params[] = 'modified[' . urlencode($filename) . ']=' . urlencode($merge_option);
+ }
+
+ $no_update = $request->variable('no_update', array(0 => ''));
+
+ foreach ($no_update as $index => $filename)
+ {
+ $s_hidden_fields .= '<input type="hidden" name="no_update[]" value="' . htmlspecialchars($filename) . '" />';
+ $params[] = 'no_update[]=' . urlencode($filename);
+ }
+
+ // Before the user is choosing his preferred method, let's create the content list...
+ $update_list = $cache->get('_update_list');
+
+ if ($update_list === false)
+ {
+ trigger_error($user->lang['NO_UPDATE_INFO'], E_USER_ERROR);
+ }
+
+ // Check if the conflicts data is valid
+ if (sizeof($conflicts))
+ {
+ $conflict_filenames = array();
+ foreach ($update_list['conflict'] as $files)
+ {
+ $conflict_filenames[] = $files['filename'];
+ }
+
+ $new_conflicts = array();
+ foreach ($conflicts as $filename => $diff_method)
+ {
+ if (in_array($filename, $conflict_filenames))
+ {
+ $new_conflicts[$filename] = $diff_method;
+ }
+ }
+
+ $conflicts = $new_conflicts;
+ }
+
+ // Build list for modifications
+ if (sizeof($modified))
+ {
+ $modified_filenames = array();
+ foreach ($update_list['modified'] as $files)
+ {
+ $modified_filenames[] = $files['filename'];
+ }
+
+ $new_modified = array();
+ foreach ($modified as $filename => $diff_method)
+ {
+ if (in_array($filename, $modified_filenames))
+ {
+ $new_modified[$filename] = $diff_method;
+ }
+ }
+
+ $modified = $new_modified;
+ }
+
+ // Check number of conflicting files, they need to be equal. For modified files the number can differ
+ if (sizeof($update_list['conflict']) != sizeof($conflicts))
+ {
+ trigger_error($user->lang['MERGE_SELECT_ERROR'], E_USER_ERROR);
+ }
+
+ // Before we do anything, let us diff the files and store the raw file information "somewhere"
+ $get_files = false;
+ $file_list = $cache->get('_diff_files');
+ $expected_files = $cache->get('_expected_files');
+
+ if ($file_list === false || $file_list['status'] != -1)
+ {
+ $get_files = true;
+ }
+
+ if ($get_files)
+ {
+ if ($file_list === false)
+ {
+ $file_list = array(
+ 'status' => 0,
+ );
+ }
+
+ if (!isset($expected_files) || $expected_files === false)
+ {
+ $expected_files = array();
+ }
+
+ $processed = 0;
+ foreach ($update_list as $status => $files)
+ {
+ if (!is_array($files))
+ {
+ continue;
+ }
+
+ foreach ($files as $file_struct)
+ {
+ // Skip this file if the user selected to not update it
+ if (in_array($file_struct['filename'], $no_update))
+ {
+ $expected_files[$file_struct['filename']] = false;
+ continue;
+ }
+
+ // Already handled... then skip of course...
+ if (isset($file_list[$file_struct['filename']]))
+ {
+ continue;
+ }
+
+ // Refresh if we reach 5 diffs...
+ if ($processed >= 5)
+ {
+ $cache->put('_diff_files', $file_list);
+
+ if ($request->variable('download', false))
+ {
+ $params[] = 'download=1';
+ }
+
+ $redirect_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;" . implode('&amp;', $params));
+ meta_refresh(3, $redirect_url);
+
+ $template->assign_vars(array(
+ 'S_IN_PROGRESS' => true,
+ 'L_IN_PROGRESS' => $user->lang['MERGING_FILES'],
+ 'L_IN_PROGRESS_EXPLAIN' => $user->lang['MERGING_FILES_EXPLAIN'],
+ ));
+
+ return;
+ }
+
+ if (file_exists($phpbb_root_path . $file_struct['filename']))
+ {
+ $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
+ if (isset($expected_files[$file_struct['filename']]) && md5($contents) == $expected_files[$file_struct['filename']])
+ {
+ continue;
+ }
+ }
+
+ $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
+
+ switch ($status)
+ {
+ case 'modified':
+
+ $option = (isset($modified[$file_struct['filename']])) ? $modified[$file_struct['filename']] : 0;
+
+ switch ($option)
+ {
+ case MERGE_NO_MERGE_NEW:
+ $contents = file_get_contents($this->new_location . $original_filename);
+ break;
+
+ case MERGE_NO_MERGE_MOD:
+ $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
+ break;
+
+ default:
+ $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
+
+ $contents = implode("\n", $diff->merged_output());
+ unset($diff);
+ break;
+ }
+
+ $expected_files[$file_struct['filename']] = md5($contents);
+ $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
+ $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
+
+ $file_list['status']++;
+ $processed++;
+
+ break;
+
+ case 'conflict':
+
+ $option = $conflicts[$file_struct['filename']];
+ $contents = '';
+
+ switch ($option)
+ {
+ case MERGE_NO_MERGE_NEW:
+ $contents = file_get_contents($this->new_location . $original_filename);
+ break;
+
+ case MERGE_NO_MERGE_MOD:
+ $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
+ break;
+
+ default:
+
+ $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
+
+ if ($option == MERGE_NEW_FILE)
+ {
+ $contents = implode("\n", $diff->merged_new_output());
+ }
+ else if ($option == MERGE_MOD_FILE)
+ {
+ $contents = implode("\n", $diff->merged_orig_output());
+ }
+ else
+ {
+ unset($diff);
+ break 2;
+ }
+
+ unset($diff);
+ break;
+ }
+
+ $expected_files[$file_struct['filename']] = md5($contents);
+ $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
+ $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
+
+ $file_list['status']++;
+ $processed++;
+
+ break;
+ }
+ }
+ }
+ $cache->put('_expected_files', $expected_files);
+ }
+
+ $file_list['status'] = -1;
+ $cache->put('_diff_files', $file_list);
+
+ if ($request->variable('download', false))
+ {
+ $this->include_file('includes/functions_compress.' . $phpEx);
+
+ $use_method = $request->variable('use_method', '');
+ $methods = array('.tar');
+
+ $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
+ foreach ($available_methods as $type => $module)
+ {
+ if (!@extension_loaded($module))
+ {
+ continue;
+ }
+
+ $methods[] = $type;
+ }
+
+ // Let the user decide in which format he wants to have the pack
+ if (!$use_method)
+ {
+ $this->page_title = 'SELECT_DOWNLOAD_FORMAT';
+
+ $radio_buttons = '';
+ foreach ($methods as $method)
+ {
+ $radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>';
+ }
+
+ $template->assign_vars(array(
+ 'S_DOWNLOAD_FILES' => true,
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
+ 'RADIO_BUTTONS' => $radio_buttons,
+ 'S_HIDDEN_FIELDS' => $s_hidden_fields)
+ );
+
+ // To ease the update process create a file location map
+ $update_list = $cache->get('_update_list');
+ $script_path = ($config['force_server_vars']) ? (($config['script_path'] == '/') ? '/' : $config['script_path'] . '/') : $user->page['root_script_path'];
+
+ foreach ($update_list as $status => $files)
+ {
+ if ($status == 'up_to_date' || $status == 'no_update' || $status == 'status' || $status == 'status_deleted')
+ {
+ continue;
+ }
+
+ foreach ($files as $file_struct)
+ {
+ if (in_array($file_struct['filename'], $no_update))
+ {
+ continue;
+ }
+
+ $template->assign_block_vars('location', array(
+ 'SOURCE' => htmlspecialchars($file_struct['filename']),
+ 'DESTINATION' => $script_path . htmlspecialchars($file_struct['filename']),
+ ));
+ }
+ }
+ return;
+ }
+
+ if (!in_array($use_method, $methods))
+ {
+ $use_method = '.tar';
+ }
+
+ $update_mode = 'download';
+ }
+ else
+ {
+ $this->include_file('includes/functions_transfer.' . $phpEx);
+
+ // Choose FTP, if not available use fsock...
+ $method = basename($request->variable('method', ''));
+ $submit = (isset($_POST['submit'])) ? true : false;
+ $test_ftp_connection = $request->variable('test_connection', '');
+
+ if (!$method || !class_exists($method))
+ {
+ $method = 'ftp';
+ $methods = transfer::methods();
+
+ if (!in_array('ftp', $methods))
+ {
+ $method = $methods[0];
+ }
+ }
+
+ $test_connection = false;
+ if ($test_ftp_connection || $submit)
+ {
+ $transfer = new $method(
+ $request->variable('host', ''),
+ $request->variable('username', ''),
+ htmlspecialchars_decode($request->untrimmed_variable('password', '')),
+ $request->variable('root_path', ''),
+ $request->variable('port', ''),
+ $request->variable('timeout', '')
+ );
+ $test_connection = $transfer->open_session();
+
+ // Make sure that the directory is correct by checking for the existence of common.php
+ if ($test_connection === true)
+ {
+ // Check for common.php file
+ if (!$transfer->file_exists($phpbb_root_path, 'common.' . $phpEx))
+ {
+ $test_connection = 'ERR_WRONG_PATH_TO_PHPBB';
+ }
+ }
+
+ $transfer->close_session();
+
+ // Make sure the login details are correct before continuing
+ if ($submit && $test_connection !== true)
+ {
+ $submit = false;
+ $test_ftp_connection = true;
+ }
+ }
+
+ $s_hidden_fields .= build_hidden_fields(array('method' => $method));
+
+ if (!$submit)
+ {
+ $this->page_title = 'SELECT_FTP_SETTINGS';
+
+ if (!class_exists($method))
+ {
+ trigger_error('Method does not exist.', E_USER_ERROR);
+ }
+
+ $requested_data = call_user_func(array($method, 'data'));
+ foreach ($requested_data as $data => $default)
+ {
+ $template->assign_block_vars('data', array(
+ 'DATA' => $data,
+ 'NAME' => $user->lang[strtoupper($method . '_' . $data)],
+ 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'],
+ 'DEFAULT' => $request->variable($data, (string) $default),
+ ));
+ }
+
+ $template->assign_vars(array(
+ 'S_CONNECTION_SUCCESS' => ($test_ftp_connection && $test_connection === true) ? true : false,
+ 'S_CONNECTION_FAILED' => ($test_ftp_connection && $test_connection !== true) ? true : false,
+ 'ERROR_MSG' => ($test_ftp_connection && $test_connection !== true) ? $user->lang[$test_connection] : '',
+
+ 'S_FTP_UPLOAD' => true,
+ 'UPLOAD_METHOD' => $method,
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
+ 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;download=1"),
+ 'S_HIDDEN_FIELDS' => $s_hidden_fields,
+ ));
+
+ return;
+ }
+
+ $update_mode = 'upload';
+ }
+
+ // Now update the installation or download the archive...
+ $download_filename = 'update_' . $this->update_info['version']['from'] . '_to_' . $this->update_info['version']['to'];
+ $archive_filename = $download_filename . '_' . time() . '_' . unique_id();
+
+ // Now init the connection
+ if ($update_mode == 'download')
+ {
+ if ($this->filesystem->is_writable($phpbb_root_path . 'store/'))
+ {
+ trigger_error(sprintf('The directory “%s” is not writable.', $phpbb_root_path . 'store/'), E_USER_ERROR);
+ }
+
+ if ($use_method == '.zip')
+ {
+ $compress = new compress_zip('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method);
+ }
+ else
+ {
+ $compress = new compress_tar('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method, $use_method);
+ }
+ }
+ else
+ {
+ $transfer = new $method(
+ $request->variable('host', ''),
+ $request->variable('username', ''),
+ htmlspecialchars_decode($request->untrimmed_variable('password', '')),
+ $request->variable('root_path', ''),
+ $request->variable('port', ''),
+ $request->variable('timeout', '')
+ );
+ $transfer->open_session();
+ }
+
+ // Ok, go through the update list and do the operations based on their status
+ foreach ($update_list as $status => $files)
+ {
+ if (!is_array($files))
+ {
+ continue;
+ }
+
+ foreach ($files as $file_struct)
+ {
+ // Skip this file if the user selected to not update it
+ if (in_array($file_struct['filename'], $no_update))
+ {
+ continue;
+ }
+
+ $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
+
+ switch ($status)
+ {
+ case 'new':
+ case 'new_conflict':
+ case 'not_modified':
+
+ if ($update_mode == 'download')
+ {
+ $compress->add_custom_file($this->new_location . $original_filename, $file_struct['filename']);
+ }
+ else
+ {
+ if ($status != 'new')
+ {
+ $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
+ }
+
+ // New directory too?
+ $dirname = dirname($file_struct['filename']);
+
+ if ($dirname && !file_exists($phpbb_root_path . $dirname))
+ {
+ $transfer->make_dir($dirname);
+ }
+
+ $transfer->copy_file($this->new_location . $original_filename, $file_struct['filename']);
+ }
+ break;
+
+ case 'modified':
+
+ $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
+
+ if ($update_mode == 'download')
+ {
+ $compress->add_data($contents, $file_struct['filename']);
+ }
+ else
+ {
+ // @todo add option to specify if a backup file should be created?
+ $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
+ $transfer->write_file($file_struct['filename'], $contents);
+ }
+ break;
+
+ case 'conflict':
+
+ $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
+
+ if ($update_mode == 'download')
+ {
+ $compress->add_data($contents, $file_struct['filename']);
+ }
+ else
+ {
+ $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
+ $transfer->write_file($file_struct['filename'], $contents);
+ }
+ break;
+
+ case 'deleted':
+
+ if ($update_mode != 'download')
+ {
+ $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
+ }
+ break;
+ }
+ }
+ }
+
+ if ($update_mode == 'download')
+ {
+ $compress->close();
+
+ $compress->download($archive_filename, $download_filename);
+ @unlink($phpbb_root_path . 'store/' . $archive_filename . $use_method);
+
+ exit;
+ }
+ else
+ {
+ $transfer->close_session();
+
+ $template->assign_vars(array(
+ 'S_UPLOAD_SUCCESS' => true,
+ 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"))
+ );
+ return;
+ }
+
+ break;
+
+ }
+ }
+
+ /**
+ * Show file diff
+ */
+ function show_diff(&$update_list)
+ {
+ global $phpbb_root_path, $template, $user, $request, $phpbb_adm_relative_path;
+
+ $this->tpl_name = 'install_update_diff';
+
+ $this->page_title = 'VIEWING_FILE_DIFF';
+
+ $status = $request->variable('status', '');
+ $file = $request->variable('file', '');
+ $diff_mode = $request->variable('diff_mode', 'inline');
+
+ // First of all make sure the file is within our file update list with the correct status
+ $found_entry = array();
+ foreach ($update_list[$status] as $index => $file_struct)
+ {
+ if ($file_struct['filename'] === $file)
+ {
+ $found_entry = $update_list[$status][$index];
+ }
+ }
+
+ if (empty($found_entry))
+ {
+ trigger_error($user->lang['FILE_DIFF_NOT_ALLOWED'], E_USER_ERROR);
+ }
+
+ // If the status is 'up_to_date' then we do not need to show a diff
+ if ($status == 'up_to_date')
+ {
+ trigger_error($user->lang['FILE_ALREADY_UP_TO_DATE'], E_USER_ERROR);
+ }
+
+ $original_file = ($found_entry['custom']) ? $found_entry['original'] : $file;
+
+ // Get the correct diff
+ switch ($status)
+ {
+ case 'conflict':
+ $option = $request->variable('op', 0);
+
+ switch ($option)
+ {
+ case MERGE_NO_MERGE_NEW:
+ case MERGE_NO_MERGE_MOD:
+
+ $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
+
+ $template->assign_var('S_DIFF_NEW_FILE', true);
+ $diff_mode = 'inline';
+ $this->page_title = 'VIEWING_FILE_CONTENTS';
+
+ break;
+
+ // Merge differences and use new phpBB code for conflicted blocks
+ case MERGE_NEW_FILE:
+ case MERGE_MOD_FILE:
+
+ $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
+
+ $template->assign_vars(array(
+ 'S_DIFF_CONFLICT_FILE' => true,
+ 'NUM_CONFLICTS' => $diff->get_num_conflicts())
+ );
+
+ $diff = $this->return_diff($phpbb_root_path . $file, ($option == MERGE_NEW_FILE) ? $diff->merged_new_output() : $diff->merged_orig_output());
+ break;
+
+ // Download conflict file
+ default:
+
+ $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
+
+ header('Pragma: no-cache');
+ header("Content-Type: application/octetstream; name=\"$file\"");
+ header("Content-disposition: attachment; filename=$file");
+
+ @set_time_limit(0);
+
+ echo implode("\n", $diff->get_conflicts_content());
+
+ flush();
+ exit;
+
+ break;
+ }
+
+ break;
+
+ case 'modified':
+ $option = $request->variable('op', 0);
+
+ switch ($option)
+ {
+ case MERGE_NO_MERGE_NEW:
+ case MERGE_NO_MERGE_MOD:
+
+ $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
+
+ $template->assign_var('S_DIFF_NEW_FILE', true);
+ $diff_mode = 'inline';
+ $this->page_title = 'VIEWING_FILE_CONTENTS';
+
+ break;
+
+ default:
+ $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $original_file, $this->new_location . $file);
+ $diff = $this->return_diff($phpbb_root_path . $file, $diff->merged_output());
+ break;
+ }
+ break;
+
+ case 'not_modified':
+ case 'new_conflict':
+ $diff = $this->return_diff($phpbb_root_path . $file, $this->new_location . $original_file);
+ break;
+
+ case 'new':
+
+ $diff = $this->return_diff(array(), $this->new_location . $original_file);
+
+ $template->assign_var('S_DIFF_NEW_FILE', true);
+ $diff_mode = 'inline';
+ $this->page_title = 'VIEWING_FILE_CONTENTS';
+
+ break;
+
+ case 'deleted':
+
+ $diff = $this->return_diff(array(), $phpbb_root_path . $original_file);
+
+ $template->assign_var('S_DIFF_NEW_FILE', true);
+ $diff_mode = 'inline';
+ $this->page_title = 'VIEWING_FILE_CONTENTS';
+
+ break;
+ }
+
+ $diff_mode_options = '';
+ foreach (array('side_by_side', 'inline', 'unified', 'raw') as $option)
+ {
+ $diff_mode_options .= '<option value="' . $option . '"' . (($diff_mode == $option) ? ' selected="selected"' : '') . '>' . $user->lang['DIFF_' . strtoupper($option)] . '</option>';
+ }
+
+ // Now the correct renderer
+ $render_class = 'diff_renderer_' . $diff_mode;
+
+ if (!class_exists($render_class))
+ {
+ trigger_error('Chosen diff mode is not supported', E_USER_ERROR);
+ }
+
+ $renderer = new $render_class();
+
+ $template->assign_vars(array(
+ 'DIFF_CONTENT' => $renderer->get_diff_content($diff),
+ 'DIFF_MODE' => $diff_mode,
+ 'S_DIFF_MODE_OPTIONS' => $diff_mode_options,
+ 'S_SHOW_DIFF' => true,
+ ));
+
+ unset($diff, $renderer);
+ }
+
+ /**
+ * Collect all file status infos we need for the update by diffing all files
+ */
+ function get_update_structure(&$update_list, $expected_files)
+ {
+ global $phpbb_root_path, $phpEx, $user;
+
+ if ($update_list === false)
+ {
+ $update_list = array(
+ 'up_to_date' => array(),
+ 'new' => array(),
+ 'not_modified' => array(),
+ 'modified' => array(),
+ 'new_conflict' => array(),
+ 'conflict' => array(),
+ 'no_update' => array(),
+ 'deleted' => array(),
+ 'status' => 0,
+ 'status_deleted'=> 0,
+ );
+ }
+
+ /* if (!empty($this->update_info['custom']))
+ {
+ foreach ($this->update_info['custom'] as $original_file => $file_ary)
+ {
+ foreach ($file_ary as $index => $file)
+ {
+ $this->make_update_diff($update_list, $original_file, $file, true);
+ }
+ }
+ } */
+
+ // Get a list of those files which are completely new by checking with file_exists...
+ $num_bytes_processed = 0;
+
+ foreach ($this->update_info['files'] as $index => $file)
+ {
+ if (is_int($update_list['status']) && $index < $update_list['status'])
+ {
+ continue;
+ }
+
+ if ($num_bytes_processed >= 500 * 1024)
+ {
+ return;
+ }
+
+ if (!file_exists($phpbb_root_path . $file))
+ {
+ // Make sure the update files are consistent by checking if the file is in new_files...
+ if (!file_exists($this->new_location . $file))
+ {
+ trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
+ }
+
+ // If the file exists within the old directory the file got removed and we will write it back
+ // not a biggie, but we might want to state this circumstance separately later.
+ // if (file_exists($this->old_location . $file))
+ // {
+ // $update_list['removed'][] = $file;
+ // }
+
+ /* Only include a new file as new if the underlying path exist
+ // The path normally do not exist if the original style or language has been removed
+ if (file_exists($phpbb_root_path . dirname($file)))
+ {
+ $this->get_custom_info($update_list['new'], $file);
+ $update_list['new'][] = array('filename' => $file, 'custom' => false);
+ }
+ else
+ {
+ // Do not include style-related or language-related content
+ if (strpos($file, 'styles/') !== 0 && strpos($file, 'language/') !== 0)
+ {
+ $update_list['no_update'][] = $file;
+ }
+ }*/
+
+ if (!phpbb_ignore_new_file_on_update($phpbb_root_path, $file))
+ {
+ $this->get_custom_info($update_list['new'], $file);
+ $update_list['new'][] = array('filename' => $file, 'custom' => false);
+ }
+
+ // unset($this->update_info['files'][$index]);
+ }
+ else
+ {
+ // not modified?
+ $this->make_update_diff($update_list, $file, $file, $expected_files);
+ }
+
+ $num_bytes_processed += (file_exists($this->new_location . $file)) ? filesize($this->new_location . $file) : 100 * 1024;
+ $update_list['status']++;
+ }
+
+ foreach ($this->update_info['deleted'] as $index => $file)
+ {
+ if (is_int($update_list['status_deleted']) && $index < $update_list['status_deleted'])
+ {
+ continue;
+ }
+
+ if ($num_bytes_processed >= 500 * 1024)
+ {
+ return;
+ }
+
+ if (file_exists($phpbb_root_path . $file))
+ {
+ $update_list['deleted'][] = array('filename' => $file, 'custom' => false, 'as_expected' => false);
+ $num_bytes_processed += filesize($phpbb_root_path . $file);
+ }
+
+ $update_list['status_deleted']++;
+ $update_list['status']++;
+ }
+
+ $update_list['status_deleted'] = -1;
+ $update_list['status'] = -1;
+
+/* if (!sizeof($this->update_info['files']))
+ {
+ return $update_list;
+ }
+
+ // Now diff the remaining files to get information about their status (not modified/modified/up-to-date)
+
+ // not modified?
+ foreach ($this->update_info['files'] as $index => $file)
+ {
+ $this->make_update_diff($update_list, $file, $file);
+ }
+
+ // Now to the styles...
+ if (empty($this->update_info['custom']))
+ {
+ return $update_list;
+ }
+
+ foreach ($this->update_info['custom'] as $original_file => $file_ary)
+ {
+ foreach ($file_ary as $index => $file)
+ {
+ $this->make_update_diff($update_list, $original_file, $file, true);
+ }
+ }
+
+ return $update_list;*/
+ }
+
+ /**
+ * Compare files for storage in update_list
+ */
+ function make_update_diff(&$update_list, $original_file, $file, $expected_files, $custom = false)
+ {
+ global $phpbb_root_path, $user;
+
+ $update_ary = array('filename' => $file, 'custom' => $custom, 'as_expected' => false);
+
+ if ($custom)
+ {
+ $update_ary['original'] = $original_file;
+ }
+
+ if (file_exists($phpbb_root_path . $file))
+ {
+ $content = file_get_contents($phpbb_root_path . $file);
+
+ if (isset($expected_files[$file]) && // the user already selected what to do with this file
+ ($expected_files[$file] === false || // the user wanted this file to stay the same, so just assume it's alright
+ $expected_files[$file] === md5($content)))
+ {
+ // the file contains what it was supposed to contain after the merge
+ $update_ary['as_expected'] = true;
+ $update_ary['was_ignored'] = ($expected_files[$file] === false);
+ $update_list['up_to_date'][] = $update_ary;
+
+ return;
+ }
+ }
+
+ // we only want to know if the files are successfully merged and newlines could result in errors (duplicate addition of lines and such things)
+ // Therefore we check for empty diffs with two methods, preserving newlines and not preserving them (which mostly works best, therefore the first option)
+
+ // On a successfull update the new location file exists but the old one does not exist.
+ // Check for this circumstance, the new file need to be up-to-date with the current file then...
+ if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file))
+ {
+ $tmp = array(
+ 'file1' => file_get_contents($this->new_location . $original_file),
+ 'file2' => $content,
+ );
+
+ // We need to diff the contents here to make sure the file is really the one we expect
+ $diff = new diff($tmp['file1'], $tmp['file2'], false);
+ $empty = $diff->is_empty();
+
+ unset($tmp, $diff);
+
+ // if there are no differences we have an up-to-date file...
+ if ($empty)
+ {
+ $update_list['up_to_date'][] = $update_ary;
+ return;
+ }
+
+ // If no other status matches we have another file in the way...
+ $update_list['new_conflict'][] = $update_ary;
+ return;
+ }
+
+ // Old file removed?
+ if (file_exists($this->old_location . $original_file) && !file_exists($this->new_location . $original_file))
+ {
+ return;
+ }
+
+ // Check for existance, else abort immediately
+ if (!file_exists($this->old_location . $original_file) || !file_exists($this->new_location . $original_file))
+ {
+ trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
+ }
+
+ $preserve_cr_ary = array(false, true);
+
+ foreach ($preserve_cr_ary as $preserve_cr)
+ {
+ $tmp = array(
+ 'file1' => file_get_contents($this->old_location . $original_file),
+ 'file2' => $content,
+ );
+
+ // We need to diff the contents here to make sure the file is really the one we expect
+ $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
+ $empty_1 = $diff->is_empty();
+
+ unset($tmp, $diff);
+
+ $tmp = array(
+ 'file1' => file_get_contents($this->new_location . $original_file),
+ 'file2' => $content,
+ );
+
+ $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
+ $empty_2 = $diff->is_empty();
+
+ unset($tmp, $diff);
+
+ // If the file is not modified we are finished here...
+ if ($empty_1)
+ {
+ // Further check if it is already up to date - it could happen that non-modified files
+ // slip through
+ if ($empty_2)
+ {
+ $update_list['up_to_date'][] = $update_ary;
+ return;
+ }
+
+ $update_list['not_modified'][] = $update_ary;
+ return;
+ }
+
+ // If the file had been modified then we need to check if it is already up to date
+
+ // if there are no differences we have an up-to-date file...
+ if ($empty_2)
+ {
+ $update_list['up_to_date'][] = $update_ary;
+ return;
+ }
+ }
+
+ $conflicts = false;
+
+ foreach ($preserve_cr_ary as $preserve_cr)
+ {
+ // if the file is modified we try to make sure a merge succeed
+ $tmp = array(
+ 'orig' => file_get_contents($this->old_location . $original_file),
+ 'final1' => file_get_contents($phpbb_root_path . $file),
+ 'final2' => file_get_contents($this->new_location . $original_file),
+ );
+
+ $diff = new diff3($tmp['orig'], $tmp['final1'], $tmp['final2'], $preserve_cr);
+ unset($tmp);
+
+ if (!$diff->get_num_conflicts())
+ {
+ $tmp = array(
+ 'file1' => file_get_contents($phpbb_root_path . $file),
+ 'file2' => implode("\n", $diff->merged_output()),
+ );
+
+ // now compare the merged output with the original file to see if the modified file is up to date
+ $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
+ $empty = $diff2->is_empty();
+
+ unset($diff, $diff2);
+
+ if ($empty)
+ {
+ $update_list['up_to_date'][] = $update_ary;
+ return;
+ }
+
+ // If we preserve cr tag it as modified because the conflict would not show in this mode anyway
+ if ($preserve_cr)
+ {
+ $update_list['modified'][] = $update_ary;
+ return;
+ }
+ }
+ else
+ {
+ // There is one special case... users having merged with a conflicting file... we need to check this
+ $tmp = array(
+ 'file1' => file_get_contents($phpbb_root_path . $file),
+ 'file2' => implode("\n", $diff->merged_new_output()),
+ );
+
+ $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
+ $empty = $diff2->is_empty();
+
+ if (!$empty)
+ {
+ unset($tmp, $diff2);
+
+ // We check if the user merged with his output
+ $tmp = array(
+ 'file1' => file_get_contents($phpbb_root_path . $file),
+ 'file2' => implode("\n", $diff->merged_orig_output()),
+ );
+
+ $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
+ $empty = $diff2->is_empty();
+ }
+
+ if (!$empty)
+ {
+ $conflicts = $diff->get_num_conflicts();
+ }
+
+ unset($diff, $diff2);
+
+ if ($empty)
+ {
+ // A conflict got resolved...
+ $update_list['up_to_date'][] = $update_ary;
+ return;
+ }
+ }
+ }
+
+ if ($conflicts !== false)
+ {
+ $update_ary['conflicts'] = $conflicts;
+ $update_list['conflict'][] = $update_ary;
+ return;
+ }
+
+ // If no other status matches we have a modified file...
+ $update_list['modified'][] = $update_ary;
+ }
+
+ /**
+ * Update update_list with custom new files
+ */
+ function get_custom_info(&$update_list, $file)
+ {
+ if (empty($this->update_info['custom']))
+ {
+ return;
+ }
+
+ if (isset($this->update_info['custom'][$file]))
+ {
+ foreach ($this->update_info['custom'][$file] as $_file)
+ {
+ $update_list[] = array('filename' => $_file, 'custom' => true, 'original' => $file);
+ }
+ }
+ }
+
+ /**
+ * Get remote file
+ */
+ function get_file($mode)
+ {
+ global $user, $db;
+
+ $errstr = '';
+ $errno = 0;
+
+ switch ($mode)
+ {
+ case 'update_info':
+ global $phpbb_root_path, $phpEx;
+
+ $update_info = array();
+ include($phpbb_root_path . 'install/update/index.' . $phpEx);
+
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+ $errstr = ($info === false) ? $user->lang['WRONG_INFO_FILE_FORMAT'] : '';
+
+ if ($info !== false)
+ {
+ // We assume that all file extensions have been renamed to .$phpEx,
+ // if someone is using a non .php file extension for php files.
+ // However, in $update_info['files'] we use hardcoded .php.
+ // We therefore replace .php with .$phpEx.
+ $info['files'] = preg_replace('/\.php$/i', ".$phpEx", $info['files']);
+
+ // Adjust the update info file to hold some specific style-related information
+ $info['custom'] = array();
+/*
+ // Get custom installed styles...
+ $sql = 'SELECT style_name, style_path
+ FROM ' . STYLES_TABLE . "
+ WHERE LOWER(style_name) NOT IN ('prosilver')";
+ $result = $db->sql_query($sql);
+
+ $templates = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $templates[] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($templates))
+ {
+ foreach ($info['files'] as $filename)
+ {
+ // Template update?
+ if (strpos(strtolower($filename), 'styles/prosilver/template/') === 0)
+ {
+ foreach ($templates as $row)
+ {
+ $info['custom'][$filename][] = str_replace('/prosilver/', '/' . $row['style_path'] . '/', $filename);
+ }
+ }
+ }
+ }
+*/
+ }
+ break;
+
+ default:
+ trigger_error('Mode for getting remote file not specified', E_USER_ERROR);
+ break;
+ }
+
+ if ($info === false)
+ {
+ trigger_error($errstr, E_USER_ERROR);
+ }
+
+ return $info;
+ }
+
+ /**
+ * Function for including files...
+ */
+ function include_file($filename)
+ {
+ global $phpbb_root_path, $phpEx;
+
+ if (!empty($this->update_info['files']) && in_array($filename, $this->update_info['files']))
+ {
+ include_once($this->new_location . $filename);
+ }
+ else
+ {
+ include_once($phpbb_root_path . $filename);
+ }
+ }
+
+ /**
+ * Wrapper for returning a diff object
+ */
+ function return_diff()
+ {
+ $args = func_get_args();
+ $three_way_diff = (func_num_args() > 2) ? true : false;
+
+ $file1 = array_shift($args);
+ $file2 = array_shift($args);
+
+ $tmp['file1'] = (!empty($file1) && is_string($file1)) ? file_get_contents($file1) : $file1;
+ $tmp['file2'] = (!empty($file2) && is_string($file2)) ? file_get_contents($file2) : $file2;
+
+ if ($three_way_diff)
+ {
+ $file3 = array_shift($args);
+ $tmp['file3'] = (!empty($file3) && is_string($file3)) ? file_get_contents($file3) : $file3;
+
+ $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3']);
+ }
+ else
+ {
+ $diff = new diff($tmp['file1'], $tmp['file2']);
+ }
+
+ unset($tmp);
+
+ return $diff;
+ }
+}
diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php
deleted file mode 100755
index 20a202f584..0000000000
--- a/phpBB/install/phpbbcli.php
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env php
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-use Symfony\Component\Console\Input\ArgvInput;
-
-if (php_sapi_name() !== 'cli')
-{
- echo 'This program must be run from the command line.' . PHP_EOL;
- exit(1);
-}
-
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-define('PHPBB_ENVIRONMENT', 'production');
-$phpbb_root_path = __DIR__ . '/../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-//
-// Let's do the common.php logic
-//
-require($phpbb_root_path . 'includes/startup.' . $phpEx);
-require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
-
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include files
-require($phpbb_root_path . 'includes/functions.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
-include($phpbb_root_path . 'includes/functions_compatibility.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_user.' . $phpEx);
-require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
-$phpbb_installer_container = $phpbb_installer_container_builder
- ->with_environment('installer')
- ->without_extensions()
- ->without_cache()
- ->get_container();
-
-/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
-$phpbb_filesystem = $phpbb_installer_container->get('filesystem');
-
-/** @var \phpbb\language\language $language */
-$language = $phpbb_installer_container->get('language');
-$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting', 'cli'));
-
-$application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language);
-$application->register_container_commands($phpbb_installer_container->get('console.installer.command_collection'));
-$application->run($input);
diff --git a/phpBB/install/phpinfo.php b/phpBB/install/phpinfo.php
new file mode 100644
index 0000000000..1512b00563
--- /dev/null
+++ b/phpBB/install/phpinfo.php
@@ -0,0 +1,14 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+phpinfo();
diff --git a/phpBB/install/schemas/index.htm b/phpBB/install/schemas/index.htm
new file mode 100644
index 0000000000..ee1f723a7d
--- /dev/null
+++ b/phpBB/install/schemas/index.htm
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+
+</body>
+</html>
diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql
new file mode 100644
index 0000000000..2473d31aab
--- /dev/null
+++ b/phpBB/install/schemas/oracle_schema.sql
@@ -0,0 +1,37 @@
+/*
+ This first section is optional, however its probably the best method
+ of running phpBB on Oracle. If you already have a tablespace and user created
+ for phpBB you can leave this section commented out!
+
+ The first set of statements create a phpBB tablespace and a phpBB user,
+ make sure you change the password of the phpBB user before you run this script!!
+*/
+
+/*
+CREATE TABLESPACE "PHPBB"
+ LOGGING
+ DATAFILE 'E:\ORACLE\ORADATA\LOCAL\PHPBB.ora'
+ SIZE 10M
+ AUTOEXTEND ON NEXT 10M
+ MAXSIZE 100M;
+
+CREATE USER "PHPBB"
+ PROFILE "DEFAULT"
+ IDENTIFIED BY "phpbb_password"
+ DEFAULT TABLESPACE "PHPBB"
+ QUOTA UNLIMITED ON "PHPBB"
+ ACCOUNT UNLOCK;
+
+GRANT ANALYZE ANY TO "PHPBB";
+GRANT CREATE SEQUENCE TO "PHPBB";
+GRANT CREATE SESSION TO "PHPBB";
+GRANT CREATE TABLE TO "PHPBB";
+GRANT CREATE TRIGGER TO "PHPBB";
+GRANT CREATE VIEW TO "PHPBB";
+GRANT "CONNECT" TO "PHPBB";
+
+COMMIT;
+DISCONNECT;
+
+CONNECT phpbb/phpbb_password;
+*/
diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql
new file mode 100644
index 0000000000..65caba8d1c
--- /dev/null
+++ b/phpBB/install/schemas/postgres_schema.sql
@@ -0,0 +1,80 @@
+
+BEGIN;
+
+/*
+ Domain definition
+*/
+CREATE DOMAIN varchar_ci AS varchar(255) NOT NULL DEFAULT ''::character varying;
+
+/*
+ Operation Functions
+*/
+CREATE FUNCTION _varchar_ci_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) = LOWER($2)' LANGUAGE SQL STRICT;
+CREATE FUNCTION _varchar_ci_not_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) != LOWER($2)' LANGUAGE SQL STRICT;
+CREATE FUNCTION _varchar_ci_less_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) < LOWER($2)' LANGUAGE SQL STRICT;
+CREATE FUNCTION _varchar_ci_less_equal(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) <= LOWER($2)' LANGUAGE SQL STRICT;
+CREATE FUNCTION _varchar_ci_greater_than(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) > LOWER($2)' LANGUAGE SQL STRICT;
+CREATE FUNCTION _varchar_ci_greater_equals(varchar_ci, varchar_ci) RETURNS boolean AS 'SELECT LOWER($1) >= LOWER($2)' LANGUAGE SQL STRICT;
+
+/*
+ Operators
+*/
+CREATE OPERATOR <(
+ PROCEDURE = _varchar_ci_less_than,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = >,
+ NEGATOR = >=,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel);
+
+CREATE OPERATOR <=(
+ PROCEDURE = _varchar_ci_less_equal,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = >=,
+ NEGATOR = >,
+ RESTRICT = scalarltsel,
+ JOIN = scalarltjoinsel);
+
+CREATE OPERATOR >(
+ PROCEDURE = _varchar_ci_greater_than,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = <,
+ NEGATOR = <=,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel);
+
+CREATE OPERATOR >=(
+ PROCEDURE = _varchar_ci_greater_equals,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = <=,
+ NEGATOR = <,
+ RESTRICT = scalargtsel,
+ JOIN = scalargtjoinsel);
+
+CREATE OPERATOR <>(
+ PROCEDURE = _varchar_ci_not_equal,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = <>,
+ NEGATOR = =,
+ RESTRICT = neqsel,
+ JOIN = neqjoinsel);
+
+CREATE OPERATOR =(
+ PROCEDURE = _varchar_ci_equal,
+ LEFTARG = varchar_ci,
+ RIGHTARG = varchar_ci,
+ COMMUTATOR = =,
+ NEGATOR = <>,
+ RESTRICT = eqsel,
+ JOIN = eqjoinsel,
+ HASHES,
+ MERGES,
+ SORT1= <);
+
+COMMIT;
+
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
new file mode 100644
index 0000000000..1f856f016c
--- /dev/null
+++ b/phpBB/install/schemas/schema_data.sql
@@ -0,0 +1,821 @@
+#
+# $Id$
+#
+
+# POSTGRES BEGIN #
+
+# -- Config
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('active_sessions', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_attachments', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_autologin', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_gravatar', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_local', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_upload', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_avatar_remote_upload', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bbcode', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_birthdays', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_bookmarks', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_cdn', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_emailreuse', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_password_reset', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_forum_notify', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_live_searches', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_mass_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_name_chars', 'USERNAME_CHARS_ANY');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_namechange', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_nocensors', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_attach', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_pm_report', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_flash', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_post_links', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_privmsg', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_quick_reply', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_bbcode', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_flash', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_img', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_links', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_sig_smilies', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_smilies', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_topic_notify', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('assets_version', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('attachment_quota', '52428800');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_bbcode_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_flash_pm', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_img_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_method', 'db');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('auth_smilies_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_filesize', '6144');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_gallery_path', 'images/avatars/gallery');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_height', '90');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_max_width', '90');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_height', '20');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_min_width', '20');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_path', 'images/avatars/upload');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('avatar_salt', 'phpbb_avatar');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact', 'contact@yourdomain.tld');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_contact_name', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_disable_msg', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email', 'address@yourdomain.tld');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_form', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_email_sig', '{L_CONFIG_BOARD_EMAIL_SIG}');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_hide_emails', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_index_text', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('board_timezone', 'UTC');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('browser_check', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_interval', '10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('bump_type', 'd');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('cache_gc', '7200');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_plugin', 'core.captcha.plugins.nogd');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_foreground_noise', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_x_grid', '25');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_y_grid', '25');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_wave', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_3d_noise', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('captcha_gd_fonts', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('confirm_refresh', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_attachment_content', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_dnsbl', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('chg_passforce', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('contact_admin_form_enable', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_domain', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_name', 'phpbb3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_path', '/');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_secure', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_enable', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_fax', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('coppa_mail', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('database_gc', '604800');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('dbms_version', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_dateformat', 'D M d, Y g:i a');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('default_style', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_edited', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_last_subject', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('display_order', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('edit_time', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('extension_force_unstable', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('delete_time', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_check_mx', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_enable', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_function_name', 'mail');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_size', '50');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_mod_rewrite', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_post_confirm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_enable', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_http_auth', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_post', '15');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_limit_topic', '10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall_forums', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_overall', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_forum', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topic', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_new', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_topics_active', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('feed_item_statistics', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('flood_interval', '15');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('force_server_vars', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_lifetime', '7200');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_mintime', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('form_token_sid_guests', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('forward_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('forwarded_for_check', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('full_folder_action', '2');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_max_word_len', '254');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_mysql_min_word_len', '4');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_common_thres', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_load_upd', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_max_chars', '14');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_min_chars', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_max_word_len', '254');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_min_word_len', '4');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ts_name', 'simple');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_indexer_mem_limit', '512');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_sphinx_stopwords', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_display_inlined', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_imagick', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_height', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_width', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_height', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_thumb_width', '400');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_width', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_min_thumb_filesize', '12000');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_check', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_max', '50');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_time', '21600');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ip_login_limit_use_forwarded', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_enable', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_host', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_password', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_package_size', '20');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_port', '5222');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_use_ssl', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('jab_username', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_base_dn', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_email', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_password', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_port', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_server', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_uid', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ldap_user_filter', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('legend_sort_groupname', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_load', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('limit_search_load', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_anon_lastread', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_birthdays', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_memberlist', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewprofile', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_notifications', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_guests', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online_time', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_onlinetrack', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_search', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_tplcompile', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_unreads_search', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_user_activity', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_attachments_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_autologin_time', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize', '262144');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_filesize_pm', '262144');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_login_attempts', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_name_chars', '20');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_num_search_keywords', '10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_pass_chars', '100');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_poll_options', '10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_chars', '60000');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_font_size', '200');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_height', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_img_width', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_smilies', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_post_urls', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_quote_depth', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_reg_attempts', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_chars', '255');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_font_size', '200');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_height', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_img_width', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_smilies', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('max_sig_urls', '5');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_name_chars', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_pass_chars', '6');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_post_chars', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('min_search_author_chars', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_post_limit', '3');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('new_member_group_default', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('override_user_style', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('pass_complex', 'PASS_TYPE_ANY');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('plupload_salt', 'phpbb_plupload');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_edit_time', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_boxes', '4');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_msgs', '50');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('pm_max_recipients', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('posts_per_page', '10');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('print_pm', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', '60');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_expire_days', '30');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_gc', '86400');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_block_size', '250');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_gc', '7200');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_interval', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_anonymous_interval', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_type', '\phpbb\search\fulltext_native');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('search_store_results', '1800');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_deny', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_allow_empty_referer', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('secure_downloads', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_name', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_port', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('server_protocol', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_gc', '3600');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('session_length', '3600');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_desc', '{L_CONFIG_SITE_DESC}');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_url', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('site_home_text', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('sitename', '{L_CONFIG_SITENAME}');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_path', 'images/smilies');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_per_page', '50');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_auth_method', 'PLAIN');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_delivery', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_username', '');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_memberships', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_forums', '1');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', '25');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a1-dev');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400');
+
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cache_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('database_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('last_queue_run', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_colour', 'AA0000', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_user_id', '2', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('newest_username', '', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_files', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_posts', '1', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_topics', '1', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('num_users', '1', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('plupload_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('rand_seed_last_update', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('read_notification_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_date', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('record_online_users', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_indexing_state', '', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('search_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('session_last_gc', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('upload_dir_size', '0', 1);
+INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('warnings_last_gc', '0', 1);
+
+# Config text
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_uid', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_bitfield', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_flags', '7');
+
+# -- Forum related auth options
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_attach', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bbcode', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_bump', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_delete', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_download', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_edit', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_email', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_flash', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_icons', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_ignoreflood', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_img', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_list', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_noapprove', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_poll', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_post', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_postcount', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_print', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_read', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_reply', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_report', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_search', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sigs', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_smilies', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_sticky', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_subscribe', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_user_lock', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_vote', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_votechg', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_softdelete', 1);
+
+# -- Moderator related auth options
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_approve', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_chgposter', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_delete', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_edit', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_info', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_lock', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_merge', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_move', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_report', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_split', 1, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_softdelete', 1, 1);
+
+# -- Global moderator auth option (not a local option)
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_ban', 0, 1);
+INSERT INTO phpbb_acl_options (auth_option, is_local, is_global) VALUES ('m_warn', 0, 1);
+
+# -- Admin related auth options
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_aauth', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_attach', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authgroups', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_authusers', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_backup', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ban', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bbcode', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_board', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bots', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_clearlogs', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_email', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_extensions', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_fauth', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forum', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumadd', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumdel', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_group', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupadd', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_groupdel', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_icons', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_jabber', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_language', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_mauth', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_modules', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_names', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_phpinfo', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_profile', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_prune', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_ranks', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_reasons', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_roles', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_search', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_server', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_styles', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_switchperm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_uauth', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_user', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_userdel', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewauth', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_viewlogs', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_words', 1);
+
+# -- User related auth options
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_attach', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgavatar', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgcensors', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgemail', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chggrp', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgname', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgpasswd', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgprofileinfo', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_download', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_hideonline', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_ignoreflood', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_masspm_group', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_attach', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_bbcode', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_delete', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_download', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_edit', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_emailpm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_flash', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_forward', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_img', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_printpm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_pm_smilies', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_readpm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_savedrafts', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_search', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendemail', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendim', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sendpm', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_sig', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewonline', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_viewprofile', 1);
+
+
+# -- standard auth roles
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_STANDARD', 'ROLE_DESCRIPTION_ADMIN_STANDARD', 'a_', 1);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FORUM', 'ROLE_DESCRIPTION_ADMIN_FORUM', 'a_', 3);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_USERGROUP', 'ROLE_DESCRIPTION_ADMIN_USERGROUP', 'a_', 4);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_ADMIN_FULL', 'ROLE_DESCRIPTION_ADMIN_FULL', 'a_', 2);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_FULL', 'ROLE_DESCRIPTION_USER_FULL', 'u_', 3);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_STANDARD', 'ROLE_DESCRIPTION_USER_STANDARD', 'u_', 1);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_LIMITED', 'ROLE_DESCRIPTION_USER_LIMITED', 'u_', 2);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOPM', 'ROLE_DESCRIPTION_USER_NOPM', 'u_', 4);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NOAVATAR', 'ROLE_DESCRIPTION_USER_NOAVATAR', 'u_', 5);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_FULL', 'ROLE_DESCRIPTION_MOD_FULL', 'm_', 3);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_STANDARD', 'ROLE_DESCRIPTION_MOD_STANDARD', 'm_', 1);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_SIMPLE', 'ROLE_DESCRIPTION_MOD_SIMPLE', 'm_', 2);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_MOD_QUEUE', 'ROLE_DESCRIPTION_MOD_QUEUE', 'm_', 4);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_FULL', 'ROLE_DESCRIPTION_FORUM_FULL', 'f_', 7);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_STANDARD', 'ROLE_DESCRIPTION_FORUM_STANDARD', 'f_', 5);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NOACCESS', 'ROLE_DESCRIPTION_FORUM_NOACCESS', 'f_', 1);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_READONLY', 'ROLE_DESCRIPTION_FORUM_READONLY', 'f_', 2);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED', 'ROLE_DESCRIPTION_FORUM_LIMITED', 'f_', 3);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_BOT', 'ROLE_DESCRIPTION_FORUM_BOT', 'f_', 9);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_ONQUEUE', 'ROLE_DESCRIPTION_FORUM_ONQUEUE', 'f_', 8);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_POLLS', 'ROLE_DESCRIPTION_FORUM_POLLS', 'f_', 6);
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_LIMITED_POLLS', 'ROLE_DESCRIPTION_FORUM_LIMITED_POLLS', 'f_', 4);
+
+# 23
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', 6);
+
+# 24
+INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', 10);
+
+# -- phpbb_styles
+INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '&copy; phpBB Limited', 1, 'prosilver', 'kNg=', 0, '');
+
+# -- Forums
+INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents) VALUES ('{L_FORUMS_FIRST_CATEGORY}', '', 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 'Admin', 'AA0000', 972086460, '', '', '', '', '', '', '', 0, 0, '');
+
+INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_subject, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents, forum_flags) VALUES ('{L_FORUMS_TEST_FORUM_TITLE}', '{L_FORUMS_TEST_FORUM_DESC}', 2, 3, 1, 1, 1, 0, 0, 1, 0, 0, 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, '', '', '', '', '', '', '', 0, 0, '', 48);
+
+# -- Users / Anonymous user
+INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd, user_allow_massemail) VALUES (2, 1, 'Anonymous', 'anonymous', 0, '', '', 'en', 1, 0, '', 0, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', 0);
+
+# -- username: Admin password: admin (change this or remove it once everything is working!)
+INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_jabber, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '');
+
+# -- Groups
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GUESTS', 3, 0, '', 0, '', '', '', 5);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED', 3, 0, '', 0, '', '', '', 5);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('REGISTERED_COPPA', 3, 0, '', 0, '', '', '', 5);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GLOBAL_MODERATORS', 3, 0, '00AA00', 2, '', '', '', 0);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('ADMINISTRATORS', 3, 1, 'AA0000', 1, '', '', '', 0);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('BOTS', 3, 0, '9E8DA7', 0, '', '', '', 5);
+INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5);
+
+# -- Teampage
+INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (5, '', 1, 0);
+INSERT INTO phpbb_teampage (group_id, teampage_name, teampage_position, teampage_parent) VALUES (4, '', 2, 0);
+
+# -- User -> Group
+INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (1, 1, 0, 0);
+INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (2, 2, 0, 0);
+INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (4, 2, 0, 0);
+INSERT INTO phpbb_user_group (group_id, user_id, user_pending, group_leader) VALUES (5, 2, 0, 1);
+
+# -- Ranks
+INSERT INTO phpbb_ranks (rank_title, rank_min, rank_special, rank_image) VALUES ('{L_RANKS_SITE_ADMIN_TITLE}', 0, 1, '');
+
+# -- Roles data
+
+# Standard Admin (a_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 1, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option NOT IN ('a_switchperm', 'a_jabber', 'a_phpinfo', 'a_server', 'a_backup', 'a_styles', 'a_clearlogs', 'a_modules', 'a_language', 'a_email', 'a_bots', 'a_search', 'a_aauth', 'a_roles');
+
+# Forum admin (a_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 2, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_fauth', 'a_forum', 'a_forumadd', 'a_forumdel', 'a_mauth', 'a_prune', 'a_uauth', 'a_viewauth', 'a_viewlogs');
+
+# User and Groups Admin (a_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 3, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%' AND auth_option IN ('a_', 'a_authgroups', 'a_authusers', 'a_ban', 'a_group', 'a_groupadd', 'a_groupdel', 'a_ranks', 'a_uauth', 'a_user', 'a_viewauth', 'a_viewlogs');
+
+# Full Admin (a_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 4, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'a_%';
+
+# All Features (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 5, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%';
+
+# Standard Features (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 6, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_flash', 'u_pm_forward');
+
+# Limited Features (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 7, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group');
+
+# No Private Messages (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_', 'u_chgavatar', 'u_chgcensors', 'u_chgemail', 'u_chgpasswd', 'u_download', 'u_hideonline', 'u_sig', 'u_viewprofile');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 8, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_readpm', 'u_sendpm', 'u_masspm', 'u_masspm_group');
+
+# No Avatar (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option NOT IN ('u_attach', 'u_chgavatar', 'u_viewonline', 'u_chggrp', 'u_chgname', 'u_ignoreflood', 'u_pm_attach', 'u_pm_emailpm', 'u_pm_flash', 'u_savedrafts', 'u_search', 'u_sendemail', 'u_sendim', 'u_masspm', 'u_masspm_group');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 9, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_chgavatar');
+
+# Full Moderator (m_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 10, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%';
+
+# Standard Moderator (m_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 11, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option NOT IN ('m_ban', 'm_chgposter');
+
+# Simple Moderator (m_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 12, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_delete', 'm_softdelete', 'm_edit', 'm_info', 'm_report');
+
+# Queue Moderator (m_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 13, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'm_%' AND auth_option IN ('m_', 'm_approve', 'm_edit');
+
+# Full Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 14, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%';
+
+# Standard Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 15, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock');
+
+# No Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 16, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option = 'f_';
+
+# Read Only Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_search', 'f_subscribe', 'f_print');
+
+# Limited Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg');
+
+# Bot Access (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_print');
+
+# On Moderation Queue (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove');
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove');
+
+# Standard Access + Polls (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 21, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_flash', 'f_ignoreflood', 'f_sticky', 'f_user_lock');
+
+# Limited Access + Polls (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg');
+
+# New Member (u_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo');
+
+# New Member (f_)
+INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 24, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove');
+
+
+# Permissions
+
+# GUESTS - u_download and u_search ability
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) SELECT 1, 0, auth_option_id, 0, 1 FROM phpbb_acl_options WHERE auth_option IN ('u_', 'u_download', 'u_search');
+
+# Admin user - full user features
+INSERT INTO phpbb_acl_users (user_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 5, 0);
+
+# ADMINISTRATOR Group - full user features
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 5, 0);
+
+# ADMINISTRATOR Group - standard admin
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 0, 0, 1, 0);
+
+# REGISTERED and REGISTERED_COPPA having standard user features
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 0, 0, 6, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 0, 0, 6, 0);
+
+# GLOBAL_MODERATORS having full user features
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 5, 0);
+
+# GLOBAL_MODERATORS having full global moderator access
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 0, 0, 10, 0);
+
+# Giving all groups read only access to the first category
+# since administrators and moderators are already within the registered users group we do not need to set them here
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 1, 0, 17, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 1, 0, 17, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 1, 0, 17, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 1, 0, 17, 0);
+
+# Giving access to the first forum
+
+# guests having read only access
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (1, 2, 0, 17, 0);
+
+# registered and registered_coppa having standard access
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (2, 2, 0, 15, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (3, 2, 0, 15, 0);
+
+# global moderators having standard access + polls
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (4, 2, 0, 21, 0);
+
+# administrators having full forum and full moderator access
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 14, 0);
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (5, 2, 0, 10, 0);
+
+# Bots having bot access
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (6, 2, 0, 19, 0);
+
+# NEW MEMBERS are not allowed to send private messages
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 0, 0, 23, 0);
+
+# NEW MEMBERS on the queue
+INSERT INTO phpbb_acl_groups (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (7, 2, 0, 24, 0);
+
+
+# -- Demo Topic
+INSERT INTO phpbb_topics (topic_title, topic_poster, topic_time, topic_views, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, forum_id, topic_status, topic_type, topic_first_post_id, topic_first_poster_name, topic_first_poster_colour, topic_last_post_id, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour, topic_last_post_subject, topic_last_post_time, topic_last_view_time, poll_title, topic_visibility) VALUES ('{L_TOPICS_TOPIC_TITLE}', 2, 972086460, 0, 1, 0, 0, 2, 0, 0, 1, 'Admin', 'AA0000', 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, 972086460, '', 1);
+
+# -- Demo Post
+INSERT INTO phpbb_posts (topic_id, forum_id, poster_id, icon_id, post_time, post_username, poster_ip, post_subject, post_text, post_checksum, bbcode_uid, post_visibility) VALUES (1, 2, 2, 0, 972086460, '', '127.0.0.1', '{L_TOPICS_TOPIC_TITLE}', '{L_DEFAULT_INSTALL_POST}', '5dd683b17f641daf84c040bfefc58ce9', '', 1);
+
+# -- Admin posted to the demo topic
+INSERT INTO phpbb_topics_posted (user_id, topic_id, topic_posted) VALUES (2, 1, 1);
+
+# -- Smilies
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 1);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-D', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 2);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':grin:', 'icon_e_biggrin.gif', '{L_SMILIES_VERY_HAPPY}', 15, 17, 3);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 4);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-)', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 5);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':smile:', 'icon_e_smile.gif', '{L_SMILIES_SMILE}', 15, 17, 6);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 7);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (';-)', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 8);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':wink:', 'icon_e_wink.gif', '{L_SMILIES_WINK}', 15, 17, 9);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 10);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-(', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 11);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':sad:', 'icon_e_sad.gif', '{L_SMILIES_SAD}', 15, 17, 12);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 13);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-o', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 14);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':eek:', 'icon_e_surprised.gif', '{L_SMILIES_SURPRISED}', 15, 17, 15);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':shock:', 'icon_eek.gif', '{L_SMILIES_SHOCKED}', 15, 17, 16);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 17);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-?', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 18);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':???:', 'icon_e_confused.gif', '{L_SMILIES_CONFUSED}', 15, 17, 19);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES ('8-)', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 20);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cool:', 'icon_cool.gif', '{L_SMILIES_COOL}', 15, 17, 21);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':lol:', 'icon_lol.gif', '{L_SMILIES_LAUGHING}', 15, 17, 22);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 23);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-x', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 24);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mad:', 'icon_mad.gif', '{L_SMILIES_MAD}', 15, 17, 25);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 26);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-P', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 27);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':razz:', 'icon_razz.gif', '{L_SMILIES_RAZZ}', 15, 17, 28);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':oops:', 'icon_redface.gif', '{L_SMILIES_EMARRASSED}', 15, 17, 29);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':cry:', 'icon_cry.gif', '{L_SMILIES_CRYING}', 15, 17, 30);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':evil:', 'icon_evil.gif', '{L_SMILIES_EVIL}', 15, 17, 31);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':twisted:', 'icon_twisted.gif', '{L_SMILIES_TWISTED_EVIL}', 15, 17, 32);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':roll:', 'icon_rolleyes.gif', '{L_SMILIES_ROLLING_EYES}', 15, 17, 33);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':!:', 'icon_exclaim.gif', '{L_SMILIES_EXCLAMATION}', 15, 17, 34);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':?:', 'icon_question.gif', '{L_SMILIES_QUESTION}', 15, 17, 35);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':idea:', 'icon_idea.gif', '{L_SMILIES_IDEA}', 15, 17, 36);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':arrow:', 'icon_arrow.gif', '{L_SMILIES_ARROW}', 15, 17, 37);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 38);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':-|', 'icon_neutral.gif', '{L_SMILIES_NEUTRAL}', 15, 17, 39);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':mrgreen:', 'icon_mrgreen.gif', '{L_SMILIES_MR_GREEN}', 15, 17, 40);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':geek:', 'icon_e_geek.gif', '{L_SMILIES_GEEK}', 17, 17, 41);
+INSERT INTO phpbb_smilies (code, smiley_url, emotion, smiley_width, smiley_height, smiley_order) VALUES (':ugeek:', 'icon_e_ugeek.gif', '{L_SMILIES_UBER_GEEK}', 17, 18, 42);
+
+# -- icons
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/fire.gif', 16, 16, 1, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/redface.gif', 16, 16, 9, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/mrgreen.gif', 16, 16, 10, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/heart.gif', 16, 16, 4, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/star.gif', 16, 16, 2, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/radioactive.gif', 16, 16, 3, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('misc/thinking.gif', 16, 16, 5, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/info.gif', 16, 16, 8, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/question.gif', 16, 16, 6, 1);
+INSERT INTO phpbb_icons (icons_url, icons_width, icons_height, icons_order, display_on_posting) VALUES ('smile/alert.gif', 16, 16, 7, 1);
+
+# -- reasons
+INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('warez', '{L_REPORT_WAREZ}', 1);
+INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('spam', '{L_REPORT_SPAM}', 2);
+INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('off_topic', '{L_REPORT_OFF_TOPIC}', 3);
+INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('other', '{L_REPORT_OTHER}', 4);
+
+# -- extension_groups
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('IMAGES', 1, 1, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, '');
+INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, '');
+
+# -- extensions
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'gif');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'png');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpeg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'jpg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tif');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tiff');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'tga');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gtar');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'gz');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tar');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'zip');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'rar');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'ace');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'torrent');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'tgz');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, 'bz2');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (2, '7z');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'txt');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'c');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'h');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'cpp');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'hpp');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'diz');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'csv');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'ini');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'log');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'js');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (3, 'xml');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xls');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsx');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'xlsb');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'doc');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docx');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'docm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dot');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotx');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'dotm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pdf');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ai');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ps');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ppt');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptx');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'pptm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odp');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'ods');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'odt');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (4, 'rtf');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'rm');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (5, 'ram');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wma');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (6, 'wmv');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (7, 'swf');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mov');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4v');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'm4a');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'mp4');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3gp');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, '3g2');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (8, 'qt');
+
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpeg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mpg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'mp3');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogg');
+INSERT INTO phpbb_extensions (group_id, extension) VALUES (9, 'ogm');
+
+# Add default profile fields
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_location', 'profilefields.type.string', 'phpbb_location', '20', '2', '100', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, '', '');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_website', 'profilefields.type.url', 'phpbb_website', '40', '12', '255', '', '', '', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 2, 1, 'VISIT_WEBSITE', '%s');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_interests', 'profilefields.type.text', 'phpbb_interests', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, '', '');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_occupation', 'profilefields.type.text', 'phpbb_occupation', '3|30', '2', '500', '', '', '.*', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, '', '');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_aol', 'profilefields.type.string', 'phpbb_aol', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 5, 1, '', '');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_icq', 'profilefields.type.string', 'phpbb_icq', '20', '3', '15', '', '', '[0-9]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 6, 1, 'SEND_ICQ_MESSAGE', 'https://www.icq.com/people/%s/');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_wlm', 'profilefields.type.string', 'phpbb_wlm', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 7, 1, '', '');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_yahoo', 'profilefields.type.string', 'phpbb_yahoo', '40', '5', '255', '', '', '.*', 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 8, 1, 'SEND_YIM_MESSAGE', 'ymsgr:sendim?%s');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_facebook', 'profilefields.type.string', 'phpbb_facebook', '20', '5', '50', '', '', '[\w.]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 9, 1, 'VIEW_FACEBOOK_PROFILE', 'http://facebook.com/%s/');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_twitter', 'profilefields.type.string', 'phpbb_twitter', '20', '1', '15', '', '', '[\w_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 10, 1, 'VIEW_TWITTER_PROFILE', 'http://twitter.com/%s');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_skype', 'profilefields.type.string', 'phpbb_skype', '20', '6', '32', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 11, 1, 'VIEW_SKYPE_PROFILE', 'skype:%s?userinfo');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_youtube', 'profilefields.type.string', 'phpbb_youtube', '20', '3', '60', '', '', '[a-zA-Z][\w\.,\-_]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 12, 1, 'VIEW_YOUTUBE_CHANNEL', 'http://youtube.com/user/%s');
+INSERT INTO phpbb_profile_fields (field_name, field_type, field_ident, field_length, field_minlen, field_maxlen, field_novalue, field_default_value, field_validation, field_required, field_show_novalue, field_show_on_reg, field_show_on_pm, field_show_on_vt, field_show_on_ml, field_show_profile, field_hide, field_no_view, field_active, field_order, field_is_contact, field_contact_desc, field_contact_url) VALUES ('phpbb_googleplus', 'profilefields.type.googleplus', 'phpbb_googleplus', '20', '3', '255', '', '', '[\w]+', 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 13, 1, 'VIEW_GOOGLEPLUS_PROFILE', 'http://plus.google.com/%s');
+
+# User Notification Options (for first user)
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, '');
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.post', 0, 2, 'notification.method.email');
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, '');
+INSERT INTO phpbb_user_notifications (item_type, item_id, user_id, method) VALUES('notification.type.topic', 0, 2, 'notification.method.email');
+
+# POSTGRES COMMIT #