diff options
author | Mate Bartus <mate.bartus@gmail.com> | 2015-06-30 16:36:34 +0200 |
---|---|---|
committer | Mate Bartus <mate.bartus@gmail.com> | 2015-07-08 01:28:10 +0200 |
commit | 10f6716566fce9d9c38f3dd99419595b2a1cba4c (patch) | |
tree | 435a7a88bea17219187c271e38f2b07a677223aa /phpBB/install | |
parent | 249345d9cc6d6bff380436d6e05f24918d762c0d (diff) | |
download | forums-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.php | 79 | ||||
-rw-r--r-- | phpBB/install/convertors/convert_phpbb20.php | 975 | ||||
-rw-r--r-- | phpBB/install/convertors/functions_phpbb20.php | 1984 | ||||
-rw-r--r-- | phpBB/install/data/confusables.php | 645 | ||||
-rw-r--r-- | phpBB/install/database_update.php | 267 | ||||
-rw-r--r-- | phpBB/install/index.php | 867 | ||||
-rw-r--r-- | phpBB/install/install_convert.php | 2153 | ||||
-rw-r--r-- | phpBB/install/install_install.php | 2368 | ||||
-rw-r--r-- | phpBB/install/install_main.php | 78 | ||||
-rw-r--r-- | phpBB/install/install_update.php | 1790 | ||||
-rwxr-xr-x | phpBB/install/phpbbcli.php | 68 | ||||
-rw-r--r-- | phpBB/install/phpinfo.php | 14 | ||||
-rw-r--r-- | phpBB/install/schemas/index.htm | 10 | ||||
-rw-r--r-- | phpBB/install/schemas/oracle_schema.sql | 37 | ||||
-rw-r--r-- | phpBB/install/schemas/postgres_schema.sql | 80 | ||||
-rw-r--r-- | phpBB/install/schemas/schema_data.sql | 821 |
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="\1"]', $message); + $message = preg_replace('/\[quote=\\\"(.*?)\\\"\]/s', '[quote="\1"]', $message); + + // let's hope that this solves more problems than it causes. Deal with escaped quotes. + $message = str_replace('\"', '"', $message); + $message = str_replace('\"', '"', $message); + } + + // Already the new user id ;) + $user_id = $convert->row['poster_id']; + + $message = str_replace('<br />', "\n", $message); + $message = str_replace('<', '<', $message); + $message = str_replace('>', '>', $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('<', '<', $code); + return str_replace('>', '>', $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>® Forum Software © 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"> </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) . '&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&sub=update_db&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&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 . "&sub=$option&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>® Forum Software © 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 />» 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 . ' ' . $tpl_no : $tpl_no . ' ' . $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}&sub=intro&new_conv=1&language=$language", + 'U_CONTINUE_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=in_progress&tag={$options['tag']}{$options['step']}&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&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}&language=$language&sub=settings&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}&sub=in_progress&tag=$convertor_tag&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}&sub=settings&tag=$convertor_tag&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}&sub=in_progress&tag={$convert->convertor_tag}&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('&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('&current_table=' . $current_table . '&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('&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('&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('&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}&sub=in_progress&tag={$convert->convertor_tag}$step&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}&sub=final&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('&jump=1&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('&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('&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&sub=requirements&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&sub=database&language=$language" : $this->p_master->module_url . "?mode=$mode&sub=requirements&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&sub=administrator" : $this->p_master->module_url . "?mode=$mode&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&sub=config_file" : $this->p_master->module_url . "?mode=$mode&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&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&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&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&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&language=' . $data['language']), '../docs/README.html'), + 'L_SUBMIT' => $lang['INSTALL_LOGIN'], + 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&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&mode=$mode&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&mode=$mode&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&language=' . $user->data['user_lang']), + 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&sub=update_db"), + 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&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&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&mode=$mode&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&mode=$mode&sub=file_check&action=diff&status=$status&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 . '&op=' . MERGE_MOD_FILE, + 'U_VIEW_NEW_FILE' => $diff_url . '&op=' . MERGE_NEW_FILE, + 'U_VIEW_NO_MERGE_MOD' => $diff_url . '&op=' . MERGE_NO_MERGE_MOD, + 'U_VIEW_NO_MERGE_NEW' => $diff_url . '&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&mode=$mode&sub=file_check"), + 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&sub=update_files"), + 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&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&mode=$mode&sub=update_files&" . implode('&', $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&mode=$mode&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&mode=$mode&sub=update_files"), + 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&sub=update_files&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&mode=$mode&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', '© 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 # |